1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/window.cpp
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #define XWarpPointer XWARPPOINTER
20 #include "wx/window.h"
21 #include "wx/dcclient.h"
24 #include "wx/layout.h"
26 #include "wx/dialog.h"
27 #include "wx/msgdlg.h"
28 #include "wx/module.h"
30 #if wxUSE_DRAG_AND_DROP
35 #include "wx/tooltip.h"
43 #include "wx/textctrl.h"
47 #include "wx/statusbr.h"
49 #include "wx/settings.h"
53 #include "wx/thread.h"
58 #include "wx/gtk/private.h"
59 #include <gdk/gdkprivate.h>
60 #include <gdk/gdkkeysyms.h>
64 #include <gtk/gtkprivate.h>
66 #include "wx/gtk/win_gtk.h"
69 #define SET_CONTAINER_FOCUS(w, d) gtk_widget_child_focus((w), (d))
71 #define SET_CONTAINER_FOCUS(w, d) gtk_container_focus(GTK_CONTAINER(w), (d))
81 extern GtkContainerClass
*pizza_parent_class
;
84 //-----------------------------------------------------------------------------
85 // documentation on internals
86 //-----------------------------------------------------------------------------
89 I have been asked several times about writing some documentation about
90 the GTK port of wxWindows, especially its internal structures. Obviously,
91 you cannot understand wxGTK without knowing a little about the GTK, but
92 some more information about what the wxWindow, which is the base class
93 for all other window classes, does seems required as well.
97 What does wxWindow do? It contains the common interface for the following
98 jobs of its descendants:
100 1) Define the rudimentary behaviour common to all window classes, such as
101 resizing, intercepting user input (so as to make it possible to use these
102 events for special purposes in a derived class), window names etc.
104 2) Provide the possibility to contain and manage children, if the derived
105 class is allowed to contain children, which holds true for those window
106 classes which do not display a native GTK widget. To name them, these
107 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
108 work classes are a special case and are handled a bit differently from
109 the rest. The same holds true for the wxNotebook class.
111 3) Provide the possibility to draw into a client area of a window. This,
112 too, only holds true for classes that do not display a native GTK widget
115 4) Provide the entire mechanism for scrolling widgets. This actual inter-
116 face for this is usually in wxScrolledWindow, but the GTK implementation
119 5) A multitude of helper or extra methods for special purposes, such as
120 Drag'n'Drop, managing validators etc.
122 6) Display a border (sunken, raised, simple or none).
124 Normally one might expect, that one wxWindows window would always correspond
125 to one GTK widget. Under GTK, there is no such allround widget that has all
126 the functionality. Moreover, the GTK defines a client area as a different
127 widget from the actual widget you are handling. Last but not least some
128 special classes (e.g. wxFrame) handle different categories of widgets and
129 still have the possibility to draw something in the client area.
130 It was therefore required to write a special purpose GTK widget, that would
131 represent a client area in the sense of wxWindows capable to do the jobs
132 2), 3) and 4). I have written this class and it resides in win_gtk.c of
135 All windows must have a widget, with which they interact with other under-
136 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
137 thw wxWindow class has a member variable called m_widget which holds a
138 pointer to this widget. When the window class represents a GTK native widget,
139 this is (in most cases) the only GTK widget the class manages. E.g. the
140 wxStatitText class handles only a GtkLabel widget a pointer to which you
141 can find in m_widget (defined in wxWindow)
143 When the class has a client area for drawing into and for containing children
144 it has to handle the client area widget (of the type GtkPizza, defined in
145 win_gtk.c), but there could be any number of widgets, handled by a class
146 The common rule for all windows is only, that the widget that interacts with
147 the rest of GTK must be referenced in m_widget and all other widgets must be
148 children of this widget on the GTK level. The top-most widget, which also
149 represents the client area, must be in the m_wxwindow field and must be of
152 As I said, the window classes that display a GTK native widget only have
153 one widget, so in the case of e.g. the wxButton class m_widget holds a
154 pointer to a GtkButton widget. But windows with client areas (for drawing
155 and children) have a m_widget field that is a pointer to a GtkScrolled-
156 Window and a m_wxwindow field that is pointer to a GtkPizza and this
157 one is (in the GTK sense) a child of the GtkScrolledWindow.
159 If the m_wxwindow field is set, then all input to this widget is inter-
160 cepted and sent to the wxWindows class. If not, all input to the widget
161 that gets pointed to by m_widget gets intercepted and sent to the class.
165 The design of scrolling in wxWindows is markedly different from that offered
166 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
167 clicking on a scrollbar belonging to scrolled window will inevitably move
168 the window. In wxWindows, the scrollbar will only emit an event, send this
169 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
170 which actually moves the window and its subchildren. Note that GtkPizza
171 memorizes how much it has been scrolled but that wxWindows forgets this
172 so that the two coordinates systems have to be kept in synch. This is done
173 in various places using the pizza->xoffset and pizza->yoffset values.
177 Singularily the most broken code in GTK is the code that is supposes to
178 inform subwindows (child windows) about new positions. Very often, duplicate
179 events are sent without changes in size or position, equally often no
180 events are sent at all (All this is due to a bug in the GtkContainer code
181 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
182 GTK's own system and it simply waits for size events for toplevel windows
183 and then iterates down the respective size events to all window. This has
184 the disadvantage, that windows might get size events before the GTK widget
185 actually has the reported size. This doesn't normally pose any problem, but
186 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
187 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
188 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
189 window that is used for OpenGl output really has that size (as reported by
194 If someone at some point of time feels the immense desire to have a look at,
195 change or attempt to optimse the Refresh() logic, this person will need an
196 intimate understanding of what a "draw" and what an "expose" events are and
197 what there are used for, in particular when used in connection with GTK's
198 own windowless widgets. Beware.
202 Cursors, too, have been a constant source of pleasure. The main difficulty
203 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
204 for the parent. To prevent this from doing too much harm, I use idle time
205 to set the cursor over and over again, starting from the toplevel windows
206 and ending with the youngest generation (speaking of parent and child windows).
207 Also don't forget that cursors (like much else) are connected to GdkWindows,
208 not GtkWidgets and that the "window" field of a GtkWidget might very well
209 point to the GdkWindow of the parent widget (-> "window less widget") and
210 that the two obviously have very different meanings.
214 //-----------------------------------------------------------------------------
216 //-----------------------------------------------------------------------------
218 extern wxList wxPendingDelete
;
219 extern bool g_blockEventsOnDrag
;
220 extern bool g_blockEventsOnScroll
;
221 extern wxCursor g_globalCursor
;
223 static GdkGC
*g_eraseGC
= NULL
;
225 // mouse capture state: the window which has it and if the mouse is currently
227 static wxWindowGTK
*g_captureWindow
= (wxWindowGTK
*) NULL
;
228 static bool g_captureWindowHasMouse
= FALSE
;
230 /* extern */ wxWindowGTK
*g_focusWindow
= (wxWindowGTK
*) NULL
;
232 // the last window which had the focus - this is normally never NULL (except
233 // if we never had focus at all) as even when g_focusWindow is NULL it still
234 // keeps its previous value
235 static wxWindowGTK
*g_focusWindowLast
= (wxWindowGTK
*) NULL
;
237 // the frame that is currently active (i.e. its child has focus). It is
238 // used to generate wxActivateEvents
239 static wxWindowGTK
*g_activeFrame
= (wxWindowGTK
*) NULL
;
240 static bool g_activeFrameLostFocus
= FALSE
;
242 // If a window get the focus set but has not been realized
243 // yet, defer setting the focus to idle time.
244 wxWindowGTK
*g_delayedFocus
= (wxWindowGTK
*) NULL
;
246 // if we detect that the app has got/lost the focus, we set this variable to
247 // either TRUE or FALSE and an activate event will be sent during the next
248 // OnIdle() call and it is reset to -1: this value means that we shouldn't
249 // send any activate events at all
250 static int g_sendActivateEvent
= -1;
252 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
253 the last click here */
254 static guint32 gs_timeLastClick
= 0;
256 extern bool g_mainThreadLocked
;
258 //-----------------------------------------------------------------------------
260 //-----------------------------------------------------------------------------
263 #define DISABLE_STYLE_IF_BROKEN_THEME 1
269 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
271 # define DEBUG_MAIN_THREAD
274 #define DEBUG_MAIN_THREAD
277 // the trace mask used for the focus debugging messages
278 #define TRACE_FOCUS _T("focus")
280 //-----------------------------------------------------------------------------
281 // missing gdk functions
282 //-----------------------------------------------------------------------------
285 gdk_window_warp_pointer (GdkWindow
*window
,
290 GdkWindowPrivate
*priv
;
294 window
= GDK_ROOT_PARENT();
297 if (!GDK_WINDOW_DESTROYED(window
))
299 XWarpPointer (GDK_WINDOW_XDISPLAY(window
),
300 None
, /* not source window -> move from anywhere */
301 GDK_WINDOW_XID(window
), /* dest window */
302 0, 0, 0, 0, /* not source window -> move from anywhere */
306 priv
= (GdkWindowPrivate
*) window
;
308 if (!priv
->destroyed
)
310 XWarpPointer (priv
->xdisplay
,
311 None
, /* not source window -> move from anywhere */
312 priv
->xwindow
, /* dest window */
313 0, 0, 0, 0, /* not source window -> move from anywhere */
319 //-----------------------------------------------------------------------------
321 //-----------------------------------------------------------------------------
323 extern void wxapp_install_idle_handler();
324 extern bool g_isIdle
;
326 //-----------------------------------------------------------------------------
327 // local code (see below)
328 //-----------------------------------------------------------------------------
330 // returns the child of win which currently has focus or NULL if not found
332 // Note: can't be static, needed by textctrl.cpp.
333 wxWindow
*wxFindFocusedChild(wxWindowGTK
*win
)
335 wxWindow
*winFocus
= wxWindowGTK::FindFocus();
337 return (wxWindow
*)NULL
;
339 if ( winFocus
== win
)
340 return (wxWindow
*)win
;
342 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
344 node
= node
->GetNext() )
346 wxWindow
*child
= wxFindFocusedChild(node
->GetData());
351 return (wxWindow
*)NULL
;
354 static void draw_frame( GtkWidget
*widget
, wxWindowGTK
*win
)
356 // wxUniversal widgets draw the borders and scrollbars themselves
357 #ifndef __WXUNIVERSAL__
364 if (win
->m_hasScrolling
)
366 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
368 GtkRequisition vscroll_req
;
369 vscroll_req
.width
= 2;
370 vscroll_req
.height
= 2;
371 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
372 (scroll_window
->vscrollbar
, &vscroll_req
);
374 GtkRequisition hscroll_req
;
375 hscroll_req
.width
= 2;
376 hscroll_req
.height
= 2;
377 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
378 (scroll_window
->hscrollbar
, &hscroll_req
);
380 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) );
382 if (scroll_window
->vscrollbar_visible
)
384 dw
+= vscroll_req
.width
;
385 dw
+= scroll_class
->scrollbar_spacing
;
388 if (scroll_window
->hscrollbar_visible
)
390 dh
+= hscroll_req
.height
;
391 dh
+= scroll_class
->scrollbar_spacing
;
397 if (GTK_WIDGET_NO_WINDOW (widget
))
399 dx
+= widget
->allocation
.x
;
400 dy
+= widget
->allocation
.y
;
403 if (win
->HasFlag(wxRAISED_BORDER
))
405 gtk_draw_shadow( widget
->style
,
410 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
414 if (win
->HasFlag(wxSUNKEN_BORDER
))
416 gtk_draw_shadow( widget
->style
,
421 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
425 if (win
->HasFlag(wxSIMPLE_BORDER
))
428 gc
= gdk_gc_new( widget
->window
);
429 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
430 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
432 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
436 #endif // __WXUNIVERSAL__
439 //-----------------------------------------------------------------------------
440 // "expose_event" of m_widget
441 //-----------------------------------------------------------------------------
443 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindowGTK
*win
)
445 if (gdk_event
->count
> 0) return FALSE
;
447 draw_frame( widget
, win
);
451 (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
);
457 //-----------------------------------------------------------------------------
458 // "draw" of m_widget
459 //-----------------------------------------------------------------------------
463 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindowGTK
*win
)
465 draw_frame( widget
, win
);
470 //-----------------------------------------------------------------------------
471 // "size_request" of m_widget
472 //-----------------------------------------------------------------------------
474 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
477 win
->GetSize( &w
, &h
);
481 requisition
->height
= h
;
482 requisition
->width
= w
;
485 //-----------------------------------------------------------------------------
486 // "expose_event" of m_wxwindow
487 //-----------------------------------------------------------------------------
489 static int gtk_window_expose_callback( GtkWidget
*widget
,
490 GdkEventExpose
*gdk_event
,
496 wxapp_install_idle_handler();
501 wxPrintf( wxT("OnExpose from ") );
502 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
503 wxPrintf( win
->GetClassInfo()->GetClassName() );
504 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event
->area
.x
,
505 (int)gdk_event
->area
.y
,
506 (int)gdk_event
->area
.width
,
507 (int)gdk_event
->area
.height
);
511 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
513 gdk_event
->area
.width
,
514 gdk_event
->area
.height
);
515 win
->m_clearRegion
.Union( gdk_event
->area
.x
,
517 gdk_event
->area
.width
,
518 gdk_event
->area
.height
);
520 // Actual redrawing takes place in idle time.
525 (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
);
532 //-----------------------------------------------------------------------------
533 // "event" of m_wxwindow
534 //-----------------------------------------------------------------------------
536 // GTK thinks it is clever and filters out a certain amount of "unneeded"
537 // expose events. We need them, of course, so we override the main event
538 // procedure in GtkWidget by giving our own handler for all system events.
539 // There, we look for expose events ourselves whereas all other events are
542 gint
gtk_window_event_event_callback( GtkWidget
*widget
,
543 GdkEventExpose
*event
,
546 if (event
->type
== GDK_EXPOSE
)
548 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
555 //-----------------------------------------------------------------------------
556 // "draw" of m_wxwindow
557 //-----------------------------------------------------------------------------
561 // This callback is a complete replacement of the gtk_pizza_draw() function,
562 // which is disabled.
564 static void gtk_window_draw_callback( GtkWidget
*widget
,
571 wxapp_install_idle_handler();
573 // The wxNO_FULL_REPAINT_ON_RESIZE flag only works if
574 // there are no child windows.
575 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
576 (win
->GetChildren().GetCount() == 0))
584 wxPrintf( wxT("OnDraw from ") );
585 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
586 wxPrintf( win
->GetClassInfo()->GetClassName() );
587 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect
->x
,
594 #ifndef __WXUNIVERSAL__
595 GtkPizza
*pizza
= GTK_PIZZA (widget
);
597 if (win
->GetThemeEnabled())
599 wxWindow
*parent
= win
->GetParent();
600 while (parent
&& !parent
->IsTopLevel())
601 parent
= parent
->GetParent();
605 gtk_paint_flat_box (parent
->m_widget
->style
,
616 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
617 (pizza
->clear_on_draw
))
619 gdk_window_clear_area( pizza
->bin_window
,
620 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
624 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
626 // Actual redrawing takes place in idle time.
630 #ifndef __WXUNIVERSAL__
631 // Redraw child widgets
632 GList
*children
= pizza
->children
;
635 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
636 children
= children
->next
;
638 GdkRectangle child_area
;
639 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
641 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
649 //-----------------------------------------------------------------------------
650 // "key_press_event" from any window
651 //-----------------------------------------------------------------------------
653 // set WXTRACE to this to see the key event codes on the console
654 #define TRACE_KEYS _T("keyevent")
656 // translates an X key symbol to WXK_XXX value
658 // if isChar is true it means that the value returned will be used for EVT_CHAR
659 // event and then we choose the logical WXK_XXX, i.e. '/' for GDK_KP_Divide,
660 // for example, while if it is false it means that the value is going to be
661 // used for KEY_DOWN/UP events and then we translate GDK_KP_Divide to
663 static long wxTranslateKeySymToWXKey(KeySym keysym
, bool isChar
)
669 // Shift, Control and Alt don't generate the CHAR events at all
672 key_code
= isChar
? 0 : WXK_SHIFT
;
676 key_code
= isChar
? 0 : WXK_CONTROL
;
684 key_code
= isChar
? 0 : WXK_ALT
;
687 // neither do the toggle modifies
688 case GDK_Scroll_Lock
:
689 key_code
= isChar
? 0 : WXK_SCROLL
;
693 key_code
= isChar
? 0 : WXK_CAPITAL
;
697 key_code
= isChar
? 0 : WXK_NUMLOCK
;
701 // various other special keys
714 case GDK_ISO_Left_Tab
:
721 key_code
= WXK_RETURN
;
725 key_code
= WXK_CLEAR
;
729 key_code
= WXK_PAUSE
;
733 key_code
= WXK_SELECT
;
737 key_code
= WXK_PRINT
;
741 key_code
= WXK_EXECUTE
;
745 key_code
= WXK_ESCAPE
;
748 // cursor and other extended keyboard keys
750 key_code
= WXK_DELETE
;
766 key_code
= WXK_RIGHT
;
773 case GDK_Prior
: // == GDK_Page_Up
774 key_code
= WXK_PRIOR
;
777 case GDK_Next
: // == GDK_Page_Down
790 key_code
= WXK_INSERT
;
805 key_code
= (isChar
? '0' : WXK_NUMPAD0
) + keysym
- GDK_KP_0
;
809 key_code
= isChar
? ' ' : WXK_NUMPAD_SPACE
;
813 key_code
= isChar
? WXK_TAB
: WXK_NUMPAD_TAB
;
817 key_code
= isChar
? WXK_RETURN
: WXK_NUMPAD_ENTER
;
821 key_code
= isChar
? WXK_F1
: WXK_NUMPAD_F1
;
825 key_code
= isChar
? WXK_F2
: WXK_NUMPAD_F2
;
829 key_code
= isChar
? WXK_F3
: WXK_NUMPAD_F3
;
833 key_code
= isChar
? WXK_F4
: WXK_NUMPAD_F4
;
837 key_code
= isChar
? WXK_HOME
: WXK_NUMPAD_HOME
;
841 key_code
= isChar
? WXK_LEFT
: WXK_NUMPAD_LEFT
;
845 key_code
= isChar
? WXK_UP
: WXK_NUMPAD_UP
;
849 key_code
= isChar
? WXK_RIGHT
: WXK_NUMPAD_RIGHT
;
853 key_code
= isChar
? WXK_DOWN
: WXK_NUMPAD_DOWN
;
856 case GDK_KP_Prior
: // == GDK_KP_Page_Up
857 key_code
= isChar
? WXK_PRIOR
: WXK_NUMPAD_PRIOR
;
860 case GDK_KP_Next
: // == GDK_KP_Page_Down
861 key_code
= isChar
? WXK_NEXT
: WXK_NUMPAD_NEXT
;
865 key_code
= isChar
? WXK_END
: WXK_NUMPAD_END
;
869 key_code
= isChar
? WXK_HOME
: WXK_NUMPAD_BEGIN
;
873 key_code
= isChar
? WXK_INSERT
: WXK_NUMPAD_INSERT
;
877 key_code
= isChar
? WXK_DELETE
: WXK_NUMPAD_DELETE
;
881 key_code
= isChar
? '=' : WXK_NUMPAD_EQUAL
;
884 case GDK_KP_Multiply
:
885 key_code
= isChar
? '*' : WXK_NUMPAD_MULTIPLY
;
889 key_code
= isChar
? '+' : WXK_NUMPAD_ADD
;
892 case GDK_KP_Separator
:
893 // FIXME: what is this?
894 key_code
= isChar
? '.' : WXK_NUMPAD_SEPARATOR
;
897 case GDK_KP_Subtract
:
898 key_code
= isChar
? '-' : WXK_NUMPAD_SUBTRACT
;
902 key_code
= isChar
? '.' : WXK_NUMPAD_DECIMAL
;
906 key_code
= isChar
? '/' : WXK_NUMPAD_DIVIDE
;
923 key_code
= WXK_F1
+ keysym
- GDK_F1
;
933 static inline bool wxIsAsciiKeysym(KeySym ks
)
939 wxTranslateGTKKeyEventToWx(wxKeyEvent
& event
,
941 GdkEventKey
*gdk_event
)
943 // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string
944 // but only event->keyval which is quite useless to us, so remember
945 // the last character from GDK_KEY_PRESS and reuse it as last resort
947 // NB: should be MT-safe as we're always called from the main thread only
952 } s_lastKeyPress
= { 0, 0 };
954 KeySym keysym
= gdk_event
->keyval
;
956 wxLogTrace(TRACE_KEYS
, _T("Key %s event: keysym = %d"),
957 event
.GetEventType() == wxEVT_KEY_UP
? _T("release")
961 long key_code
= wxTranslateKeySymToWXKey(keysym
, FALSE
/* !isChar */);
965 // do we have the translation or is it a plain ASCII character?
966 if ( (gdk_event
->length
== 1) || wxIsAsciiKeysym(keysym
) )
968 // we should use keysym if it is ASCII as X does some translations
969 // like "I pressed while Control is down" => "Ctrl-I" == "TAB"
970 // which we don't want here (but which we do use for OnChar())
971 if ( !wxIsAsciiKeysym(keysym
) )
973 keysym
= (KeySym
)gdk_event
->string
[0];
976 // we want to always get the same key code when the same key is
977 // pressed regardless of the state of the modifies, i.e. on a
978 // standard US keyboard pressing '5' or '%' ('5' key with
979 // Shift) should result in the same key code in OnKeyDown():
980 // '5' (although OnChar() will get either '5' or '%').
982 // to do it we first translate keysym to keycode (== scan code)
983 // and then back but always using the lower register
984 Display
*dpy
= (Display
*)wxGetDisplay();
985 KeyCode keycode
= XKeysymToKeycode(dpy
, keysym
);
987 wxLogTrace(TRACE_KEYS
, _T("\t-> keycode %d"), keycode
);
989 KeySym keysymNormalized
= XKeycodeToKeysym(dpy
, keycode
, 0);
991 // use the normalized, i.e. lower register, keysym if we've
993 key_code
= keysymNormalized
? keysymNormalized
: keysym
;
995 // as explained above, we want to have lower register key codes
996 // normally but for the letter keys we want to have the upper ones
998 // NB: don't use XConvertCase() here, we want to do it for letters
1000 key_code
= toupper(key_code
);
1002 else // non ASCII key, what to do?
1004 // by default, ignore it
1007 // but if we have cached information from the last KEY_PRESS
1008 if ( gdk_event
->type
== GDK_KEY_RELEASE
)
1011 if ( keysym
== s_lastKeyPress
.keysym
)
1013 key_code
= s_lastKeyPress
.keycode
;
1018 if ( gdk_event
->type
== GDK_KEY_PRESS
)
1020 // remember it to be reused for KEY_UP event later
1021 s_lastKeyPress
.keysym
= keysym
;
1022 s_lastKeyPress
.keycode
= key_code
;
1026 wxLogTrace(TRACE_KEYS
, _T("\t-> wxKeyCode %d"), key_code
);
1028 // sending unknown key events doesn't really make sense
1032 // now fill all the other fields
1035 GdkModifierType state
;
1036 if (gdk_event
->window
)
1037 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1039 event
.SetTimestamp( gdk_event
->time
);
1040 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
) != 0;
1041 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
) != 0;
1042 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
) != 0;
1043 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
) != 0;
1044 event
.m_keyCode
= key_code
;
1045 event
.m_scanCode
= gdk_event
->keyval
;
1046 event
.m_rawCode
= (wxUint32
) gdk_event
->keyval
;
1047 event
.m_rawFlags
= 0;
1050 event
.SetEventObject( win
);
1055 static gint
gtk_window_key_press_callback( GtkWidget
*widget
,
1056 GdkEventKey
*gdk_event
,
1062 wxapp_install_idle_handler();
1066 if (g_blockEventsOnDrag
)
1069 wxKeyEvent
event( wxEVT_KEY_DOWN
);
1070 if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) )
1072 // unknown key pressed, ignore (the event would be useless anyhow)
1076 bool ret
= win
->GetEventHandler()->ProcessEvent( event
);
1081 wxWindowGTK
*ancestor
= win
;
1084 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
1087 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
1088 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
1091 if (ancestor
->IsTopLevel())
1093 ancestor
= ancestor
->GetParent();
1096 #endif // wxUSE_ACCEL
1098 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
1099 will only be sent if it is not in an accelerator table. */
1102 KeySym keysym
= gdk_event
->keyval
;
1103 long key_code
= wxTranslateKeySymToWXKey(keysym
, TRUE
/* isChar */);
1106 if ( gdk_event
->length
== 1 )
1108 key_code
= (unsigned char)gdk_event
->string
[0];
1110 else if ( wxIsAsciiKeysym(keysym
) )
1113 key_code
= (unsigned char)keysym
;
1119 wxLogTrace(TRACE_KEYS
, _T("Char event: %ld"), key_code
);
1121 // reuse the same event object, just change its type and use the
1122 // translated keycode instead of the raw one
1123 event
.SetEventType(wxEVT_CHAR
);
1124 event
.m_keyCode
= key_code
;
1126 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1130 /* win is a control: tab can be propagated up */
1132 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
1133 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
1134 // have this style, yet choose not to process this particular TAB in which
1135 // case TAB must still work as a navigational character
1137 !win
->HasFlag(wxTE_PROCESS_TAB
) &&
1139 win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
1141 wxNavigationKeyEvent new_event
;
1142 new_event
.SetEventObject( win
->GetParent() );
1143 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
1144 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
1145 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1146 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
1147 new_event
.SetCurrentFocus( win
);
1148 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
1151 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
1153 (gdk_event
->keyval
== GDK_Escape
) )
1155 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
1156 new_event
.SetEventObject( win
);
1157 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
1161 #if 0 // (GTK_MINOR_VERSION > 0)
1162 /* Pressing F10 will activate the menu bar of the top frame. */
1164 (gdk_event
->keyval
== GDK_F10
) )
1166 wxWindowGTK
*ancestor
= win
;
1169 if (wxIsKindOf(ancestor
,wxFrame
))
1171 wxFrame
*frame
= (wxFrame
*) ancestor
;
1172 wxMenuBar
*menubar
= frame
->GetMenuBar();
1175 wxNode
*node
= menubar
->GetMenus().First();
1178 wxMenu
*firstMenu
= (wxMenu
*) node
->Data();
1179 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu
->m_owner
) );
1185 ancestor
= ancestor
->GetParent();
1192 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1199 //-----------------------------------------------------------------------------
1200 // "key_release_event" from any window
1201 //-----------------------------------------------------------------------------
1203 static gint
gtk_window_key_release_callback( GtkWidget
*widget
,
1204 GdkEventKey
*gdk_event
,
1210 wxapp_install_idle_handler();
1215 if (g_blockEventsOnDrag
)
1218 wxKeyEvent
event( wxEVT_KEY_UP
);
1219 if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) )
1221 // unknown key pressed, ignore (the event would be useless anyhow
1225 if ( !win
->GetEventHandler()->ProcessEvent( event
) )
1228 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1232 // ============================================================================
1234 // ============================================================================
1236 // init wxMouseEvent with the info from gdk_event
1237 #define InitMouseEvent(win, event, gdk_event) \
1239 event.SetTimestamp( gdk_event->time ); \
1240 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
1241 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
1242 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
1243 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
1244 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
1245 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
1246 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
1248 wxPoint pt = win->GetClientAreaOrigin(); \
1249 event.m_x = (wxCoord)gdk_event->x - pt.x; \
1250 event.m_y = (wxCoord)gdk_event->y - pt.y; \
1253 // ----------------------------------------------------------------------------
1254 // mouse event processing helper
1255 // ----------------------------------------------------------------------------
1257 static void AdjustEventButtonState(wxMouseEvent
& event
)
1259 // GDK reports the old state of the button for a button press event, but
1260 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1261 // for a LEFT_DOWN event, not FALSE, so we will invert
1262 // left/right/middleDown for the corresponding click events
1264 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1265 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1266 (event
.GetEventType() == wxEVT_LEFT_UP
))
1268 event
.m_leftDown
= !event
.m_leftDown
;
1272 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1273 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1274 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1276 event
.m_middleDown
= !event
.m_middleDown
;
1280 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1281 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1282 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1284 event
.m_rightDown
= !event
.m_rightDown
;
1289 //-----------------------------------------------------------------------------
1290 // "button_press_event"
1291 //-----------------------------------------------------------------------------
1293 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1298 wxapp_install_idle_handler();
1301 wxPrintf( wxT("1) OnButtonPress from ") );
1302 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1303 wxPrintf( win->GetClassInfo()->GetClassName() );
1304 wxPrintf( wxT(".\n") );
1306 if (!win
->m_hasVMT
) return FALSE
;
1307 if (g_blockEventsOnDrag
) return TRUE
;
1308 if (g_blockEventsOnScroll
) return TRUE
;
1310 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1312 if (win
->m_wxwindow
&& (g_focusWindow
!= win
) && win
->AcceptsFocus())
1314 gtk_widget_grab_focus( win
->m_wxwindow
);
1316 wxPrintf( wxT("GrabFocus from ") );
1317 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1318 wxPrintf( win->GetClassInfo()->GetClassName() );
1319 wxPrintf( wxT(".\n") );
1323 wxEventType event_type
= wxEVT_NULL
;
1325 if (gdk_event
->button
== 1)
1327 switch (gdk_event
->type
)
1329 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1330 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1334 else if (gdk_event
->button
== 2)
1336 switch (gdk_event
->type
)
1338 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1339 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1343 else if (gdk_event
->button
== 3)
1345 switch (gdk_event
->type
)
1347 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1348 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1353 if ( event_type
== wxEVT_NULL
)
1355 // unknown mouse button or click type
1359 wxMouseEvent
event( event_type
);
1360 InitMouseEvent( win
, event
, gdk_event
);
1362 AdjustEventButtonState(event
);
1364 // wxListBox actually get mouse events from the item
1366 if (win
->m_isListBox
)
1368 event
.m_x
+= widget
->allocation
.x
;
1369 event
.m_y
+= widget
->allocation
.y
;
1372 // Some control don't have their own X window and thus cannot get
1375 if (!g_captureWindow
)
1377 wxCoord x
= event
.m_x
;
1378 wxCoord y
= event
.m_y
;
1379 if (win
->m_wxwindow
)
1381 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1382 x
+= pizza
->xoffset
;
1383 y
+= pizza
->yoffset
;
1386 wxNode
*node
= win
->GetChildren().First();
1389 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1391 node
= node
->Next();
1392 if (!child
->IsShown())
1395 if (child
->m_isStaticBox
)
1397 // wxStaticBox is transparent in the box itself
1398 int xx1
= child
->m_x
;
1399 int yy1
= child
->m_y
;
1400 int xx2
= child
->m_x
+ child
->m_width
;
1401 int yy2
= child
->m_x
+ child
->m_height
;
1404 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1406 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1408 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1410 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1413 event
.m_x
-= child
->m_x
;
1414 event
.m_y
-= child
->m_y
;
1421 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1422 (child
->m_x
<= x
) &&
1423 (child
->m_y
<= y
) &&
1424 (child
->m_x
+child
->m_width
>= x
) &&
1425 (child
->m_y
+child
->m_height
>= y
))
1428 event
.m_x
-= child
->m_x
;
1429 event
.m_y
-= child
->m_y
;
1436 event
.SetEventObject( win
);
1438 gs_timeLastClick
= gdk_event
->time
;
1441 wxPrintf( wxT("2) OnButtonPress from ") );
1442 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1443 wxPrintf( win->GetClassInfo()->GetClassName() );
1444 wxPrintf( wxT(".\n") );
1447 if (win
->GetEventHandler()->ProcessEvent( event
))
1449 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1456 //-----------------------------------------------------------------------------
1457 // "button_release_event"
1458 //-----------------------------------------------------------------------------
1460 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1465 wxapp_install_idle_handler();
1467 if (!win
->m_hasVMT
) return FALSE
;
1468 if (g_blockEventsOnDrag
) return FALSE
;
1469 if (g_blockEventsOnScroll
) return FALSE
;
1471 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1474 printf( "OnButtonRelease from " );
1475 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1476 printf( win->GetClassInfo()->GetClassName() );
1480 wxEventType event_type
= wxEVT_NULL
;
1482 switch (gdk_event
->button
)
1484 case 1: event_type
= wxEVT_LEFT_UP
; break;
1485 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1486 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1487 default: return FALSE
;
1490 wxMouseEvent
event( event_type
);
1491 InitMouseEvent( win
, event
, gdk_event
);
1493 AdjustEventButtonState(event
);
1495 // wxListBox actually get mouse events from the item
1497 if (win
->m_isListBox
)
1499 event
.m_x
+= widget
->allocation
.x
;
1500 event
.m_y
+= widget
->allocation
.y
;
1503 // Some control don't have their own X window and thus cannot get
1506 if (!g_captureWindow
)
1508 wxCoord x
= event
.m_x
;
1509 wxCoord y
= event
.m_y
;
1510 if (win
->m_wxwindow
)
1512 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1513 x
+= pizza
->xoffset
;
1514 y
+= pizza
->yoffset
;
1517 wxNode
*node
= win
->GetChildren().First();
1520 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1522 node
= node
->Next();
1523 if (!child
->IsShown())
1526 if (child
->m_isStaticBox
)
1528 // wxStaticBox is transparent in the box itself
1529 int xx1
= child
->m_x
;
1530 int yy1
= child
->m_y
;
1531 int xx2
= child
->m_x
+ child
->m_width
;
1532 int yy2
= child
->m_x
+ child
->m_height
;
1535 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1537 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1539 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1541 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1544 event
.m_x
-= child
->m_x
;
1545 event
.m_y
-= child
->m_y
;
1552 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1553 (child
->m_x
<= x
) &&
1554 (child
->m_y
<= y
) &&
1555 (child
->m_x
+child
->m_width
>= x
) &&
1556 (child
->m_y
+child
->m_height
>= y
))
1559 event
.m_x
-= child
->m_x
;
1560 event
.m_y
-= child
->m_y
;
1567 event
.SetEventObject( win
);
1569 if (win
->GetEventHandler()->ProcessEvent( event
))
1571 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1578 //-----------------------------------------------------------------------------
1579 // "motion_notify_event"
1580 //-----------------------------------------------------------------------------
1582 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
,
1583 GdkEventMotion
*gdk_event
,
1589 wxapp_install_idle_handler();
1591 if (!win
->m_hasVMT
) return FALSE
;
1592 if (g_blockEventsOnDrag
) return FALSE
;
1593 if (g_blockEventsOnScroll
) return FALSE
;
1595 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1597 if (gdk_event
->is_hint
)
1601 GdkModifierType state
;
1602 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1608 printf( "OnMotion from " );
1609 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1610 printf( win->GetClassInfo()->GetClassName() );
1614 wxMouseEvent
event( wxEVT_MOTION
);
1615 InitMouseEvent(win
, event
, gdk_event
);
1617 if ( g_captureWindow
)
1619 // synthetize a mouse enter or leave event if needed
1620 GdkWindow
*winUnderMouse
= gdk_window_at_pointer(NULL
, NULL
);
1621 bool hasMouse
= winUnderMouse
== gdk_event
->window
;
1622 if ( hasMouse
!= g_captureWindowHasMouse
)
1624 // the mouse changed window
1625 g_captureWindowHasMouse
= hasMouse
;
1627 wxMouseEvent
event(g_captureWindowHasMouse
? wxEVT_ENTER_WINDOW
1628 : wxEVT_LEAVE_WINDOW
);
1629 InitMouseEvent(win
, event
, gdk_event
);
1630 event
.SetEventObject(win
);
1631 win
->GetEventHandler()->ProcessEvent(event
);
1636 // Some control don't have their own X window and thus cannot get
1639 wxCoord x
= event
.m_x
;
1640 wxCoord y
= event
.m_y
;
1641 if (win
->m_wxwindow
)
1643 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1644 x
+= pizza
->xoffset
;
1645 y
+= pizza
->yoffset
;
1648 wxNode
*node
= win
->GetChildren().First();
1651 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1653 node
= node
->Next();
1654 if (!child
->IsShown())
1657 if (child
->m_isStaticBox
)
1659 // wxStaticBox is transparent in the box itself
1660 int xx1
= child
->m_x
;
1661 int yy1
= child
->m_y
;
1662 int xx2
= child
->m_x
+ child
->m_width
;
1663 int yy2
= child
->m_x
+ child
->m_height
;
1666 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1668 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1670 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1672 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1675 event
.m_x
-= child
->m_x
;
1676 event
.m_y
-= child
->m_y
;
1683 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1684 (child
->m_x
<= x
) &&
1685 (child
->m_y
<= y
) &&
1686 (child
->m_x
+child
->m_width
>= x
) &&
1687 (child
->m_y
+child
->m_height
>= y
))
1690 event
.m_x
-= child
->m_x
;
1691 event
.m_y
-= child
->m_y
;
1698 event
.SetEventObject( win
);
1700 if (win
->GetEventHandler()->ProcessEvent( event
))
1702 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1709 //-----------------------------------------------------------------------------
1711 //-----------------------------------------------------------------------------
1713 // send the wxChildFocusEvent and wxFocusEvent, common code of
1714 // gtk_window_focus_in_callback() and SetFocus()
1715 static bool DoSendFocusEvents(wxWindow
*win
)
1717 // Notify the parent keeping track of focus for the kbd navigation
1718 // purposes that we got it.
1719 wxChildFocusEvent
eventChildFocus(win
);
1720 (void)win
->GetEventHandler()->ProcessEvent(eventChildFocus
);
1722 wxFocusEvent
eventFocus(wxEVT_SET_FOCUS
, win
->GetId());
1723 eventFocus
.SetEventObject(win
);
1725 return win
->GetEventHandler()->ProcessEvent(eventFocus
);
1728 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
,
1729 GdkEvent
*WXUNUSED(event
),
1735 wxapp_install_idle_handler();
1737 if (!win
->m_hasVMT
) return FALSE
;
1738 if (g_blockEventsOnDrag
) return FALSE
;
1740 switch ( g_sendActivateEvent
)
1743 // we've got focus from outside, synthetize wxActivateEvent
1744 g_sendActivateEvent
= 1;
1748 // another our window just lost focus, it was already ours before
1749 // - don't send any wxActivateEvent
1750 g_sendActivateEvent
= -1;
1755 g_focusWindow
= win
;
1757 wxLogTrace(TRACE_FOCUS
,
1758 _T("%s: focus in"), win
->GetName().c_str());
1762 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1766 // caret needs to be informed about focus change
1767 wxCaret
*caret
= win
->GetCaret();
1770 caret
->OnSetFocus();
1772 #endif // wxUSE_CARET
1774 g_activeFrameLostFocus
= FALSE
;
1776 wxWindowGTK
*active
= wxGetTopLevelParent(win
);
1777 if ( active
!= g_activeFrame
)
1779 if ( g_activeFrame
)
1781 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame
);
1782 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
1783 event
.SetEventObject(g_activeFrame
);
1784 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1787 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active
);
1788 g_activeFrame
= active
;
1789 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId());
1790 event
.SetEventObject(g_activeFrame
);
1791 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1793 // Don't send focus events in addition to activate
1794 // if (win == g_activeFrame)
1798 // does the window itself think that it has the focus?
1799 if ( !win
->m_hasFocus
)
1801 // not yet, notify it
1802 win
->m_hasFocus
= TRUE
;
1804 if ( DoSendFocusEvents(win
) )
1806 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1814 //-----------------------------------------------------------------------------
1815 // "focus_out_event"
1816 //-----------------------------------------------------------------------------
1818 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEventFocus
*gdk_event
, wxWindowGTK
*win
)
1823 wxapp_install_idle_handler();
1825 if (!win
->m_hasVMT
) return FALSE
;
1826 if (g_blockEventsOnDrag
) return FALSE
;
1828 wxLogTrace( TRACE_FOCUS
,
1829 _T("%s: focus out"), win
->GetName().c_str() );
1831 if ( !g_activeFrameLostFocus
&& g_activeFrame
)
1833 // VZ: commenting this out because it does happen (although not easy
1834 // to reproduce, I only see it when using wxMiniFrame and not
1835 // always) and makes using Mahogany quite annoying
1837 wxASSERT_MSG( wxGetTopLevelParent(win
) == g_activeFrame
,
1838 wxT("unfocusing window that hasn't gained focus properly") )
1841 g_activeFrameLostFocus
= TRUE
;
1844 // if the focus goes out of our app alltogether, OnIdle() will send
1845 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1846 // g_sendActivateEvent to -1
1847 g_sendActivateEvent
= 0;
1849 wxWindowGTK
*winFocus
= wxFindFocusedChild(win
);
1853 g_focusWindow
= (wxWindowGTK
*)NULL
;
1861 // caret needs to be informed about focus change
1862 wxCaret
*caret
= win
->GetCaret();
1865 caret
->OnKillFocus();
1867 #endif // wxUSE_CARET
1869 // don't send the window a kill focus event if it thinks that it doesn't
1870 // have focus already
1871 if ( win
->m_hasFocus
)
1873 win
->m_hasFocus
= FALSE
;
1875 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1876 event
.SetEventObject( win
);
1878 if (win
->GetEventHandler()->ProcessEvent( event
))
1880 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1888 //-----------------------------------------------------------------------------
1889 // "enter_notify_event"
1890 //-----------------------------------------------------------------------------
1892 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1897 wxapp_install_idle_handler();
1899 if (!win
->m_hasVMT
) return FALSE
;
1900 if (g_blockEventsOnDrag
) return FALSE
;
1902 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1904 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1905 event
.SetTimestamp( gdk_event
->time
);
1906 event
.SetEventObject( win
);
1910 GdkModifierType state
= (GdkModifierType
)0;
1912 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1914 InitMouseEvent(win
, event
, gdk_event
);
1915 wxPoint pt
= win
->GetClientAreaOrigin();
1916 event
.m_x
= x
+ pt
.x
;
1917 event
.m_y
= y
+ pt
.y
;
1919 if (win
->GetEventHandler()->ProcessEvent( event
))
1921 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1928 //-----------------------------------------------------------------------------
1929 // "leave_notify_event"
1930 //-----------------------------------------------------------------------------
1932 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1937 wxapp_install_idle_handler();
1939 if (!win
->m_hasVMT
) return FALSE
;
1940 if (g_blockEventsOnDrag
) return FALSE
;
1942 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1944 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1945 event
.SetTimestamp( gdk_event
->time
);
1946 event
.SetEventObject( win
);
1950 GdkModifierType state
= (GdkModifierType
)0;
1952 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1954 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
) != 0;
1955 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
) != 0;
1956 event
.m_altDown
= (state
& GDK_MOD1_MASK
) != 0;
1957 event
.m_metaDown
= (state
& GDK_MOD2_MASK
) != 0;
1958 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
) != 0;
1959 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
) != 0;
1960 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
) != 0;
1962 wxPoint pt
= win
->GetClientAreaOrigin();
1963 event
.m_x
= x
+ pt
.x
;
1964 event
.m_y
= y
+ pt
.y
;
1966 if (win
->GetEventHandler()->ProcessEvent( event
))
1968 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1975 //-----------------------------------------------------------------------------
1976 // "value_changed" from m_vAdjust
1977 //-----------------------------------------------------------------------------
1979 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
,
1986 wxapp_install_idle_handler();
1988 if (g_blockEventsOnDrag
) return;
1990 if (!win
->m_hasVMT
) return;
1992 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1993 if (fabs(diff
) < 0.2) return;
1995 win
->m_oldVerticalPos
= adjust
->value
;
1997 GtkScrolledWindow
*sw
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1998 wxEventType command
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->vscrollbar
));
2000 int value
= (int)(adjust
->value
+0.5);
2002 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
2003 event
.SetEventObject( win
);
2004 win
->GetEventHandler()->ProcessEvent( event
);
2007 //-----------------------------------------------------------------------------
2008 // "value_changed" from m_hAdjust
2009 //-----------------------------------------------------------------------------
2011 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
,
2018 wxapp_install_idle_handler();
2020 if (g_blockEventsOnDrag
) return;
2021 if (!win
->m_hasVMT
) return;
2023 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
2024 if (fabs(diff
) < 0.2) return;
2026 GtkScrolledWindow
*sw
= GTK_SCROLLED_WINDOW(win
->m_widget
);
2027 wxEventType command
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->hscrollbar
));
2029 win
->m_oldHorizontalPos
= adjust
->value
;
2031 int value
= (int)(adjust
->value
+0.5);
2033 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
2034 event
.SetEventObject( win
);
2035 win
->GetEventHandler()->ProcessEvent( event
);
2038 //-----------------------------------------------------------------------------
2039 // "button_press_event" from scrollbar
2040 //-----------------------------------------------------------------------------
2042 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
2043 GdkEventButton
*gdk_event
,
2049 wxapp_install_idle_handler();
2052 g_blockEventsOnScroll
= TRUE
;
2054 // FIXME: there is no 'slider' field in GTK+ 2.0 any more
2056 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
2062 //-----------------------------------------------------------------------------
2063 // "button_release_event" from scrollbar
2064 //-----------------------------------------------------------------------------
2066 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
2067 GdkEventButton
*WXUNUSED(gdk_event
),
2072 // don't test here as we can release the mouse while being over
2073 // a different window than the slider
2075 // if (gdk_event->window != widget->slider) return FALSE;
2077 g_blockEventsOnScroll
= FALSE
;
2079 if (win
->m_isScrolling
)
2081 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
2085 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
2086 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
2088 value
= (int)(win
->m_hAdjust
->value
+0.5);
2091 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
2093 value
= (int)(win
->m_vAdjust
->value
+0.5);
2097 wxScrollWinEvent
event( command
, value
, dir
);
2098 event
.SetEventObject( win
);
2099 win
->GetEventHandler()->ProcessEvent( event
);
2102 win
->m_isScrolling
= FALSE
;
2107 // ----------------------------------------------------------------------------
2108 // this wxWindowBase function is implemented here (in platform-specific file)
2109 // because it is static and so couldn't be made virtual
2110 // ----------------------------------------------------------------------------
2112 wxWindow
*wxWindowBase::FindFocus()
2114 // the cast is necessary when we compile in wxUniversal mode
2115 return (wxWindow
*)g_focusWindow
;
2118 //-----------------------------------------------------------------------------
2119 // "realize" from m_widget
2120 //-----------------------------------------------------------------------------
2122 /* We cannot set colours and fonts before the widget has
2123 been realized, so we do this directly after realization. */
2126 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
2131 wxapp_install_idle_handler();
2133 if (win
->m_delayedBackgroundColour
)
2134 win
->GtkSetBackgroundColour( win
->GetBackgroundColour() );
2136 if (win
->m_delayedForegroundColour
)
2137 win
->GtkSetForegroundColour( win
->GetForegroundColour() );
2139 wxWindowCreateEvent
event( win
);
2140 event
.SetEventObject( win
);
2141 win
->GetEventHandler()->ProcessEvent( event
);
2146 //-----------------------------------------------------------------------------
2148 //-----------------------------------------------------------------------------
2151 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
2152 GtkAllocation
*WXUNUSED(alloc
),
2156 wxapp_install_idle_handler();
2158 if (!win
->m_hasScrolling
) return;
2160 int client_width
= 0;
2161 int client_height
= 0;
2162 win
->GetClientSize( &client_width
, &client_height
);
2163 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
2166 win
->m_oldClientWidth
= client_width
;
2167 win
->m_oldClientHeight
= client_height
;
2169 if (!win
->m_nativeSizeEvent
)
2171 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
2172 event
.SetEventObject( win
);
2173 win
->GetEventHandler()->ProcessEvent( event
);
2179 #define WXUNUSED_UNLESS_XIM(param) param
2181 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2184 /* Resize XIM window */
2187 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2188 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
2189 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2192 wxapp_install_idle_handler();
2198 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
2202 gdk_window_get_size (widget
->window
, &width
, &height
);
2203 win
->m_icattr
->preedit_area
.width
= width
;
2204 win
->m_icattr
->preedit_area
.height
= height
;
2205 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2210 //-----------------------------------------------------------------------------
2211 // "realize" from m_wxwindow
2212 //-----------------------------------------------------------------------------
2214 /* Initialize XIM support */
2217 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2218 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2221 wxapp_install_idle_handler();
2224 if (win
->m_ic
) return FALSE
;
2225 if (!widget
) return FALSE
;
2226 if (!gdk_im_ready()) return FALSE
;
2228 win
->m_icattr
= gdk_ic_attr_new();
2229 if (!win
->m_icattr
) return FALSE
;
2233 GdkColormap
*colormap
;
2234 GdkICAttr
*attr
= win
->m_icattr
;
2235 unsigned attrmask
= GDK_IC_ALL_REQ
;
2237 GdkIMStyle supported_style
= (GdkIMStyle
)
2238 (GDK_IM_PREEDIT_NONE
|
2239 GDK_IM_PREEDIT_NOTHING
|
2240 GDK_IM_PREEDIT_POSITION
|
2241 GDK_IM_STATUS_NONE
|
2242 GDK_IM_STATUS_NOTHING
);
2244 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2245 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2247 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2248 attr
->client_window
= widget
->window
;
2250 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2251 gtk_widget_get_default_colormap ())
2253 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2254 attr
->preedit_colormap
= colormap
;
2257 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2258 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2259 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2260 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2262 switch (style
& GDK_IM_PREEDIT_MASK
)
2264 case GDK_IM_PREEDIT_POSITION
:
2265 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2267 g_warning ("over-the-spot style requires fontset");
2271 gdk_window_get_size (widget
->window
, &width
, &height
);
2273 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2274 attr
->spot_location
.x
= 0;
2275 attr
->spot_location
.y
= height
;
2276 attr
->preedit_area
.x
= 0;
2277 attr
->preedit_area
.y
= 0;
2278 attr
->preedit_area
.width
= width
;
2279 attr
->preedit_area
.height
= height
;
2280 attr
->preedit_fontset
= widget
->style
->font
;
2285 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2287 if (win
->m_ic
== NULL
)
2288 g_warning ("Can't create input context.");
2291 mask
= gdk_window_get_events (widget
->window
);
2292 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2293 gdk_window_set_events (widget
->window
, mask
);
2295 if (GTK_WIDGET_HAS_FOCUS(widget
))
2296 gdk_im_begin (win
->m_ic
, widget
->window
);
2303 //-----------------------------------------------------------------------------
2304 // InsertChild for wxWindowGTK.
2305 //-----------------------------------------------------------------------------
2307 /* Callback for wxWindowGTK. This very strange beast has to be used because
2308 * C++ has no virtual methods in a constructor. We have to emulate a
2309 * virtual function here as wxNotebook requires a different way to insert
2310 * a child in it. I had opted for creating a wxNotebookPage window class
2311 * which would have made this superfluous (such in the MDI window system),
2312 * but no-one was listening to me... */
2314 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child
)
2316 /* the window might have been scrolled already, do we
2317 have to adapt the position */
2318 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2319 child
->m_x
+= pizza
->xoffset
;
2320 child
->m_y
+= pizza
->yoffset
;
2322 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2323 GTK_WIDGET(child
->m_widget
),
2330 //-----------------------------------------------------------------------------
2332 //-----------------------------------------------------------------------------
2334 wxWindow
*wxGetActiveWindow()
2336 return wxWindow::FindFocus();
2339 //-----------------------------------------------------------------------------
2341 //-----------------------------------------------------------------------------
2343 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
2345 #ifdef __WXUNIVERSAL__
2346 IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
)
2348 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2349 #endif // __WXUNIVERSAL__/__WXGTK__
2351 void wxWindowGTK::Init()
2357 m_widget
= (GtkWidget
*) NULL
;
2358 m_wxwindow
= (GtkWidget
*) NULL
;
2359 m_focusWidget
= (GtkWidget
*) NULL
;
2369 m_needParent
= TRUE
;
2370 m_isBeingDeleted
= FALSE
;
2373 m_nativeSizeEvent
= FALSE
;
2375 m_hasScrolling
= FALSE
;
2376 m_isScrolling
= FALSE
;
2378 m_hAdjust
= (GtkAdjustment
*) NULL
;
2379 m_vAdjust
= (GtkAdjustment
*) NULL
;
2380 m_oldHorizontalPos
= 0.0;
2381 m_oldVerticalPos
= 0.0;
2384 m_widgetStyle
= (GtkStyle
*) NULL
;
2386 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2388 m_isStaticBox
= FALSE
;
2389 m_isRadioButton
= FALSE
;
2390 m_isListBox
= FALSE
;
2392 m_acceptsFocus
= FALSE
;
2395 m_clipPaintRegion
= FALSE
;
2397 m_cursor
= *wxSTANDARD_CURSOR
;
2399 m_delayedForegroundColour
= FALSE
;
2400 m_delayedBackgroundColour
= FALSE
;
2403 m_ic
= (GdkIC
*) NULL
;
2404 m_icattr
= (GdkICAttr
*) NULL
;
2408 wxWindowGTK::wxWindowGTK()
2413 wxWindowGTK::wxWindowGTK( wxWindow
*parent
,
2418 const wxString
&name
)
2422 Create( parent
, id
, pos
, size
, style
, name
);
2425 bool wxWindowGTK::Create( wxWindow
*parent
,
2430 const wxString
&name
)
2432 if (!PreCreation( parent
, pos
, size
) ||
2433 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2435 wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
2439 m_insertCallback
= wxInsertChildInWindow
;
2441 // always needed for background clearing
2442 m_delayedBackgroundColour
= TRUE
;
2444 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2445 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2447 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2449 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2450 scroll_class
->scrollbar_spacing
= 0;
2452 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2454 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2455 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2457 m_wxwindow
= gtk_pizza_new();
2459 #ifndef __WXUNIVERSAL__
2460 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2462 if (HasFlag(wxRAISED_BORDER
))
2464 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2466 else if (HasFlag(wxSUNKEN_BORDER
))
2468 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2470 else if (HasFlag(wxSIMPLE_BORDER
))
2472 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2476 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2478 #endif // __WXUNIVERSAL__
2480 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2482 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2483 m_acceptsFocus
= TRUE
;
2485 // I _really_ don't want scrollbars in the beginning
2486 m_vAdjust
->lower
= 0.0;
2487 m_vAdjust
->upper
= 1.0;
2488 m_vAdjust
->value
= 0.0;
2489 m_vAdjust
->step_increment
= 1.0;
2490 m_vAdjust
->page_increment
= 1.0;
2491 m_vAdjust
->page_size
= 5.0;
2492 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2493 m_hAdjust
->lower
= 0.0;
2494 m_hAdjust
->upper
= 1.0;
2495 m_hAdjust
->value
= 0.0;
2496 m_hAdjust
->step_increment
= 1.0;
2497 m_hAdjust
->page_increment
= 1.0;
2498 m_hAdjust
->page_size
= 5.0;
2499 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2501 // these handlers block mouse events to any window during scrolling such as
2502 // motion events and prevent GTK and wxWindows from fighting over where the
2505 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2506 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2508 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2509 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2511 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2512 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2514 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2515 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2517 // these handlers get notified when screen updates are required either when
2518 // scrolling or when the window size (and therefore scrollbar configuration)
2521 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2522 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2523 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2524 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2526 gtk_widget_show( m_wxwindow
);
2529 m_parent
->DoAddChild( this );
2531 m_focusWidget
= m_wxwindow
;
2540 wxWindowGTK::~wxWindowGTK()
2542 if (g_focusWindow
== this)
2543 g_focusWindow
= NULL
;
2545 if (g_activeFrame
== this)
2546 g_activeFrame
= NULL
;
2548 if ( g_delayedFocus
== this )
2549 g_delayedFocus
= NULL
;
2551 m_isBeingDeleted
= TRUE
;
2560 m_parent
->RemoveChild( this );
2564 gdk_ic_destroy (m_ic
);
2566 gdk_ic_attr_destroy (m_icattr
);
2571 #if DISABLE_STYLE_IF_BROKEN_THEME
2572 // don't delete if it's a pixmap theme style
2573 if (!m_widgetStyle
->engine_data
)
2574 gtk_style_unref( m_widgetStyle
);
2576 m_widgetStyle
= (GtkStyle
*) NULL
;
2581 gtk_widget_destroy( m_wxwindow
);
2582 m_wxwindow
= (GtkWidget
*) NULL
;
2587 gtk_widget_destroy( m_widget
);
2588 m_widget
= (GtkWidget
*) NULL
;
2592 bool wxWindowGTK::PreCreation( wxWindowGTK
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2594 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2596 /* this turns -1 into 20 so that a minimal window is
2597 visible even although -1,-1 has been given as the
2598 size of the window. the same trick is used in other
2599 ports and should make debugging easier */
2600 m_width
= WidthDefault(size
.x
);
2601 m_height
= HeightDefault(size
.y
);
2606 /* some reasonable defaults */
2611 m_x
= (gdk_screen_width () - m_width
) / 2;
2612 if (m_x
< 10) m_x
= 10;
2616 m_y
= (gdk_screen_height () - m_height
) / 2;
2617 if (m_y
< 10) m_y
= 10;
2624 void wxWindowGTK::PostCreation()
2626 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2632 // these get reported to wxWindows -> wxPaintEvent
2634 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2636 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2637 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2640 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2641 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2643 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2645 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2646 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2649 gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow
), HasFlag( wxNO_FULL_REPAINT_ON_RESIZE
) );
2653 // these are called when the "sunken" or "raised" borders are drawn
2654 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2655 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2658 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2659 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2665 if (m_focusWidget
== NULL
)
2666 m_focusWidget
= m_widget
;
2668 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event",
2669 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2671 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event",
2672 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2674 // connect to the various key and mouse handlers
2676 GtkWidget
*connect_widget
= GetConnectWidget();
2678 ConnectWidget( connect_widget
);
2680 /* We cannot set colours, fonts and cursors before the widget has
2681 been realized, so we do this directly after realization */
2682 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2683 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2687 // Catch native resize events
2688 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2689 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2691 // Initialize XIM support
2692 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2693 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2695 // And resize XIM window
2696 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2697 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2700 if (!GTK_IS_COMBO(m_widget
))
2702 // This is needed if we want to add our windows into native
2703 // GTK control, such as the toolbar. With this callback, the
2704 // toolbar gets to know the correct size (the one set by the
2705 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2706 // when moving to GTK 2.0.
2707 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2708 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2714 void wxWindowGTK::ConnectWidget( GtkWidget
*widget
)
2716 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2717 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2719 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2720 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2722 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2723 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2725 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2726 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2728 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2729 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2731 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2732 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2734 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2735 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2738 bool wxWindowGTK::Destroy()
2740 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2744 return wxWindowBase::Destroy();
2747 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
)
2749 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2752 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2754 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2755 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") );
2758 printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
2761 if (m_resizing
) return; /* I don't like recursions */
2764 int currentX
, currentY
;
2765 GetPosition(¤tX
, ¤tY
);
2770 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
2772 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2774 /* don't set the size for children of wxNotebook, just take the values. */
2782 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2783 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2785 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2786 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2787 if (width
!= -1) m_width
= width
;
2788 if (height
!= -1) m_height
= height
;
2792 m_x
= x
+ pizza
->xoffset
;
2793 m_y
= y
+ pizza
->yoffset
;
2798 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2800 if (width
== -1) m_width
= 80;
2803 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2805 if (height
== -1) m_height
= 26;
2808 int minWidth
= GetMinWidth(),
2809 minHeight
= GetMinHeight(),
2810 maxWidth
= GetMaxWidth(),
2811 maxHeight
= GetMaxHeight();
2813 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
2814 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
2815 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
2816 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
2819 int bottom_border
= 0;
2822 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2824 /* the default button has a border around it */
2830 DoMoveWindow( m_x
-border
,
2833 m_height
+border
+bottom_border
);
2838 /* Sometimes the client area changes size without the
2839 whole windows's size changing, but if the whole
2840 windows's size doesn't change, no wxSizeEvent will
2841 normally be sent. Here we add an extra test if
2842 the client test has been changed and this will
2844 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2848 wxPrintf( "OnSize sent from " );
2849 if (GetClassInfo() && GetClassInfo()->GetClassName())
2850 wxPrintf( GetClassInfo()->GetClassName() );
2851 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2854 if (!m_nativeSizeEvent
)
2856 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2857 event
.SetEventObject( this );
2858 GetEventHandler()->ProcessEvent( event
);
2864 void wxWindowGTK::OnInternalIdle()
2866 // Update invalidated regions.
2869 // Synthetize activate events.
2870 if ( g_sendActivateEvent
!= -1 )
2872 bool activate
= g_sendActivateEvent
!= 0;
2875 g_sendActivateEvent
= -1;
2877 wxTheApp
->SetActive(activate
, (wxWindow
*)g_focusWindowLast
);
2880 if ( g_activeFrameLostFocus
)
2882 if ( g_activeFrame
)
2884 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame
);
2885 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
2886 event
.SetEventObject(g_activeFrame
);
2887 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
2888 g_activeFrame
= NULL
;
2890 g_activeFrameLostFocus
= FALSE
;
2893 wxCursor cursor
= m_cursor
;
2894 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2898 /* I now set the cursor anew in every OnInternalIdle call
2899 as setting the cursor in a parent window also effects the
2900 windows above so that checking for the current cursor is
2905 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2907 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2909 if (!g_globalCursor
.Ok())
2910 cursor
= *wxSTANDARD_CURSOR
;
2912 window
= m_widget
->window
;
2913 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2914 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2920 GdkWindow
*window
= m_widget
->window
;
2921 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2922 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2930 void wxWindowGTK::DoGetSize( int *width
, int *height
) const
2932 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2934 if (width
) (*width
) = m_width
;
2935 if (height
) (*height
) = m_height
;
2938 void wxWindowGTK::DoSetClientSize( int width
, int height
)
2940 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2944 SetSize( width
, height
);
2951 #ifndef __WXUNIVERSAL__
2952 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2954 /* when using GTK 1.2 we set the shadow border size to 2 */
2958 if (HasFlag(wxSIMPLE_BORDER
))
2960 /* when using GTK 1.2 we set the simple border size to 1 */
2964 #endif // __WXUNIVERSAL__
2968 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2970 GtkRequisition vscroll_req
;
2971 vscroll_req
.width
= 2;
2972 vscroll_req
.height
= 2;
2973 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2974 (scroll_window
->vscrollbar
, &vscroll_req
);
2976 GtkRequisition hscroll_req
;
2977 hscroll_req
.width
= 2;
2978 hscroll_req
.height
= 2;
2979 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2980 (scroll_window
->hscrollbar
, &hscroll_req
);
2982 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2984 if (scroll_window
->vscrollbar_visible
)
2986 dw
+= vscroll_req
.width
;
2987 dw
+= scroll_class
->scrollbar_spacing
;
2990 if (scroll_window
->hscrollbar_visible
)
2992 dh
+= hscroll_req
.height
;
2993 dh
+= scroll_class
->scrollbar_spacing
;
2997 SetSize( width
+dw
, height
+dh
);
3001 void wxWindowGTK::DoGetClientSize( int *width
, int *height
) const
3003 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3007 if (width
) (*width
) = m_width
;
3008 if (height
) (*height
) = m_height
;
3015 #ifndef __WXUNIVERSAL__
3016 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
3018 /* when using GTK 1.2 we set the shadow border size to 2 */
3022 if (HasFlag(wxSIMPLE_BORDER
))
3024 /* when using GTK 1.2 we set the simple border size to 1 */
3028 #endif // __WXUNIVERSAL__
3032 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
3034 GtkRequisition vscroll_req
;
3035 vscroll_req
.width
= 2;
3036 vscroll_req
.height
= 2;
3037 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
3038 (scroll_window
->vscrollbar
, &vscroll_req
);
3040 GtkRequisition hscroll_req
;
3041 hscroll_req
.width
= 2;
3042 hscroll_req
.height
= 2;
3043 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
3044 (scroll_window
->hscrollbar
, &hscroll_req
);
3046 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
3048 if (scroll_window
->vscrollbar_visible
)
3050 dw
+= vscroll_req
.width
;
3051 dw
+= scroll_class
->scrollbar_spacing
;
3054 if (scroll_window
->hscrollbar_visible
)
3056 dh
+= hscroll_req
.height
;
3057 dh
+= scroll_class
->scrollbar_spacing
;
3061 if (width
) (*width
) = m_width
- dw
;
3062 if (height
) (*height
) = m_height
- dh
;
3066 printf( "GetClientSize, name %s ", GetName().c_str() );
3067 if (width) printf( " width = %d", (*width) );
3068 if (height) printf( " height = %d", (*height) );
3073 void wxWindowGTK::DoGetPosition( int *x
, int *y
) const
3075 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3079 if (m_parent
&& m_parent
->m_wxwindow
)
3081 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
3082 dx
= pizza
->xoffset
;
3083 dy
= pizza
->yoffset
;
3086 if (x
) (*x
) = m_x
- dx
;
3087 if (y
) (*y
) = m_y
- dy
;
3090 void wxWindowGTK::DoClientToScreen( int *x
, int *y
) const
3092 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3094 if (!m_widget
->window
) return;
3096 GdkWindow
*source
= (GdkWindow
*) NULL
;
3098 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3100 source
= m_widget
->window
;
3104 gdk_window_get_origin( source
, &org_x
, &org_y
);
3108 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3110 org_x
+= m_widget
->allocation
.x
;
3111 org_y
+= m_widget
->allocation
.y
;
3119 void wxWindowGTK::DoScreenToClient( int *x
, int *y
) const
3121 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3123 if (!m_widget
->window
) return;
3125 GdkWindow
*source
= (GdkWindow
*) NULL
;
3127 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3129 source
= m_widget
->window
;
3133 gdk_window_get_origin( source
, &org_x
, &org_y
);
3137 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3139 org_x
+= m_widget
->allocation
.x
;
3140 org_y
+= m_widget
->allocation
.y
;
3148 bool wxWindowGTK::Show( bool show
)
3150 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3152 if (!wxWindowBase::Show(show
))
3159 gtk_widget_show( m_widget
);
3161 gtk_widget_hide( m_widget
);
3166 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
)
3168 win
->OnParentEnable(enable
);
3170 // Recurse, so that children have the opportunity to Do The Right Thing
3171 // and reset colours that have been messed up by a parent's (really ancestor's)
3173 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
3175 node
= node
->GetNext() )
3177 wxWindow
*child
= node
->GetData();
3178 if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
)))
3179 wxWindowNotifyEnable(child
, enable
);
3183 bool wxWindowGTK::Enable( bool enable
)
3185 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3187 if (!wxWindowBase::Enable(enable
))
3193 gtk_widget_set_sensitive( m_widget
, enable
);
3195 gtk_widget_set_sensitive( m_wxwindow
, enable
);
3197 wxWindowNotifyEnable(this, enable
);
3202 int wxWindowGTK::GetCharHeight() const
3204 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
3206 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
3208 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3210 return font
->ascent
+ font
->descent
;
3213 int wxWindowGTK::GetCharWidth() const
3215 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
3217 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
3219 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3221 return gdk_string_width( font
, "H" );
3224 void wxWindowGTK::GetTextExtent( const wxString
& string
,
3228 int *externalLeading
,
3229 const wxFont
*theFont
) const
3231 wxFont fontToUse
= m_font
;
3232 if (theFont
) fontToUse
= *theFont
;
3234 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
3236 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
3237 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
3238 if (y
) (*y
) = font
->ascent
+ font
->descent
;
3239 if (descent
) (*descent
) = font
->descent
;
3240 if (externalLeading
) (*externalLeading
) = 0; // ??
3243 void wxWindowGTK::SetFocus()
3245 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3249 // don't do anything if we already have focus
3255 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3257 gtk_widget_grab_focus (m_wxwindow
);
3262 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
3264 if (!GTK_WIDGET_REALIZED(m_widget
))
3266 // we can't set the focus to the widget now so we remember that
3267 // it should be focused and will do it later, during the idle
3268 // time, as soon as we can
3269 wxLogTrace(TRACE_FOCUS
,
3270 _T("Delaying setting focus to %s(%s)"),
3271 GetClassInfo()->GetClassName(), GetLabel().c_str());
3273 g_delayedFocus
= this;
3277 wxLogTrace(TRACE_FOCUS
,
3278 _T("Setting focus to %s(%s)"),
3279 GetClassInfo()->GetClassName(), GetLabel().c_str());
3281 gtk_widget_grab_focus (m_widget
);
3284 else if (GTK_IS_CONTAINER(m_widget
))
3286 SET_CONTAINER_FOCUS( m_widget
, GTK_DIR_TAB_FORWARD
);
3290 wxLogTrace(TRACE_FOCUS
,
3291 _T("Can't set focus to %s(%s)"),
3292 GetClassInfo()->GetClassName(), GetLabel().c_str());
3297 bool wxWindowGTK::AcceptsFocus() const
3299 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3302 bool wxWindowGTK::Reparent( wxWindowBase
*newParentBase
)
3304 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3306 wxWindowGTK
*oldParent
= m_parent
,
3307 *newParent
= (wxWindowGTK
*)newParentBase
;
3309 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3311 if ( !wxWindowBase::Reparent(newParent
) )
3314 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3316 /* prevent GTK from deleting the widget arbitrarily */
3317 gtk_widget_ref( m_widget
);
3321 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3324 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3328 /* insert GTK representation */
3329 (*(newParent
->m_insertCallback
))(newParent
, this);
3332 /* reverse: prevent GTK from deleting the widget arbitrarily */
3333 gtk_widget_unref( m_widget
);
3338 void wxWindowGTK::DoAddChild(wxWindowGTK
*child
)
3340 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3342 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3344 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3349 /* insert GTK representation */
3350 (*m_insertCallback
)(this, child
);
3353 void wxWindowGTK::Raise()
3355 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3357 if (!m_widget
->window
) return;
3359 gdk_window_raise( m_widget
->window
);
3362 void wxWindowGTK::Lower()
3364 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3366 if (!m_widget
->window
) return;
3368 gdk_window_lower( m_widget
->window
);
3371 bool wxWindowGTK::SetCursor( const wxCursor
&cursor
)
3373 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3375 if (cursor
== m_cursor
)
3379 wxapp_install_idle_handler();
3381 if (cursor
== wxNullCursor
)
3382 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3384 return wxWindowBase::SetCursor( cursor
);
3387 void wxWindowGTK::WarpPointer( int x
, int y
)
3389 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3391 // We provide this function ourselves as it is
3392 // missing in GDK (top of this file).
3394 GdkWindow
*window
= (GdkWindow
*) NULL
;
3396 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3398 window
= GetConnectWidget()->window
;
3401 gdk_window_warp_pointer( window
, x
, y
);
3404 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect
*rect
)
3406 if (!m_widget
) return;
3407 if (!m_widget
->window
) return;
3411 wxapp_install_idle_handler();
3413 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3417 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3418 m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
3422 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3423 m_clearRegion
.Clear();
3424 m_clearRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height
);
3432 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3433 m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
3437 GdkRectangle gdk_rect
;
3438 gdk_rect
.x
= rect
->x
;
3439 gdk_rect
.y
= rect
->y
;
3440 gdk_rect
.width
= rect
->width
;
3441 gdk_rect
.height
= rect
->height
;
3442 gtk_widget_draw( m_widget
, &gdk_rect
);
3449 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3450 m_updateRegion
.Clear();
3451 m_updateRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height
);
3455 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3463 GdkRectangle gdk_rect
;
3464 gdk_rect
.x
= rect
->x
;
3465 gdk_rect
.y
= rect
->y
;
3466 gdk_rect
.width
= rect
->width
;
3467 gdk_rect
.height
= rect
->height
;
3468 gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, &gdk_rect
, TRUE
);
3472 gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, NULL
, TRUE
);
3478 void wxWindowGTK::Update()
3483 void wxWindowGTK::GtkUpdate()
3486 if (m_wxwindow
&& GTK_PIZZA(m_wxwindow
)->bin_window
)
3487 gdk_window_process_updates( GTK_PIZZA(m_wxwindow
)->bin_window
, FALSE
);
3490 if (!m_updateRegion
.IsEmpty())
3491 GtkSendPaintEvents();
3494 void wxWindowGTK::GtkSendPaintEvents()
3498 m_clearRegion
.Clear();
3499 m_updateRegion
.Clear();
3503 // widget to draw on
3504 GtkPizza
*pizza
= GTK_PIZZA (m_wxwindow
);
3506 // Clip to paint region in wxClientDC
3507 m_clipPaintRegion
= TRUE
;
3509 if (GetThemeEnabled())
3511 // find ancestor from which to steal background
3512 wxWindow
*parent
= GetParent();
3513 while (parent
&& !parent
->IsTopLevel())
3514 parent
= parent
->GetParent();
3516 parent
= (wxWindow
*)this;
3518 wxRegionIterator
upd( m_updateRegion
);
3522 rect
.x
= upd
.GetX();
3523 rect
.y
= upd
.GetY();
3524 rect
.width
= upd
.GetWidth();
3525 rect
.height
= upd
.GetHeight();
3527 gtk_paint_flat_box( parent
->m_widget
->style
,
3540 // if (!m_clearRegion.IsEmpty()) // always send an erase event
3542 wxWindowDC
dc( (wxWindow
*)this );
3543 dc
.SetClippingRegion( m_clearRegion
);
3545 wxEraseEvent
erase_event( GetId(), &dc
);
3546 erase_event
.SetEventObject( this );
3548 if (!GetEventHandler()->ProcessEvent(erase_event
))
3552 g_eraseGC
= gdk_gc_new( pizza
->bin_window
);
3553 gdk_gc_set_fill( g_eraseGC
, GDK_SOLID
);
3555 gdk_gc_set_foreground( g_eraseGC
, m_backgroundColour
.GetColor() );
3557 wxRegionIterator
upd( m_clearRegion
);
3560 gdk_draw_rectangle( pizza
->bin_window
, g_eraseGC
, 1,
3561 upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
3565 m_clearRegion
.Clear();
3568 wxNcPaintEvent
nc_paint_event( GetId() );
3569 nc_paint_event
.SetEventObject( this );
3570 GetEventHandler()->ProcessEvent( nc_paint_event
);
3572 wxPaintEvent
paint_event( GetId() );
3573 paint_event
.SetEventObject( this );
3574 GetEventHandler()->ProcessEvent( paint_event
);
3576 m_clipPaintRegion
= FALSE
;
3578 #ifndef __WXUNIVERSAL__
3580 // The following code will result in all window-less widgets
3581 // being redrawn because the wxWindows class is allowed to
3582 // paint over the window-less widgets.
3584 GList
*children
= pizza
->children
;
3587 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
3588 children
= children
->next
;
3590 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
3591 GTK_WIDGET_DRAWABLE (child
->widget
))
3593 // Get intersection of widget area and update region
3594 wxRegion
region( m_updateRegion
);
3596 GdkEventExpose gdk_event
;
3597 gdk_event
.type
= GDK_EXPOSE
;
3598 gdk_event
.window
= pizza
->bin_window
;
3599 gdk_event
.count
= 0;
3601 wxRegionIterator
upd( m_updateRegion
);
3605 rect
.x
= upd
.GetX();
3606 rect
.y
= upd
.GetY();
3607 rect
.width
= upd
.GetWidth();
3608 rect
.height
= upd
.GetHeight();
3610 if (gtk_widget_intersect (child
->widget
, &rect
, &gdk_event
.area
))
3612 gtk_widget_event (child
->widget
, (GdkEvent
*) &gdk_event
);
3622 m_updateRegion
.Clear();
3625 void wxWindowGTK::Clear()
3627 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3629 if (m_wxwindow
&& m_wxwindow
->window
)
3631 m_clearRegion
.Clear();
3632 wxSize
size( GetClientSize() );
3633 m_clearRegion
.Union( 0,0,size
.x
,size
.y
);
3635 // Better do this in idle?
3641 void wxWindowGTK::DoSetToolTip( wxToolTip
*tip
)
3643 wxWindowBase::DoSetToolTip(tip
);
3646 m_tooltip
->Apply( (wxWindow
*)this );
3649 void wxWindowGTK::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3651 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3653 #endif // wxUSE_TOOLTIPS
3655 void wxWindowGTK::GtkSetBackgroundColour( const wxColour
&colour
)
3657 GdkWindow
*window
= (GdkWindow
*) NULL
;
3659 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3661 window
= GetConnectWidget()->window
;
3665 // We need the pixel value e.g. for background clearing.
3666 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3670 // wxMSW doesn't clear the window here, either.
3671 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3677 bool wxWindowGTK::SetBackgroundColour( const wxColour
&colour
)
3679 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3681 if (!wxWindowBase::SetBackgroundColour(colour
))
3684 GdkWindow
*window
= (GdkWindow
*) NULL
;
3686 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3688 window
= GetConnectWidget()->window
;
3692 // indicate that a new style has been set
3693 // but it couldn't get applied as the
3694 // widget hasn't been realized yet.
3695 m_delayedBackgroundColour
= TRUE
;
3700 GtkSetBackgroundColour( colour
);
3706 void wxWindowGTK::GtkSetForegroundColour( const wxColour
&colour
)
3708 GdkWindow
*window
= (GdkWindow
*) NULL
;
3710 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3712 window
= GetConnectWidget()->window
;
3719 bool wxWindowGTK::SetForegroundColour( const wxColour
&colour
)
3721 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3723 if (!wxWindowBase::SetForegroundColour(colour
))
3725 // don't leave if the GTK widget has just
3727 if (!m_delayedForegroundColour
) return FALSE
;
3730 GdkWindow
*window
= (GdkWindow
*) NULL
;
3732 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3734 window
= GetConnectWidget()->window
;
3738 // indicate that a new style has been set
3739 // but it couldn't get applied as the
3740 // widget hasn't been realized yet.
3741 m_delayedForegroundColour
= TRUE
;
3745 GtkSetForegroundColour( colour
);
3751 GtkStyle
*wxWindowGTK::GetWidgetStyle()
3755 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3757 // FIXME: no more klass in 2.0
3759 remake
->klass
= m_widgetStyle
->klass
;
3762 gtk_style_unref( m_widgetStyle
);
3763 m_widgetStyle
= remake
;
3767 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3770 def
= gtk_widget_get_default_style();
3772 m_widgetStyle
= gtk_style_copy( def
);
3774 // FIXME: no more klass in 2.0
3776 m_widgetStyle
->klass
= def
->klass
;
3780 return m_widgetStyle
;
3783 void wxWindowGTK::SetWidgetStyle()
3785 #if DISABLE_STYLE_IF_BROKEN_THEME
3786 if (m_widget
->style
->engine_data
)
3788 static bool s_warningPrinted
= FALSE
;
3789 if (!s_warningPrinted
)
3791 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3792 s_warningPrinted
= TRUE
;
3794 m_widgetStyle
= m_widget
->style
;
3799 GtkStyle
*style
= GetWidgetStyle();
3801 if (m_font
!= wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT
))
3803 SET_STYLE_FONT(style
, m_font
.GetInternalFont( 1.0 ));
3806 if (m_foregroundColour
.Ok())
3808 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3809 if (m_foregroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT
))
3811 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3812 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3813 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3817 // Try to restore the gtk default style. This is still a little
3818 // oversimplified for what is probably really needed here for controls
3819 // other than buttons, but is better than not being able to (re)set a
3820 // control's foreground colour to *wxBLACK -- RL
3821 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3824 def
= gtk_widget_get_default_style();
3826 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3827 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3828 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3832 if (m_backgroundColour
.Ok())
3834 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3835 if (m_backgroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
))
3837 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3838 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3839 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3840 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3841 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3842 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3843 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3844 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3848 // Try to restore the gtk default style. This is still a little
3849 // oversimplified for what is probably really needed here for controls
3850 // other than buttons, but is better than not being able to (re)set a
3851 // control's background colour to default grey and means resetting a
3852 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3854 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3857 def
= gtk_widget_get_default_style();
3859 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3860 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3861 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3862 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3863 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3864 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3865 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3866 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3871 void wxWindowGTK::ApplyWidgetStyle()
3875 //-----------------------------------------------------------------------------
3876 // Pop-up menu stuff
3877 //-----------------------------------------------------------------------------
3879 #if wxUSE_MENUS_NATIVE
3882 void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3884 *is_waiting
= FALSE
;
3887 static void SetInvokingWindow( wxMenu
*menu
, wxWindowGTK
*win
)
3889 menu
->SetInvokingWindow( win
);
3890 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3893 wxMenuItem
*menuitem
= node
->GetData();
3894 if (menuitem
->IsSubMenu())
3896 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3899 node
= node
->GetNext();
3903 // used to pass the coordinates from wxWindowGTK::DoPopupMenu() to
3904 // wxPopupMenuPositionCallback()
3906 // should be safe even in the MT case as the user can hardly popup 2 menus
3907 // simultaneously, can he?
3908 static gint gs_pop_x
= 0;
3909 static gint gs_pop_y
= 0;
3911 extern "C" void wxPopupMenuPositionCallback( GtkMenu
*menu
,
3914 gboolean
* WXUNUSED(whatever
),
3916 gpointer
WXUNUSED(user_data
) )
3918 // ensure that the menu appears entirely on screen
3920 gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
);
3922 wxSize sizeScreen
= wxGetDisplaySize();
3924 gint xmax
= sizeScreen
.x
- req
.width
,
3925 ymax
= sizeScreen
.y
- req
.height
;
3927 *x
= gs_pop_x
< xmax
? gs_pop_x
: xmax
;
3928 *y
= gs_pop_y
< ymax
? gs_pop_y
: ymax
;
3931 bool wxWindowGTK::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3933 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3935 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3937 SetInvokingWindow( menu
, this );
3943 ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3945 bool is_waiting
= TRUE
;
3947 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
),
3949 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
),
3950 (gpointer
)&is_waiting
);
3953 GTK_MENU(menu
->m_menu
),
3954 (GtkWidget
*) NULL
, // parent menu shell
3955 (GtkWidget
*) NULL
, // parent menu item
3956 wxPopupMenuPositionCallback
, // function to position it
3957 NULL
, // client data
3958 0, // button used to activate it
3959 gs_timeLastClick
// the time of activation
3964 while (gtk_events_pending())
3965 gtk_main_iteration();
3971 #endif // wxUSE_MENUS_NATIVE
3973 #if wxUSE_DRAG_AND_DROP
3975 void wxWindowGTK::SetDropTarget( wxDropTarget
*dropTarget
)
3977 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3979 GtkWidget
*dnd_widget
= GetConnectWidget();
3981 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3983 if (m_dropTarget
) delete m_dropTarget
;
3984 m_dropTarget
= dropTarget
;
3986 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3989 #endif // wxUSE_DRAG_AND_DROP
3991 GtkWidget
* wxWindowGTK::GetConnectWidget()
3993 GtkWidget
*connect_widget
= m_widget
;
3994 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3996 return connect_widget
;
3999 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow
*window
)
4002 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
4004 return (window
== m_widget
->window
);
4007 bool wxWindowGTK::SetFont( const wxFont
&font
)
4009 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
4011 if (!wxWindowBase::SetFont(font
))
4016 wxColour sysbg
= wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE
);
4017 if ( sysbg
== m_backgroundColour
)
4019 m_backgroundColour
= wxNullColour
;
4021 m_backgroundColour
= sysbg
;
4031 void wxWindowGTK::DoCaptureMouse()
4033 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4035 GdkWindow
*window
= (GdkWindow
*) NULL
;
4037 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
4039 window
= GetConnectWidget()->window
;
4041 wxCHECK_RET( window
, _T("CaptureMouse() failed") );
4043 wxCursor
* cursor
= & m_cursor
;
4045 cursor
= wxSTANDARD_CURSOR
;
4047 gdk_pointer_grab( window
, FALSE
,
4049 (GDK_BUTTON_PRESS_MASK
|
4050 GDK_BUTTON_RELEASE_MASK
|
4051 GDK_POINTER_MOTION_HINT_MASK
|
4052 GDK_POINTER_MOTION_MASK
),
4054 cursor
->GetCursor(),
4055 (guint32
)GDK_CURRENT_TIME
);
4056 g_captureWindow
= this;
4057 g_captureWindowHasMouse
= TRUE
;
4060 void wxWindowGTK::DoReleaseMouse()
4062 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4064 wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") );
4066 g_captureWindow
= (wxWindowGTK
*) NULL
;
4068 GdkWindow
*window
= (GdkWindow
*) NULL
;
4070 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
4072 window
= GetConnectWidget()->window
;
4077 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
4081 wxWindow
*wxWindowBase::GetCapture()
4083 return (wxWindow
*)g_captureWindow
;
4086 bool wxWindowGTK::IsRetained() const
4091 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
,
4092 int range
, bool refresh
)
4094 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4096 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4098 m_hasScrolling
= TRUE
;
4100 if (orient
== wxHORIZONTAL
)
4102 float fpos
= (float)pos
;
4103 float frange
= (float)range
;
4104 float fthumb
= (float)thumbVisible
;
4105 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
4106 if (fpos
< 0.0) fpos
= 0.0;
4108 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
4109 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
4111 SetScrollPos( orient
, pos
, refresh
);
4115 m_oldHorizontalPos
= fpos
;
4117 m_hAdjust
->lower
= 0.0;
4118 m_hAdjust
->upper
= frange
;
4119 m_hAdjust
->value
= fpos
;
4120 m_hAdjust
->step_increment
= 1.0;
4121 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
4122 m_hAdjust
->page_size
= fthumb
;
4126 float fpos
= (float)pos
;
4127 float frange
= (float)range
;
4128 float fthumb
= (float)thumbVisible
;
4129 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
4130 if (fpos
< 0.0) fpos
= 0.0;
4132 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
4133 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
4135 SetScrollPos( orient
, pos
, refresh
);
4139 m_oldVerticalPos
= fpos
;
4141 m_vAdjust
->lower
= 0.0;
4142 m_vAdjust
->upper
= frange
;
4143 m_vAdjust
->value
= fpos
;
4144 m_vAdjust
->step_increment
= 1.0;
4145 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
4146 m_vAdjust
->page_size
= fthumb
;
4149 if (orient
== wxHORIZONTAL
)
4150 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
4152 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
4155 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
4157 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4159 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4161 if (orient
== wxHORIZONTAL
)
4163 float fpos
= (float)pos
;
4164 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
4165 if (fpos
< 0.0) fpos
= 0.0;
4166 m_oldHorizontalPos
= fpos
;
4168 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
4169 m_hAdjust
->value
= fpos
;
4173 float fpos
= (float)pos
;
4174 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
4175 if (fpos
< 0.0) fpos
= 0.0;
4176 m_oldVerticalPos
= fpos
;
4178 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
4179 m_vAdjust
->value
= fpos
;
4182 if (m_wxwindow
->window
)
4184 if (orient
== wxHORIZONTAL
)
4186 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
4187 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
4189 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
4191 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
4192 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
4196 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
4197 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4199 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
4201 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
4202 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4207 int wxWindowGTK::GetScrollThumb( int orient
) const
4209 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4211 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4213 if (orient
== wxHORIZONTAL
)
4214 return (int)(m_hAdjust
->page_size
+0.5);
4216 return (int)(m_vAdjust
->page_size
+0.5);
4219 int wxWindowGTK::GetScrollPos( int orient
) const
4221 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4223 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4225 if (orient
== wxHORIZONTAL
)
4226 return (int)(m_hAdjust
->value
+0.5);
4228 return (int)(m_vAdjust
->value
+0.5);
4231 int wxWindowGTK::GetScrollRange( int orient
) const
4233 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4235 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4237 if (orient
== wxHORIZONTAL
)
4238 return (int)(m_hAdjust
->upper
+0.5);
4240 return (int)(m_vAdjust
->upper
+0.5);
4243 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
4245 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4247 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4249 // No scrolling requested.
4250 if ((dx
== 0) && (dy
== 0)) return;
4253 if (!m_updateRegion
.IsEmpty())
4255 m_updateRegion
.Offset( dx
, dy
);
4259 GetClientSize( &cw
, &ch
);
4260 m_updateRegion
.Intersect( 0, 0, cw
, ch
);
4263 if (!m_clearRegion
.IsEmpty())
4265 m_clearRegion
.Offset( dx
, dy
);
4269 GetClientSize( &cw
, &ch
);
4270 m_clearRegion
.Intersect( 0, 0, cw
, ch
);
4272 m_clipPaintRegion
= TRUE
;
4274 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
4276 m_clipPaintRegion
= FALSE
;
4279 gdk_window_scroll( GTK_PIZZA(m_wxwindow
)->bin_window
, dx
, dy
);
4281 GTK_PIZZA(m_wxwindow
)->xoffset
+= dx
;
4282 GTK_PIZZA(m_wxwindow
)->yoffset
+= dy
;
4289 // Find the wxWindow at the current mouse position, also returning the mouse
4291 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
4293 pt
= wxGetMousePosition();
4294 wxWindow
* found
= wxFindWindowAtPoint(pt
);
4298 // Get the current mouse position.
4299 wxPoint
wxGetMousePosition()
4301 /* This crashes when used within wxHelpContext,
4302 so we have to use the X-specific implementation below.
4304 GdkModifierType *mask;
4305 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
4307 return wxPoint(x, y);
4311 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
4313 return wxPoint(-999, -999);
4315 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
4316 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
4317 Window rootReturn
, childReturn
;
4318 int rootX
, rootY
, winX
, winY
;
4319 unsigned int maskReturn
;
4321 XQueryPointer (display
,
4325 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
4326 return wxPoint(rootX
, rootY
);
4330 // ----------------------------------------------------------------------------
4332 // ----------------------------------------------------------------------------
4334 class wxWinModule
: public wxModule
4341 DECLARE_DYNAMIC_CLASS(wxWinModule
)
4344 IMPLEMENT_DYNAMIC_CLASS(wxWinModule
, wxModule
)
4346 bool wxWinModule::OnInit()
4348 // g_eraseGC = gdk_gc_new( GDK_ROOT_PARENT() );
4349 // gdk_gc_set_fill( g_eraseGC, GDK_SOLID );
4354 void wxWinModule::OnExit()
4357 gdk_gc_unref( g_eraseGC
);