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 //-----------------------------------------------------------------------------
278 // missing gdk functions
279 //-----------------------------------------------------------------------------
282 gdk_window_warp_pointer (GdkWindow
*window
,
287 GdkWindowPrivate
*priv
;
291 window
= GDK_ROOT_PARENT();
294 if (!GDK_WINDOW_DESTROYED(window
))
296 XWarpPointer (GDK_WINDOW_XDISPLAY(window
),
297 None
, /* not source window -> move from anywhere */
298 GDK_WINDOW_XID(window
), /* dest window */
299 0, 0, 0, 0, /* not source window -> move from anywhere */
303 priv
= (GdkWindowPrivate
*) window
;
305 if (!priv
->destroyed
)
307 XWarpPointer (priv
->xdisplay
,
308 None
, /* not source window -> move from anywhere */
309 priv
->xwindow
, /* dest window */
310 0, 0, 0, 0, /* not source window -> move from anywhere */
316 //-----------------------------------------------------------------------------
318 //-----------------------------------------------------------------------------
320 extern void wxapp_install_idle_handler();
321 extern bool g_isIdle
;
323 //-----------------------------------------------------------------------------
324 // local code (see below)
325 //-----------------------------------------------------------------------------
327 // returns the child of win which currently has focus or NULL if not found
329 // Note: can't be static, needed by textctrl.cpp.
330 wxWindow
*wxFindFocusedChild(wxWindowGTK
*win
)
332 wxWindow
*winFocus
= wxWindowGTK::FindFocus();
334 return (wxWindow
*)NULL
;
336 if ( winFocus
== win
)
337 return (wxWindow
*)win
;
339 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
341 node
= node
->GetNext() )
343 wxWindow
*child
= wxFindFocusedChild(node
->GetData());
348 return (wxWindow
*)NULL
;
351 static void draw_frame( GtkWidget
*widget
, wxWindowGTK
*win
)
353 // wxUniversal widgets draw the borders and scrollbars themselves
354 #ifndef __WXUNIVERSAL__
361 if (win
->m_hasScrolling
)
363 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
365 GtkRequisition vscroll_req
;
366 vscroll_req
.width
= 2;
367 vscroll_req
.height
= 2;
368 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
369 (scroll_window
->vscrollbar
, &vscroll_req
);
371 GtkRequisition hscroll_req
;
372 hscroll_req
.width
= 2;
373 hscroll_req
.height
= 2;
374 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
375 (scroll_window
->hscrollbar
, &hscroll_req
);
377 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) );
379 if (scroll_window
->vscrollbar_visible
)
381 dw
+= vscroll_req
.width
;
382 dw
+= scroll_class
->scrollbar_spacing
;
385 if (scroll_window
->hscrollbar_visible
)
387 dh
+= hscroll_req
.height
;
388 dh
+= scroll_class
->scrollbar_spacing
;
394 if (GTK_WIDGET_NO_WINDOW (widget
))
396 dx
+= widget
->allocation
.x
;
397 dy
+= widget
->allocation
.y
;
400 if (win
->HasFlag(wxRAISED_BORDER
))
402 gtk_draw_shadow( widget
->style
,
407 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
411 if (win
->HasFlag(wxSUNKEN_BORDER
))
413 gtk_draw_shadow( widget
->style
,
418 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
422 if (win
->HasFlag(wxSIMPLE_BORDER
))
425 gc
= gdk_gc_new( widget
->window
);
426 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
427 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
429 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
433 #endif // __WXUNIVERSAL__
436 //-----------------------------------------------------------------------------
437 // "expose_event" of m_widget
438 //-----------------------------------------------------------------------------
440 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindowGTK
*win
)
442 if (gdk_event
->count
> 0) return FALSE
;
444 draw_frame( widget
, win
);
448 (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
);
454 //-----------------------------------------------------------------------------
455 // "draw" of m_widget
456 //-----------------------------------------------------------------------------
460 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindowGTK
*win
)
462 draw_frame( widget
, win
);
467 //-----------------------------------------------------------------------------
468 // "size_request" of m_widget
469 //-----------------------------------------------------------------------------
471 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
474 win
->GetSize( &w
, &h
);
478 requisition
->height
= h
;
479 requisition
->width
= w
;
482 //-----------------------------------------------------------------------------
483 // "expose_event" of m_wxwindow
484 //-----------------------------------------------------------------------------
486 static int gtk_window_expose_callback( GtkWidget
*widget
,
487 GdkEventExpose
*gdk_event
,
493 wxapp_install_idle_handler();
498 wxPrintf( wxT("OnExpose from ") );
499 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
500 wxPrintf( win
->GetClassInfo()->GetClassName() );
501 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event
->area
.x
,
502 (int)gdk_event
->area
.y
,
503 (int)gdk_event
->area
.width
,
504 (int)gdk_event
->area
.height
);
508 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
510 gdk_event
->area
.width
,
511 gdk_event
->area
.height
);
513 // Actual redrawing takes place in idle time.
518 (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
);
525 //-----------------------------------------------------------------------------
526 // "event" of m_wxwindow
527 //-----------------------------------------------------------------------------
529 // GTK thinks it is clever and filters out a certain amount of "unneeded"
530 // expose events. We need them, of course, so we override the main event
531 // procedure in GtkWidget by giving our own handler for all system events.
532 // There, we look for expose events ourselves whereas all other events are
535 gint
gtk_window_event_event_callback( GtkWidget
*widget
,
536 GdkEventExpose
*event
,
539 if (event
->type
== GDK_EXPOSE
)
541 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
548 //-----------------------------------------------------------------------------
549 // "draw" of m_wxwindow
550 //-----------------------------------------------------------------------------
554 // This callback is a complete replacement of the gtk_pizza_draw() function,
555 // which is disabled.
557 static void gtk_window_draw_callback( GtkWidget
*widget
,
564 wxapp_install_idle_handler();
566 // The wxNO_FULL_REPAINT_ON_RESIZE flag only works if
567 // there are no child windows.
568 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
569 (win
->GetChildren().GetCount() == 0))
577 wxPrintf( wxT("OnDraw from ") );
578 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
579 wxPrintf( win
->GetClassInfo()->GetClassName() );
580 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect
->x
,
587 #ifndef __WXUNIVERSAL__
588 GtkPizza
*pizza
= GTK_PIZZA (widget
);
590 if (win
->GetThemeEnabled())
592 wxWindow
*parent
= win
->GetParent();
593 while (parent
&& !parent
->IsTopLevel())
594 parent
= parent
->GetParent();
598 gtk_paint_flat_box (parent
->m_widget
->style
,
609 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
610 (pizza
->clear_on_draw
))
612 gdk_window_clear_area( pizza
->bin_window
,
613 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
617 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
619 // Actual redrawing takes place in idle time.
623 #ifndef __WXUNIVERSAL__
624 // Redraw child widgets
625 GList
*children
= pizza
->children
;
628 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
629 children
= children
->next
;
631 GdkRectangle child_area
;
632 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
634 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
642 //-----------------------------------------------------------------------------
643 // "key_press_event" from any window
644 //-----------------------------------------------------------------------------
646 // set WXTRACE to this to see the key event codes on the console
647 #define TRACE_KEYS _T("keyevent")
649 // translates an X key symbol to WXK_XXX value
651 // if isChar is true it means that the value returned will be used for EVT_CHAR
652 // event and then we choose the logical WXK_XXX, i.e. '/' for GDK_KP_Divide,
653 // for example, while if it is false it means that the value is going to be
654 // used for KEY_DOWN/UP events and then we translate GDK_KP_Divide to
656 static long wxTranslateKeySymToWXKey(KeySym keysym
, bool isChar
)
662 // Shift, Control and Alt don't generate the CHAR events at all
665 key_code
= isChar
? 0 : WXK_SHIFT
;
669 key_code
= isChar
? 0 : WXK_CONTROL
;
677 key_code
= isChar
? 0 : WXK_ALT
;
680 // neither do the toggle modifies
681 case GDK_Scroll_Lock
:
682 key_code
= isChar
? 0 : WXK_SCROLL
;
686 key_code
= isChar
? 0 : WXK_CAPITAL
;
690 key_code
= isChar
? 0 : WXK_NUMLOCK
;
694 // various other special keys
707 case GDK_ISO_Left_Tab
:
714 key_code
= WXK_RETURN
;
718 key_code
= WXK_CLEAR
;
722 key_code
= WXK_PAUSE
;
726 key_code
= WXK_SELECT
;
730 key_code
= WXK_PRINT
;
734 key_code
= WXK_EXECUTE
;
738 key_code
= WXK_ESCAPE
;
741 // cursor and other extended keyboard keys
743 key_code
= WXK_DELETE
;
759 key_code
= WXK_RIGHT
;
766 case GDK_Prior
: // == GDK_Page_Up
767 key_code
= WXK_PRIOR
;
770 case GDK_Next
: // == GDK_Page_Down
783 key_code
= WXK_INSERT
;
798 key_code
= (isChar
? '0' : WXK_NUMPAD0
) + keysym
- GDK_KP_0
;
802 key_code
= isChar
? ' ' : WXK_NUMPAD_SPACE
;
806 key_code
= isChar
? WXK_TAB
: WXK_NUMPAD_TAB
;
810 key_code
= isChar
? WXK_RETURN
: WXK_NUMPAD_ENTER
;
814 key_code
= isChar
? WXK_F1
: WXK_NUMPAD_F1
;
818 key_code
= isChar
? WXK_F2
: WXK_NUMPAD_F2
;
822 key_code
= isChar
? WXK_F3
: WXK_NUMPAD_F3
;
826 key_code
= isChar
? WXK_F4
: WXK_NUMPAD_F4
;
830 key_code
= isChar
? WXK_HOME
: WXK_NUMPAD_HOME
;
834 key_code
= isChar
? WXK_LEFT
: WXK_NUMPAD_LEFT
;
838 key_code
= isChar
? WXK_UP
: WXK_NUMPAD_UP
;
842 key_code
= isChar
? WXK_RIGHT
: WXK_NUMPAD_RIGHT
;
846 key_code
= isChar
? WXK_DOWN
: WXK_NUMPAD_DOWN
;
849 case GDK_KP_Prior
: // == GDK_KP_Page_Up
850 key_code
= isChar
? WXK_PRIOR
: WXK_NUMPAD_PRIOR
;
853 case GDK_KP_Next
: // == GDK_KP_Page_Down
854 key_code
= isChar
? WXK_NEXT
: WXK_NUMPAD_NEXT
;
858 key_code
= isChar
? WXK_END
: WXK_NUMPAD_END
;
862 key_code
= isChar
? WXK_HOME
: WXK_NUMPAD_BEGIN
;
866 key_code
= isChar
? WXK_INSERT
: WXK_NUMPAD_INSERT
;
870 key_code
= isChar
? WXK_DELETE
: WXK_NUMPAD_DELETE
;
874 key_code
= isChar
? '=' : WXK_NUMPAD_EQUAL
;
877 case GDK_KP_Multiply
:
878 key_code
= isChar
? '*' : WXK_NUMPAD_MULTIPLY
;
882 key_code
= isChar
? '+' : WXK_NUMPAD_ADD
;
885 case GDK_KP_Separator
:
886 // FIXME: what is this?
887 key_code
= isChar
? '.' : WXK_NUMPAD_SEPARATOR
;
890 case GDK_KP_Subtract
:
891 key_code
= isChar
? '-' : WXK_NUMPAD_SUBTRACT
;
895 key_code
= isChar
? '.' : WXK_NUMPAD_DECIMAL
;
899 key_code
= isChar
? '/' : WXK_NUMPAD_DIVIDE
;
916 key_code
= WXK_F1
+ keysym
- GDK_F1
;
926 static inline bool wxIsAsciiKeysym(KeySym ks
)
932 wxTranslateGTKKeyEventToWx(wxKeyEvent
& event
,
934 GdkEventKey
*gdk_event
)
936 // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string
937 // but only event->keyval which is quite useless to us, so remember
938 // the last character from GDK_KEY_PRESS and reuse it as last resort
940 // NB: should be MT-safe as we're always called from the main thread only
945 } s_lastKeyPress
= { 0, 0 };
947 KeySym keysym
= gdk_event
->keyval
;
949 wxLogTrace(TRACE_KEYS
, _T("Key %s event: keysym = %d"),
950 event
.GetEventType() == wxEVT_KEY_UP
? _T("release")
954 long key_code
= wxTranslateKeySymToWXKey(keysym
, FALSE
/* !isChar */);
958 // do we have the translation or is it a plain ASCII character?
959 if ( (gdk_event
->length
== 1) || wxIsAsciiKeysym(keysym
) )
961 // we should use keysym if it is ASCII as X does some translations
962 // like "I pressed while Control is down" => "Ctrl-I" == "TAB"
963 // which we don't want here (but which we do use for OnChar())
964 if ( !wxIsAsciiKeysym(keysym
) )
966 keysym
= (KeySym
)gdk_event
->string
[0];
969 // we want to always get the same key code when the same key is
970 // pressed regardless of the state of the modifies, i.e. on a
971 // standard US keyboard pressing '5' or '%' ('5' key with
972 // Shift) should result in the same key code in OnKeyDown():
973 // '5' (although OnChar() will get either '5' or '%').
975 // to do it we first translate keysym to keycode (== scan code)
976 // and then back but always using the lower register
977 Display
*dpy
= (Display
*)wxGetDisplay();
978 KeyCode keycode
= XKeysymToKeycode(dpy
, keysym
);
980 wxLogTrace(TRACE_KEYS
, _T("\t-> keycode %d"), keycode
);
982 KeySym keysymNormalized
= XKeycodeToKeysym(dpy
, keycode
, 0);
984 // use the normalized, i.e. lower register, keysym if we've
986 key_code
= keysymNormalized
? keysymNormalized
: keysym
;
988 // as explained above, we want to have lower register key codes
989 // normally but for the letter keys we want to have the upper ones
991 // NB: don't use XConvertCase() here, we want to do it for letters
993 key_code
= toupper(key_code
);
995 else // non ASCII key, what to do?
997 // by default, ignore it
1000 // but if we have cached information from the last KEY_PRESS
1001 if ( gdk_event
->type
== GDK_KEY_RELEASE
)
1004 if ( keysym
== s_lastKeyPress
.keysym
)
1006 key_code
= s_lastKeyPress
.keycode
;
1011 if ( gdk_event
->type
== GDK_KEY_PRESS
)
1013 // remember it to be reused for KEY_UP event later
1014 s_lastKeyPress
.keysym
= keysym
;
1015 s_lastKeyPress
.keycode
= key_code
;
1019 wxLogTrace(TRACE_KEYS
, _T("\t-> wxKeyCode %d"), key_code
);
1021 // sending unknown key events doesn't really make sense
1025 // now fill all the other fields
1028 GdkModifierType state
;
1029 if (gdk_event
->window
)
1030 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1032 event
.SetTimestamp( gdk_event
->time
);
1033 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
) != 0;
1034 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
) != 0;
1035 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
) != 0;
1036 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
) != 0;
1037 event
.m_keyCode
= key_code
;
1038 event
.m_scanCode
= gdk_event
->keyval
;
1039 event
.m_rawCode
= (wxUint32
) gdk_event
->keyval
;
1040 event
.m_rawFlags
= 0;
1043 event
.SetEventObject( win
);
1048 static gint
gtk_window_key_press_callback( GtkWidget
*widget
,
1049 GdkEventKey
*gdk_event
,
1055 wxapp_install_idle_handler();
1059 if (g_blockEventsOnDrag
)
1062 wxKeyEvent
event( wxEVT_KEY_DOWN
);
1063 if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) )
1065 // unknown key pressed, ignore (the event would be useless anyhow)
1069 bool ret
= win
->GetEventHandler()->ProcessEvent( event
);
1074 wxWindowGTK
*ancestor
= win
;
1077 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
1080 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
1081 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
1084 if (ancestor
->IsTopLevel())
1086 ancestor
= ancestor
->GetParent();
1089 #endif // wxUSE_ACCEL
1091 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
1092 will only be sent if it is not in an accelerator table. */
1095 KeySym keysym
= gdk_event
->keyval
;
1096 long key_code
= wxTranslateKeySymToWXKey(keysym
, TRUE
/* isChar */);
1099 if ( gdk_event
->length
== 1 )
1101 key_code
= (unsigned char)gdk_event
->string
[0];
1103 else if ( wxIsAsciiKeysym(keysym
) )
1106 key_code
= (unsigned char)keysym
;
1112 wxLogTrace(TRACE_KEYS
, _T("Char event: %ld"), key_code
);
1114 // reuse the same event object, just change its type and use the
1115 // translated keycode instead of the raw one
1116 event
.SetEventType(wxEVT_CHAR
);
1117 event
.m_keyCode
= key_code
;
1119 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1123 /* win is a control: tab can be propagated up */
1125 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
1126 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
1127 // have this style, yet choose not to process this particular TAB in which
1128 // case TAB must still work as a navigational character
1130 !win
->HasFlag(wxTE_PROCESS_TAB
) &&
1132 win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
1134 wxNavigationKeyEvent new_event
;
1135 new_event
.SetEventObject( win
->GetParent() );
1136 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
1137 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
1138 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1139 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
1140 new_event
.SetCurrentFocus( win
);
1141 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
1144 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
1146 (gdk_event
->keyval
== GDK_Escape
) )
1148 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
1149 new_event
.SetEventObject( win
);
1150 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
1154 #if 0 // (GTK_MINOR_VERSION > 0)
1155 /* Pressing F10 will activate the menu bar of the top frame. */
1157 (gdk_event
->keyval
== GDK_F10
) )
1159 wxWindowGTK
*ancestor
= win
;
1162 if (wxIsKindOf(ancestor
,wxFrame
))
1164 wxFrame
*frame
= (wxFrame
*) ancestor
;
1165 wxMenuBar
*menubar
= frame
->GetMenuBar();
1168 wxNode
*node
= menubar
->GetMenus().First();
1171 wxMenu
*firstMenu
= (wxMenu
*) node
->Data();
1172 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu
->m_owner
) );
1178 ancestor
= ancestor
->GetParent();
1185 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1192 //-----------------------------------------------------------------------------
1193 // "key_release_event" from any window
1194 //-----------------------------------------------------------------------------
1196 static gint
gtk_window_key_release_callback( GtkWidget
*widget
,
1197 GdkEventKey
*gdk_event
,
1203 wxapp_install_idle_handler();
1208 if (g_blockEventsOnDrag
)
1211 wxKeyEvent
event( wxEVT_KEY_UP
);
1212 if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) )
1214 // unknown key pressed, ignore (the event would be useless anyhow
1218 if ( !win
->GetEventHandler()->ProcessEvent( event
) )
1221 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1225 // ============================================================================
1227 // ============================================================================
1229 // init wxMouseEvent with the info from gdk_event
1230 #define InitMouseEvent(win, event, gdk_event) \
1232 event.SetTimestamp( gdk_event->time ); \
1233 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
1234 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
1235 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
1236 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
1237 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
1238 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
1239 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
1241 wxPoint pt = win->GetClientAreaOrigin(); \
1242 event.m_x = (wxCoord)gdk_event->x - pt.x; \
1243 event.m_y = (wxCoord)gdk_event->y - pt.y; \
1246 // ----------------------------------------------------------------------------
1247 // mouse event processing helper
1248 // ----------------------------------------------------------------------------
1250 static void AdjustEventButtonState(wxMouseEvent
& event
)
1252 // GDK reports the old state of the button for a button press event, but
1253 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1254 // for a LEFT_DOWN event, not FALSE, so we will invert
1255 // left/right/middleDown for the corresponding click events
1257 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1258 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1259 (event
.GetEventType() == wxEVT_LEFT_UP
))
1261 event
.m_leftDown
= !event
.m_leftDown
;
1265 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1266 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1267 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1269 event
.m_middleDown
= !event
.m_middleDown
;
1273 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1274 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1275 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1277 event
.m_rightDown
= !event
.m_rightDown
;
1282 //-----------------------------------------------------------------------------
1283 // "button_press_event"
1284 //-----------------------------------------------------------------------------
1286 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1291 wxapp_install_idle_handler();
1294 wxPrintf( wxT("1) OnButtonPress from ") );
1295 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1296 wxPrintf( win->GetClassInfo()->GetClassName() );
1297 wxPrintf( wxT(".\n") );
1299 if (!win
->m_hasVMT
) return FALSE
;
1300 if (g_blockEventsOnDrag
) return TRUE
;
1301 if (g_blockEventsOnScroll
) return TRUE
;
1303 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1305 if (win
->m_wxwindow
&& (g_focusWindow
!= win
) && win
->AcceptsFocus())
1307 gtk_widget_grab_focus( win
->m_wxwindow
);
1309 wxPrintf( wxT("GrabFocus from ") );
1310 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1311 wxPrintf( win->GetClassInfo()->GetClassName() );
1312 wxPrintf( wxT(".\n") );
1316 wxEventType event_type
= wxEVT_NULL
;
1318 if (gdk_event
->button
== 1)
1320 switch (gdk_event
->type
)
1322 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1323 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1327 else if (gdk_event
->button
== 2)
1329 switch (gdk_event
->type
)
1331 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1332 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1336 else if (gdk_event
->button
== 3)
1338 switch (gdk_event
->type
)
1340 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1341 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1346 if ( event_type
== wxEVT_NULL
)
1348 // unknown mouse button or click type
1352 wxMouseEvent
event( event_type
);
1353 InitMouseEvent( win
, event
, gdk_event
);
1355 AdjustEventButtonState(event
);
1357 // wxListBox actually get mouse events from the item
1359 if (win
->m_isListBox
)
1361 event
.m_x
+= widget
->allocation
.x
;
1362 event
.m_y
+= widget
->allocation
.y
;
1365 // Some control don't have their own X window and thus cannot get
1368 if (!g_captureWindow
)
1370 wxCoord x
= event
.m_x
;
1371 wxCoord y
= event
.m_y
;
1372 if (win
->m_wxwindow
)
1374 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1375 x
+= pizza
->xoffset
;
1376 y
+= pizza
->yoffset
;
1379 wxNode
*node
= win
->GetChildren().First();
1382 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1384 node
= node
->Next();
1385 if (!child
->IsShown())
1388 if (child
->m_isStaticBox
)
1390 // wxStaticBox is transparent in the box itself
1391 int xx1
= child
->m_x
;
1392 int yy1
= child
->m_y
;
1393 int xx2
= child
->m_x
+ child
->m_width
;
1394 int yy2
= child
->m_x
+ child
->m_height
;
1397 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1399 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1401 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1403 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1406 event
.m_x
-= child
->m_x
;
1407 event
.m_y
-= child
->m_y
;
1414 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1415 (child
->m_x
<= x
) &&
1416 (child
->m_y
<= y
) &&
1417 (child
->m_x
+child
->m_width
>= x
) &&
1418 (child
->m_y
+child
->m_height
>= y
))
1421 event
.m_x
-= child
->m_x
;
1422 event
.m_y
-= child
->m_y
;
1429 event
.SetEventObject( win
);
1431 gs_timeLastClick
= gdk_event
->time
;
1434 wxPrintf( wxT("2) OnButtonPress from ") );
1435 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1436 wxPrintf( win->GetClassInfo()->GetClassName() );
1437 wxPrintf( wxT(".\n") );
1440 if (win
->GetEventHandler()->ProcessEvent( event
))
1442 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1449 //-----------------------------------------------------------------------------
1450 // "button_release_event"
1451 //-----------------------------------------------------------------------------
1453 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1458 wxapp_install_idle_handler();
1460 if (!win
->m_hasVMT
) return FALSE
;
1461 if (g_blockEventsOnDrag
) return FALSE
;
1462 if (g_blockEventsOnScroll
) return FALSE
;
1464 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1467 printf( "OnButtonRelease from " );
1468 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1469 printf( win->GetClassInfo()->GetClassName() );
1473 wxEventType event_type
= wxEVT_NULL
;
1475 switch (gdk_event
->button
)
1477 case 1: event_type
= wxEVT_LEFT_UP
; break;
1478 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1479 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1480 default: return FALSE
;
1483 wxMouseEvent
event( event_type
);
1484 InitMouseEvent( win
, event
, gdk_event
);
1486 AdjustEventButtonState(event
);
1488 // wxListBox actually get mouse events from the item
1490 if (win
->m_isListBox
)
1492 event
.m_x
+= widget
->allocation
.x
;
1493 event
.m_y
+= widget
->allocation
.y
;
1496 // Some control don't have their own X window and thus cannot get
1499 if (!g_captureWindow
)
1501 wxCoord x
= event
.m_x
;
1502 wxCoord y
= event
.m_y
;
1503 if (win
->m_wxwindow
)
1505 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1506 x
+= pizza
->xoffset
;
1507 y
+= pizza
->yoffset
;
1510 wxNode
*node
= win
->GetChildren().First();
1513 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1515 node
= node
->Next();
1516 if (!child
->IsShown())
1519 if (child
->m_isStaticBox
)
1521 // wxStaticBox is transparent in the box itself
1522 int xx1
= child
->m_x
;
1523 int yy1
= child
->m_y
;
1524 int xx2
= child
->m_x
+ child
->m_width
;
1525 int yy2
= child
->m_x
+ child
->m_height
;
1528 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1530 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1532 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1534 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1537 event
.m_x
-= child
->m_x
;
1538 event
.m_y
-= child
->m_y
;
1545 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1546 (child
->m_x
<= x
) &&
1547 (child
->m_y
<= y
) &&
1548 (child
->m_x
+child
->m_width
>= x
) &&
1549 (child
->m_y
+child
->m_height
>= y
))
1552 event
.m_x
-= child
->m_x
;
1553 event
.m_y
-= child
->m_y
;
1560 event
.SetEventObject( win
);
1562 if (win
->GetEventHandler()->ProcessEvent( event
))
1564 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1571 //-----------------------------------------------------------------------------
1572 // "motion_notify_event"
1573 //-----------------------------------------------------------------------------
1575 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
,
1576 GdkEventMotion
*gdk_event
,
1582 wxapp_install_idle_handler();
1584 if (!win
->m_hasVMT
) return FALSE
;
1585 if (g_blockEventsOnDrag
) return FALSE
;
1586 if (g_blockEventsOnScroll
) return FALSE
;
1588 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1590 if (gdk_event
->is_hint
)
1594 GdkModifierType state
;
1595 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1601 printf( "OnMotion from " );
1602 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1603 printf( win->GetClassInfo()->GetClassName() );
1607 wxMouseEvent
event( wxEVT_MOTION
);
1608 InitMouseEvent(win
, event
, gdk_event
);
1610 if ( g_captureWindow
)
1612 // synthetize a mouse enter or leave event if needed
1613 GdkWindow
*winUnderMouse
= gdk_window_at_pointer(NULL
, NULL
);
1614 bool hasMouse
= winUnderMouse
== gdk_event
->window
;
1615 if ( hasMouse
!= g_captureWindowHasMouse
)
1617 // the mouse changed window
1618 g_captureWindowHasMouse
= hasMouse
;
1620 wxMouseEvent
event(g_captureWindowHasMouse
? wxEVT_ENTER_WINDOW
1621 : wxEVT_LEAVE_WINDOW
);
1622 InitMouseEvent(win
, event
, gdk_event
);
1623 event
.SetEventObject(win
);
1624 win
->GetEventHandler()->ProcessEvent(event
);
1629 // Some control don't have their own X window and thus cannot get
1632 wxCoord x
= event
.m_x
;
1633 wxCoord y
= event
.m_y
;
1634 if (win
->m_wxwindow
)
1636 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1637 x
+= pizza
->xoffset
;
1638 y
+= pizza
->yoffset
;
1641 wxNode
*node
= win
->GetChildren().First();
1644 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1646 node
= node
->Next();
1647 if (!child
->IsShown())
1650 if (child
->m_isStaticBox
)
1652 // wxStaticBox is transparent in the box itself
1653 int xx1
= child
->m_x
;
1654 int yy1
= child
->m_y
;
1655 int xx2
= child
->m_x
+ child
->m_width
;
1656 int yy2
= child
->m_x
+ child
->m_height
;
1659 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1661 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1663 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1665 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1668 event
.m_x
-= child
->m_x
;
1669 event
.m_y
-= child
->m_y
;
1676 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1677 (child
->m_x
<= x
) &&
1678 (child
->m_y
<= y
) &&
1679 (child
->m_x
+child
->m_width
>= x
) &&
1680 (child
->m_y
+child
->m_height
>= y
))
1683 event
.m_x
-= child
->m_x
;
1684 event
.m_y
-= child
->m_y
;
1691 event
.SetEventObject( win
);
1693 if (win
->GetEventHandler()->ProcessEvent( event
))
1695 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1702 //-----------------------------------------------------------------------------
1704 //-----------------------------------------------------------------------------
1706 // send the wxChildFocusEvent and wxFocusEvent, common code of
1707 // gtk_window_focus_in_callback() and SetFocus()
1708 static bool DoSendFocusEvents(wxWindow
*win
)
1710 // Notify the parent keeping track of focus for the kbd navigation
1711 // purposes that we got it.
1712 wxChildFocusEvent
eventChildFocus(win
);
1713 (void)win
->GetEventHandler()->ProcessEvent(eventChildFocus
);
1715 wxFocusEvent
eventFocus(wxEVT_SET_FOCUS
, win
->GetId());
1716 eventFocus
.SetEventObject(win
);
1718 return win
->GetEventHandler()->ProcessEvent(eventFocus
);
1721 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
,
1722 GdkEvent
*WXUNUSED(event
),
1728 wxapp_install_idle_handler();
1730 if (!win
->m_hasVMT
) return FALSE
;
1731 if (g_blockEventsOnDrag
) return FALSE
;
1733 switch ( g_sendActivateEvent
)
1736 // we've got focus from outside, synthetize wxActivateEvent
1737 g_sendActivateEvent
= 1;
1741 // another our window just lost focus, it was already ours before
1742 // - don't send any wxActivateEvent
1743 g_sendActivateEvent
= -1;
1748 g_focusWindow
= win
;
1751 printf( "OnSetFocus 2 from %s\n", win
->GetName().c_str() );
1756 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1760 // caret needs to be informed about focus change
1761 wxCaret
*caret
= win
->GetCaret();
1764 caret
->OnSetFocus();
1766 #endif // wxUSE_CARET
1768 g_activeFrameLostFocus
= FALSE
;
1770 wxWindowGTK
*active
= wxGetTopLevelParent(win
);
1771 if ( active
!= g_activeFrame
)
1773 if ( g_activeFrame
)
1775 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame
);
1776 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
1777 event
.SetEventObject(g_activeFrame
);
1778 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1781 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active
);
1782 g_activeFrame
= active
;
1783 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId());
1784 event
.SetEventObject(g_activeFrame
);
1785 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1787 // Don't send focus events in addition to activate
1788 // if (win == g_activeFrame)
1792 if ( DoSendFocusEvents(win
) )
1794 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1801 //-----------------------------------------------------------------------------
1802 // "focus_out_event"
1803 //-----------------------------------------------------------------------------
1805 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEventFocus
*gdk_event
, wxWindowGTK
*win
)
1810 wxapp_install_idle_handler();
1812 if (!win
->m_hasVMT
) return FALSE
;
1813 if (g_blockEventsOnDrag
) return FALSE
;
1816 wxLogDebug( wxT("OnKillFocus from %s"), win
->GetName().c_str() );
1819 if ( !g_activeFrameLostFocus
&& g_activeFrame
)
1821 // VZ: commenting this out because it does happen (although not easy
1822 // to reproduce, I only see it when using wxMiniFrame and not
1823 // always) and makes using Mahogany quite annoying
1825 wxASSERT_MSG( wxGetTopLevelParent(win
) == g_activeFrame
,
1826 wxT("unfocusing window that hasn't gained focus properly") )
1829 g_activeFrameLostFocus
= TRUE
;
1832 // if the focus goes out of our app alltogether, OnIdle() will send
1833 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1834 // g_sendActivateEvent to -1
1835 g_sendActivateEvent
= 0;
1837 wxWindowGTK
*winFocus
= wxFindFocusedChild(win
);
1841 g_focusWindow
= (wxWindowGTK
*)NULL
;
1849 // caret needs to be informed about focus change
1850 wxCaret
*caret
= win
->GetCaret();
1853 caret
->OnKillFocus();
1855 #endif // wxUSE_CARET
1857 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1858 event
.SetEventObject( win
);
1860 if (win
->GetEventHandler()->ProcessEvent( event
))
1862 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1869 //-----------------------------------------------------------------------------
1870 // "enter_notify_event"
1871 //-----------------------------------------------------------------------------
1873 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1878 wxapp_install_idle_handler();
1880 if (!win
->m_hasVMT
) return FALSE
;
1881 if (g_blockEventsOnDrag
) return FALSE
;
1883 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1885 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1886 event
.SetTimestamp( gdk_event
->time
);
1887 event
.SetEventObject( win
);
1891 GdkModifierType state
= (GdkModifierType
)0;
1893 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1895 InitMouseEvent(win
, event
, gdk_event
);
1896 wxPoint pt
= win
->GetClientAreaOrigin();
1897 event
.m_x
= x
+ pt
.x
;
1898 event
.m_y
= y
+ pt
.y
;
1900 if (win
->GetEventHandler()->ProcessEvent( event
))
1902 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1909 //-----------------------------------------------------------------------------
1910 // "leave_notify_event"
1911 //-----------------------------------------------------------------------------
1913 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1918 wxapp_install_idle_handler();
1920 if (!win
->m_hasVMT
) return FALSE
;
1921 if (g_blockEventsOnDrag
) return FALSE
;
1923 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1925 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1926 event
.SetTimestamp( gdk_event
->time
);
1927 event
.SetEventObject( win
);
1931 GdkModifierType state
= (GdkModifierType
)0;
1933 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1935 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
) != 0;
1936 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
) != 0;
1937 event
.m_altDown
= (state
& GDK_MOD1_MASK
) != 0;
1938 event
.m_metaDown
= (state
& GDK_MOD2_MASK
) != 0;
1939 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
) != 0;
1940 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
) != 0;
1941 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
) != 0;
1943 wxPoint pt
= win
->GetClientAreaOrigin();
1944 event
.m_x
= x
+ pt
.x
;
1945 event
.m_y
= y
+ pt
.y
;
1947 if (win
->GetEventHandler()->ProcessEvent( event
))
1949 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1956 //-----------------------------------------------------------------------------
1957 // "value_changed" from m_vAdjust
1958 //-----------------------------------------------------------------------------
1960 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
,
1967 wxapp_install_idle_handler();
1969 if (g_blockEventsOnDrag
) return;
1971 if (!win
->m_hasVMT
) return;
1973 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1974 if (fabs(diff
) < 0.2) return;
1976 win
->m_oldVerticalPos
= adjust
->value
;
1978 GtkScrolledWindow
*sw
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1979 wxEventType command
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->vscrollbar
));
1981 int value
= (int)(adjust
->value
+0.5);
1983 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1984 event
.SetEventObject( win
);
1985 win
->GetEventHandler()->ProcessEvent( event
);
1988 //-----------------------------------------------------------------------------
1989 // "value_changed" from m_hAdjust
1990 //-----------------------------------------------------------------------------
1992 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
,
1999 wxapp_install_idle_handler();
2001 if (g_blockEventsOnDrag
) return;
2002 if (!win
->m_hasVMT
) return;
2004 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
2005 if (fabs(diff
) < 0.2) return;
2007 GtkScrolledWindow
*sw
= GTK_SCROLLED_WINDOW(win
->m_widget
);
2008 wxEventType command
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->hscrollbar
));
2010 win
->m_oldHorizontalPos
= adjust
->value
;
2012 int value
= (int)(adjust
->value
+0.5);
2014 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
2015 event
.SetEventObject( win
);
2016 win
->GetEventHandler()->ProcessEvent( event
);
2019 //-----------------------------------------------------------------------------
2020 // "button_press_event" from scrollbar
2021 //-----------------------------------------------------------------------------
2023 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
2024 GdkEventButton
*gdk_event
,
2030 wxapp_install_idle_handler();
2033 g_blockEventsOnScroll
= TRUE
;
2035 // FIXME: there is no 'slider' field in GTK+ 2.0 any more
2037 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
2043 //-----------------------------------------------------------------------------
2044 // "button_release_event" from scrollbar
2045 //-----------------------------------------------------------------------------
2047 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
2048 GdkEventButton
*WXUNUSED(gdk_event
),
2053 // don't test here as we can release the mouse while being over
2054 // a different window than the slider
2056 // if (gdk_event->window != widget->slider) return FALSE;
2058 g_blockEventsOnScroll
= FALSE
;
2060 if (win
->m_isScrolling
)
2062 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
2066 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
2067 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
2069 value
= (int)(win
->m_hAdjust
->value
+0.5);
2072 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
2074 value
= (int)(win
->m_vAdjust
->value
+0.5);
2078 wxScrollWinEvent
event( command
, value
, dir
);
2079 event
.SetEventObject( win
);
2080 win
->GetEventHandler()->ProcessEvent( event
);
2083 win
->m_isScrolling
= FALSE
;
2088 // ----------------------------------------------------------------------------
2089 // this wxWindowBase function is implemented here (in platform-specific file)
2090 // because it is static and so couldn't be made virtual
2091 // ----------------------------------------------------------------------------
2093 wxWindow
*wxWindowBase::FindFocus()
2095 // the cast is necessary when we compile in wxUniversal mode
2096 return (wxWindow
*)g_focusWindow
;
2099 //-----------------------------------------------------------------------------
2100 // "realize" from m_widget
2101 //-----------------------------------------------------------------------------
2103 /* We cannot set colours and fonts before the widget has
2104 been realized, so we do this directly after realization. */
2107 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
2112 wxapp_install_idle_handler();
2114 if (win
->m_delayedBackgroundColour
)
2115 win
->GtkSetBackgroundColour( win
->GetBackgroundColour() );
2117 if (win
->m_delayedForegroundColour
)
2118 win
->GtkSetForegroundColour( win
->GetForegroundColour() );
2120 wxWindowCreateEvent
event( win
);
2121 event
.SetEventObject( win
);
2122 win
->GetEventHandler()->ProcessEvent( event
);
2127 //-----------------------------------------------------------------------------
2129 //-----------------------------------------------------------------------------
2132 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
2133 GtkAllocation
*WXUNUSED(alloc
),
2137 wxapp_install_idle_handler();
2139 if (!win
->m_hasScrolling
) return;
2141 int client_width
= 0;
2142 int client_height
= 0;
2143 win
->GetClientSize( &client_width
, &client_height
);
2144 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
2147 win
->m_oldClientWidth
= client_width
;
2148 win
->m_oldClientHeight
= client_height
;
2150 if (!win
->m_nativeSizeEvent
)
2152 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
2153 event
.SetEventObject( win
);
2154 win
->GetEventHandler()->ProcessEvent( event
);
2160 #define WXUNUSED_UNLESS_XIM(param) param
2162 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2165 /* Resize XIM window */
2168 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2169 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
2170 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2173 wxapp_install_idle_handler();
2179 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
2183 gdk_window_get_size (widget
->window
, &width
, &height
);
2184 win
->m_icattr
->preedit_area
.width
= width
;
2185 win
->m_icattr
->preedit_area
.height
= height
;
2186 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2191 //-----------------------------------------------------------------------------
2192 // "realize" from m_wxwindow
2193 //-----------------------------------------------------------------------------
2195 /* Initialize XIM support */
2198 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2199 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2202 wxapp_install_idle_handler();
2205 if (win
->m_ic
) return FALSE
;
2206 if (!widget
) return FALSE
;
2207 if (!gdk_im_ready()) return FALSE
;
2209 win
->m_icattr
= gdk_ic_attr_new();
2210 if (!win
->m_icattr
) return FALSE
;
2214 GdkColormap
*colormap
;
2215 GdkICAttr
*attr
= win
->m_icattr
;
2216 unsigned attrmask
= GDK_IC_ALL_REQ
;
2218 GdkIMStyle supported_style
= (GdkIMStyle
)
2219 (GDK_IM_PREEDIT_NONE
|
2220 GDK_IM_PREEDIT_NOTHING
|
2221 GDK_IM_PREEDIT_POSITION
|
2222 GDK_IM_STATUS_NONE
|
2223 GDK_IM_STATUS_NOTHING
);
2225 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2226 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2228 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2229 attr
->client_window
= widget
->window
;
2231 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2232 gtk_widget_get_default_colormap ())
2234 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2235 attr
->preedit_colormap
= colormap
;
2238 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2239 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2240 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2241 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2243 switch (style
& GDK_IM_PREEDIT_MASK
)
2245 case GDK_IM_PREEDIT_POSITION
:
2246 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2248 g_warning ("over-the-spot style requires fontset");
2252 gdk_window_get_size (widget
->window
, &width
, &height
);
2254 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2255 attr
->spot_location
.x
= 0;
2256 attr
->spot_location
.y
= height
;
2257 attr
->preedit_area
.x
= 0;
2258 attr
->preedit_area
.y
= 0;
2259 attr
->preedit_area
.width
= width
;
2260 attr
->preedit_area
.height
= height
;
2261 attr
->preedit_fontset
= widget
->style
->font
;
2266 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2268 if (win
->m_ic
== NULL
)
2269 g_warning ("Can't create input context.");
2272 mask
= gdk_window_get_events (widget
->window
);
2273 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2274 gdk_window_set_events (widget
->window
, mask
);
2276 if (GTK_WIDGET_HAS_FOCUS(widget
))
2277 gdk_im_begin (win
->m_ic
, widget
->window
);
2284 //-----------------------------------------------------------------------------
2285 // InsertChild for wxWindowGTK.
2286 //-----------------------------------------------------------------------------
2288 /* Callback for wxWindowGTK. This very strange beast has to be used because
2289 * C++ has no virtual methods in a constructor. We have to emulate a
2290 * virtual function here as wxNotebook requires a different way to insert
2291 * a child in it. I had opted for creating a wxNotebookPage window class
2292 * which would have made this superfluous (such in the MDI window system),
2293 * but no-one was listening to me... */
2295 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child
)
2297 /* the window might have been scrolled already, do we
2298 have to adapt the position */
2299 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2300 child
->m_x
+= pizza
->xoffset
;
2301 child
->m_y
+= pizza
->yoffset
;
2303 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2304 GTK_WIDGET(child
->m_widget
),
2311 //-----------------------------------------------------------------------------
2313 //-----------------------------------------------------------------------------
2315 wxWindow
*wxGetActiveWindow()
2317 // the cast is necessary when we compile in wxUniversal mode
2318 return (wxWindow
*)g_focusWindow
;
2321 //-----------------------------------------------------------------------------
2323 //-----------------------------------------------------------------------------
2325 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
2327 #ifdef __WXUNIVERSAL__
2328 IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
)
2330 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2331 #endif // __WXUNIVERSAL__/__WXGTK__
2333 void wxWindowGTK::Init()
2339 m_widget
= (GtkWidget
*) NULL
;
2340 m_wxwindow
= (GtkWidget
*) NULL
;
2341 m_focusWidget
= (GtkWidget
*) NULL
;
2351 m_needParent
= TRUE
;
2352 m_isBeingDeleted
= FALSE
;
2355 m_nativeSizeEvent
= FALSE
;
2357 m_hasScrolling
= FALSE
;
2358 m_isScrolling
= FALSE
;
2360 m_hAdjust
= (GtkAdjustment
*) NULL
;
2361 m_vAdjust
= (GtkAdjustment
*) NULL
;
2362 m_oldHorizontalPos
= 0.0;
2363 m_oldVerticalPos
= 0.0;
2366 m_widgetStyle
= (GtkStyle
*) NULL
;
2368 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2370 m_isStaticBox
= FALSE
;
2371 m_isRadioButton
= FALSE
;
2372 m_isListBox
= FALSE
;
2374 m_acceptsFocus
= FALSE
;
2376 m_clipPaintRegion
= FALSE
;
2378 m_cursor
= *wxSTANDARD_CURSOR
;
2380 m_delayedForegroundColour
= FALSE
;
2381 m_delayedBackgroundColour
= FALSE
;
2384 m_ic
= (GdkIC
*) NULL
;
2385 m_icattr
= (GdkICAttr
*) NULL
;
2389 wxWindowGTK::wxWindowGTK()
2394 wxWindowGTK::wxWindowGTK( wxWindow
*parent
,
2399 const wxString
&name
)
2403 Create( parent
, id
, pos
, size
, style
, name
);
2406 bool wxWindowGTK::Create( wxWindow
*parent
,
2411 const wxString
&name
)
2413 if (!PreCreation( parent
, pos
, size
) ||
2414 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2416 wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
2420 m_insertCallback
= wxInsertChildInWindow
;
2422 // always needed for background clearing
2423 m_delayedBackgroundColour
= TRUE
;
2425 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2426 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2428 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2430 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2431 scroll_class
->scrollbar_spacing
= 0;
2433 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2435 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2436 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2438 m_wxwindow
= gtk_pizza_new();
2440 #ifndef __WXUNIVERSAL__
2441 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2443 if (HasFlag(wxRAISED_BORDER
))
2445 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2447 else if (HasFlag(wxSUNKEN_BORDER
))
2449 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2451 else if (HasFlag(wxSIMPLE_BORDER
))
2453 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2457 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2459 #endif // __WXUNIVERSAL__
2461 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2463 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2464 m_acceptsFocus
= TRUE
;
2466 // I _really_ don't want scrollbars in the beginning
2467 m_vAdjust
->lower
= 0.0;
2468 m_vAdjust
->upper
= 1.0;
2469 m_vAdjust
->value
= 0.0;
2470 m_vAdjust
->step_increment
= 1.0;
2471 m_vAdjust
->page_increment
= 1.0;
2472 m_vAdjust
->page_size
= 5.0;
2473 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2474 m_hAdjust
->lower
= 0.0;
2475 m_hAdjust
->upper
= 1.0;
2476 m_hAdjust
->value
= 0.0;
2477 m_hAdjust
->step_increment
= 1.0;
2478 m_hAdjust
->page_increment
= 1.0;
2479 m_hAdjust
->page_size
= 5.0;
2480 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2482 // these handlers block mouse events to any window during scrolling such as
2483 // motion events and prevent GTK and wxWindows from fighting over where the
2486 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2487 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2489 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2490 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2492 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2493 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2495 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2496 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2498 // these handlers get notified when screen updates are required either when
2499 // scrolling or when the window size (and therefore scrollbar configuration)
2502 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2503 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2504 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2505 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2507 gtk_widget_show( m_wxwindow
);
2510 m_parent
->DoAddChild( this );
2512 m_focusWidget
= m_wxwindow
;
2521 wxWindowGTK::~wxWindowGTK()
2523 if (g_focusWindow
== this)
2524 g_focusWindow
= NULL
;
2526 if (g_activeFrame
== this)
2527 g_activeFrame
= NULL
;
2529 if ( g_delayedFocus
== this )
2530 g_delayedFocus
= NULL
;
2532 m_isBeingDeleted
= TRUE
;
2541 m_parent
->RemoveChild( this );
2545 gdk_ic_destroy (m_ic
);
2547 gdk_ic_attr_destroy (m_icattr
);
2552 #if DISABLE_STYLE_IF_BROKEN_THEME
2553 // don't delete if it's a pixmap theme style
2554 if (!m_widgetStyle
->engine_data
)
2555 gtk_style_unref( m_widgetStyle
);
2557 m_widgetStyle
= (GtkStyle
*) NULL
;
2562 gtk_widget_destroy( m_wxwindow
);
2563 m_wxwindow
= (GtkWidget
*) NULL
;
2568 gtk_widget_destroy( m_widget
);
2569 m_widget
= (GtkWidget
*) NULL
;
2573 bool wxWindowGTK::PreCreation( wxWindowGTK
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2575 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2577 /* this turns -1 into 20 so that a minimal window is
2578 visible even although -1,-1 has been given as the
2579 size of the window. the same trick is used in other
2580 ports and should make debugging easier */
2581 m_width
= WidthDefault(size
.x
);
2582 m_height
= HeightDefault(size
.y
);
2587 /* some reasonable defaults */
2592 m_x
= (gdk_screen_width () - m_width
) / 2;
2593 if (m_x
< 10) m_x
= 10;
2597 m_y
= (gdk_screen_height () - m_height
) / 2;
2598 if (m_y
< 10) m_y
= 10;
2605 void wxWindowGTK::PostCreation()
2607 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2613 // these get reported to wxWindows -> wxPaintEvent
2615 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2617 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2618 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2621 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2622 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2624 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2626 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2627 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2630 gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow
), HasFlag( wxNO_FULL_REPAINT_ON_RESIZE
) );
2634 // these are called when the "sunken" or "raised" borders are drawn
2635 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2636 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2639 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2640 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2646 if (m_focusWidget
== NULL
)
2647 m_focusWidget
= m_widget
;
2649 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event",
2650 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2652 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event",
2653 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2655 // connect to the various key and mouse handlers
2657 GtkWidget
*connect_widget
= GetConnectWidget();
2659 ConnectWidget( connect_widget
);
2661 /* We cannot set colours, fonts and cursors before the widget has
2662 been realized, so we do this directly after realization */
2663 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2664 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2668 // Catch native resize events
2669 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2670 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2672 // Initialize XIM support
2673 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2674 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2676 // And resize XIM window
2677 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2678 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2681 if (!GTK_IS_COMBO(m_widget
))
2683 // This is needed if we want to add our windows into native
2684 // GTK control, such as the toolbar. With this callback, the
2685 // toolbar gets to know the correct size (the one set by the
2686 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2687 // when moving to GTK 2.0.
2688 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2689 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2695 void wxWindowGTK::ConnectWidget( GtkWidget
*widget
)
2697 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2698 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2700 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2701 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2703 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2704 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2706 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2707 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2709 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2710 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2712 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2713 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2715 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2716 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2719 bool wxWindowGTK::Destroy()
2721 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2725 return wxWindowBase::Destroy();
2728 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
)
2730 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2733 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2735 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2736 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") );
2739 printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
2742 if (m_resizing
) return; /* I don't like recursions */
2745 int currentX
, currentY
;
2746 GetPosition(¤tX
, ¤tY
);
2751 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
2753 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2755 /* don't set the size for children of wxNotebook, just take the values. */
2763 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2764 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2766 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2767 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2768 if (width
!= -1) m_width
= width
;
2769 if (height
!= -1) m_height
= height
;
2773 m_x
= x
+ pizza
->xoffset
;
2774 m_y
= y
+ pizza
->yoffset
;
2779 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2781 if (width
== -1) m_width
= 80;
2784 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2786 if (height
== -1) m_height
= 26;
2789 int minWidth
= GetMinWidth(),
2790 minHeight
= GetMinHeight(),
2791 maxWidth
= GetMaxWidth(),
2792 maxHeight
= GetMaxHeight();
2794 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
2795 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
2796 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
2797 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
2800 int bottom_border
= 0;
2803 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2805 /* the default button has a border around it */
2811 DoMoveWindow( m_x
-border
,
2814 m_height
+border
+bottom_border
);
2819 /* Sometimes the client area changes size without the
2820 whole windows's size changing, but if the whole
2821 windows's size doesn't change, no wxSizeEvent will
2822 normally be sent. Here we add an extra test if
2823 the client test has been changed and this will
2825 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2829 wxPrintf( "OnSize sent from " );
2830 if (GetClassInfo() && GetClassInfo()->GetClassName())
2831 wxPrintf( GetClassInfo()->GetClassName() );
2832 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2835 if (!m_nativeSizeEvent
)
2837 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2838 event
.SetEventObject( this );
2839 GetEventHandler()->ProcessEvent( event
);
2845 void wxWindowGTK::OnInternalIdle()
2847 // Update invalidated regions.
2850 // Synthetize activate events.
2851 if ( g_sendActivateEvent
!= -1 )
2853 bool activate
= g_sendActivateEvent
!= 0;
2856 g_sendActivateEvent
= -1;
2858 wxTheApp
->SetActive(activate
, (wxWindow
*)g_focusWindowLast
);
2861 if ( g_activeFrameLostFocus
)
2863 if ( g_activeFrame
)
2865 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame
);
2866 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
2867 event
.SetEventObject(g_activeFrame
);
2868 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
2869 g_activeFrame
= NULL
;
2871 g_activeFrameLostFocus
= FALSE
;
2874 wxCursor cursor
= m_cursor
;
2875 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2879 /* I now set the cursor anew in every OnInternalIdle call
2880 as setting the cursor in a parent window also effects the
2881 windows above so that checking for the current cursor is
2886 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2888 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2890 if (!g_globalCursor
.Ok())
2891 cursor
= *wxSTANDARD_CURSOR
;
2893 window
= m_widget
->window
;
2894 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2895 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2901 GdkWindow
*window
= m_widget
->window
;
2902 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2903 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2911 void wxWindowGTK::DoGetSize( int *width
, int *height
) const
2913 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2915 if (width
) (*width
) = m_width
;
2916 if (height
) (*height
) = m_height
;
2919 void wxWindowGTK::DoSetClientSize( int width
, int height
)
2921 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2925 SetSize( width
, height
);
2932 #ifndef __WXUNIVERSAL__
2933 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2935 /* when using GTK 1.2 we set the shadow border size to 2 */
2939 if (HasFlag(wxSIMPLE_BORDER
))
2941 /* when using GTK 1.2 we set the simple border size to 1 */
2945 #endif // __WXUNIVERSAL__
2949 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2951 GtkRequisition vscroll_req
;
2952 vscroll_req
.width
= 2;
2953 vscroll_req
.height
= 2;
2954 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2955 (scroll_window
->vscrollbar
, &vscroll_req
);
2957 GtkRequisition hscroll_req
;
2958 hscroll_req
.width
= 2;
2959 hscroll_req
.height
= 2;
2960 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2961 (scroll_window
->hscrollbar
, &hscroll_req
);
2963 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2965 if (scroll_window
->vscrollbar_visible
)
2967 dw
+= vscroll_req
.width
;
2968 dw
+= scroll_class
->scrollbar_spacing
;
2971 if (scroll_window
->hscrollbar_visible
)
2973 dh
+= hscroll_req
.height
;
2974 dh
+= scroll_class
->scrollbar_spacing
;
2978 SetSize( width
+dw
, height
+dh
);
2982 void wxWindowGTK::DoGetClientSize( int *width
, int *height
) const
2984 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2988 if (width
) (*width
) = m_width
;
2989 if (height
) (*height
) = m_height
;
2996 #ifndef __WXUNIVERSAL__
2997 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2999 /* when using GTK 1.2 we set the shadow border size to 2 */
3003 if (HasFlag(wxSIMPLE_BORDER
))
3005 /* when using GTK 1.2 we set the simple border size to 1 */
3009 #endif // __WXUNIVERSAL__
3013 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
3015 GtkRequisition vscroll_req
;
3016 vscroll_req
.width
= 2;
3017 vscroll_req
.height
= 2;
3018 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
3019 (scroll_window
->vscrollbar
, &vscroll_req
);
3021 GtkRequisition hscroll_req
;
3022 hscroll_req
.width
= 2;
3023 hscroll_req
.height
= 2;
3024 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
3025 (scroll_window
->hscrollbar
, &hscroll_req
);
3027 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
3029 if (scroll_window
->vscrollbar_visible
)
3031 dw
+= vscroll_req
.width
;
3032 dw
+= scroll_class
->scrollbar_spacing
;
3035 if (scroll_window
->hscrollbar_visible
)
3037 dh
+= hscroll_req
.height
;
3038 dh
+= scroll_class
->scrollbar_spacing
;
3042 if (width
) (*width
) = m_width
- dw
;
3043 if (height
) (*height
) = m_height
- dh
;
3047 printf( "GetClientSize, name %s ", GetName().c_str() );
3048 if (width) printf( " width = %d", (*width) );
3049 if (height) printf( " height = %d", (*height) );
3054 void wxWindowGTK::DoGetPosition( int *x
, int *y
) const
3056 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3060 if (m_parent
&& m_parent
->m_wxwindow
)
3062 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
3063 dx
= pizza
->xoffset
;
3064 dy
= pizza
->yoffset
;
3067 if (x
) (*x
) = m_x
- dx
;
3068 if (y
) (*y
) = m_y
- dy
;
3071 void wxWindowGTK::DoClientToScreen( int *x
, int *y
) const
3073 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3075 if (!m_widget
->window
) return;
3077 GdkWindow
*source
= (GdkWindow
*) NULL
;
3079 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3081 source
= m_widget
->window
;
3085 gdk_window_get_origin( source
, &org_x
, &org_y
);
3089 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3091 org_x
+= m_widget
->allocation
.x
;
3092 org_y
+= m_widget
->allocation
.y
;
3100 void wxWindowGTK::DoScreenToClient( int *x
, int *y
) const
3102 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3104 if (!m_widget
->window
) return;
3106 GdkWindow
*source
= (GdkWindow
*) NULL
;
3108 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3110 source
= m_widget
->window
;
3114 gdk_window_get_origin( source
, &org_x
, &org_y
);
3118 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3120 org_x
+= m_widget
->allocation
.x
;
3121 org_y
+= m_widget
->allocation
.y
;
3129 bool wxWindowGTK::Show( bool show
)
3131 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3133 if (!wxWindowBase::Show(show
))
3140 gtk_widget_show( m_widget
);
3142 gtk_widget_hide( m_widget
);
3147 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
)
3149 win
->OnParentEnable(enable
);
3151 // Recurse, so that children have the opportunity to Do The Right Thing
3152 // and reset colours that have been messed up by a parent's (really ancestor's)
3154 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
3156 node
= node
->GetNext() )
3158 wxWindow
*child
= node
->GetData();
3159 if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
)))
3160 wxWindowNotifyEnable(child
, enable
);
3164 bool wxWindowGTK::Enable( bool enable
)
3166 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3168 if (!wxWindowBase::Enable(enable
))
3174 gtk_widget_set_sensitive( m_widget
, enable
);
3176 gtk_widget_set_sensitive( m_wxwindow
, enable
);
3178 wxWindowNotifyEnable(this, enable
);
3183 int wxWindowGTK::GetCharHeight() const
3185 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
3187 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
3189 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3191 return font
->ascent
+ font
->descent
;
3194 int wxWindowGTK::GetCharWidth() const
3196 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
3198 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
3200 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3202 return gdk_string_width( font
, "H" );
3205 void wxWindowGTK::GetTextExtent( const wxString
& string
,
3209 int *externalLeading
,
3210 const wxFont
*theFont
) const
3212 wxFont fontToUse
= m_font
;
3213 if (theFont
) fontToUse
= *theFont
;
3215 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
3217 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
3218 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
3219 if (y
) (*y
) = font
->ascent
+ font
->descent
;
3220 if (descent
) (*descent
) = font
->descent
;
3221 if (externalLeading
) (*externalLeading
) = 0; // ??
3224 void wxWindowGTK::SetFocus()
3226 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3230 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3232 gtk_widget_grab_focus (m_wxwindow
);
3237 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
3239 if (!GTK_WIDGET_REALIZED(m_widget
))
3241 wxLogTrace(_T("focus"),
3242 _T("Delaying setting focus to %s(%s)\n"),
3243 GetClassInfo()->GetClassName(), GetLabel().c_str());
3245 g_delayedFocus
= this;
3249 wxLogTrace(_T("focus"),
3250 _T("Setting focus to %s(%s)\n"),
3251 GetClassInfo()->GetClassName(), GetLabel().c_str());
3253 gtk_widget_grab_focus (m_widget
);
3256 else if (GTK_IS_CONTAINER(m_widget
))
3258 SET_CONTAINER_FOCUS( m_widget
, GTK_DIR_TAB_FORWARD
);
3266 (void)DoSendFocusEvents((wxWindow
*)this);
3269 bool wxWindowGTK::AcceptsFocus() const
3271 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3274 bool wxWindowGTK::Reparent( wxWindowBase
*newParentBase
)
3276 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3278 wxWindowGTK
*oldParent
= m_parent
,
3279 *newParent
= (wxWindowGTK
*)newParentBase
;
3281 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3283 if ( !wxWindowBase::Reparent(newParent
) )
3286 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3288 /* prevent GTK from deleting the widget arbitrarily */
3289 gtk_widget_ref( m_widget
);
3293 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3296 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3300 /* insert GTK representation */
3301 (*(newParent
->m_insertCallback
))(newParent
, this);
3304 /* reverse: prevent GTK from deleting the widget arbitrarily */
3305 gtk_widget_unref( m_widget
);
3310 void wxWindowGTK::DoAddChild(wxWindowGTK
*child
)
3312 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3314 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3316 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3321 /* insert GTK representation */
3322 (*m_insertCallback
)(this, child
);
3325 void wxWindowGTK::Raise()
3327 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3329 if (!m_widget
->window
) return;
3331 gdk_window_raise( m_widget
->window
);
3334 void wxWindowGTK::Lower()
3336 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3338 if (!m_widget
->window
) return;
3340 gdk_window_lower( m_widget
->window
);
3343 bool wxWindowGTK::SetCursor( const wxCursor
&cursor
)
3345 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3347 if (cursor
== m_cursor
)
3351 wxapp_install_idle_handler();
3353 if (cursor
== wxNullCursor
)
3354 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3356 return wxWindowBase::SetCursor( cursor
);
3359 void wxWindowGTK::WarpPointer( int x
, int y
)
3361 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3363 // We provide this function ourselves as it is
3364 // missing in GDK (top of this file).
3366 GdkWindow
*window
= (GdkWindow
*) NULL
;
3368 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3370 window
= GetConnectWidget()->window
;
3373 gdk_window_warp_pointer( window
, x
, y
);
3376 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect
*rect
)
3378 if (!m_widget
) return;
3379 if (!m_widget
->window
) return;
3383 wxapp_install_idle_handler();
3385 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3389 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3390 m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
3394 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3395 m_clearRegion
.Clear();
3396 m_clearRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height
);
3404 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3405 m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
3409 GdkRectangle gdk_rect
;
3410 gdk_rect
.x
= rect
->x
;
3411 gdk_rect
.y
= rect
->y
;
3412 gdk_rect
.width
= rect
->width
;
3413 gdk_rect
.height
= rect
->height
;
3414 gtk_widget_draw( m_widget
, &gdk_rect
);
3421 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3422 m_updateRegion
.Clear();
3423 m_updateRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height
);
3427 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3435 GdkRectangle gdk_rect
;
3436 gdk_rect
.x
= rect
->x
;
3437 gdk_rect
.y
= rect
->y
;
3438 gdk_rect
.width
= rect
->width
;
3439 gdk_rect
.height
= rect
->height
;
3440 gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, &gdk_rect
, TRUE
);
3444 gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, NULL
, TRUE
);
3450 void wxWindowGTK::Update()
3455 void wxWindowGTK::GtkUpdate()
3458 if (m_wxwindow
&& GTK_PIZZA(m_wxwindow
)->bin_window
)
3459 gdk_window_process_updates( GTK_PIZZA(m_wxwindow
)->bin_window
, FALSE
);
3462 if (!m_updateRegion
.IsEmpty())
3463 GtkSendPaintEvents();
3466 void wxWindowGTK::GtkSendPaintEvents()
3470 m_clearRegion
.Clear();
3471 m_updateRegion
.Clear();
3475 // widget to draw on
3476 GtkPizza
*pizza
= GTK_PIZZA (m_wxwindow
);
3478 // Clip to paint region in wxClientDC
3479 m_clipPaintRegion
= TRUE
;
3481 if (GetThemeEnabled())
3483 // find ancestor from which to steal background
3484 wxWindow
*parent
= GetParent();
3485 while (parent
&& !parent
->IsTopLevel())
3486 parent
= parent
->GetParent();
3488 parent
= (wxWindow
*)this;
3490 wxRegionIterator
upd( m_updateRegion
);
3494 rect
.x
= upd
.GetX();
3495 rect
.y
= upd
.GetY();
3496 rect
.width
= upd
.GetWidth();
3497 rect
.height
= upd
.GetHeight();
3499 gtk_paint_flat_box( parent
->m_widget
->style
,
3512 // if (!m_clearRegion.IsEmpty()) // always send an erase event
3514 wxWindowDC
dc( (wxWindow
*)this );
3515 dc
.SetClippingRegion( m_clearRegion
);
3517 wxEraseEvent
erase_event( GetId(), &dc
);
3518 erase_event
.SetEventObject( this );
3520 if (!GetEventHandler()->ProcessEvent(erase_event
))
3524 g_eraseGC
= gdk_gc_new( pizza
->bin_window
);
3525 gdk_gc_set_fill( g_eraseGC
, GDK_SOLID
);
3527 gdk_gc_set_foreground( g_eraseGC
, m_backgroundColour
.GetColor() );
3529 wxRegionIterator
upd( m_clearRegion
);
3532 gdk_draw_rectangle( pizza
->bin_window
, g_eraseGC
, 1,
3533 upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
3537 m_clearRegion
.Clear();
3540 wxNcPaintEvent
nc_paint_event( GetId() );
3541 nc_paint_event
.SetEventObject( this );
3542 GetEventHandler()->ProcessEvent( nc_paint_event
);
3544 wxPaintEvent
paint_event( GetId() );
3545 paint_event
.SetEventObject( this );
3546 GetEventHandler()->ProcessEvent( paint_event
);
3548 m_clipPaintRegion
= FALSE
;
3550 #ifndef __WXUNIVERSAL__
3552 // The following code will result in all window-less widgets
3553 // being redrawn because the wxWindows class is allowed to
3554 // paint over the window-less widgets.
3556 GList
*children
= pizza
->children
;
3559 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
3560 children
= children
->next
;
3562 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
3563 GTK_WIDGET_DRAWABLE (child
->widget
))
3565 // Get intersection of widget area and update region
3566 wxRegion
region( m_updateRegion
);
3568 GdkEventExpose gdk_event
;
3569 gdk_event
.type
= GDK_EXPOSE
;
3570 gdk_event
.window
= pizza
->bin_window
;
3571 gdk_event
.count
= 0;
3573 wxRegionIterator
upd( m_updateRegion
);
3577 rect
.x
= upd
.GetX();
3578 rect
.y
= upd
.GetY();
3579 rect
.width
= upd
.GetWidth();
3580 rect
.height
= upd
.GetHeight();
3582 if (gtk_widget_intersect (child
->widget
, &rect
, &gdk_event
.area
))
3584 gtk_widget_event (child
->widget
, (GdkEvent
*) &gdk_event
);
3594 m_updateRegion
.Clear();
3597 void wxWindowGTK::Clear()
3599 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3601 if (m_wxwindow
&& m_wxwindow
->window
)
3603 m_clearRegion
.Clear();
3604 wxSize
size( GetClientSize() );
3605 m_clearRegion
.Union( 0,0,size
.x
,size
.y
);
3607 // Better do this in idle?
3613 void wxWindowGTK::DoSetToolTip( wxToolTip
*tip
)
3615 wxWindowBase::DoSetToolTip(tip
);
3618 m_tooltip
->Apply( (wxWindow
*)this );
3621 void wxWindowGTK::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3623 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3625 #endif // wxUSE_TOOLTIPS
3627 void wxWindowGTK::GtkSetBackgroundColour( const wxColour
&colour
)
3629 GdkWindow
*window
= (GdkWindow
*) NULL
;
3631 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3633 window
= GetConnectWidget()->window
;
3637 // We need the pixel value e.g. for background clearing.
3638 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3642 // wxMSW doesn't clear the window here, either.
3643 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3649 bool wxWindowGTK::SetBackgroundColour( const wxColour
&colour
)
3651 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3653 if (!wxWindowBase::SetBackgroundColour(colour
))
3656 GdkWindow
*window
= (GdkWindow
*) NULL
;
3658 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3660 window
= GetConnectWidget()->window
;
3664 // indicate that a new style has been set
3665 // but it couldn't get applied as the
3666 // widget hasn't been realized yet.
3667 m_delayedBackgroundColour
= TRUE
;
3672 GtkSetBackgroundColour( colour
);
3678 void wxWindowGTK::GtkSetForegroundColour( const wxColour
&colour
)
3680 GdkWindow
*window
= (GdkWindow
*) NULL
;
3682 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3684 window
= GetConnectWidget()->window
;
3691 bool wxWindowGTK::SetForegroundColour( const wxColour
&colour
)
3693 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3695 if (!wxWindowBase::SetForegroundColour(colour
))
3697 // don't leave if the GTK widget has just
3699 if (!m_delayedForegroundColour
) return FALSE
;
3702 GdkWindow
*window
= (GdkWindow
*) NULL
;
3704 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3706 window
= GetConnectWidget()->window
;
3710 // indicate that a new style has been set
3711 // but it couldn't get applied as the
3712 // widget hasn't been realized yet.
3713 m_delayedForegroundColour
= TRUE
;
3717 GtkSetForegroundColour( colour
);
3723 GtkStyle
*wxWindowGTK::GetWidgetStyle()
3727 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3729 // FIXME: no more klass in 2.0
3731 remake
->klass
= m_widgetStyle
->klass
;
3734 gtk_style_unref( m_widgetStyle
);
3735 m_widgetStyle
= remake
;
3739 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3742 def
= gtk_widget_get_default_style();
3744 m_widgetStyle
= gtk_style_copy( def
);
3746 // FIXME: no more klass in 2.0
3748 m_widgetStyle
->klass
= def
->klass
;
3752 return m_widgetStyle
;
3755 void wxWindowGTK::SetWidgetStyle()
3757 #if DISABLE_STYLE_IF_BROKEN_THEME
3758 if (m_widget
->style
->engine_data
)
3760 static bool s_warningPrinted
= FALSE
;
3761 if (!s_warningPrinted
)
3763 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3764 s_warningPrinted
= TRUE
;
3766 m_widgetStyle
= m_widget
->style
;
3771 GtkStyle
*style
= GetWidgetStyle();
3773 if (m_font
!= wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT
))
3775 SET_STYLE_FONT(style
, m_font
.GetInternalFont( 1.0 ));
3778 if (m_foregroundColour
.Ok())
3780 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3781 if (m_foregroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT
))
3783 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3784 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3785 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3789 // Try to restore the gtk default style. This is still a little
3790 // oversimplified for what is probably really needed here for controls
3791 // other than buttons, but is better than not being able to (re)set a
3792 // control's foreground colour to *wxBLACK -- RL
3793 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3796 def
= gtk_widget_get_default_style();
3798 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3799 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3800 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3804 if (m_backgroundColour
.Ok())
3806 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3807 if (m_backgroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
))
3809 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3810 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3811 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3812 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3813 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3814 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3815 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3816 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3820 // Try to restore the gtk default style. This is still a little
3821 // oversimplified for what is probably really needed here for controls
3822 // other than buttons, but is better than not being able to (re)set a
3823 // control's background colour to default grey and means resetting a
3824 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3826 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3829 def
= gtk_widget_get_default_style();
3831 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3832 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3833 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3834 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3835 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3836 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3837 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3838 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3843 void wxWindowGTK::ApplyWidgetStyle()
3847 //-----------------------------------------------------------------------------
3848 // Pop-up menu stuff
3849 //-----------------------------------------------------------------------------
3851 #if wxUSE_MENUS_NATIVE
3854 void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3856 *is_waiting
= FALSE
;
3859 static void SetInvokingWindow( wxMenu
*menu
, wxWindowGTK
*win
)
3861 menu
->SetInvokingWindow( win
);
3862 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3865 wxMenuItem
*menuitem
= node
->GetData();
3866 if (menuitem
->IsSubMenu())
3868 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3871 node
= node
->GetNext();
3875 // used to pass the coordinates from wxWindowGTK::DoPopupMenu() to
3876 // wxPopupMenuPositionCallback()
3878 // should be safe even in the MT case as the user can hardly popup 2 menus
3879 // simultaneously, can he?
3880 static gint gs_pop_x
= 0;
3881 static gint gs_pop_y
= 0;
3883 extern "C" void wxPopupMenuPositionCallback( GtkMenu
*menu
,
3886 gboolean
* WXUNUSED(whatever
),
3888 gpointer
WXUNUSED(user_data
) )
3890 // ensure that the menu appears entirely on screen
3892 gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
);
3894 wxSize sizeScreen
= wxGetDisplaySize();
3896 gint xmax
= sizeScreen
.x
- req
.width
,
3897 ymax
= sizeScreen
.y
- req
.height
;
3899 *x
= gs_pop_x
< xmax
? gs_pop_x
: xmax
;
3900 *y
= gs_pop_y
< ymax
? gs_pop_y
: ymax
;
3903 bool wxWindowGTK::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3905 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3907 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3909 SetInvokingWindow( menu
, this );
3915 ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3917 bool is_waiting
= TRUE
;
3919 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
),
3921 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
),
3922 (gpointer
)&is_waiting
);
3925 GTK_MENU(menu
->m_menu
),
3926 (GtkWidget
*) NULL
, // parent menu shell
3927 (GtkWidget
*) NULL
, // parent menu item
3928 wxPopupMenuPositionCallback
, // function to position it
3929 NULL
, // client data
3930 0, // button used to activate it
3931 gs_timeLastClick
// the time of activation
3936 while (gtk_events_pending())
3937 gtk_main_iteration();
3943 #endif // wxUSE_MENUS_NATIVE
3945 #if wxUSE_DRAG_AND_DROP
3947 void wxWindowGTK::SetDropTarget( wxDropTarget
*dropTarget
)
3949 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3951 GtkWidget
*dnd_widget
= GetConnectWidget();
3953 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3955 if (m_dropTarget
) delete m_dropTarget
;
3956 m_dropTarget
= dropTarget
;
3958 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3961 #endif // wxUSE_DRAG_AND_DROP
3963 GtkWidget
* wxWindowGTK::GetConnectWidget()
3965 GtkWidget
*connect_widget
= m_widget
;
3966 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3968 return connect_widget
;
3971 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow
*window
)
3974 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3976 return (window
== m_widget
->window
);
3979 bool wxWindowGTK::SetFont( const wxFont
&font
)
3981 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3983 if (!wxWindowBase::SetFont(font
))
3988 wxColour sysbg
= wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE
);
3989 if ( sysbg
== m_backgroundColour
)
3991 m_backgroundColour
= wxNullColour
;
3993 m_backgroundColour
= sysbg
;
4003 void wxWindowGTK::DoCaptureMouse()
4005 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4007 GdkWindow
*window
= (GdkWindow
*) NULL
;
4009 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
4011 window
= GetConnectWidget()->window
;
4013 wxCHECK_RET( window
, _T("CaptureMouse() failed") );
4015 wxCursor
* cursor
= & m_cursor
;
4017 cursor
= wxSTANDARD_CURSOR
;
4019 gdk_pointer_grab( window
, FALSE
,
4021 (GDK_BUTTON_PRESS_MASK
|
4022 GDK_BUTTON_RELEASE_MASK
|
4023 GDK_POINTER_MOTION_HINT_MASK
|
4024 GDK_POINTER_MOTION_MASK
),
4026 cursor
->GetCursor(),
4027 (guint32
)GDK_CURRENT_TIME
);
4028 g_captureWindow
= this;
4029 g_captureWindowHasMouse
= TRUE
;
4032 void wxWindowGTK::DoReleaseMouse()
4034 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4036 wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") );
4038 g_captureWindow
= (wxWindowGTK
*) NULL
;
4040 GdkWindow
*window
= (GdkWindow
*) NULL
;
4042 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
4044 window
= GetConnectWidget()->window
;
4049 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
4053 wxWindow
*wxWindowBase::GetCapture()
4055 return (wxWindow
*)g_captureWindow
;
4058 bool wxWindowGTK::IsRetained() const
4063 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
,
4064 int range
, bool refresh
)
4066 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4068 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4070 m_hasScrolling
= TRUE
;
4072 if (orient
== wxHORIZONTAL
)
4074 float fpos
= (float)pos
;
4075 float frange
= (float)range
;
4076 float fthumb
= (float)thumbVisible
;
4077 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
4078 if (fpos
< 0.0) fpos
= 0.0;
4080 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
4081 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
4083 SetScrollPos( orient
, pos
, refresh
);
4087 m_oldHorizontalPos
= fpos
;
4089 m_hAdjust
->lower
= 0.0;
4090 m_hAdjust
->upper
= frange
;
4091 m_hAdjust
->value
= fpos
;
4092 m_hAdjust
->step_increment
= 1.0;
4093 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
4094 m_hAdjust
->page_size
= fthumb
;
4098 float fpos
= (float)pos
;
4099 float frange
= (float)range
;
4100 float fthumb
= (float)thumbVisible
;
4101 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
4102 if (fpos
< 0.0) fpos
= 0.0;
4104 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
4105 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
4107 SetScrollPos( orient
, pos
, refresh
);
4111 m_oldVerticalPos
= fpos
;
4113 m_vAdjust
->lower
= 0.0;
4114 m_vAdjust
->upper
= frange
;
4115 m_vAdjust
->value
= fpos
;
4116 m_vAdjust
->step_increment
= 1.0;
4117 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
4118 m_vAdjust
->page_size
= fthumb
;
4121 if (orient
== wxHORIZONTAL
)
4122 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
4124 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
4127 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
4129 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4131 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4133 if (orient
== wxHORIZONTAL
)
4135 float fpos
= (float)pos
;
4136 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
4137 if (fpos
< 0.0) fpos
= 0.0;
4138 m_oldHorizontalPos
= fpos
;
4140 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
4141 m_hAdjust
->value
= fpos
;
4145 float fpos
= (float)pos
;
4146 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
4147 if (fpos
< 0.0) fpos
= 0.0;
4148 m_oldVerticalPos
= fpos
;
4150 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
4151 m_vAdjust
->value
= fpos
;
4154 if (m_wxwindow
->window
)
4156 if (orient
== wxHORIZONTAL
)
4158 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
4159 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
4161 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
4163 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
4164 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
4168 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
4169 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4171 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
4173 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
4174 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4179 int wxWindowGTK::GetScrollThumb( int orient
) const
4181 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4183 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4185 if (orient
== wxHORIZONTAL
)
4186 return (int)(m_hAdjust
->page_size
+0.5);
4188 return (int)(m_vAdjust
->page_size
+0.5);
4191 int wxWindowGTK::GetScrollPos( int orient
) const
4193 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4195 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4197 if (orient
== wxHORIZONTAL
)
4198 return (int)(m_hAdjust
->value
+0.5);
4200 return (int)(m_vAdjust
->value
+0.5);
4203 int wxWindowGTK::GetScrollRange( int orient
) const
4205 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4207 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4209 if (orient
== wxHORIZONTAL
)
4210 return (int)(m_hAdjust
->upper
+0.5);
4212 return (int)(m_vAdjust
->upper
+0.5);
4215 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
4217 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4219 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4221 // No scrolling requested.
4222 if ((dx
== 0) && (dy
== 0)) return;
4225 if (!m_updateRegion
.IsEmpty())
4227 m_updateRegion
.Offset( dx
, dy
);
4231 GetClientSize( &cw
, &ch
);
4232 m_updateRegion
.Intersect( 0, 0, cw
, ch
);
4235 if (!m_clearRegion
.IsEmpty())
4237 m_clearRegion
.Offset( dx
, dy
);
4241 GetClientSize( &cw
, &ch
);
4242 m_clearRegion
.Intersect( 0, 0, cw
, ch
);
4245 m_clipPaintRegion
= TRUE
;
4247 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
4249 m_clipPaintRegion
= FALSE
;
4252 gdk_window_scroll( GTK_PIZZA(m_wxwindow
)->bin_window
, dx
, dy
);
4254 GTK_PIZZA(m_wxwindow
)->xoffset
+= dx
;
4255 GTK_PIZZA(m_wxwindow
)->yoffset
+= dy
;
4262 // Find the wxWindow at the current mouse position, also returning the mouse
4264 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
4266 pt
= wxGetMousePosition();
4267 wxWindow
* found
= wxFindWindowAtPoint(pt
);
4271 // Get the current mouse position.
4272 wxPoint
wxGetMousePosition()
4274 /* This crashes when used within wxHelpContext,
4275 so we have to use the X-specific implementation below.
4277 GdkModifierType *mask;
4278 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
4280 return wxPoint(x, y);
4284 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
4286 return wxPoint(-999, -999);
4288 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
4289 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
4290 Window rootReturn
, childReturn
;
4291 int rootX
, rootY
, winX
, winY
;
4292 unsigned int maskReturn
;
4294 XQueryPointer (display
,
4298 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
4299 return wxPoint(rootX
, rootY
);
4303 // ----------------------------------------------------------------------------
4305 // ----------------------------------------------------------------------------
4307 class wxWinModule
: public wxModule
4314 DECLARE_DYNAMIC_CLASS(wxWinModule
)
4317 IMPLEMENT_DYNAMIC_CLASS(wxWinModule
, wxModule
)
4319 bool wxWinModule::OnInit()
4321 // g_eraseGC = gdk_gc_new( GDK_ROOT_PARENT() );
4322 // gdk_gc_set_fill( g_eraseGC, GDK_SOLID );
4327 void wxWinModule::OnExit()
4330 gdk_gc_unref( g_eraseGC
);