1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #include "wx/window.h"
20 #include "wx/layout.h"
22 #include "wx/dialog.h"
23 #include "wx/msgdlg.h"
25 #if wxUSE_DRAG_AND_DROP
30 #include "wx/tooltip.h"
34 #include "wx/statusbr.h"
36 #include "wx/settings.h"
43 #include "gdk/gdkprivate.h"
44 #include "gdk/gdkkeysyms.h"
45 #include "wx/gtk/win_gtk.h"
47 //-----------------------------------------------------------------------------
48 // documentation on internals
49 //-----------------------------------------------------------------------------
52 I have been asked several times about writing some documentation about
53 the GTK port of wxWindows, especially its internal structures. Obviously,
54 you cannot understand wxGTK without knowing a little about the GTK, but
55 some more information about what the wxWindow, which is the base class
56 for all other window classes, does seems required as well.
58 What does wxWindow do? It contains the common interface for the following
59 jobs of its descendants:
61 1) Define the rudimentary behaviour common to all window classes, such as
62 resizing, intercepting user input (so as to make it possible to use these
63 events for special purposes in a derived class), window names etc.
65 2) Provide the possibility to contain and manage children, if the derived
66 class is allowed to contain children, which holds true for those window
67 classes which do not display a native GTK widget. To name them, these
68 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
69 work classes are a special case and are handled a bit differently from
70 the rest. The same holds true for the wxNotebook class.
72 3) Provide the possibility to draw into a client area of a window. This,
73 too, only holds true for classes that do not display a native GTK widget
76 4) Provide the entire mechanism for scrolling widgets. This actual inter-
77 face for this is usually in wxScrolledWindow, but the GTK implementation
80 5) A multitude of helper or extra methods for special purposes, such as
81 Drag'n'Drop, managing validators etc.
83 Normally one might expect, that one wxWindows window would always correspond
84 to one GTK widget. Under GTK, there is no such allround widget that has all
85 the functionality. Moreover, the GTK defines a client area as a different
86 widget from the actual widget you are handling. Last but not least some
87 special classes (e.g. wxFrame) handle different categories of widgets and
88 still have the possibility to draw something in the client area.
89 It was therefore required to write a special purpose GTK widget, that would
90 represent a client area in the sense of wxWindows capable to do the jobs
91 2), 3) and 4). I have written this class and it resides in win_gtk.c of
94 All windows must have a widget, with which they interact with other under-
95 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
96 thw wxWindow class has a member variable called m_widget which holds a
97 pointer to this widget. When the window class represents a GTK native widget,
98 this is (in most cases) the only GTK widget the class manages. E.g. the
99 wxStatitText class handles only a GtkLabel widget a pointer to which you
100 can find in m_widget (defined in wxWindow)
102 When the class has a client area for drawing into and for containing children
103 it has to handle the client area widget (of the type GtkMyFixed, defined in
104 win_gtk.c), but there could be any number of widgets, handled by a class
105 The common rule for all windows is only, that the widget that interacts with
106 the rest of GTK must be referenced in m_widget and all other widgets must be
107 children of this widget on the GTK level. The top-most widget, which also
108 represents the client area, must be in the m_wxwindow field and must be of
111 As I said, the window classes that display a GTK native widget only have
112 one widget, so in the case of e.g. the wxButton class m_widget holds a
113 pointer to a GtkButton widget. But windows with client areas (for drawing
114 and children) have a m_widget field that is a pointer to a GtkScrolled-
115 Window and a m_wxwindow field that is pointer to a GtkMyFixed and this
116 one is (in the GTK sense) a child of the GtkScrolledWindow.
118 If the m_wxwindow field is set, then all input to this widget is inter-
119 cepted and sent to the wxWindows class. If not, all input to the widget
120 that gets pointed to by m_widget gets intercepted and sent to the class.
124 //-----------------------------------------------------------------------------
126 //-----------------------------------------------------------------------------
128 extern wxList wxPendingDelete
;
129 extern bool g_blockEventsOnDrag
;
130 extern bool g_blockEventsOnScroll
;
131 static bool g_capturing
= FALSE
;
132 static wxWindow
*g_focusWindow
= (wxWindow
*) NULL
;
134 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
135 the last click here */
136 static guint32 gs_timeLastClick
= 0;
138 //-----------------------------------------------------------------------------
140 //-----------------------------------------------------------------------------
144 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
145 GdkEvent
*WXUNUSED(event
),
148 // to enable logging of the focus events replace 0 with 1
150 static bool s_done
= FALSE
;
153 wxLog::AddTraceMask("focus");
157 wxLogTrace(_T("FOCUS NOW AT: %s"), name
);
162 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
168 wxChar
*s
= new wxChar
[tmp
.Length()+1];
172 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
173 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
178 //-----------------------------------------------------------------------------
180 //-----------------------------------------------------------------------------
182 extern void wxapp_install_idle_handler();
183 extern bool g_isIdle
;
185 //-----------------------------------------------------------------------------
186 // local code (see below)
187 //-----------------------------------------------------------------------------
189 #if (GTK_MINOR_VERSION > 0)
191 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
199 if (win
->HasScrolling())
201 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
202 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget
)->klass
);
205 GtkWidget *hscrollbar = scroll_window->hscrollbar;
206 GtkWidget *vscrollbar = scroll_window->vscrollbar;
208 we use this instead: range.slider_width = 11 + 2*2pts edge
211 if (scroll_window
->vscrollbar_visible
)
213 dw
+= 15; /* dw += vscrollbar->allocation.width; */
214 dw
+= scroll_class
->scrollbar_spacing
;
217 if (scroll_window
->hscrollbar_visible
)
219 dh
+= 15; /* dh += hscrollbar->allocation.height; */
220 dw
+= scroll_class
->scrollbar_spacing
;
226 if (GTK_WIDGET_NO_WINDOW (widget
))
228 dx
+= widget
->allocation
.x
;
229 dy
+= widget
->allocation
.y
;
232 if (win
->HasFlag(wxRAISED_BORDER
))
234 gtk_draw_shadow( widget
->style
,
239 win
->m_width
-dw
, win
->m_height
-dh
);
243 if (win
->HasFlag(wxSUNKEN_BORDER
))
245 gtk_draw_shadow( widget
->style
,
250 win
->m_width
-dw
, win
->m_height
-dh
);
255 //-----------------------------------------------------------------------------
256 // "expose_event" of m_widget
257 //-----------------------------------------------------------------------------
259 static void gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
261 if (gdk_event
->count
> 0) return;
262 draw_frame( widget
, win
);
265 //-----------------------------------------------------------------------------
266 // "draw" of m_wxwindow
267 //-----------------------------------------------------------------------------
269 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
271 draw_frame( widget
, win
);
274 #endif // GTK_MINOR_VERSION > 0
276 //-----------------------------------------------------------------------------
277 // "expose_event" of m_wxwindow
278 //-----------------------------------------------------------------------------
280 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
282 if ( !win
->m_hasVMT
)
285 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
287 gdk_event
->area
.width
,
288 gdk_event
->area
.height
);
290 if ( gdk_event
->count
> 0 )
294 printf( "OnExpose from " );
295 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
296 printf( win->GetClassInfo()->GetClassName() );
300 wxPaintEvent
event( win
->GetId() );
301 event
.SetEventObject( win
);
302 win
->GetEventHandler()->ProcessEvent( event
);
304 win
->GetUpdateRegion().Clear();
307 //-----------------------------------------------------------------------------
308 // "draw" of m_wxwindow
309 //-----------------------------------------------------------------------------
311 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
), GdkRectangle
*rect
, wxWindow
*win
)
314 wxapp_install_idle_handler();
319 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
,
320 rect
->width
, rect
->height
);
322 wxPaintEvent
event( win
->GetId() );
323 event
.SetEventObject( win
);
324 win
->GetEventHandler()->ProcessEvent( event
);
326 win
->GetUpdateRegion().Clear();
329 //-----------------------------------------------------------------------------
330 // "key_press_event" from any window
331 //-----------------------------------------------------------------------------
333 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
336 wxapp_install_idle_handler();
338 if (!win
->m_hasVMT
) return FALSE
;
339 if (g_blockEventsOnDrag
) return FALSE
;
342 printf( "OnKeyPress from " );
343 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
344 printf( win->GetClassInfo()->GetClassName() );
349 switch (gdk_event
->keyval
)
351 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
352 case GDK_ISO_Left_Tab
:
354 case GDK_Tab
: key_code
= WXK_TAB
; break;
355 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
356 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
357 case GDK_Return
: key_code
= WXK_RETURN
; break;
358 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
359 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
360 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
361 case GDK_Delete
: key_code
= WXK_DELETE
; break;
362 case GDK_Home
: key_code
= WXK_HOME
; break;
363 case GDK_Left
: key_code
= WXK_LEFT
; break;
364 case GDK_Up
: key_code
= WXK_UP
; break;
365 case GDK_Right
: key_code
= WXK_RIGHT
; break;
366 case GDK_Down
: key_code
= WXK_DOWN
; break;
367 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
368 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
369 case GDK_Next
: key_code
= WXK_NEXT
; break;
370 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
371 case GDK_End
: key_code
= WXK_END
; break;
372 case GDK_Begin
: key_code
= WXK_HOME
; break;
373 case GDK_Select
: key_code
= WXK_SELECT
; break;
374 case GDK_Print
: key_code
= WXK_PRINT
; break;
375 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
376 case GDK_Insert
: key_code
= WXK_INSERT
; break;
377 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
378 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break;
379 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
380 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
381 case GDK_KP_Up
: key_code
= WXK_UP
; break;
382 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
383 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
384 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
385 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
386 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
387 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
388 case GDK_KP_End
: key_code
= WXK_END
; break;
389 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
390 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
391 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
392 case GDK_KP_Multiply
: key_code
= WXK_MULTIPLY
; break;
393 case GDK_KP_Add
: key_code
= WXK_ADD
; break;
394 case GDK_KP_Separator
: key_code
= WXK_SEPARATOR
; break;
395 case GDK_KP_Subtract
: key_code
= WXK_SUBTRACT
; break;
396 case GDK_KP_Decimal
: key_code
= WXK_DECIMAL
; break;
397 case GDK_KP_Divide
: key_code
= WXK_DIVIDE
; break;
398 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
399 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
400 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
401 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
402 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
403 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
404 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
405 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
406 case GDK_KP_8
: key_code
= WXK_NUMPAD7
; break;
407 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
408 case GDK_F1
: key_code
= WXK_F1
; break;
409 case GDK_F2
: key_code
= WXK_F2
; break;
410 case GDK_F3
: key_code
= WXK_F3
; break;
411 case GDK_F4
: key_code
= WXK_F4
; break;
412 case GDK_F5
: key_code
= WXK_F5
; break;
413 case GDK_F6
: key_code
= WXK_F6
; break;
414 case GDK_F7
: key_code
= WXK_F7
; break;
415 case GDK_F8
: key_code
= WXK_F8
; break;
416 case GDK_F9
: key_code
= WXK_F9
; break;
417 case GDK_F10
: key_code
= WXK_F10
; break;
418 case GDK_F11
: key_code
= WXK_F11
; break;
419 case GDK_F12
: key_code
= WXK_F12
; break;
422 if ((gdk_event
->keyval
>= 0x20) && (gdk_event
->keyval
<= 0xFF))
423 key_code
= gdk_event
->keyval
;
427 if (!key_code
) return FALSE
;
429 wxKeyEvent
event( wxEVT_KEY_DOWN
);
430 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
431 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
432 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
433 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
434 event
.m_keyCode
= key_code
;
437 event
.SetEventObject( win
);
439 bool ret
= win
->GetEventHandler()->ProcessEvent( event
);
443 wxWindow
*ancestor
= win
;
446 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
449 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
450 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
453 ancestor
= ancestor
->GetParent();
457 // win is a control: tab can be propagated up
459 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
460 (win
->HasFlag(wxTE_PROCESS_TAB
) == 0))
462 wxNavigationKeyEvent new_event
;
463 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
464 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
465 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
466 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
467 new_event
.SetCurrentFocus( win
);
468 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
472 (gdk_event
->keyval
== GDK_Escape
) )
474 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
475 new_event
.SetEventObject( win
);
476 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
480 Damn, I forgot why this didn't work, but it didn't work.
482 // win is a panel: up can be propagated to the panel
483 if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
484 (gdk_event->keyval == GDK_Up))
486 win->m_parent->SetFocus();
490 // win is a panel: left/right can be propagated to the panel
491 if ((!ret) && (win->m_wxwindow) &&
492 ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
493 (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
495 wxNavigationKeyEvent new_event;
496 new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
497 new_event.SetCurrentFocus( win );
498 ret = win->GetEventHandler()->ProcessEvent( new_event );
504 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
511 //-----------------------------------------------------------------------------
512 // "key_release_event" from any window
513 //-----------------------------------------------------------------------------
515 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
518 wxapp_install_idle_handler();
520 if (!win
->m_hasVMT
) return FALSE
;
521 if (g_blockEventsOnDrag
) return FALSE
;
524 printf( "OnKeyRelease from " );
525 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
526 printf( win->GetClassInfo()->GetClassName() );
531 switch (gdk_event
->keyval
)
533 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
534 case GDK_ISO_Left_Tab
:
536 case GDK_Tab
: key_code
= WXK_TAB
; break;
537 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
538 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
539 case GDK_Return
: key_code
= WXK_RETURN
; break;
540 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
541 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
542 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
543 case GDK_Delete
: key_code
= WXK_DELETE
; break;
544 case GDK_Home
: key_code
= WXK_HOME
; break;
545 case GDK_Left
: key_code
= WXK_LEFT
; break;
546 case GDK_Up
: key_code
= WXK_UP
; break;
547 case GDK_Right
: key_code
= WXK_RIGHT
; break;
548 case GDK_Down
: key_code
= WXK_DOWN
; break;
549 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
550 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
551 case GDK_Next
: key_code
= WXK_NEXT
; break;
552 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
553 case GDK_End
: key_code
= WXK_END
; break;
554 case GDK_Begin
: key_code
= WXK_HOME
; break;
555 case GDK_Select
: key_code
= WXK_SELECT
; break;
556 case GDK_Print
: key_code
= WXK_PRINT
; break;
557 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
558 case GDK_Insert
: key_code
= WXK_INSERT
; break;
559 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
560 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break;
561 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
562 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
563 case GDK_KP_Up
: key_code
= WXK_UP
; break;
564 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
565 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
566 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
567 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
568 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
569 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
570 case GDK_KP_End
: key_code
= WXK_END
; break;
571 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
572 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
573 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
574 case GDK_KP_Multiply
: key_code
= WXK_MULTIPLY
; break;
575 case GDK_KP_Add
: key_code
= WXK_ADD
; break;
576 case GDK_KP_Separator
: key_code
= WXK_SEPARATOR
; break;
577 case GDK_KP_Subtract
: key_code
= WXK_SUBTRACT
; break;
578 case GDK_KP_Decimal
: key_code
= WXK_DECIMAL
; break;
579 case GDK_KP_Divide
: key_code
= WXK_DIVIDE
; break;
580 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
581 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
582 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
583 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
584 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
585 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
586 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
587 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
588 case GDK_KP_8
: key_code
= WXK_NUMPAD7
; break;
589 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
590 case GDK_F1
: key_code
= WXK_F1
; break;
591 case GDK_F2
: key_code
= WXK_F2
; break;
592 case GDK_F3
: key_code
= WXK_F3
; break;
593 case GDK_F4
: key_code
= WXK_F4
; break;
594 case GDK_F5
: key_code
= WXK_F5
; break;
595 case GDK_F6
: key_code
= WXK_F6
; break;
596 case GDK_F7
: key_code
= WXK_F7
; break;
597 case GDK_F8
: key_code
= WXK_F8
; break;
598 case GDK_F9
: key_code
= WXK_F9
; break;
599 case GDK_F10
: key_code
= WXK_F10
; break;
600 case GDK_F11
: key_code
= WXK_F11
; break;
601 case GDK_F12
: key_code
= WXK_F12
; break;
604 if ((gdk_event
->keyval
>= 0x20) && (gdk_event
->keyval
<= 0xFF))
605 key_code
= gdk_event
->keyval
;
609 if (!key_code
) return FALSE
;
611 wxKeyEvent
event( wxEVT_KEY_UP
);
612 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
613 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
614 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
615 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
616 event
.m_keyCode
= key_code
;
619 event
.SetEventObject( win
);
621 if (win
->GetEventHandler()->ProcessEvent( event
))
623 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
630 //-----------------------------------------------------------------------------
631 // "button_press_event"
632 //-----------------------------------------------------------------------------
634 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
637 wxapp_install_idle_handler();
640 wxPrintf( _T("1) OnButtonPress from ") );
641 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
642 wxPrintf( win->GetClassInfo()->GetClassName() );
643 wxPrintf( _T(".\n") );
646 if (!win
->m_hasVMT
) return FALSE
;
647 if (g_blockEventsOnDrag
) return TRUE
;
648 if (g_blockEventsOnScroll
) return TRUE
;
650 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
654 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
656 gtk_widget_grab_focus (win
->m_wxwindow
);
659 wxPrintf( _T("GrabFocus from ") );
660 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
661 wxPrintf( win->GetClassInfo()->GetClassName() );
662 wxPrintf( _T(".\n") );
669 wxPrintf( _T("2) OnButtonPress from ") );
670 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
671 wxPrintf( win->GetClassInfo()->GetClassName() );
672 wxPrintf( _T(".\n") );
675 wxEventType event_type
= wxEVT_LEFT_DOWN
;
677 if (gdk_event
->button
== 1)
679 switch (gdk_event
->type
)
681 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
682 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
686 else if (gdk_event
->button
== 2)
688 switch (gdk_event
->type
)
690 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
691 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
695 else if (gdk_event
->button
== 3)
697 switch (gdk_event
->type
)
699 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
700 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
705 wxMouseEvent
event( event_type
);
706 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
707 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
708 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
709 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
710 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
711 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
712 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
714 event
.m_x
= (long)gdk_event
->x
;
715 event
.m_y
= (long)gdk_event
->y
;
717 // Some control don't have their own X window and thus cannot get
722 wxNode
*node
= win
->GetChildren().First();
725 wxWindow
*child
= (wxWindow
*)node
->Data();
727 if (child
->m_isStaticBox
)
729 // wxStaticBox is transparent in the box itself
732 int xx1
= child
->m_x
;
733 int yy1
= child
->m_y
;
734 int xx2
= child
->m_x
+ child
->m_width
;
735 int yy2
= child
->m_x
+ child
->m_height
;
738 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
740 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
742 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
744 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
747 event
.m_x
-= child
->m_x
;
748 event
.m_y
-= child
->m_y
;
755 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
756 (child
->m_x
<= event
.m_x
) &&
757 (child
->m_y
<= event
.m_y
) &&
758 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
759 (child
->m_y
+child
->m_height
>= event
.m_y
))
762 event
.m_x
-= child
->m_x
;
763 event
.m_y
-= child
->m_y
;
771 event
.SetEventObject( win
);
773 gs_timeLastClick
= gdk_event
->time
;
775 if (win
->GetEventHandler()->ProcessEvent( event
))
777 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
784 //-----------------------------------------------------------------------------
785 // "button_release_event"
786 //-----------------------------------------------------------------------------
788 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
791 wxapp_install_idle_handler();
793 if (!win
->m_hasVMT
) return FALSE
;
794 if (g_blockEventsOnDrag
) return FALSE
;
795 if (g_blockEventsOnScroll
) return FALSE
;
797 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
800 printf( "OnButtonRelease from " );
801 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
802 printf( win->GetClassInfo()->GetClassName() );
806 wxEventType event_type
= wxEVT_NULL
;
808 switch (gdk_event
->button
)
810 case 1: event_type
= wxEVT_LEFT_UP
; break;
811 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
812 case 3: event_type
= wxEVT_RIGHT_UP
; break;
815 wxMouseEvent
event( event_type
);
816 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
817 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
818 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
819 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
820 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
821 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
822 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
823 event
.m_x
= (long)gdk_event
->x
;
824 event
.m_y
= (long)gdk_event
->y
;
826 // Some control don't have their own X window and thus cannot get
831 wxNode
*node
= win
->GetChildren().First();
834 wxWindow
*child
= (wxWindow
*)node
->Data();
836 if (child
->m_isStaticBox
)
838 // wxStaticBox is transparent in the box itself
841 int xx1
= child
->m_x
;
842 int yy1
= child
->m_y
;
843 int xx2
= child
->m_x
+ child
->m_width
;
844 int yy2
= child
->m_x
+ child
->m_height
;
847 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
849 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
851 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
853 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
856 event
.m_x
-= child
->m_x
;
857 event
.m_y
-= child
->m_y
;
864 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
865 (child
->m_x
<= event
.m_x
) &&
866 (child
->m_y
<= event
.m_y
) &&
867 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
868 (child
->m_y
+child
->m_height
>= event
.m_y
))
871 event
.m_x
-= child
->m_x
;
872 event
.m_y
-= child
->m_y
;
880 event
.SetEventObject( win
);
882 if (win
->GetEventHandler()->ProcessEvent( event
))
884 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
891 //-----------------------------------------------------------------------------
892 // "motion_notify_event"
893 //-----------------------------------------------------------------------------
895 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
898 wxapp_install_idle_handler();
900 if (!win
->m_hasVMT
) return FALSE
;
901 if (g_blockEventsOnDrag
) return FALSE
;
902 if (g_blockEventsOnScroll
) return FALSE
;
904 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
906 if (gdk_event
->is_hint
)
910 GdkModifierType state
;
911 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
914 gdk_event
->state
= state
;
918 printf( "OnMotion from " );
919 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
920 printf( win->GetClassInfo()->GetClassName() );
924 wxMouseEvent
event( wxEVT_MOTION
);
925 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
926 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
927 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
928 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
929 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
930 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
931 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
933 event
.m_x
= (long)gdk_event
->x
;
934 event
.m_y
= (long)gdk_event
->y
;
936 // Some control don't have their own X window and thus cannot get
941 wxNode
*node
= win
->GetChildren().First();
944 wxWindow
*child
= (wxWindow
*)node
->Data();
946 if (child
->m_isStaticBox
)
948 // wxStaticBox is transparent in the box itself
951 int xx1
= child
->m_x
;
952 int yy1
= child
->m_y
;
953 int xx2
= child
->m_x
+ child
->m_width
;
954 int yy2
= child
->m_x
+ child
->m_height
;
957 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
959 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
961 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
963 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
966 event
.m_x
-= child
->m_x
;
967 event
.m_y
-= child
->m_y
;
974 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
975 (child
->m_x
<= event
.m_x
) &&
976 (child
->m_y
<= event
.m_y
) &&
977 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
978 (child
->m_y
+child
->m_height
>= event
.m_y
))
981 event
.m_x
-= child
->m_x
;
982 event
.m_y
-= child
->m_y
;
990 event
.SetEventObject( win
);
992 if (win
->GetEventHandler()->ProcessEvent( event
))
994 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1001 //-----------------------------------------------------------------------------
1003 //-----------------------------------------------------------------------------
1005 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1008 wxapp_install_idle_handler();
1010 if (!win
->m_hasVMT
) return FALSE
;
1011 if (g_blockEventsOnDrag
) return FALSE
;
1013 g_focusWindow
= win
;
1015 if (win
->m_wxwindow
)
1017 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1019 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1021 printf( "SetFocus flag from " );
1022 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1023 printf( win->GetClassInfo()->GetClassName() );
1031 printf( "OnSetFocus from " );
1032 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1033 printf( win->GetClassInfo()->GetClassName() );
1035 printf( WXSTRINGCAST win->GetLabel() );
1039 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1040 event
.SetEventObject( win
);
1042 if (win
->GetEventHandler()->ProcessEvent( event
))
1044 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1051 //-----------------------------------------------------------------------------
1052 // "focus_out_event"
1053 //-----------------------------------------------------------------------------
1055 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1058 wxapp_install_idle_handler();
1060 if (!win
->m_hasVMT
) return FALSE
;
1061 if (g_blockEventsOnDrag
) return FALSE
;
1063 if (win
->m_wxwindow
)
1065 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1066 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1070 printf( "OnKillFocus from " );
1071 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1072 printf( win->GetClassInfo()->GetClassName() );
1076 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1077 event
.SetEventObject( win
);
1079 if (win
->GetEventHandler()->ProcessEvent( event
))
1081 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1088 //-----------------------------------------------------------------------------
1089 // "enter_notify_event"
1090 //-----------------------------------------------------------------------------
1092 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1095 wxapp_install_idle_handler();
1097 if (!win
->m_hasVMT
) return FALSE
;
1098 if (g_blockEventsOnDrag
) return FALSE
;
1100 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1102 if (widget
->window
&& win
->GetCursor().Ok() )
1103 gdk_window_set_cursor( widget
->window
, win
->GetCursor().GetCursor() );
1105 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1106 event
.SetEventObject( win
);
1110 GdkModifierType state
= (GdkModifierType
)0;
1112 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1114 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1115 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1116 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1117 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1118 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1119 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1120 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1122 event
.m_x
= (long)x
;
1123 event
.m_y
= (long)y
;
1125 if (win
->GetEventHandler()->ProcessEvent( event
))
1127 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1134 //-----------------------------------------------------------------------------
1135 // "leave_notify_event"
1136 //-----------------------------------------------------------------------------
1138 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1141 wxapp_install_idle_handler();
1143 if (!win
->m_hasVMT
) return FALSE
;
1144 if (g_blockEventsOnDrag
) return FALSE
;
1146 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1148 if (widget
->window
&& win
->GetCursor().Ok() )
1149 gdk_window_set_cursor( widget
->window
, wxSTANDARD_CURSOR
->GetCursor() );
1151 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1152 event
.SetEventObject( win
);
1156 GdkModifierType state
= (GdkModifierType
)0;
1158 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1160 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1161 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1162 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1163 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1164 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1165 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1166 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1168 event
.m_x
= (long)x
;
1169 event
.m_y
= (long)y
;
1171 if (win
->GetEventHandler()->ProcessEvent( event
))
1173 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1180 //-----------------------------------------------------------------------------
1181 // "value_changed" from m_vAdjust
1182 //-----------------------------------------------------------------------------
1184 static void gtk_window_vscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1187 wxapp_install_idle_handler();
1189 if (g_blockEventsOnDrag
) return;
1191 if (!win
->m_hasVMT
) return;
1193 float diff
= win
->m_vAdjust
->value
- win
->m_oldVerticalPos
;
1194 if (fabs(diff
) < 0.2) return;
1195 win
->m_oldVerticalPos
= win
->m_vAdjust
->value
;
1197 wxEventType command
= wxEVT_NULL
;
1199 float line_step
= win
->m_vAdjust
->step_increment
;
1200 float page_step
= win
->m_vAdjust
->page_increment
;
1202 if (win
->IsScrolling())
1204 command
= wxEVT_SCROLL_THUMBTRACK
;
1208 if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->lower
) < 0.2) command
= wxEVT_SCROLL_BOTTOM
;
1209 else if (fabs(win
->m_vAdjust
->value
-win
->m_vAdjust
->upper
) < 0.2) command
= wxEVT_SCROLL_TOP
;
1210 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
1211 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
1212 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
1213 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
1214 else command
= wxEVT_SCROLL_THUMBTRACK
;
1217 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1219 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
1220 event
.SetEventObject( win
);
1221 win
->GetEventHandler()->ProcessEvent( event
);
1224 //-----------------------------------------------------------------------------
1225 // "value_changed" from m_hAdjust
1226 //-----------------------------------------------------------------------------
1228 static void gtk_window_hscroll_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1231 wxapp_install_idle_handler();
1233 if (g_blockEventsOnDrag
) return;
1234 if (!win
->m_hasVMT
) return;
1236 float diff
= win
->m_hAdjust
->value
- win
->m_oldHorizontalPos
;
1237 if (fabs(diff
) < 0.2) return;
1238 win
->m_oldHorizontalPos
= win
->m_hAdjust
->value
;
1240 wxEventType command
= wxEVT_NULL
;
1242 float line_step
= win
->m_hAdjust
->step_increment
;
1243 float page_step
= win
->m_hAdjust
->page_increment
;
1245 if (win
->IsScrolling())
1247 command
= wxEVT_SCROLL_THUMBTRACK
;
1251 if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->lower
) < 0.2) command
= wxEVT_SCROLL_BOTTOM
;
1252 else if (fabs(win
->m_hAdjust
->value
-win
->m_hAdjust
->upper
) < 0.2) command
= wxEVT_SCROLL_TOP
;
1253 else if (fabs(diff
-line_step
) < 0.2) command
= wxEVT_SCROLL_LINEDOWN
;
1254 else if (fabs(diff
+line_step
) < 0.2) command
= wxEVT_SCROLL_LINEUP
;
1255 else if (fabs(diff
-page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEDOWN
;
1256 else if (fabs(diff
+page_step
) < 0.2) command
= wxEVT_SCROLL_PAGEUP
;
1257 else command
= wxEVT_SCROLL_THUMBTRACK
;
1260 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1262 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
1263 event
.SetEventObject( win
);
1264 win
->GetEventHandler()->ProcessEvent( event
);
1267 //-----------------------------------------------------------------------------
1268 // "changed" from m_vAdjust
1269 //-----------------------------------------------------------------------------
1271 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1274 wxapp_install_idle_handler();
1276 if (g_blockEventsOnDrag
) return;
1277 if (!win
->m_hasVMT
) return;
1279 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
1280 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1282 wxScrollEvent
event( command
, win
->GetId(), value
, wxVERTICAL
);
1283 event
.SetEventObject( win
);
1284 win
->GetEventHandler()->ProcessEvent( event
);
1287 //-----------------------------------------------------------------------------
1288 // "changed" from m_hAdjust
1289 //-----------------------------------------------------------------------------
1291 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1294 wxapp_install_idle_handler();
1296 if (g_blockEventsOnDrag
) return;
1297 if (!win
->m_hasVMT
) return;
1299 wxEventType command
= wxEVT_SCROLL_THUMBTRACK
;
1300 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1302 wxScrollEvent
event( command
, win
->GetId(), value
, wxHORIZONTAL
);
1303 event
.SetEventObject( win
);
1304 win
->GetEventHandler()->ProcessEvent( event
);
1307 //-----------------------------------------------------------------------------
1308 // "button_press_event" from scrollbar
1309 //-----------------------------------------------------------------------------
1311 static gint
gtk_scrollbar_button_press_callback( GtkRange
*WXUNUSED(widget
),
1312 GdkEventButton
*WXUNUSED(gdk_event
),
1316 wxapp_install_idle_handler();
1318 // don't test here as we can release the mouse while being over
1319 // a different window then the slider
1321 // if (gdk_event->window != widget->slider) return FALSE;
1323 win
->SetScrolling( TRUE
);
1328 //-----------------------------------------------------------------------------
1329 // "button_release_event" from scrollbar
1330 //-----------------------------------------------------------------------------
1332 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1333 GdkEventButton
*WXUNUSED(gdk_event
),
1337 // don't test here as we can release the mouse while being over
1338 // a different window then the slider
1340 // if (gdk_event->window != widget->slider) return FALSE;
1342 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1344 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1345 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_hAdjust
), "value_changed" );
1347 gtk_signal_emit_by_name( GTK_OBJECT(win
->m_vAdjust
), "value_changed" );
1349 win
->SetScrolling( FALSE
);
1354 // ----------------------------------------------------------------------------
1355 // this wxWindowBase function is implemented here (in platform-specific file)
1356 // because it is static and so couldn't be made virtual
1357 // ----------------------------------------------------------------------------
1359 wxWindow
*wxWindowBase::FindFocus()
1361 return g_focusWindow
;
1364 //-----------------------------------------------------------------------------
1365 // "realize" from m_widget
1366 //-----------------------------------------------------------------------------
1368 /* we cannot set colours, fonts and cursors before the widget has
1369 been realized, so we do this directly after realization */
1372 gtk_window_realized_callback( GtkWidget
*widget
, wxWindow
*win
)
1375 wxapp_install_idle_handler();
1377 if (win
->m_delayedFont
)
1378 win
->SetFont( win
->GetFont() );
1380 if (win
->m_delayedBackgroundColour
)
1381 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1383 if (win
->m_delayedForegroundColour
)
1384 win
->SetForegroundColour( win
->GetForegroundColour() );
1386 win
->SetCursor( win
->GetCursor() );
1391 //-----------------------------------------------------------------------------
1392 // InsertChild for wxWindow.
1393 //-----------------------------------------------------------------------------
1395 /* Callback for wxWindow. This very strange beast has to be used because
1396 * C++ has no virtual methods in a constructor. We have to emulate a
1397 * virtual function here as wxNotebook requires a different way to insert
1398 * a child in it. I had opted for creating a wxNotebookPage window class
1399 * which would have made this superfluous (such in the MDI window system),
1400 * but no-one was listening to me... */
1402 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1404 gtk_myfixed_put( GTK_MYFIXED(parent
->m_wxwindow
),
1405 GTK_WIDGET(child
->m_widget
),
1411 if (parent
->HasFlag(wxTAB_TRAVERSAL
))
1413 /* we now allow a window to get the focus as long as it
1414 doesn't have any children. */
1415 GTK_WIDGET_UNSET_FLAGS( parent
->m_wxwindow
, GTK_CAN_FOCUS
);
1419 //-----------------------------------------------------------------------------
1421 //-----------------------------------------------------------------------------
1423 wxWindow
* wxGetActiveWindow()
1425 return g_focusWindow
;
1428 //-----------------------------------------------------------------------------
1430 //-----------------------------------------------------------------------------
1432 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
1434 BEGIN_EVENT_TABLE(wxWindow
, wxWindowBase
)
1435 EVT_KEY_DOWN(wxWindow::OnKeyDown
)
1438 void wxWindow::Init()
1444 m_widget
= (GtkWidget
*) NULL
;
1445 m_wxwindow
= (GtkWidget
*) NULL
;
1455 m_needParent
= TRUE
;
1457 m_hasScrolling
= FALSE
;
1458 m_isScrolling
= FALSE
;
1460 m_hAdjust
= (GtkAdjustment
*) NULL
;
1461 m_vAdjust
= (GtkAdjustment
*) NULL
;
1462 m_oldHorizontalPos
= 0.0;
1463 m_oldVerticalPos
= 0.0;
1466 m_scrollGC
= (GdkGC
*) NULL
;
1467 m_widgetStyle
= (GtkStyle
*) NULL
;
1469 m_insertCallback
= wxInsertChildInWindow
;
1471 m_isStaticBox
= FALSE
;
1472 m_acceptsFocus
= FALSE
;
1475 wxWindow::wxWindow()
1480 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1481 const wxPoint
&pos
, const wxSize
&size
,
1482 long style
, const wxString
&name
)
1486 Create( parent
, id
, pos
, size
, style
, name
);
1489 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1490 const wxPoint
&pos
, const wxSize
&size
,
1491 long style
, const wxString
&name
)
1493 PreCreation( parent
, id
, pos
, size
, style
, name
);
1495 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
1496 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1499 debug_focus_in( m_widget
, _T("wxWindow::m_widget"), name
);
1502 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
1505 debug_focus_in( scrolledWindow
->hscrollbar
, _T("wxWindow::hsrcollbar"), name
);
1506 debug_focus_in( scrolledWindow
->vscrollbar
, _T("wxWindow::vsrcollbar"), name
);
1509 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1510 scroll_class
->scrollbar_spacing
= 0;
1512 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1514 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
1515 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
1517 m_wxwindow
= gtk_myfixed_new();
1520 debug_focus_in( m_wxwindow
, _T("wxWindow::m_wxwindow"), name
);
1523 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
1525 #if (GTK_MINOR_VERSION > 0)
1526 GtkMyFixed
*myfixed
= GTK_MYFIXED(m_wxwindow
);
1528 if (HasFlag(wxRAISED_BORDER
))
1530 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_OUT
);
1532 else if (HasFlag(wxSUNKEN_BORDER
))
1534 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_IN
);
1538 gtk_myfixed_set_shadow_type( myfixed
, GTK_SHADOW_NONE
);
1540 #else // GTK_MINOR_VERSION == 0
1541 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
1543 if (HasFlag(wxRAISED_BORDER
))
1545 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
1547 else if (HasFlag(wxSUNKEN_BORDER
))
1549 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
1553 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
1555 #endif // GTK_MINOR_VERSION
1557 if (HasFlag(wxTAB_TRAVERSAL
))
1559 /* we now allow a window to get the focus as long as it
1560 doesn't have any children. */
1561 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1562 m_acceptsFocus
= FALSE
;
1566 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1567 m_acceptsFocus
= TRUE
;
1570 #if (GTK_MINOR_VERSION == 0)
1571 // shut the viewport up
1572 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1573 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1574 #endif // GTK_MINOR_VERSION == 0
1576 // I _really_ don't want scrollbars in the beginning
1577 m_vAdjust
->lower
= 0.0;
1578 m_vAdjust
->upper
= 1.0;
1579 m_vAdjust
->value
= 0.0;
1580 m_vAdjust
->step_increment
= 1.0;
1581 m_vAdjust
->page_increment
= 1.0;
1582 m_vAdjust
->page_size
= 5.0;
1583 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
1584 m_hAdjust
->lower
= 0.0;
1585 m_hAdjust
->upper
= 1.0;
1586 m_hAdjust
->value
= 0.0;
1587 m_hAdjust
->step_increment
= 1.0;
1588 m_hAdjust
->page_increment
= 1.0;
1589 m_hAdjust
->page_size
= 5.0;
1590 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1592 // these handlers block mouse events to any window during scrolling such as
1593 // motion events and prevent GTK and wxWindows from fighting over where the
1596 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
1597 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1599 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
1600 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1602 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
1603 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1605 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
1606 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1608 // these handlers get notified when screen updates are required either when
1609 // scrolling or when the window size (and therefore scrollbar configuration)
1612 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
1613 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
1614 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
1615 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
1617 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
1618 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
1619 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
1620 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
1622 gtk_widget_show( m_wxwindow
);
1625 m_parent
->DoAddChild( this );
1634 wxWindow::~wxWindow()
1644 m_parent
->RemoveChild( this );
1648 gtk_style_unref( m_widgetStyle
);
1649 m_widgetStyle
= (GtkStyle
*) NULL
;
1654 gdk_gc_unref( m_scrollGC
);
1655 m_scrollGC
= (GdkGC
*) NULL
;
1660 gtk_widget_destroy( m_wxwindow
);
1661 m_wxwindow
= (GtkWidget
*) NULL
;
1666 gtk_widget_destroy( m_widget
);
1667 m_widget
= (GtkWidget
*) NULL
;
1671 void wxWindow::PreCreation( wxWindow
*parent
,
1676 const wxString
&name
)
1678 wxASSERT_MSG( !m_needParent
|| parent
, _T("Need complete parent.") );
1680 if ( !CreateBase(parent
, id
, pos
, size
, style
, name
) )
1682 wxFAIL_MSG(_T("window creation failed"));
1685 m_width
= WidthDefault(size
.x
);
1686 m_height
= HeightDefault(size
.y
);
1691 if (!parent
) /* some reasonable defaults */
1695 m_x
= (gdk_screen_width () - m_width
) / 2;
1696 if (m_x
< 10) m_x
= 10;
1700 m_y
= (gdk_screen_height () - m_height
) / 2;
1701 if (m_y
< 10) m_y
= 10;
1706 void wxWindow::PostCreation()
1708 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1712 /* these get reported to wxWindows -> wxPaintEvent */
1713 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1714 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1716 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1717 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1719 #if (GTK_MINOR_VERSION > 0)
1720 /* these are called when the "sunken" or "raised" borders are drawn */
1721 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
1722 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
1724 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
1725 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
1729 GtkWidget
*connect_widget
= GetConnectWidget();
1731 ConnectWidget( connect_widget
);
1733 /* we cannot set colours, fonts and cursors before the widget has
1734 been realized, so we do this directly after realization */
1735 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
1736 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
1741 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1743 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1744 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1746 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
1747 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
1749 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1750 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1752 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1753 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1755 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
1756 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
1758 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
1759 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
1761 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
1762 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
1764 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
1765 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
1767 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
1768 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
1771 bool wxWindow::Destroy()
1773 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1777 return wxWindowBase::Destroy();
1780 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
1782 wxASSERT_MSG( (m_widget
!= NULL
), _T("invalid window") );
1783 wxASSERT_MSG( (m_parent
!= NULL
), _T("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 if ((sizeFlags
& wxSIZE_USE_EXISTING
) == wxSIZE_USE_EXISTING
)
1800 if (x
!= -1) m_x
= x
;
1801 if (y
!= -1) m_y
= y
;
1802 if (width
!= -1) m_width
= width
;
1803 if (height
!= -1) m_height
= height
;
1813 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
1815 if (width
== -1) m_width
= 80;
1818 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
1820 if (height
== -1) m_height
= 26;
1823 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
1824 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
1825 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
1826 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
1830 if (GTK_WIDGET_HAS_DEFAULT(m_widget
))
1832 /* the default button has a border around it */
1836 /* this is the result of hours of debugging: the following code
1837 means that if we have a m_wxwindow and we set the size of
1838 m_widget, m_widget (which is a GtkScrolledWindow) does NOT
1839 automatically propagate its size down to its m_wxwindow,
1840 which is its client area. therefore, we have to tell the
1841 client area directly that it has to resize itself.
1842 this will lead to that m_widget (GtkScrolledWindow) will
1843 calculate how much size it needs for scrollbars etc and
1844 it will then call XXX_size_allocate of its child, which
1845 is m_wxwindow. m_wxwindow in turn will do the same with its
1846 children and so on. problems can arise if this happens
1847 before all the children have been realized as some widgets
1848 stupidy need to be realized during XXX_size_allocate (e.g.
1849 GtkNotebook) and they will segv if called otherwise. this
1850 emergency is tested in gtk_myfixed_size_allocate. Normally
1851 this shouldn't be needed and only gtk_widget_queue_resize()
1852 should be enough to provoke a resize at the next appropriate
1853 moment, but this seems to fail, e.g. when a wxNotebook contains
1854 a wxSplitterWindow: the splitter window's children won't
1855 show up properly resized then. */
1857 gtk_myfixed_set_size( GTK_MYFIXED(m_parent
->m_wxwindow
),
1862 m_height
+2*border
);
1867 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
1868 event
.SetEventObject( this );
1869 GetEventHandler()->ProcessEvent( event
);
1874 void wxWindow::OnInternalIdle()
1879 void wxWindow::DoGetSize( int *width
, int *height
) const
1881 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
1883 if (width
) (*width
) = m_width
;
1884 if (height
) (*height
) = m_height
;
1887 void wxWindow::DoSetClientSize( int width
, int height
)
1889 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
1893 SetSize( width
, height
);
1900 if (!m_hasScrolling
)
1902 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
1904 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
1906 dw
+= 2 * window_class
->xthickness
;
1907 dh
+= 2 * window_class
->ythickness
;
1912 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1913 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1915 #if (GTK_MINOR_VERSION == 0)
1916 GtkWidget
*viewport
= scroll_window
->viewport
;
1917 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1919 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
1921 dw
+= 2 * viewport_class
->xthickness
;
1922 dh
+= 2 * viewport_class
->ythickness
;
1927 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1928 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1930 we use this instead: range.slider_width = 11 + 2*2pts edge
1933 if (scroll_window
->vscrollbar_visible
)
1935 dw
+= 15; /* dw += vscrollbar->allocation.width; */
1936 dw
+= scroll_class
->scrollbar_spacing
;
1939 if (scroll_window
->hscrollbar_visible
)
1941 dh
+= 15; /* dh += hscrollbar->allocation.height; */
1942 dw
+= scroll_class
->scrollbar_spacing
;
1946 SetSize( width
+dw
, height
+dh
);
1950 void wxWindow::DoGetClientSize( int *width
, int *height
) const
1952 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
1956 if (width
) (*width
) = m_width
;
1957 if (height
) (*height
) = m_height
;
1964 if (!m_hasScrolling
)
1966 GtkStyleClass
*window_class
= m_wxwindow
->style
->klass
;
1968 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
1970 dw
+= 2 * window_class
->xthickness
;
1971 dh
+= 2 * window_class
->ythickness
;
1976 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
1977 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1979 #if (GTK_MINOR_VERSION == 0)
1980 GtkWidget
*viewport
= scroll_window
->viewport
;
1981 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
1983 if ( HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
) )
1985 dw
+= 2 * viewport_class
->xthickness
;
1986 dh
+= 2 * viewport_class
->ythickness
;
1990 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1991 GtkWidget *vscrollbar = scroll_window->vscrollbar;
1993 we use this instead: range.slider_width = 11 + 2*2pts edge
1996 if (scroll_window
->vscrollbar_visible
)
1998 dw
+= 15; /* dw += vscrollbar->allocation.width; */
1999 dw
+= scroll_class
->scrollbar_spacing
;
2002 if (scroll_window
->hscrollbar_visible
)
2004 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2005 dh
+= scroll_class
->scrollbar_spacing
;
2009 if (width
) (*width
) = m_width
- dw
;
2010 if (height
) (*height
) = m_height
- dh
;
2014 void wxWindow::DoGetPosition( int *x
, int *y
) const
2016 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2022 void wxWindow::ClientToScreen( int *x
, int *y
) const
2024 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2026 if (!m_widget
->window
) return;
2028 GdkWindow
*source
= (GdkWindow
*) NULL
;
2030 source
= m_wxwindow
->window
;
2032 source
= m_widget
->window
;
2036 gdk_window_get_origin( source
, &org_x
, &org_y
);
2040 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2042 org_x
+= m_widget
->allocation
.x
;
2043 org_y
+= m_widget
->allocation
.y
;
2051 void wxWindow::ScreenToClient( int *x
, int *y
) const
2053 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2055 if (!m_widget
->window
) return;
2057 GdkWindow
*source
= (GdkWindow
*) NULL
;
2059 source
= m_wxwindow
->window
;
2061 source
= m_widget
->window
;
2065 gdk_window_get_origin( source
, &org_x
, &org_y
);
2069 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2071 org_x
+= m_widget
->allocation
.x
;
2072 org_y
+= m_widget
->allocation
.y
;
2080 bool wxWindow::Show( bool show
)
2082 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2084 if (!wxWindowBase::Show(show
))
2091 gtk_widget_show( m_widget
);
2093 gtk_widget_hide( m_widget
);
2098 bool wxWindow::Enable( bool enable
)
2100 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2102 if (!wxWindowBase::Enable(enable
))
2108 gtk_widget_set_sensitive( m_widget
, enable
);
2110 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2115 int wxWindow::GetCharHeight() const
2117 wxCHECK_MSG( (m_widget
!= NULL
), 12, _T("invalid window") );
2119 wxCHECK_MSG( m_font
.Ok(), 12, _T("invalid font") );
2121 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2123 return font
->ascent
+ font
->descent
;
2126 int wxWindow::GetCharWidth() const
2128 wxCHECK_MSG( (m_widget
!= NULL
), 8, _T("invalid window") );
2130 wxCHECK_MSG( m_font
.Ok(), 8, _T("invalid font") );
2132 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2134 return gdk_string_width( font
, "H" );
2137 void wxWindow::GetTextExtent( const wxString
& string
,
2141 int *externalLeading
,
2142 const wxFont
*theFont
) const
2144 wxFont fontToUse
= m_font
;
2145 if (theFont
) fontToUse
= *theFont
;
2147 wxCHECK_RET( fontToUse
.Ok(), _T("invalid font") );
2149 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2150 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2151 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2152 if (descent
) (*descent
) = font
->descent
;
2153 if (externalLeading
) (*externalLeading
) = 0; // ??
2156 void wxWindow::OnKeyDown( wxKeyEvent
&event
)
2158 event
.SetEventType( wxEVT_CHAR
);
2160 if (!GetEventHandler()->ProcessEvent( event
))
2166 void wxWindow::SetFocus()
2168 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2170 GtkWidget
*connect_widget
= GetConnectWidget();
2173 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
2175 gtk_widget_grab_focus (connect_widget
);
2177 else if (GTK_IS_CONTAINER(connect_widget
))
2179 gtk_container_focus( GTK_CONTAINER(connect_widget
), GTK_DIR_TAB_FORWARD
);
2187 bool wxWindow::AcceptsFocus() const
2189 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2192 bool wxWindow::Reparent( wxWindow
*newParent
)
2194 wxCHECK_MSG( (m_widget
!= NULL
), (wxWindow
*) NULL
, _T("invalid window") );
2196 gtk_widget_unparent( m_widget
);
2198 if ( !wxWindowBase::Reparent(newParent
) )
2204 void wxWindow::Raise()
2206 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2208 if (!m_widget
->window
) return;
2210 gdk_window_raise( m_widget
->window
);
2213 void wxWindow::Lower()
2215 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2217 if (!m_widget
->window
) return;
2219 gdk_window_lower( m_widget
->window
);
2222 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2224 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, _T("invalid window") );
2226 if (!wxWindowBase::SetCursor(cursor
))
2228 // don't leave if the GTK widget has just
2230 if (!m_delayedCursor
) return FALSE
;
2233 GtkWidget
*connect_widget
= GetConnectWidget();
2234 if (!connect_widget
->window
)
2236 // indicate that a new style has been set
2237 // but it couldn't get applied as the
2238 // widget hasn't been realized yet.
2239 m_delayedCursor
= TRUE
;
2241 // pretend we have done something
2245 if ((m_widget
) && (m_widget
->window
))
2246 gdk_window_set_cursor( m_widget
->window
, GetCursor().GetCursor() );
2248 if ((m_wxwindow
) && (m_wxwindow
->window
))
2249 gdk_window_set_cursor( m_wxwindow
->window
, GetCursor().GetCursor() );
2255 void wxWindow::WarpPointer( int WXUNUSED(x
), int WXUNUSED(y
) )
2260 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2262 wxCHECK_RET( (m_widget
!= NULL
), _T("invalid window") );
2264 if (!m_widget
->window
) return;
2266 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2270 gdk_window_clear_area( m_wxwindow
->window
,
2272 rect
->width
, rect
->height
);
2276 gdk_window_clear( m_wxwindow
->window
);
2283 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2285 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2289 GdkRectangle gdk_rect
;
2290 gdk_rect
.x
= rect
->x
;
2291 gdk_rect
.y
= rect
->y
;
2292 gdk_rect
.width
= rect
->width
;
2293 gdk_rect
.height
= rect
->height
;
2296 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2298 gtk_widget_draw( m_widget
, &gdk_rect
);
2302 void wxWindow::Clear()
2304 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2306 if (!m_widget
->window
) return;
2308 if (m_wxwindow
&& m_wxwindow
->window
)
2310 gdk_window_clear( m_wxwindow
->window
);
2315 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2317 wxWindowBase::DoSetToolTip(tip
);
2320 m_tooltip
->Apply( this );
2323 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2325 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConv_current
->cWX2MB(tip
), (gchar
*) NULL
);
2327 #endif // wxUSE_TOOLTIPS
2329 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2331 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2333 if (!wxWindowBase::SetBackgroundColour(colour
))
2335 // don't leave if the GTK widget has just
2337 if (!m_delayedBackgroundColour
) return FALSE
;
2340 GtkWidget
*connect_widget
= GetConnectWidget();
2341 if (!connect_widget
->window
)
2343 // indicate that a new style has been set
2344 // but it couldn't get applied as the
2345 // widget hasn't been realized yet.
2346 m_delayedBackgroundColour
= TRUE
;
2348 // pretend we have done something
2352 if (m_wxwindow
&& m_wxwindow
->window
)
2354 /* wxMSW doesn't clear the window here. I don't do that either to
2355 provide compatibility. call Clear() to do the job. */
2357 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_wxwindow
->window
) );
2358 gdk_window_set_background( m_wxwindow
->window
, m_backgroundColour
.GetColor() );
2361 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2363 if (sysbg
== m_backgroundColour
)
2365 m_backgroundColour
= wxNullColour
;
2367 m_backgroundColour
= sysbg
;
2377 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
2379 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2381 if (!wxWindowBase::SetForegroundColour(colour
))
2383 // don't leave if the GTK widget has just
2385 if (!m_delayedForegroundColour
) return FALSE
;
2388 GtkWidget
*connect_widget
= GetConnectWidget();
2389 if (!connect_widget
->window
)
2391 // indicate that a new style has been set
2392 // but it couldn't get applied as the
2393 // widget hasn't been realized yet.
2394 m_delayedForegroundColour
= TRUE
;
2396 // pretend we have done something
2400 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2401 if (sysbg
== m_foregroundColour
)
2403 m_backgroundColour
= wxNullColour
;
2405 m_backgroundColour
= sysbg
;
2415 GtkStyle
*wxWindow::GetWidgetStyle()
2417 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
2419 m_widgetStyle
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
2421 return m_widgetStyle
;
2424 void wxWindow::SetWidgetStyle()
2426 GtkStyle
*style
= GetWidgetStyle();
2428 gdk_font_unref( style
->font
);
2429 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2431 if (m_foregroundColour
.Ok())
2433 m_foregroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2434 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
2435 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
2436 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
2439 if (m_backgroundColour
.Ok())
2441 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2442 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2443 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2444 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2445 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2446 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2447 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2448 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2449 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2453 void wxWindow::ApplyWidgetStyle()
2457 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2459 menu
->SetInvokingWindow( win
);
2460 wxNode
*node
= menu
->GetItems().First();
2463 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
2464 if (menuitem
->IsSubMenu())
2466 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2468 node
= node
->Next();
2472 static gint gs_pop_x
= 0;
2473 static gint gs_pop_y
= 0;
2475 static void pop_pos_callback( GtkMenu
*menu
, gint
*x
, gint
*y
, wxWindow
*win
)
2477 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
2482 bool wxWindow::PopupMenu( wxMenu
*menu
, int x
, int y
)
2484 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T("invalid window") );
2486 wxCHECK_MSG( menu
!= NULL
, FALSE
, _T("invalid popup-menu") );
2488 SetInvokingWindow( menu
, this );
2496 GTK_MENU(menu
->m_menu
),
2497 (GtkWidget
*) NULL
, // parent menu shell
2498 (GtkWidget
*) NULL
, // parent menu item
2499 (GtkMenuPositionFunc
) pop_pos_callback
,
2500 (gpointer
) this, // client data
2501 0, // button used to activate it
2502 0 //gs_timeLastClick // the time of activation
2507 #if wxUSE_DRAG_AND_DROP
2509 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2511 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2513 GtkWidget
*dnd_widget
= GetConnectWidget();
2515 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
2517 if (m_dropTarget
) delete m_dropTarget
;
2518 m_dropTarget
= dropTarget
;
2520 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
2523 #endif // wxUSE_DRAG_AND_DROP
2525 GtkWidget
* wxWindow::GetConnectWidget()
2527 GtkWidget
*connect_widget
= m_widget
;
2528 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2530 return connect_widget
;
2533 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2535 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
2536 return (window
== m_widget
->window
);
2539 bool wxWindow::SetFont( const wxFont
&font
)
2541 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, _T( "invalid window") );
2543 if (!wxWindowBase::SetFont(font
))
2545 // don't leave if the GTK widget has just
2547 if (!m_delayedFont
) return FALSE
;
2550 GtkWidget
*connect_widget
= GetConnectWidget();
2551 if (!connect_widget
->window
)
2553 // indicate that a new style has been set
2554 // but it couldn't get applied as the
2555 // widget hasn't been realized yet.
2556 m_delayedFont
= TRUE
;
2558 // pretend we have done something
2562 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2563 if ( sysbg
== m_backgroundColour
)
2565 m_backgroundColour
= wxNullColour
;
2567 m_backgroundColour
= sysbg
;
2577 void wxWindow::CaptureMouse()
2579 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2581 wxCHECK_RET( g_capturing
== FALSE
, _T("CaptureMouse called twice") );
2583 GtkWidget
*connect_widget
= GetConnectWidget();
2584 if (!connect_widget
->window
) return;
2586 gtk_grab_add( connect_widget
);
2587 gdk_pointer_grab( connect_widget
->window
, FALSE
,
2589 (GDK_BUTTON_PRESS_MASK
|
2590 GDK_BUTTON_RELEASE_MASK
|
2591 GDK_POINTER_MOTION_MASK
),
2598 void wxWindow::ReleaseMouse()
2600 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2602 wxCHECK_RET( g_capturing
== TRUE
, _T("ReleaseMouse called twice") );
2604 GtkWidget
*connect_widget
= GetConnectWidget();
2605 if (!connect_widget
->window
) return;
2607 gtk_grab_remove( connect_widget
);
2608 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2609 g_capturing
= FALSE
;
2612 bool wxWindow::IsRetained() const
2617 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
2618 int range
, bool refresh
)
2620 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2622 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2624 m_hasScrolling
= TRUE
;
2626 if (orient
== wxHORIZONTAL
)
2628 float fpos
= (float)pos
;
2629 float frange
= (float)range
;
2630 float fthumb
= (float)thumbVisible
;
2631 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2632 if (fpos
< 0.0) fpos
= 0.0;
2634 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
2635 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
2637 SetScrollPos( orient
, pos
, refresh
);
2641 m_oldHorizontalPos
= fpos
;
2643 m_hAdjust
->lower
= 0.0;
2644 m_hAdjust
->upper
= frange
;
2645 m_hAdjust
->value
= fpos
;
2646 m_hAdjust
->step_increment
= 1.0;
2647 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2648 m_hAdjust
->page_size
= fthumb
;
2652 float fpos
= (float)pos
;
2653 float frange
= (float)range
;
2654 float fthumb
= (float)thumbVisible
;
2655 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
2656 if (fpos
< 0.0) fpos
= 0.0;
2658 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
2659 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
2661 SetScrollPos( orient
, pos
, refresh
);
2665 m_oldVerticalPos
= fpos
;
2667 m_vAdjust
->lower
= 0.0;
2668 m_vAdjust
->upper
= frange
;
2669 m_vAdjust
->value
= fpos
;
2670 m_vAdjust
->step_increment
= 1.0;
2671 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
2672 m_vAdjust
->page_size
= fthumb
;
2675 if (m_wxwindow
->window
)
2677 if (orient
== wxHORIZONTAL
)
2678 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2680 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2682 gtk_widget_set_usize( m_widget
, m_width
, m_height
);
2686 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
2688 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2690 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2692 if (orient
== wxHORIZONTAL
)
2694 float fpos
= (float)pos
;
2695 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
2696 if (fpos
< 0.0) fpos
= 0.0;
2697 m_oldHorizontalPos
= fpos
;
2699 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
2700 m_hAdjust
->value
= fpos
;
2704 float fpos
= (float)pos
;
2705 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
2706 if (fpos
< 0.0) fpos
= 0.0;
2707 m_oldVerticalPos
= fpos
;
2709 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
2710 m_vAdjust
->value
= fpos
;
2715 if (m_wxwindow
->window
)
2717 if (orient
== wxHORIZONTAL
)
2718 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
2720 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
2725 int wxWindow::GetScrollThumb( int orient
) const
2727 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2729 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2731 if (orient
== wxHORIZONTAL
)
2732 return (int)(m_hAdjust
->page_size
+0.5);
2734 return (int)(m_vAdjust
->page_size
+0.5);
2737 int wxWindow::GetScrollPos( int orient
) const
2739 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2741 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2743 if (orient
== wxHORIZONTAL
)
2744 return (int)(m_hAdjust
->value
+0.5);
2746 return (int)(m_vAdjust
->value
+0.5);
2749 int wxWindow::GetScrollRange( int orient
) const
2751 wxCHECK_MSG( m_widget
!= NULL
, 0, _T("invalid window") );
2753 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, _T("window needs client area for scrolling") );
2755 if (orient
== wxHORIZONTAL
)
2756 return (int)(m_hAdjust
->upper
+0.5);
2758 return (int)(m_vAdjust
->upper
+0.5);
2761 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
2763 wxCHECK_RET( m_widget
!= NULL
, _T("invalid window") );
2765 wxCHECK_RET( m_wxwindow
!= NULL
, _T("window needs client area for scrolling") );
2769 m_scrollGC
= gdk_gc_new( m_wxwindow
->window
);
2770 gdk_gc_set_exposures( m_scrollGC
, TRUE
);
2775 GetClientSize( &cw
, &ch
);
2776 int w
= cw
- abs(dx
);
2777 int h
= ch
- abs(dy
);
2779 if ((h
< 0) || (w
< 0))
2787 if (dx
< 0) s_x
= -dx
;
2788 if (dy
< 0) s_y
= -dy
;
2791 if (dx
> 0) d_x
= dx
;
2792 if (dy
> 0) d_y
= dy
;
2794 gdk_window_copy_area( m_wxwindow
->window
, m_scrollGC
, d_x
, d_y
,
2795 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
2798 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
2799 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
2800 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
2801 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
2803 Refresh( TRUE
, &rect
);
2806 wxNode
*node
= m_children
.First();
2809 wxWindow
*child
= (wxWindow
*) node
->Data();
2810 child
->Move( child
->m_x
+ dx
, child
->m_y
+ dy
);
2811 node
= node
->Next();
2815 void wxWindow::SetScrolling(bool scroll
)
2817 m_isScrolling
= g_blockEventsOnScroll
= scroll
;