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 // ----------------------------------------------------------------------------
1237 // mouse event processing helpers
1238 // ----------------------------------------------------------------------------
1240 // init wxMouseEvent with the info from gdk_event
1241 #define InitMouseEvent(win, event, gdk_event) \
1243 event.SetTimestamp( gdk_event->time ); \
1244 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
1245 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
1246 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
1247 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
1248 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
1249 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
1250 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
1252 wxPoint pt = win->GetClientAreaOrigin(); \
1253 event.m_x = (wxCoord)gdk_event->x - pt.x; \
1254 event.m_y = (wxCoord)gdk_event->y - pt.y; \
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 // find the window to send the mouse event too
1291 wxWindowGTK
*FindWindowForMouseEvent(wxWindowGTK
*win
, wxCoord
& x
, wxCoord
& y
)
1293 if (win
->m_wxwindow
)
1295 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1296 x
+= pizza
->xoffset
;
1297 y
+= pizza
->yoffset
;
1300 wxNode
*node
= win
->GetChildren().First();
1303 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1305 node
= node
->Next();
1306 if (!child
->IsShown())
1309 if (child
->IsTransparentForMouse())
1311 // wxStaticBox is transparent in the box itself
1312 int xx1
= child
->m_x
;
1313 int yy1
= child
->m_y
;
1314 int xx2
= child
->m_x
+ child
->m_width
;
1315 int yy2
= child
->m_x
+ child
->m_height
;
1318 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1320 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1322 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1324 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1335 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1336 (child
->m_x
<= x
) &&
1337 (child
->m_y
<= y
) &&
1338 (child
->m_x
+child
->m_width
>= x
) &&
1339 (child
->m_y
+child
->m_height
>= y
))
1352 //-----------------------------------------------------------------------------
1353 // "button_press_event"
1354 //-----------------------------------------------------------------------------
1356 static gint
gtk_window_button_press_callback( GtkWidget
*widget
,
1357 GdkEventButton
*gdk_event
,
1363 wxapp_install_idle_handler();
1366 wxPrintf( wxT("1) OnButtonPress from ") );
1367 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1368 wxPrintf( win->GetClassInfo()->GetClassName() );
1369 wxPrintf( wxT(".\n") );
1371 if (!win
->m_hasVMT
) return FALSE
;
1372 if (g_blockEventsOnDrag
) return TRUE
;
1373 if (g_blockEventsOnScroll
) return TRUE
;
1375 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1377 if (win
->m_wxwindow
&& (g_focusWindow
!= win
) && win
->AcceptsFocus())
1379 gtk_widget_grab_focus( win
->m_wxwindow
);
1381 wxPrintf( wxT("GrabFocus from ") );
1382 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1383 wxPrintf( win->GetClassInfo()->GetClassName() );
1384 wxPrintf( wxT(".\n") );
1388 wxEventType event_type
= wxEVT_NULL
;
1390 if (gdk_event
->button
== 1)
1392 switch (gdk_event
->type
)
1394 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1395 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1399 else if (gdk_event
->button
== 2)
1401 switch (gdk_event
->type
)
1403 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1404 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1408 else if (gdk_event
->button
== 3)
1410 switch (gdk_event
->type
)
1412 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1413 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1418 if ( event_type
== wxEVT_NULL
)
1420 // unknown mouse button or click type
1424 wxMouseEvent
event( event_type
);
1425 InitMouseEvent( win
, event
, gdk_event
);
1427 AdjustEventButtonState(event
);
1429 // wxListBox actually get mouse events from the item, so we need to give it
1430 // a chance to correct this
1431 win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
);
1433 // find the correct window to send the event too: it may be a different one
1434 // from the one which got it at GTK+ level because some control don't have
1435 // their own X window and thus cannot get any events.
1436 if ( !g_captureWindow
)
1437 win
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
);
1439 event
.SetEventObject( win
);
1441 gs_timeLastClick
= gdk_event
->time
;
1444 wxPrintf( wxT("2) OnButtonPress from ") );
1445 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1446 wxPrintf( win->GetClassInfo()->GetClassName() );
1447 wxPrintf( wxT(".\n") );
1450 if (win
->GetEventHandler()->ProcessEvent( event
))
1452 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1459 //-----------------------------------------------------------------------------
1460 // "button_release_event"
1461 //-----------------------------------------------------------------------------
1463 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1468 wxapp_install_idle_handler();
1470 if (!win
->m_hasVMT
) return FALSE
;
1471 if (g_blockEventsOnDrag
) return FALSE
;
1472 if (g_blockEventsOnScroll
) return FALSE
;
1474 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1477 printf( "OnButtonRelease from " );
1478 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1479 printf( win->GetClassInfo()->GetClassName() );
1483 wxEventType event_type
= wxEVT_NULL
;
1485 switch (gdk_event
->button
)
1487 case 1: event_type
= wxEVT_LEFT_UP
; break;
1488 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1489 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1490 default: return FALSE
;
1493 wxMouseEvent
event( event_type
);
1494 InitMouseEvent( win
, event
, gdk_event
);
1496 AdjustEventButtonState(event
);
1498 // same wxListBox hack as above
1499 win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
);
1501 if ( !g_captureWindow
)
1502 win
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
);
1504 event
.SetEventObject( win
);
1506 if (win
->GetEventHandler()->ProcessEvent( event
))
1508 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1515 //-----------------------------------------------------------------------------
1516 // "motion_notify_event"
1517 //-----------------------------------------------------------------------------
1519 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
,
1520 GdkEventMotion
*gdk_event
,
1526 wxapp_install_idle_handler();
1528 if (!win
->m_hasVMT
) return FALSE
;
1529 if (g_blockEventsOnDrag
) return FALSE
;
1530 if (g_blockEventsOnScroll
) return FALSE
;
1532 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1534 if (gdk_event
->is_hint
)
1538 GdkModifierType state
;
1539 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1545 printf( "OnMotion from " );
1546 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1547 printf( win->GetClassInfo()->GetClassName() );
1551 wxMouseEvent
event( wxEVT_MOTION
);
1552 InitMouseEvent(win
, event
, gdk_event
);
1554 if ( g_captureWindow
)
1556 // synthetize a mouse enter or leave event if needed
1557 GdkWindow
*winUnderMouse
= gdk_window_at_pointer(NULL
, NULL
);
1558 bool hasMouse
= winUnderMouse
== gdk_event
->window
;
1559 if ( hasMouse
!= g_captureWindowHasMouse
)
1561 // the mouse changed window
1562 g_captureWindowHasMouse
= hasMouse
;
1564 wxMouseEvent
event(g_captureWindowHasMouse
? wxEVT_ENTER_WINDOW
1565 : wxEVT_LEAVE_WINDOW
);
1566 InitMouseEvent(win
, event
, gdk_event
);
1567 event
.SetEventObject(win
);
1568 win
->GetEventHandler()->ProcessEvent(event
);
1573 win
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
);
1576 event
.SetEventObject( win
);
1578 if (win
->GetEventHandler()->ProcessEvent( event
))
1580 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1587 //-----------------------------------------------------------------------------
1589 //-----------------------------------------------------------------------------
1591 // send the wxChildFocusEvent and wxFocusEvent, common code of
1592 // gtk_window_focus_in_callback() and SetFocus()
1593 static bool DoSendFocusEvents(wxWindow
*win
)
1595 // Notify the parent keeping track of focus for the kbd navigation
1596 // purposes that we got it.
1597 wxChildFocusEvent
eventChildFocus(win
);
1598 (void)win
->GetEventHandler()->ProcessEvent(eventChildFocus
);
1600 wxFocusEvent
eventFocus(wxEVT_SET_FOCUS
, win
->GetId());
1601 eventFocus
.SetEventObject(win
);
1603 return win
->GetEventHandler()->ProcessEvent(eventFocus
);
1606 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
,
1607 GdkEvent
*WXUNUSED(event
),
1613 wxapp_install_idle_handler();
1615 if (!win
->m_hasVMT
) return FALSE
;
1616 if (g_blockEventsOnDrag
) return FALSE
;
1618 switch ( g_sendActivateEvent
)
1621 // we've got focus from outside, synthetize wxActivateEvent
1622 g_sendActivateEvent
= 1;
1626 // another our window just lost focus, it was already ours before
1627 // - don't send any wxActivateEvent
1628 g_sendActivateEvent
= -1;
1633 g_focusWindow
= win
;
1635 wxLogTrace(TRACE_FOCUS
,
1636 _T("%s: focus in"), win
->GetName().c_str());
1640 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1644 // caret needs to be informed about focus change
1645 wxCaret
*caret
= win
->GetCaret();
1648 caret
->OnSetFocus();
1650 #endif // wxUSE_CARET
1652 g_activeFrameLostFocus
= FALSE
;
1654 wxWindowGTK
*active
= wxGetTopLevelParent(win
);
1655 if ( active
!= g_activeFrame
)
1657 if ( g_activeFrame
)
1659 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame
);
1660 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
1661 event
.SetEventObject(g_activeFrame
);
1662 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1665 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active
);
1666 g_activeFrame
= active
;
1667 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId());
1668 event
.SetEventObject(g_activeFrame
);
1669 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1671 // Don't send focus events in addition to activate
1672 // if (win == g_activeFrame)
1676 // does the window itself think that it has the focus?
1677 if ( !win
->m_hasFocus
)
1679 // not yet, notify it
1680 win
->m_hasFocus
= TRUE
;
1682 if ( DoSendFocusEvents(win
) )
1684 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1692 //-----------------------------------------------------------------------------
1693 // "focus_out_event"
1694 //-----------------------------------------------------------------------------
1696 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEventFocus
*gdk_event
, wxWindowGTK
*win
)
1701 wxapp_install_idle_handler();
1703 if (!win
->m_hasVMT
) return FALSE
;
1704 if (g_blockEventsOnDrag
) return FALSE
;
1706 wxLogTrace( TRACE_FOCUS
,
1707 _T("%s: focus out"), win
->GetName().c_str() );
1709 if ( !g_activeFrameLostFocus
&& g_activeFrame
)
1711 // VZ: commenting this out because it does happen (although not easy
1712 // to reproduce, I only see it when using wxMiniFrame and not
1713 // always) and makes using Mahogany quite annoying
1715 wxASSERT_MSG( wxGetTopLevelParent(win
) == g_activeFrame
,
1716 wxT("unfocusing window that hasn't gained focus properly") )
1719 g_activeFrameLostFocus
= TRUE
;
1722 // if the focus goes out of our app alltogether, OnIdle() will send
1723 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1724 // g_sendActivateEvent to -1
1725 g_sendActivateEvent
= 0;
1727 wxWindowGTK
*winFocus
= wxFindFocusedChild(win
);
1731 g_focusWindow
= (wxWindowGTK
*)NULL
;
1739 // caret needs to be informed about focus change
1740 wxCaret
*caret
= win
->GetCaret();
1743 caret
->OnKillFocus();
1745 #endif // wxUSE_CARET
1747 // don't send the window a kill focus event if it thinks that it doesn't
1748 // have focus already
1749 if ( win
->m_hasFocus
)
1751 win
->m_hasFocus
= FALSE
;
1753 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1754 event
.SetEventObject( win
);
1756 if (win
->GetEventHandler()->ProcessEvent( event
))
1758 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1766 //-----------------------------------------------------------------------------
1767 // "enter_notify_event"
1768 //-----------------------------------------------------------------------------
1770 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1775 wxapp_install_idle_handler();
1777 if (!win
->m_hasVMT
) return FALSE
;
1778 if (g_blockEventsOnDrag
) return FALSE
;
1780 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1782 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1783 event
.SetTimestamp( gdk_event
->time
);
1784 event
.SetEventObject( win
);
1788 GdkModifierType state
= (GdkModifierType
)0;
1790 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1792 InitMouseEvent(win
, event
, gdk_event
);
1793 wxPoint pt
= win
->GetClientAreaOrigin();
1794 event
.m_x
= x
+ pt
.x
;
1795 event
.m_y
= y
+ pt
.y
;
1797 if (win
->GetEventHandler()->ProcessEvent( event
))
1799 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1806 //-----------------------------------------------------------------------------
1807 // "leave_notify_event"
1808 //-----------------------------------------------------------------------------
1810 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1815 wxapp_install_idle_handler();
1817 if (!win
->m_hasVMT
) return FALSE
;
1818 if (g_blockEventsOnDrag
) return FALSE
;
1820 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1822 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1823 event
.SetTimestamp( gdk_event
->time
);
1824 event
.SetEventObject( win
);
1828 GdkModifierType state
= (GdkModifierType
)0;
1830 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1832 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
) != 0;
1833 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
) != 0;
1834 event
.m_altDown
= (state
& GDK_MOD1_MASK
) != 0;
1835 event
.m_metaDown
= (state
& GDK_MOD2_MASK
) != 0;
1836 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
) != 0;
1837 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
) != 0;
1838 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
) != 0;
1840 wxPoint pt
= win
->GetClientAreaOrigin();
1841 event
.m_x
= x
+ pt
.x
;
1842 event
.m_y
= y
+ pt
.y
;
1844 if (win
->GetEventHandler()->ProcessEvent( event
))
1846 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1853 //-----------------------------------------------------------------------------
1854 // "value_changed" from m_vAdjust
1855 //-----------------------------------------------------------------------------
1857 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
,
1864 wxapp_install_idle_handler();
1866 if (g_blockEventsOnDrag
) return;
1868 if (!win
->m_hasVMT
) return;
1870 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1871 if (fabs(diff
) < 0.2) return;
1873 win
->m_oldVerticalPos
= adjust
->value
;
1875 GtkScrolledWindow
*sw
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1876 wxEventType command
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->vscrollbar
));
1878 int value
= (int)(adjust
->value
+0.5);
1880 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1881 event
.SetEventObject( win
);
1882 win
->GetEventHandler()->ProcessEvent( event
);
1885 //-----------------------------------------------------------------------------
1886 // "value_changed" from m_hAdjust
1887 //-----------------------------------------------------------------------------
1889 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
,
1896 wxapp_install_idle_handler();
1898 if (g_blockEventsOnDrag
) return;
1899 if (!win
->m_hasVMT
) return;
1901 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1902 if (fabs(diff
) < 0.2) return;
1904 GtkScrolledWindow
*sw
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1905 wxEventType command
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->hscrollbar
));
1907 win
->m_oldHorizontalPos
= adjust
->value
;
1909 int value
= (int)(adjust
->value
+0.5);
1911 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1912 event
.SetEventObject( win
);
1913 win
->GetEventHandler()->ProcessEvent( event
);
1916 //-----------------------------------------------------------------------------
1917 // "button_press_event" from scrollbar
1918 //-----------------------------------------------------------------------------
1920 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1921 GdkEventButton
*gdk_event
,
1927 wxapp_install_idle_handler();
1930 g_blockEventsOnScroll
= TRUE
;
1932 // FIXME: there is no 'slider' field in GTK+ 2.0 any more
1934 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1940 //-----------------------------------------------------------------------------
1941 // "button_release_event" from scrollbar
1942 //-----------------------------------------------------------------------------
1944 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1945 GdkEventButton
*WXUNUSED(gdk_event
),
1950 // don't test here as we can release the mouse while being over
1951 // a different window than the slider
1953 // if (gdk_event->window != widget->slider) return FALSE;
1955 g_blockEventsOnScroll
= FALSE
;
1957 if (win
->m_isScrolling
)
1959 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
1963 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1964 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1966 value
= (int)(win
->m_hAdjust
->value
+0.5);
1969 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1971 value
= (int)(win
->m_vAdjust
->value
+0.5);
1975 wxScrollWinEvent
event( command
, value
, dir
);
1976 event
.SetEventObject( win
);
1977 win
->GetEventHandler()->ProcessEvent( event
);
1980 win
->m_isScrolling
= FALSE
;
1985 // ----------------------------------------------------------------------------
1986 // this wxWindowBase function is implemented here (in platform-specific file)
1987 // because it is static and so couldn't be made virtual
1988 // ----------------------------------------------------------------------------
1990 wxWindow
*wxWindowBase::FindFocus()
1992 // the cast is necessary when we compile in wxUniversal mode
1993 return (wxWindow
*)g_focusWindow
;
1996 //-----------------------------------------------------------------------------
1997 // "realize" from m_widget
1998 //-----------------------------------------------------------------------------
2000 /* We cannot set colours and fonts before the widget has
2001 been realized, so we do this directly after realization. */
2004 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
2009 wxapp_install_idle_handler();
2011 if (win
->m_delayedBackgroundColour
)
2012 win
->GtkSetBackgroundColour( win
->GetBackgroundColour() );
2014 if (win
->m_delayedForegroundColour
)
2015 win
->GtkSetForegroundColour( win
->GetForegroundColour() );
2017 wxWindowCreateEvent
event( win
);
2018 event
.SetEventObject( win
);
2019 win
->GetEventHandler()->ProcessEvent( event
);
2024 //-----------------------------------------------------------------------------
2026 //-----------------------------------------------------------------------------
2029 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
2030 GtkAllocation
*WXUNUSED(alloc
),
2034 wxapp_install_idle_handler();
2036 if (!win
->m_hasScrolling
) return;
2038 int client_width
= 0;
2039 int client_height
= 0;
2040 win
->GetClientSize( &client_width
, &client_height
);
2041 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
2044 win
->m_oldClientWidth
= client_width
;
2045 win
->m_oldClientHeight
= client_height
;
2047 if (!win
->m_nativeSizeEvent
)
2049 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
2050 event
.SetEventObject( win
);
2051 win
->GetEventHandler()->ProcessEvent( event
);
2057 #define WXUNUSED_UNLESS_XIM(param) param
2059 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2062 /* Resize XIM window */
2065 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2066 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
2067 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2070 wxapp_install_idle_handler();
2076 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
2080 gdk_window_get_size (widget
->window
, &width
, &height
);
2081 win
->m_icattr
->preedit_area
.width
= width
;
2082 win
->m_icattr
->preedit_area
.height
= height
;
2083 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2088 //-----------------------------------------------------------------------------
2089 // "realize" from m_wxwindow
2090 //-----------------------------------------------------------------------------
2092 /* Initialize XIM support */
2095 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2096 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2099 wxapp_install_idle_handler();
2102 if (win
->m_ic
) return FALSE
;
2103 if (!widget
) return FALSE
;
2104 if (!gdk_im_ready()) return FALSE
;
2106 win
->m_icattr
= gdk_ic_attr_new();
2107 if (!win
->m_icattr
) return FALSE
;
2111 GdkColormap
*colormap
;
2112 GdkICAttr
*attr
= win
->m_icattr
;
2113 unsigned attrmask
= GDK_IC_ALL_REQ
;
2115 GdkIMStyle supported_style
= (GdkIMStyle
)
2116 (GDK_IM_PREEDIT_NONE
|
2117 GDK_IM_PREEDIT_NOTHING
|
2118 GDK_IM_PREEDIT_POSITION
|
2119 GDK_IM_STATUS_NONE
|
2120 GDK_IM_STATUS_NOTHING
);
2122 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2123 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2125 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2126 attr
->client_window
= widget
->window
;
2128 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2129 gtk_widget_get_default_colormap ())
2131 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2132 attr
->preedit_colormap
= colormap
;
2135 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2136 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2137 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2138 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2140 switch (style
& GDK_IM_PREEDIT_MASK
)
2142 case GDK_IM_PREEDIT_POSITION
:
2143 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2145 g_warning ("over-the-spot style requires fontset");
2149 gdk_window_get_size (widget
->window
, &width
, &height
);
2151 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2152 attr
->spot_location
.x
= 0;
2153 attr
->spot_location
.y
= height
;
2154 attr
->preedit_area
.x
= 0;
2155 attr
->preedit_area
.y
= 0;
2156 attr
->preedit_area
.width
= width
;
2157 attr
->preedit_area
.height
= height
;
2158 attr
->preedit_fontset
= widget
->style
->font
;
2163 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2165 if (win
->m_ic
== NULL
)
2166 g_warning ("Can't create input context.");
2169 mask
= gdk_window_get_events (widget
->window
);
2170 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2171 gdk_window_set_events (widget
->window
, mask
);
2173 if (GTK_WIDGET_HAS_FOCUS(widget
))
2174 gdk_im_begin (win
->m_ic
, widget
->window
);
2181 //-----------------------------------------------------------------------------
2182 // InsertChild for wxWindowGTK.
2183 //-----------------------------------------------------------------------------
2185 /* Callback for wxWindowGTK. This very strange beast has to be used because
2186 * C++ has no virtual methods in a constructor. We have to emulate a
2187 * virtual function here as wxNotebook requires a different way to insert
2188 * a child in it. I had opted for creating a wxNotebookPage window class
2189 * which would have made this superfluous (such in the MDI window system),
2190 * but no-one was listening to me... */
2192 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child
)
2194 /* the window might have been scrolled already, do we
2195 have to adapt the position */
2196 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2197 child
->m_x
+= pizza
->xoffset
;
2198 child
->m_y
+= pizza
->yoffset
;
2200 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2201 GTK_WIDGET(child
->m_widget
),
2208 //-----------------------------------------------------------------------------
2210 //-----------------------------------------------------------------------------
2212 wxWindow
*wxGetActiveWindow()
2214 return wxWindow::FindFocus();
2217 //-----------------------------------------------------------------------------
2219 //-----------------------------------------------------------------------------
2221 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
2223 #ifdef __WXUNIVERSAL__
2224 IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
)
2226 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2227 #endif // __WXUNIVERSAL__/__WXGTK__
2229 void wxWindowGTK::Init()
2235 m_widget
= (GtkWidget
*) NULL
;
2236 m_wxwindow
= (GtkWidget
*) NULL
;
2237 m_focusWidget
= (GtkWidget
*) NULL
;
2247 m_needParent
= TRUE
;
2248 m_isBeingDeleted
= FALSE
;
2251 m_nativeSizeEvent
= FALSE
;
2253 m_hasScrolling
= FALSE
;
2254 m_isScrolling
= FALSE
;
2256 m_hAdjust
= (GtkAdjustment
*) NULL
;
2257 m_vAdjust
= (GtkAdjustment
*) NULL
;
2258 m_oldHorizontalPos
= 0.0;
2259 m_oldVerticalPos
= 0.0;
2262 m_widgetStyle
= (GtkStyle
*) NULL
;
2264 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2266 m_isRadioButton
= FALSE
;
2268 m_acceptsFocus
= FALSE
;
2271 m_clipPaintRegion
= FALSE
;
2273 m_cursor
= *wxSTANDARD_CURSOR
;
2275 m_delayedForegroundColour
= FALSE
;
2276 m_delayedBackgroundColour
= FALSE
;
2279 m_ic
= (GdkIC
*) NULL
;
2280 m_icattr
= (GdkICAttr
*) NULL
;
2284 wxWindowGTK::wxWindowGTK()
2289 wxWindowGTK::wxWindowGTK( wxWindow
*parent
,
2294 const wxString
&name
)
2298 Create( parent
, id
, pos
, size
, style
, name
);
2301 bool wxWindowGTK::Create( wxWindow
*parent
,
2306 const wxString
&name
)
2308 if (!PreCreation( parent
, pos
, size
) ||
2309 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2311 wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
2315 m_insertCallback
= wxInsertChildInWindow
;
2317 // always needed for background clearing
2318 m_delayedBackgroundColour
= TRUE
;
2320 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2321 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2323 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2325 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2326 scroll_class
->scrollbar_spacing
= 0;
2328 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2330 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2331 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2333 m_wxwindow
= gtk_pizza_new();
2335 #ifndef __WXUNIVERSAL__
2336 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2338 if (HasFlag(wxRAISED_BORDER
))
2340 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2342 else if (HasFlag(wxSUNKEN_BORDER
))
2344 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2346 else if (HasFlag(wxSIMPLE_BORDER
))
2348 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2352 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2354 #endif // __WXUNIVERSAL__
2356 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2358 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2359 m_acceptsFocus
= TRUE
;
2361 // I _really_ don't want scrollbars in the beginning
2362 m_vAdjust
->lower
= 0.0;
2363 m_vAdjust
->upper
= 1.0;
2364 m_vAdjust
->value
= 0.0;
2365 m_vAdjust
->step_increment
= 1.0;
2366 m_vAdjust
->page_increment
= 1.0;
2367 m_vAdjust
->page_size
= 5.0;
2368 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2369 m_hAdjust
->lower
= 0.0;
2370 m_hAdjust
->upper
= 1.0;
2371 m_hAdjust
->value
= 0.0;
2372 m_hAdjust
->step_increment
= 1.0;
2373 m_hAdjust
->page_increment
= 1.0;
2374 m_hAdjust
->page_size
= 5.0;
2375 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2377 // these handlers block mouse events to any window during scrolling such as
2378 // motion events and prevent GTK and wxWindows from fighting over where the
2381 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2382 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2384 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2385 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2387 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2388 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2390 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2391 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2393 // these handlers get notified when screen updates are required either when
2394 // scrolling or when the window size (and therefore scrollbar configuration)
2397 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2398 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2399 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2400 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2402 gtk_widget_show( m_wxwindow
);
2405 m_parent
->DoAddChild( this );
2407 m_focusWidget
= m_wxwindow
;
2416 wxWindowGTK::~wxWindowGTK()
2418 if (g_focusWindow
== this)
2419 g_focusWindow
= NULL
;
2421 if (g_activeFrame
== this)
2422 g_activeFrame
= NULL
;
2424 if ( g_delayedFocus
== this )
2425 g_delayedFocus
= NULL
;
2427 m_isBeingDeleted
= TRUE
;
2436 m_parent
->RemoveChild( this );
2440 gdk_ic_destroy (m_ic
);
2442 gdk_ic_attr_destroy (m_icattr
);
2447 #if DISABLE_STYLE_IF_BROKEN_THEME
2448 // don't delete if it's a pixmap theme style
2449 if (!m_widgetStyle
->engine_data
)
2450 gtk_style_unref( m_widgetStyle
);
2452 m_widgetStyle
= (GtkStyle
*) NULL
;
2457 gtk_widget_destroy( m_wxwindow
);
2458 m_wxwindow
= (GtkWidget
*) NULL
;
2463 gtk_widget_destroy( m_widget
);
2464 m_widget
= (GtkWidget
*) NULL
;
2468 bool wxWindowGTK::PreCreation( wxWindowGTK
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2470 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2472 /* this turns -1 into 20 so that a minimal window is
2473 visible even although -1,-1 has been given as the
2474 size of the window. the same trick is used in other
2475 ports and should make debugging easier */
2476 m_width
= WidthDefault(size
.x
);
2477 m_height
= HeightDefault(size
.y
);
2482 /* some reasonable defaults */
2487 m_x
= (gdk_screen_width () - m_width
) / 2;
2488 if (m_x
< 10) m_x
= 10;
2492 m_y
= (gdk_screen_height () - m_height
) / 2;
2493 if (m_y
< 10) m_y
= 10;
2500 void wxWindowGTK::PostCreation()
2502 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2508 // these get reported to wxWindows -> wxPaintEvent
2510 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2512 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2513 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2516 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2517 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2519 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2521 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2522 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2525 gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow
), HasFlag( wxNO_FULL_REPAINT_ON_RESIZE
) );
2529 // these are called when the "sunken" or "raised" borders are drawn
2530 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2531 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2534 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2535 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2541 if (m_focusWidget
== NULL
)
2542 m_focusWidget
= m_widget
;
2544 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event",
2545 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2547 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event",
2548 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2550 // connect to the various key and mouse handlers
2552 GtkWidget
*connect_widget
= GetConnectWidget();
2554 ConnectWidget( connect_widget
);
2556 /* We cannot set colours, fonts and cursors before the widget has
2557 been realized, so we do this directly after realization */
2558 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2559 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2563 // Catch native resize events
2564 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2565 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2567 // Initialize XIM support
2568 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2569 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2571 // And resize XIM window
2572 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2573 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2576 if (!GTK_IS_COMBO(m_widget
))
2578 // This is needed if we want to add our windows into native
2579 // GTK control, such as the toolbar. With this callback, the
2580 // toolbar gets to know the correct size (the one set by the
2581 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2582 // when moving to GTK 2.0.
2583 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2584 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2590 void wxWindowGTK::ConnectWidget( GtkWidget
*widget
)
2592 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2593 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2595 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2596 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2598 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2599 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2601 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2602 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2604 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2605 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2607 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2608 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2610 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2611 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2614 bool wxWindowGTK::Destroy()
2616 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2620 return wxWindowBase::Destroy();
2623 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
)
2625 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2628 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2630 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2631 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") );
2634 printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
2637 if (m_resizing
) return; /* I don't like recursions */
2640 int currentX
, currentY
;
2641 GetPosition(¤tX
, ¤tY
);
2646 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
2648 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2650 /* don't set the size for children of wxNotebook, just take the values. */
2658 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2659 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2661 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2662 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2663 if (width
!= -1) m_width
= width
;
2664 if (height
!= -1) m_height
= height
;
2668 m_x
= x
+ pizza
->xoffset
;
2669 m_y
= y
+ pizza
->yoffset
;
2674 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2676 if (width
== -1) m_width
= 80;
2679 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2681 if (height
== -1) m_height
= 26;
2684 int minWidth
= GetMinWidth(),
2685 minHeight
= GetMinHeight(),
2686 maxWidth
= GetMaxWidth(),
2687 maxHeight
= GetMaxHeight();
2689 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
2690 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
2691 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
2692 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
2695 int bottom_border
= 0;
2698 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2700 /* the default button has a border around it */
2706 DoMoveWindow( m_x
-border
,
2709 m_height
+border
+bottom_border
);
2714 /* Sometimes the client area changes size without the
2715 whole windows's size changing, but if the whole
2716 windows's size doesn't change, no wxSizeEvent will
2717 normally be sent. Here we add an extra test if
2718 the client test has been changed and this will
2720 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2724 wxPrintf( "OnSize sent from " );
2725 if (GetClassInfo() && GetClassInfo()->GetClassName())
2726 wxPrintf( GetClassInfo()->GetClassName() );
2727 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2730 if (!m_nativeSizeEvent
)
2732 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2733 event
.SetEventObject( this );
2734 GetEventHandler()->ProcessEvent( event
);
2740 void wxWindowGTK::OnInternalIdle()
2742 // Update invalidated regions.
2745 // Synthetize activate events.
2746 if ( g_sendActivateEvent
!= -1 )
2748 bool activate
= g_sendActivateEvent
!= 0;
2751 g_sendActivateEvent
= -1;
2753 wxTheApp
->SetActive(activate
, (wxWindow
*)g_focusWindowLast
);
2756 if ( g_activeFrameLostFocus
)
2758 if ( g_activeFrame
)
2760 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame
);
2761 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
2762 event
.SetEventObject(g_activeFrame
);
2763 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
2764 g_activeFrame
= NULL
;
2766 g_activeFrameLostFocus
= FALSE
;
2769 wxCursor cursor
= m_cursor
;
2770 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2774 /* I now set the cursor anew in every OnInternalIdle call
2775 as setting the cursor in a parent window also effects the
2776 windows above so that checking for the current cursor is
2781 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2783 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2785 if (!g_globalCursor
.Ok())
2786 cursor
= *wxSTANDARD_CURSOR
;
2788 window
= m_widget
->window
;
2789 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2790 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2796 GdkWindow
*window
= m_widget
->window
;
2797 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2798 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2806 void wxWindowGTK::DoGetSize( int *width
, int *height
) const
2808 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2810 if (width
) (*width
) = m_width
;
2811 if (height
) (*height
) = m_height
;
2814 void wxWindowGTK::DoSetClientSize( int width
, int height
)
2816 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2820 SetSize( width
, height
);
2827 #ifndef __WXUNIVERSAL__
2828 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2830 /* when using GTK 1.2 we set the shadow border size to 2 */
2834 if (HasFlag(wxSIMPLE_BORDER
))
2836 /* when using GTK 1.2 we set the simple border size to 1 */
2840 #endif // __WXUNIVERSAL__
2844 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2846 GtkRequisition vscroll_req
;
2847 vscroll_req
.width
= 2;
2848 vscroll_req
.height
= 2;
2849 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2850 (scroll_window
->vscrollbar
, &vscroll_req
);
2852 GtkRequisition hscroll_req
;
2853 hscroll_req
.width
= 2;
2854 hscroll_req
.height
= 2;
2855 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2856 (scroll_window
->hscrollbar
, &hscroll_req
);
2858 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2860 if (scroll_window
->vscrollbar_visible
)
2862 dw
+= vscroll_req
.width
;
2863 dw
+= scroll_class
->scrollbar_spacing
;
2866 if (scroll_window
->hscrollbar_visible
)
2868 dh
+= hscroll_req
.height
;
2869 dh
+= scroll_class
->scrollbar_spacing
;
2873 SetSize( width
+dw
, height
+dh
);
2877 void wxWindowGTK::DoGetClientSize( int *width
, int *height
) const
2879 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2883 if (width
) (*width
) = m_width
;
2884 if (height
) (*height
) = m_height
;
2891 #ifndef __WXUNIVERSAL__
2892 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2894 /* when using GTK 1.2 we set the shadow border size to 2 */
2898 if (HasFlag(wxSIMPLE_BORDER
))
2900 /* when using GTK 1.2 we set the simple border size to 1 */
2904 #endif // __WXUNIVERSAL__
2908 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2910 GtkRequisition vscroll_req
;
2911 vscroll_req
.width
= 2;
2912 vscroll_req
.height
= 2;
2913 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2914 (scroll_window
->vscrollbar
, &vscroll_req
);
2916 GtkRequisition hscroll_req
;
2917 hscroll_req
.width
= 2;
2918 hscroll_req
.height
= 2;
2919 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2920 (scroll_window
->hscrollbar
, &hscroll_req
);
2922 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2924 if (scroll_window
->vscrollbar_visible
)
2926 dw
+= vscroll_req
.width
;
2927 dw
+= scroll_class
->scrollbar_spacing
;
2930 if (scroll_window
->hscrollbar_visible
)
2932 dh
+= hscroll_req
.height
;
2933 dh
+= scroll_class
->scrollbar_spacing
;
2937 if (width
) (*width
) = m_width
- dw
;
2938 if (height
) (*height
) = m_height
- dh
;
2942 printf( "GetClientSize, name %s ", GetName().c_str() );
2943 if (width) printf( " width = %d", (*width) );
2944 if (height) printf( " height = %d", (*height) );
2949 void wxWindowGTK::DoGetPosition( int *x
, int *y
) const
2951 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2955 if (m_parent
&& m_parent
->m_wxwindow
)
2957 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2958 dx
= pizza
->xoffset
;
2959 dy
= pizza
->yoffset
;
2962 if (x
) (*x
) = m_x
- dx
;
2963 if (y
) (*y
) = m_y
- dy
;
2966 void wxWindowGTK::DoClientToScreen( int *x
, int *y
) const
2968 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2970 if (!m_widget
->window
) return;
2972 GdkWindow
*source
= (GdkWindow
*) NULL
;
2974 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2976 source
= m_widget
->window
;
2980 gdk_window_get_origin( source
, &org_x
, &org_y
);
2984 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2986 org_x
+= m_widget
->allocation
.x
;
2987 org_y
+= m_widget
->allocation
.y
;
2995 void wxWindowGTK::DoScreenToClient( int *x
, int *y
) const
2997 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2999 if (!m_widget
->window
) return;
3001 GdkWindow
*source
= (GdkWindow
*) NULL
;
3003 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3005 source
= m_widget
->window
;
3009 gdk_window_get_origin( source
, &org_x
, &org_y
);
3013 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3015 org_x
+= m_widget
->allocation
.x
;
3016 org_y
+= m_widget
->allocation
.y
;
3024 bool wxWindowGTK::Show( bool show
)
3026 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3028 if (!wxWindowBase::Show(show
))
3035 gtk_widget_show( m_widget
);
3037 gtk_widget_hide( m_widget
);
3042 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
)
3044 win
->OnParentEnable(enable
);
3046 // Recurse, so that children have the opportunity to Do The Right Thing
3047 // and reset colours that have been messed up by a parent's (really ancestor's)
3049 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
3051 node
= node
->GetNext() )
3053 wxWindow
*child
= node
->GetData();
3054 if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
)))
3055 wxWindowNotifyEnable(child
, enable
);
3059 bool wxWindowGTK::Enable( bool enable
)
3061 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3063 if (!wxWindowBase::Enable(enable
))
3069 gtk_widget_set_sensitive( m_widget
, enable
);
3071 gtk_widget_set_sensitive( m_wxwindow
, enable
);
3073 wxWindowNotifyEnable(this, enable
);
3078 int wxWindowGTK::GetCharHeight() const
3080 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
3082 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
3084 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3086 return font
->ascent
+ font
->descent
;
3089 int wxWindowGTK::GetCharWidth() const
3091 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
3093 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
3095 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3097 return gdk_string_width( font
, "H" );
3100 void wxWindowGTK::GetTextExtent( const wxString
& string
,
3104 int *externalLeading
,
3105 const wxFont
*theFont
) const
3107 wxFont fontToUse
= m_font
;
3108 if (theFont
) fontToUse
= *theFont
;
3110 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
3112 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
3113 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
3114 if (y
) (*y
) = font
->ascent
+ font
->descent
;
3115 if (descent
) (*descent
) = font
->descent
;
3116 if (externalLeading
) (*externalLeading
) = 0; // ??
3119 void wxWindowGTK::SetFocus()
3121 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3125 // don't do anything if we already have focus
3131 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3133 gtk_widget_grab_focus (m_wxwindow
);
3138 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
3140 if (!GTK_WIDGET_REALIZED(m_widget
))
3142 // we can't set the focus to the widget now so we remember that
3143 // it should be focused and will do it later, during the idle
3144 // time, as soon as we can
3145 wxLogTrace(TRACE_FOCUS
,
3146 _T("Delaying setting focus to %s(%s)"),
3147 GetClassInfo()->GetClassName(), GetLabel().c_str());
3149 g_delayedFocus
= this;
3153 wxLogTrace(TRACE_FOCUS
,
3154 _T("Setting focus to %s(%s)"),
3155 GetClassInfo()->GetClassName(), GetLabel().c_str());
3157 gtk_widget_grab_focus (m_widget
);
3160 else if (GTK_IS_CONTAINER(m_widget
))
3162 SET_CONTAINER_FOCUS( m_widget
, GTK_DIR_TAB_FORWARD
);
3166 wxLogTrace(TRACE_FOCUS
,
3167 _T("Can't set focus to %s(%s)"),
3168 GetClassInfo()->GetClassName(), GetLabel().c_str());
3173 bool wxWindowGTK::AcceptsFocus() const
3175 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3178 bool wxWindowGTK::Reparent( wxWindowBase
*newParentBase
)
3180 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3182 wxWindowGTK
*oldParent
= m_parent
,
3183 *newParent
= (wxWindowGTK
*)newParentBase
;
3185 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3187 if ( !wxWindowBase::Reparent(newParent
) )
3190 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3192 /* prevent GTK from deleting the widget arbitrarily */
3193 gtk_widget_ref( m_widget
);
3197 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3200 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3204 /* insert GTK representation */
3205 (*(newParent
->m_insertCallback
))(newParent
, this);
3208 /* reverse: prevent GTK from deleting the widget arbitrarily */
3209 gtk_widget_unref( m_widget
);
3214 void wxWindowGTK::DoAddChild(wxWindowGTK
*child
)
3216 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3218 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3220 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3225 /* insert GTK representation */
3226 (*m_insertCallback
)(this, child
);
3229 void wxWindowGTK::Raise()
3231 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3233 if (!m_widget
->window
) return;
3235 gdk_window_raise( m_widget
->window
);
3238 void wxWindowGTK::Lower()
3240 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3242 if (!m_widget
->window
) return;
3244 gdk_window_lower( m_widget
->window
);
3247 bool wxWindowGTK::SetCursor( const wxCursor
&cursor
)
3249 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3251 if (cursor
== m_cursor
)
3255 wxapp_install_idle_handler();
3257 if (cursor
== wxNullCursor
)
3258 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3260 return wxWindowBase::SetCursor( cursor
);
3263 void wxWindowGTK::WarpPointer( int x
, int y
)
3265 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3267 // We provide this function ourselves as it is
3268 // missing in GDK (top of this file).
3270 GdkWindow
*window
= (GdkWindow
*) NULL
;
3272 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3274 window
= GetConnectWidget()->window
;
3277 gdk_window_warp_pointer( window
, x
, y
);
3280 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect
*rect
)
3282 if (!m_widget
) return;
3283 if (!m_widget
->window
) return;
3287 wxapp_install_idle_handler();
3289 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3293 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3294 m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
3298 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3299 m_clearRegion
.Clear();
3300 m_clearRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height
);
3308 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3309 m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
3313 GdkRectangle gdk_rect
;
3314 gdk_rect
.x
= rect
->x
;
3315 gdk_rect
.y
= rect
->y
;
3316 gdk_rect
.width
= rect
->width
;
3317 gdk_rect
.height
= rect
->height
;
3318 gtk_widget_draw( m_widget
, &gdk_rect
);
3325 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3326 m_updateRegion
.Clear();
3327 m_updateRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height
);
3331 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3339 GdkRectangle gdk_rect
;
3340 gdk_rect
.x
= rect
->x
;
3341 gdk_rect
.y
= rect
->y
;
3342 gdk_rect
.width
= rect
->width
;
3343 gdk_rect
.height
= rect
->height
;
3344 gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, &gdk_rect
, TRUE
);
3348 gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, NULL
, TRUE
);
3354 void wxWindowGTK::Update()
3359 void wxWindowGTK::GtkUpdate()
3362 if (m_wxwindow
&& GTK_PIZZA(m_wxwindow
)->bin_window
)
3363 gdk_window_process_updates( GTK_PIZZA(m_wxwindow
)->bin_window
, FALSE
);
3366 if (!m_updateRegion
.IsEmpty())
3367 GtkSendPaintEvents();
3370 void wxWindowGTK::GtkSendPaintEvents()
3374 m_clearRegion
.Clear();
3375 m_updateRegion
.Clear();
3379 // widget to draw on
3380 GtkPizza
*pizza
= GTK_PIZZA (m_wxwindow
);
3382 // Clip to paint region in wxClientDC
3383 m_clipPaintRegion
= TRUE
;
3385 if (GetThemeEnabled())
3387 // find ancestor from which to steal background
3388 wxWindow
*parent
= GetParent();
3389 while (parent
&& !parent
->IsTopLevel())
3390 parent
= parent
->GetParent();
3392 parent
= (wxWindow
*)this;
3394 wxRegionIterator
upd( m_updateRegion
);
3398 rect
.x
= upd
.GetX();
3399 rect
.y
= upd
.GetY();
3400 rect
.width
= upd
.GetWidth();
3401 rect
.height
= upd
.GetHeight();
3403 gtk_paint_flat_box( parent
->m_widget
->style
,
3416 // if (!m_clearRegion.IsEmpty()) // always send an erase event
3418 wxWindowDC
dc( (wxWindow
*)this );
3419 dc
.SetClippingRegion( m_clearRegion
);
3421 wxEraseEvent
erase_event( GetId(), &dc
);
3422 erase_event
.SetEventObject( this );
3424 if (!GetEventHandler()->ProcessEvent(erase_event
))
3428 g_eraseGC
= gdk_gc_new( pizza
->bin_window
);
3429 gdk_gc_set_fill( g_eraseGC
, GDK_SOLID
);
3431 gdk_gc_set_foreground( g_eraseGC
, m_backgroundColour
.GetColor() );
3433 wxRegionIterator
upd( m_clearRegion
);
3436 gdk_draw_rectangle( pizza
->bin_window
, g_eraseGC
, 1,
3437 upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
3441 m_clearRegion
.Clear();
3444 wxNcPaintEvent
nc_paint_event( GetId() );
3445 nc_paint_event
.SetEventObject( this );
3446 GetEventHandler()->ProcessEvent( nc_paint_event
);
3448 wxPaintEvent
paint_event( GetId() );
3449 paint_event
.SetEventObject( this );
3450 GetEventHandler()->ProcessEvent( paint_event
);
3452 m_clipPaintRegion
= FALSE
;
3454 #ifndef __WXUNIVERSAL__
3456 // The following code will result in all window-less widgets
3457 // being redrawn because the wxWindows class is allowed to
3458 // paint over the window-less widgets.
3460 GList
*children
= pizza
->children
;
3463 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
3464 children
= children
->next
;
3466 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
3467 GTK_WIDGET_DRAWABLE (child
->widget
))
3469 // Get intersection of widget area and update region
3470 wxRegion
region( m_updateRegion
);
3472 GdkEventExpose gdk_event
;
3473 gdk_event
.type
= GDK_EXPOSE
;
3474 gdk_event
.window
= pizza
->bin_window
;
3475 gdk_event
.count
= 0;
3477 wxRegionIterator
upd( m_updateRegion
);
3481 rect
.x
= upd
.GetX();
3482 rect
.y
= upd
.GetY();
3483 rect
.width
= upd
.GetWidth();
3484 rect
.height
= upd
.GetHeight();
3486 if (gtk_widget_intersect (child
->widget
, &rect
, &gdk_event
.area
))
3488 gtk_widget_event (child
->widget
, (GdkEvent
*) &gdk_event
);
3498 m_updateRegion
.Clear();
3501 void wxWindowGTK::Clear()
3503 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3505 if (m_wxwindow
&& m_wxwindow
->window
)
3507 m_clearRegion
.Clear();
3508 wxSize
size( GetClientSize() );
3509 m_clearRegion
.Union( 0,0,size
.x
,size
.y
);
3511 // Better do this in idle?
3517 void wxWindowGTK::DoSetToolTip( wxToolTip
*tip
)
3519 wxWindowBase::DoSetToolTip(tip
);
3522 m_tooltip
->Apply( (wxWindow
*)this );
3525 void wxWindowGTK::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3527 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3529 #endif // wxUSE_TOOLTIPS
3531 void wxWindowGTK::GtkSetBackgroundColour( const wxColour
&colour
)
3533 GdkWindow
*window
= (GdkWindow
*) NULL
;
3535 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3537 window
= GetConnectWidget()->window
;
3541 // We need the pixel value e.g. for background clearing.
3542 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3546 // wxMSW doesn't clear the window here, either.
3547 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3553 bool wxWindowGTK::SetBackgroundColour( const wxColour
&colour
)
3555 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3557 if (!wxWindowBase::SetBackgroundColour(colour
))
3560 GdkWindow
*window
= (GdkWindow
*) NULL
;
3562 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3564 window
= GetConnectWidget()->window
;
3568 // indicate that a new style has been set
3569 // but it couldn't get applied as the
3570 // widget hasn't been realized yet.
3571 m_delayedBackgroundColour
= TRUE
;
3576 GtkSetBackgroundColour( colour
);
3582 void wxWindowGTK::GtkSetForegroundColour( const wxColour
&colour
)
3584 GdkWindow
*window
= (GdkWindow
*) NULL
;
3586 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3588 window
= GetConnectWidget()->window
;
3595 bool wxWindowGTK::SetForegroundColour( const wxColour
&colour
)
3597 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3599 if (!wxWindowBase::SetForegroundColour(colour
))
3601 // don't leave if the GTK widget has just
3603 if (!m_delayedForegroundColour
) return FALSE
;
3606 GdkWindow
*window
= (GdkWindow
*) NULL
;
3608 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3610 window
= GetConnectWidget()->window
;
3614 // indicate that a new style has been set
3615 // but it couldn't get applied as the
3616 // widget hasn't been realized yet.
3617 m_delayedForegroundColour
= TRUE
;
3621 GtkSetForegroundColour( colour
);
3627 GtkStyle
*wxWindowGTK::GetWidgetStyle()
3631 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3633 // FIXME: no more klass in 2.0
3635 remake
->klass
= m_widgetStyle
->klass
;
3638 gtk_style_unref( m_widgetStyle
);
3639 m_widgetStyle
= remake
;
3643 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3646 def
= gtk_widget_get_default_style();
3648 m_widgetStyle
= gtk_style_copy( def
);
3650 // FIXME: no more klass in 2.0
3652 m_widgetStyle
->klass
= def
->klass
;
3656 return m_widgetStyle
;
3659 void wxWindowGTK::SetWidgetStyle()
3661 #if DISABLE_STYLE_IF_BROKEN_THEME
3662 if (m_widget
->style
->engine_data
)
3664 static bool s_warningPrinted
= FALSE
;
3665 if (!s_warningPrinted
)
3667 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3668 s_warningPrinted
= TRUE
;
3670 m_widgetStyle
= m_widget
->style
;
3675 GtkStyle
*style
= GetWidgetStyle();
3677 if (m_font
!= wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT
))
3679 SET_STYLE_FONT(style
, m_font
.GetInternalFont( 1.0 ));
3682 if (m_foregroundColour
.Ok())
3684 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3685 if (m_foregroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT
))
3687 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3688 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3689 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3693 // Try to restore the gtk default style. This is still a little
3694 // oversimplified for what is probably really needed here for controls
3695 // other than buttons, but is better than not being able to (re)set a
3696 // control's foreground colour to *wxBLACK -- RL
3697 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3700 def
= gtk_widget_get_default_style();
3702 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3703 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3704 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3708 if (m_backgroundColour
.Ok())
3710 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3711 if (m_backgroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
))
3713 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3714 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3715 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3716 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3717 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3718 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3719 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3720 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3724 // Try to restore the gtk default style. This is still a little
3725 // oversimplified for what is probably really needed here for controls
3726 // other than buttons, but is better than not being able to (re)set a
3727 // control's background colour to default grey and means resetting a
3728 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3730 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3733 def
= gtk_widget_get_default_style();
3735 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3736 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3737 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3738 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3739 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3740 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3741 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3742 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3747 void wxWindowGTK::ApplyWidgetStyle()
3751 //-----------------------------------------------------------------------------
3752 // Pop-up menu stuff
3753 //-----------------------------------------------------------------------------
3755 #if wxUSE_MENUS_NATIVE
3758 void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3760 *is_waiting
= FALSE
;
3763 static void SetInvokingWindow( wxMenu
*menu
, wxWindowGTK
*win
)
3765 menu
->SetInvokingWindow( win
);
3766 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3769 wxMenuItem
*menuitem
= node
->GetData();
3770 if (menuitem
->IsSubMenu())
3772 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3775 node
= node
->GetNext();
3779 // used to pass the coordinates from wxWindowGTK::DoPopupMenu() to
3780 // wxPopupMenuPositionCallback()
3782 // should be safe even in the MT case as the user can hardly popup 2 menus
3783 // simultaneously, can he?
3784 static gint gs_pop_x
= 0;
3785 static gint gs_pop_y
= 0;
3787 extern "C" void wxPopupMenuPositionCallback( GtkMenu
*menu
,
3790 gboolean
* WXUNUSED(whatever
),
3792 gpointer
WXUNUSED(user_data
) )
3794 // ensure that the menu appears entirely on screen
3796 gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
);
3798 wxSize sizeScreen
= wxGetDisplaySize();
3800 gint xmax
= sizeScreen
.x
- req
.width
,
3801 ymax
= sizeScreen
.y
- req
.height
;
3803 *x
= gs_pop_x
< xmax
? gs_pop_x
: xmax
;
3804 *y
= gs_pop_y
< ymax
? gs_pop_y
: ymax
;
3807 bool wxWindowGTK::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3809 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3811 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3813 SetInvokingWindow( menu
, this );
3819 ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3821 bool is_waiting
= TRUE
;
3823 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
),
3825 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
),
3826 (gpointer
)&is_waiting
);
3829 GTK_MENU(menu
->m_menu
),
3830 (GtkWidget
*) NULL
, // parent menu shell
3831 (GtkWidget
*) NULL
, // parent menu item
3832 wxPopupMenuPositionCallback
, // function to position it
3833 NULL
, // client data
3834 0, // button used to activate it
3835 gs_timeLastClick
// the time of activation
3840 while (gtk_events_pending())
3841 gtk_main_iteration();
3847 #endif // wxUSE_MENUS_NATIVE
3849 #if wxUSE_DRAG_AND_DROP
3851 void wxWindowGTK::SetDropTarget( wxDropTarget
*dropTarget
)
3853 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3855 GtkWidget
*dnd_widget
= GetConnectWidget();
3857 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3859 if (m_dropTarget
) delete m_dropTarget
;
3860 m_dropTarget
= dropTarget
;
3862 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3865 #endif // wxUSE_DRAG_AND_DROP
3867 GtkWidget
* wxWindowGTK::GetConnectWidget()
3869 GtkWidget
*connect_widget
= m_widget
;
3870 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3872 return connect_widget
;
3875 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow
*window
)
3878 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3880 return (window
== m_widget
->window
);
3883 bool wxWindowGTK::SetFont( const wxFont
&font
)
3885 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3887 if (!wxWindowBase::SetFont(font
))
3892 wxColour sysbg
= wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE
);
3893 if ( sysbg
== m_backgroundColour
)
3895 m_backgroundColour
= wxNullColour
;
3897 m_backgroundColour
= sysbg
;
3907 void wxWindowGTK::DoCaptureMouse()
3909 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3911 GdkWindow
*window
= (GdkWindow
*) NULL
;
3913 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3915 window
= GetConnectWidget()->window
;
3917 wxCHECK_RET( window
, _T("CaptureMouse() failed") );
3919 wxCursor
* cursor
= & m_cursor
;
3921 cursor
= wxSTANDARD_CURSOR
;
3923 gdk_pointer_grab( window
, FALSE
,
3925 (GDK_BUTTON_PRESS_MASK
|
3926 GDK_BUTTON_RELEASE_MASK
|
3927 GDK_POINTER_MOTION_HINT_MASK
|
3928 GDK_POINTER_MOTION_MASK
),
3930 cursor
->GetCursor(),
3931 (guint32
)GDK_CURRENT_TIME
);
3932 g_captureWindow
= this;
3933 g_captureWindowHasMouse
= TRUE
;
3936 void wxWindowGTK::DoReleaseMouse()
3938 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3940 wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") );
3942 g_captureWindow
= (wxWindowGTK
*) NULL
;
3944 GdkWindow
*window
= (GdkWindow
*) NULL
;
3946 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3948 window
= GetConnectWidget()->window
;
3953 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3957 wxWindow
*wxWindowBase::GetCapture()
3959 return (wxWindow
*)g_captureWindow
;
3962 bool wxWindowGTK::IsRetained() const
3967 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3968 int range
, bool refresh
)
3970 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3972 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3974 m_hasScrolling
= TRUE
;
3976 if (orient
== wxHORIZONTAL
)
3978 float fpos
= (float)pos
;
3979 float frange
= (float)range
;
3980 float fthumb
= (float)thumbVisible
;
3981 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3982 if (fpos
< 0.0) fpos
= 0.0;
3984 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3985 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3987 SetScrollPos( orient
, pos
, refresh
);
3991 m_oldHorizontalPos
= fpos
;
3993 m_hAdjust
->lower
= 0.0;
3994 m_hAdjust
->upper
= frange
;
3995 m_hAdjust
->value
= fpos
;
3996 m_hAdjust
->step_increment
= 1.0;
3997 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3998 m_hAdjust
->page_size
= fthumb
;
4002 float fpos
= (float)pos
;
4003 float frange
= (float)range
;
4004 float fthumb
= (float)thumbVisible
;
4005 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
4006 if (fpos
< 0.0) fpos
= 0.0;
4008 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
4009 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
4011 SetScrollPos( orient
, pos
, refresh
);
4015 m_oldVerticalPos
= fpos
;
4017 m_vAdjust
->lower
= 0.0;
4018 m_vAdjust
->upper
= frange
;
4019 m_vAdjust
->value
= fpos
;
4020 m_vAdjust
->step_increment
= 1.0;
4021 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
4022 m_vAdjust
->page_size
= fthumb
;
4025 if (orient
== wxHORIZONTAL
)
4026 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
4028 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
4031 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
4033 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4035 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4037 if (orient
== wxHORIZONTAL
)
4039 float fpos
= (float)pos
;
4040 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
4041 if (fpos
< 0.0) fpos
= 0.0;
4042 m_oldHorizontalPos
= fpos
;
4044 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
4045 m_hAdjust
->value
= fpos
;
4049 float fpos
= (float)pos
;
4050 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
4051 if (fpos
< 0.0) fpos
= 0.0;
4052 m_oldVerticalPos
= fpos
;
4054 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
4055 m_vAdjust
->value
= fpos
;
4058 if (m_wxwindow
->window
)
4060 if (orient
== wxHORIZONTAL
)
4062 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
4063 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
4065 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
4067 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
4068 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
4072 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
4073 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4075 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
4077 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
4078 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4083 int wxWindowGTK::GetScrollThumb( int orient
) const
4085 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4087 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4089 if (orient
== wxHORIZONTAL
)
4090 return (int)(m_hAdjust
->page_size
+0.5);
4092 return (int)(m_vAdjust
->page_size
+0.5);
4095 int wxWindowGTK::GetScrollPos( int orient
) const
4097 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4099 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4101 if (orient
== wxHORIZONTAL
)
4102 return (int)(m_hAdjust
->value
+0.5);
4104 return (int)(m_vAdjust
->value
+0.5);
4107 int wxWindowGTK::GetScrollRange( int orient
) const
4109 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4111 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4113 if (orient
== wxHORIZONTAL
)
4114 return (int)(m_hAdjust
->upper
+0.5);
4116 return (int)(m_vAdjust
->upper
+0.5);
4119 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
4121 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4123 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4125 // No scrolling requested.
4126 if ((dx
== 0) && (dy
== 0)) return;
4129 if (!m_updateRegion
.IsEmpty())
4131 m_updateRegion
.Offset( dx
, dy
);
4135 GetClientSize( &cw
, &ch
);
4136 m_updateRegion
.Intersect( 0, 0, cw
, ch
);
4139 if (!m_clearRegion
.IsEmpty())
4141 m_clearRegion
.Offset( dx
, dy
);
4145 GetClientSize( &cw
, &ch
);
4146 m_clearRegion
.Intersect( 0, 0, cw
, ch
);
4148 m_clipPaintRegion
= TRUE
;
4150 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
4152 m_clipPaintRegion
= FALSE
;
4155 gdk_window_scroll( GTK_PIZZA(m_wxwindow
)->bin_window
, dx
, dy
);
4157 GTK_PIZZA(m_wxwindow
)->xoffset
+= dx
;
4158 GTK_PIZZA(m_wxwindow
)->yoffset
+= dy
;
4165 // Find the wxWindow at the current mouse position, also returning the mouse
4167 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
4169 pt
= wxGetMousePosition();
4170 wxWindow
* found
= wxFindWindowAtPoint(pt
);
4174 // Get the current mouse position.
4175 wxPoint
wxGetMousePosition()
4177 /* This crashes when used within wxHelpContext,
4178 so we have to use the X-specific implementation below.
4180 GdkModifierType *mask;
4181 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
4183 return wxPoint(x, y);
4187 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
4189 return wxPoint(-999, -999);
4191 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
4192 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
4193 Window rootReturn
, childReturn
;
4194 int rootX
, rootY
, winX
, winY
;
4195 unsigned int maskReturn
;
4197 XQueryPointer (display
,
4201 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
4202 return wxPoint(rootX
, rootY
);
4206 // ----------------------------------------------------------------------------
4208 // ----------------------------------------------------------------------------
4210 class wxWinModule
: public wxModule
4217 DECLARE_DYNAMIC_CLASS(wxWinModule
)
4220 IMPLEMENT_DYNAMIC_CLASS(wxWinModule
, wxModule
)
4222 bool wxWinModule::OnInit()
4224 // g_eraseGC = gdk_gc_new( GDK_ROOT_PARENT() );
4225 // gdk_gc_set_fill( g_eraseGC, GDK_SOLID );
4230 void wxWinModule::OnExit()
4233 gdk_gc_unref( g_eraseGC
);