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"
59 #include "wx/gtk/private.h"
60 #include <gdk/gdkprivate.h>
61 #include <gdk/gdkkeysyms.h>
65 #include <gtk/gtkprivate.h>
67 #include "wx/gtk/win_gtk.h"
70 #define SET_CONTAINER_FOCUS(w, d) gtk_widget_child_focus((w), (d))
72 #define SET_CONTAINER_FOCUS(w, d) gtk_container_focus(GTK_CONTAINER(w), (d))
82 extern GtkContainerClass
*pizza_parent_class
;
85 //-----------------------------------------------------------------------------
86 // documentation on internals
87 //-----------------------------------------------------------------------------
90 I have been asked several times about writing some documentation about
91 the GTK port of wxWindows, especially its internal structures. Obviously,
92 you cannot understand wxGTK without knowing a little about the GTK, but
93 some more information about what the wxWindow, which is the base class
94 for all other window classes, does seems required as well.
98 What does wxWindow do? It contains the common interface for the following
99 jobs of its descendants:
101 1) Define the rudimentary behaviour common to all window classes, such as
102 resizing, intercepting user input (so as to make it possible to use these
103 events for special purposes in a derived class), window names etc.
105 2) Provide the possibility to contain and manage children, if the derived
106 class is allowed to contain children, which holds true for those window
107 classes which do not display a native GTK widget. To name them, these
108 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
109 work classes are a special case and are handled a bit differently from
110 the rest. The same holds true for the wxNotebook class.
112 3) Provide the possibility to draw into a client area of a window. This,
113 too, only holds true for classes that do not display a native GTK widget
116 4) Provide the entire mechanism for scrolling widgets. This actual inter-
117 face for this is usually in wxScrolledWindow, but the GTK implementation
120 5) A multitude of helper or extra methods for special purposes, such as
121 Drag'n'Drop, managing validators etc.
123 6) Display a border (sunken, raised, simple or none).
125 Normally one might expect, that one wxWindows window would always correspond
126 to one GTK widget. Under GTK, there is no such allround widget that has all
127 the functionality. Moreover, the GTK defines a client area as a different
128 widget from the actual widget you are handling. Last but not least some
129 special classes (e.g. wxFrame) handle different categories of widgets and
130 still have the possibility to draw something in the client area.
131 It was therefore required to write a special purpose GTK widget, that would
132 represent a client area in the sense of wxWindows capable to do the jobs
133 2), 3) and 4). I have written this class and it resides in win_gtk.c of
136 All windows must have a widget, with which they interact with other under-
137 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
138 thw wxWindow class has a member variable called m_widget which holds a
139 pointer to this widget. When the window class represents a GTK native widget,
140 this is (in most cases) the only GTK widget the class manages. E.g. the
141 wxStatitText class handles only a GtkLabel widget a pointer to which you
142 can find in m_widget (defined in wxWindow)
144 When the class has a client area for drawing into and for containing children
145 it has to handle the client area widget (of the type GtkPizza, defined in
146 win_gtk.c), but there could be any number of widgets, handled by a class
147 The common rule for all windows is only, that the widget that interacts with
148 the rest of GTK must be referenced in m_widget and all other widgets must be
149 children of this widget on the GTK level. The top-most widget, which also
150 represents the client area, must be in the m_wxwindow field and must be of
153 As I said, the window classes that display a GTK native widget only have
154 one widget, so in the case of e.g. the wxButton class m_widget holds a
155 pointer to a GtkButton widget. But windows with client areas (for drawing
156 and children) have a m_widget field that is a pointer to a GtkScrolled-
157 Window and a m_wxwindow field that is pointer to a GtkPizza and this
158 one is (in the GTK sense) a child of the GtkScrolledWindow.
160 If the m_wxwindow field is set, then all input to this widget is inter-
161 cepted and sent to the wxWindows class. If not, all input to the widget
162 that gets pointed to by m_widget gets intercepted and sent to the class.
166 The design of scrolling in wxWindows is markedly different from that offered
167 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
168 clicking on a scrollbar belonging to scrolled window will inevitably move
169 the window. In wxWindows, the scrollbar will only emit an event, send this
170 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
171 which actually moves the window and its subchildren. Note that GtkPizza
172 memorizes how much it has been scrolled but that wxWindows forgets this
173 so that the two coordinates systems have to be kept in synch. This is done
174 in various places using the pizza->xoffset and pizza->yoffset values.
178 Singularily the most broken code in GTK is the code that is supposes to
179 inform subwindows (child windows) about new positions. Very often, duplicate
180 events are sent without changes in size or position, equally often no
181 events are sent at all (All this is due to a bug in the GtkContainer code
182 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
183 GTK's own system and it simply waits for size events for toplevel windows
184 and then iterates down the respective size events to all window. This has
185 the disadvantage, that windows might get size events before the GTK widget
186 actually has the reported size. This doesn't normally pose any problem, but
187 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
188 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
189 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
190 window that is used for OpenGl output really has that size (as reported by
195 If someone at some point of time feels the immense desire to have a look at,
196 change or attempt to optimse the Refresh() logic, this person will need an
197 intimate understanding of what a "draw" and what an "expose" events are and
198 what there are used for, in particular when used in connection with GTK's
199 own windowless widgets. Beware.
203 Cursors, too, have been a constant source of pleasure. The main difficulty
204 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
205 for the parent. To prevent this from doing too much harm, I use idle time
206 to set the cursor over and over again, starting from the toplevel windows
207 and ending with the youngest generation (speaking of parent and child windows).
208 Also don't forget that cursors (like much else) are connected to GdkWindows,
209 not GtkWidgets and that the "window" field of a GtkWidget might very well
210 point to the GdkWindow of the parent widget (-> "window less widget") and
211 that the two obviously have very different meanings.
215 //-----------------------------------------------------------------------------
217 //-----------------------------------------------------------------------------
219 extern wxList wxPendingDelete
;
220 extern bool g_blockEventsOnDrag
;
221 extern bool g_blockEventsOnScroll
;
222 extern wxCursor g_globalCursor
;
224 static GdkGC
*g_eraseGC
= NULL
;
226 // mouse capture state: the window which has it and if the mouse is currently
228 static wxWindowGTK
*g_captureWindow
= (wxWindowGTK
*) NULL
;
229 static bool g_captureWindowHasMouse
= FALSE
;
231 /* extern */ wxWindowGTK
*g_focusWindow
= (wxWindowGTK
*) NULL
;
233 // the last window which had the focus - this is normally never NULL (except
234 // if we never had focus at all) as even when g_focusWindow is NULL it still
235 // keeps its previous value
236 static wxWindowGTK
*g_focusWindowLast
= (wxWindowGTK
*) NULL
;
238 // the frame that is currently active (i.e. its child has focus). It is
239 // used to generate wxActivateEvents
240 static wxWindowGTK
*g_activeFrame
= (wxWindowGTK
*) NULL
;
241 static bool g_activeFrameLostFocus
= FALSE
;
243 // If a window get the focus set but has not been realized
244 // yet, defer setting the focus to idle time.
245 wxWindowGTK
*g_delayedFocus
= (wxWindowGTK
*) NULL
;
247 // if we detect that the app has got/lost the focus, we set this variable to
248 // either TRUE or FALSE and an activate event will be sent during the next
249 // OnIdle() call and it is reset to -1: this value means that we shouldn't
250 // send any activate events at all
251 static int g_sendActivateEvent
= -1;
253 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
254 the last click here */
255 static guint32 gs_timeLastClick
= 0;
257 extern bool g_mainThreadLocked
;
259 //-----------------------------------------------------------------------------
261 //-----------------------------------------------------------------------------
264 #define DISABLE_STYLE_IF_BROKEN_THEME 1
270 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
272 # define DEBUG_MAIN_THREAD
275 #define DEBUG_MAIN_THREAD
278 // the trace mask used for the focus debugging messages
279 #define TRACE_FOCUS _T("focus")
281 //-----------------------------------------------------------------------------
282 // missing gdk functions
283 //-----------------------------------------------------------------------------
286 gdk_window_warp_pointer (GdkWindow
*window
,
291 GdkWindowPrivate
*priv
;
295 window
= GDK_ROOT_PARENT();
298 if (!GDK_WINDOW_DESTROYED(window
))
300 XWarpPointer (GDK_WINDOW_XDISPLAY(window
),
301 None
, /* not source window -> move from anywhere */
302 GDK_WINDOW_XID(window
), /* dest window */
303 0, 0, 0, 0, /* not source window -> move from anywhere */
307 priv
= (GdkWindowPrivate
*) window
;
309 if (!priv
->destroyed
)
311 XWarpPointer (priv
->xdisplay
,
312 None
, /* not source window -> move from anywhere */
313 priv
->xwindow
, /* dest window */
314 0, 0, 0, 0, /* not source window -> move from anywhere */
320 //-----------------------------------------------------------------------------
322 //-----------------------------------------------------------------------------
324 extern void wxapp_install_idle_handler();
325 extern bool g_isIdle
;
327 //-----------------------------------------------------------------------------
328 // local code (see below)
329 //-----------------------------------------------------------------------------
331 // returns the child of win which currently has focus or NULL if not found
333 // Note: can't be static, needed by textctrl.cpp.
334 wxWindow
*wxFindFocusedChild(wxWindowGTK
*win
)
336 wxWindow
*winFocus
= wxWindowGTK::FindFocus();
338 return (wxWindow
*)NULL
;
340 if ( winFocus
== win
)
341 return (wxWindow
*)win
;
343 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
345 node
= node
->GetNext() )
347 wxWindow
*child
= wxFindFocusedChild(node
->GetData());
352 return (wxWindow
*)NULL
;
355 static void draw_frame( GtkWidget
*widget
, wxWindowGTK
*win
)
357 // wxUniversal widgets draw the borders and scrollbars themselves
358 #ifndef __WXUNIVERSAL__
365 if (win
->m_hasScrolling
)
367 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
369 GtkRequisition vscroll_req
;
370 vscroll_req
.width
= 2;
371 vscroll_req
.height
= 2;
372 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
373 (scroll_window
->vscrollbar
, &vscroll_req
);
375 GtkRequisition hscroll_req
;
376 hscroll_req
.width
= 2;
377 hscroll_req
.height
= 2;
378 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
379 (scroll_window
->hscrollbar
, &hscroll_req
);
381 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) );
383 if (scroll_window
->vscrollbar_visible
)
385 dw
+= vscroll_req
.width
;
386 dw
+= scroll_class
->scrollbar_spacing
;
389 if (scroll_window
->hscrollbar_visible
)
391 dh
+= hscroll_req
.height
;
392 dh
+= scroll_class
->scrollbar_spacing
;
398 if (GTK_WIDGET_NO_WINDOW (widget
))
400 dx
+= widget
->allocation
.x
;
401 dy
+= widget
->allocation
.y
;
404 if (win
->HasFlag(wxRAISED_BORDER
))
406 gtk_draw_shadow( widget
->style
,
411 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
415 if (win
->HasFlag(wxSUNKEN_BORDER
))
417 gtk_draw_shadow( widget
->style
,
422 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
426 if (win
->HasFlag(wxSIMPLE_BORDER
))
429 gc
= gdk_gc_new( widget
->window
);
430 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
431 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
433 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
437 #endif // __WXUNIVERSAL__
440 //-----------------------------------------------------------------------------
441 // "expose_event" of m_widget
442 //-----------------------------------------------------------------------------
444 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindowGTK
*win
)
446 if (gdk_event
->count
> 0) return FALSE
;
448 draw_frame( widget
, win
);
452 (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
);
458 //-----------------------------------------------------------------------------
459 // "draw" of m_widget
460 //-----------------------------------------------------------------------------
464 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindowGTK
*win
)
466 draw_frame( widget
, win
);
471 //-----------------------------------------------------------------------------
472 // "size_request" of m_widget
473 //-----------------------------------------------------------------------------
475 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
478 win
->GetSize( &w
, &h
);
482 requisition
->height
= h
;
483 requisition
->width
= w
;
486 //-----------------------------------------------------------------------------
487 // "expose_event" of m_wxwindow
488 //-----------------------------------------------------------------------------
490 static int gtk_window_expose_callback( GtkWidget
*widget
,
491 GdkEventExpose
*gdk_event
,
497 wxapp_install_idle_handler();
502 wxPrintf( wxT("OnExpose from ") );
503 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
504 wxPrintf( win
->GetClassInfo()->GetClassName() );
505 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event
->area
.x
,
506 (int)gdk_event
->area
.y
,
507 (int)gdk_event
->area
.width
,
508 (int)gdk_event
->area
.height
);
512 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
514 gdk_event
->area
.width
,
515 gdk_event
->area
.height
);
516 win
->m_clearRegion
.Union( gdk_event
->area
.x
,
518 gdk_event
->area
.width
,
519 gdk_event
->area
.height
);
521 // Actual redrawing takes place in idle time.
526 (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
);
533 //-----------------------------------------------------------------------------
534 // "event" of m_wxwindow
535 //-----------------------------------------------------------------------------
537 // GTK thinks it is clever and filters out a certain amount of "unneeded"
538 // expose events. We need them, of course, so we override the main event
539 // procedure in GtkWidget by giving our own handler for all system events.
540 // There, we look for expose events ourselves whereas all other events are
543 gint
gtk_window_event_event_callback( GtkWidget
*widget
,
544 GdkEventExpose
*event
,
547 if (event
->type
== GDK_EXPOSE
)
549 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
556 //-----------------------------------------------------------------------------
557 // "draw" of m_wxwindow
558 //-----------------------------------------------------------------------------
562 // This callback is a complete replacement of the gtk_pizza_draw() function,
563 // which is disabled.
565 static void gtk_window_draw_callback( GtkWidget
*widget
,
572 wxapp_install_idle_handler();
574 // The wxNO_FULL_REPAINT_ON_RESIZE flag only works if
575 // there are no child windows.
576 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
577 (win
->GetChildren().GetCount() == 0))
585 wxPrintf( wxT("OnDraw from ") );
586 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
587 wxPrintf( win
->GetClassInfo()->GetClassName() );
588 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect
->x
,
595 #ifndef __WXUNIVERSAL__
596 GtkPizza
*pizza
= GTK_PIZZA (widget
);
598 if (win
->GetThemeEnabled())
600 wxWindow
*parent
= win
->GetParent();
601 while (parent
&& !parent
->IsTopLevel())
602 parent
= parent
->GetParent();
606 gtk_paint_flat_box (parent
->m_widget
->style
,
617 win
->m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
618 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
620 // Update immediately, not 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 = %ld"),
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 %ld"), 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
)
1063 wxKeyEvent
event( wxEVT_KEY_DOWN
);
1064 if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) )
1066 // unknown key pressed, ignore (the event would be useless anyhow)
1070 // Emit KEY_DOWN event
1071 bool ret
= win
->GetEventHandler()->ProcessEvent( event
);
1076 wxWindowGTK
*ancestor
= win
;
1079 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
1082 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
1083 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
1086 if (ancestor
->IsTopLevel())
1088 ancestor
= ancestor
->GetParent();
1091 #endif // wxUSE_ACCEL
1093 // Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
1094 // will only be sent if it is not in an accelerator table.
1097 // Find key code for EVT_CHAR and EVT_CHAR_HOOK events
1098 KeySym keysym
= gdk_event
->keyval
;
1099 long key_code
= wxTranslateKeySymToWXKey(keysym
, TRUE
/* isChar */);
1102 if ( gdk_event
->length
== 1 )
1104 key_code
= (unsigned char)gdk_event
->string
[0];
1106 else if ( wxIsAsciiKeysym(keysym
) )
1109 key_code
= (unsigned char)keysym
;
1115 wxLogTrace(TRACE_KEYS
, _T("Char event: %ld"), key_code
);
1117 event
.m_keyCode
= key_code
;
1119 // Implement OnCharHook by checking ancesteror top level windows
1120 wxWindow
*parent
= win
;
1121 while (parent
&& !parent
->IsTopLevel())
1122 parent
= parent
->GetParent();
1125 event
.SetEventType( wxEVT_CHAR_HOOK
);
1126 ret
= parent
->GetEventHandler()->ProcessEvent( event
);
1131 event
.SetEventType(wxEVT_CHAR
);
1132 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1137 // win is a control: tab can be propagated up
1139 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
1140 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
1141 // have this style, yet choose not to process this particular TAB in which
1142 // case TAB must still work as a navigational character
1144 !win
->HasFlag(wxTE_PROCESS_TAB
) &&
1146 win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
1148 wxNavigationKeyEvent new_event
;
1149 new_event
.SetEventObject( win
->GetParent() );
1150 // GDK reports GDK_ISO_Left_Tab for SHIFT-TAB
1151 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
1152 // CTRL-TAB changes the (parent) window, i.e. switch notebook page
1153 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
1154 new_event
.SetCurrentFocus( win
);
1155 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
1158 // generate wxID_CANCEL if <esc> has been pressed (typically in dialogs)
1160 (gdk_event
->keyval
== GDK_Escape
) )
1162 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
1163 new_event
.SetEventObject( win
);
1164 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
1169 // Pressing F10 will activate the menu bar of the top frame
1171 (gdk_event
->keyval
== GDK_F10
) )
1173 wxWindowGTK
*ancestor
= win
;
1176 if (wxIsKindOf(ancestor
,wxFrame
))
1178 wxFrame
*frame
= (wxFrame
*) ancestor
;
1179 wxMenuBar
*menubar
= frame
->GetMenuBar();
1182 wxNode
*node
= menubar
->GetMenus().First();
1185 wxMenu
*firstMenu
= (wxMenu
*) node
->Data();
1186 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu
->m_owner
) );
1192 ancestor
= ancestor
->GetParent();
1199 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1206 //-----------------------------------------------------------------------------
1207 // "key_release_event" from any window
1208 //-----------------------------------------------------------------------------
1210 static gint
gtk_window_key_release_callback( GtkWidget
*widget
,
1211 GdkEventKey
*gdk_event
,
1217 wxapp_install_idle_handler();
1222 if (g_blockEventsOnDrag
)
1225 wxKeyEvent
event( wxEVT_KEY_UP
);
1226 if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) )
1228 // unknown key pressed, ignore (the event would be useless anyhow
1232 if ( !win
->GetEventHandler()->ProcessEvent( event
) )
1235 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1239 // ============================================================================
1241 // ============================================================================
1243 // ----------------------------------------------------------------------------
1244 // mouse event processing helpers
1245 // ----------------------------------------------------------------------------
1247 // init wxMouseEvent with the info from gdk_event
1249 // NB: this has to be a macro as gdk_event type is different for different
1250 // events we're used with
1251 #define InitMouseEvent(/* wxWindowGTK * */ win, \
1252 /* wxMouseEvent& */ event, \
1253 /* GdkEventXXX * */ gdk_event) \
1255 event.SetTimestamp( gdk_event->time ); \
1256 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
1257 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
1258 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
1259 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
1260 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
1261 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
1262 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
1264 wxPoint pt = win->GetClientAreaOrigin(); \
1265 event.m_x = (wxCoord)gdk_event->x - pt.x; \
1266 event.m_y = (wxCoord)gdk_event->y - pt.y; \
1268 event.SetEventObject( win ); \
1269 event.SetId( win->GetId() ); \
1270 event.SetTimestamp( gdk_event->time ); \
1273 static void AdjustEventButtonState(wxMouseEvent& event)
1275 // GDK reports the old state of the button for a button press event, but
1276 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1277 // for a LEFT_DOWN event, not FALSE, so we will invert
1278 // left/right/middleDown for the corresponding click events
1280 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1281 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1282 (event
.GetEventType() == wxEVT_LEFT_UP
))
1284 event
.m_leftDown
= !event
.m_leftDown
;
1288 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1289 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1290 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1292 event
.m_middleDown
= !event
.m_middleDown
;
1296 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1297 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1298 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1300 event
.m_rightDown
= !event
.m_rightDown
;
1305 // find the window to send the mouse event too
1307 wxWindowGTK
*FindWindowForMouseEvent(wxWindowGTK
*win
, wxCoord
& x
, wxCoord
& y
)
1312 if (win
->m_wxwindow
)
1314 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1315 xx
+= pizza
->xoffset
;
1316 yy
+= pizza
->yoffset
;
1319 wxNode
*node
= win
->GetChildren().First();
1322 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1324 node
= node
->Next();
1325 if (!child
->IsShown())
1328 if (child
->IsTransparentForMouse())
1330 // wxStaticBox is transparent in the box itself
1331 int xx1
= child
->m_x
;
1332 int yy1
= child
->m_y
;
1333 int xx2
= child
->m_x
+ child
->m_width
;
1334 int yy2
= child
->m_x
+ child
->m_height
;
1337 if (((xx
>= xx1
) && (xx
<= xx1
+10) && (yy
>= yy1
) && (yy
<= yy2
)) ||
1339 ((xx
>= xx2
-10) && (xx
<= xx2
) && (yy
>= yy1
) && (yy
<= yy2
)) ||
1341 ((xx
>= xx1
) && (xx
<= xx2
) && (yy
>= yy1
) && (yy
<= yy1
+10)) ||
1343 ((xx
>= xx1
) && (xx
<= xx2
) && (yy
>= yy2
-1) && (yy
<= yy2
)))
1354 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1355 (child
->m_x
<= xx
) &&
1356 (child
->m_y
<= yy
) &&
1357 (child
->m_x
+child
->m_width
>= xx
) &&
1358 (child
->m_y
+child
->m_height
>= yy
))
1371 //-----------------------------------------------------------------------------
1372 // "button_press_event"
1373 //-----------------------------------------------------------------------------
1375 static gint
gtk_window_button_press_callback( GtkWidget
*widget
,
1376 GdkEventButton
*gdk_event
,
1382 wxapp_install_idle_handler();
1385 wxPrintf( wxT("1) OnButtonPress from ") );
1386 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1387 wxPrintf( win->GetClassInfo()->GetClassName() );
1388 wxPrintf( wxT(".\n") );
1390 if (!win
->m_hasVMT
) return FALSE
;
1391 if (g_blockEventsOnDrag
) return TRUE
;
1392 if (g_blockEventsOnScroll
) return TRUE
;
1394 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1396 if (win
->m_wxwindow
&& (g_focusWindow
!= win
) && win
->AcceptsFocus())
1398 gtk_widget_grab_focus( win
->m_wxwindow
);
1400 wxPrintf( wxT("GrabFocus from ") );
1401 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1402 wxPrintf( win->GetClassInfo()->GetClassName() );
1403 wxPrintf( wxT(".\n") );
1407 wxEventType event_type
= wxEVT_NULL
;
1409 if (gdk_event
->button
== 1)
1411 switch (gdk_event
->type
)
1413 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1414 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1418 else if (gdk_event
->button
== 2)
1420 switch (gdk_event
->type
)
1422 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1423 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1427 else if (gdk_event
->button
== 3)
1429 switch (gdk_event
->type
)
1431 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1432 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1437 if ( event_type
== wxEVT_NULL
)
1439 // unknown mouse button or click type
1443 wxMouseEvent
event( event_type
);
1444 InitMouseEvent( win
, event
, gdk_event
);
1446 AdjustEventButtonState(event
);
1448 // wxListBox actually get mouse events from the item, so we need to give it
1449 // a chance to correct this
1450 win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
);
1452 // find the correct window to send the event too: it may be a different one
1453 // from the one which got it at GTK+ level because some control don't have
1454 // their own X window and thus cannot get any events.
1455 if ( !g_captureWindow
)
1456 win
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
);
1458 gs_timeLastClick
= gdk_event
->time
;
1461 wxPrintf( wxT("2) OnButtonPress from ") );
1462 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1463 wxPrintf( win->GetClassInfo()->GetClassName() );
1464 wxPrintf( wxT(".\n") );
1467 if (win
->GetEventHandler()->ProcessEvent( event
))
1469 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1476 //-----------------------------------------------------------------------------
1477 // "button_release_event"
1478 //-----------------------------------------------------------------------------
1480 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1485 wxapp_install_idle_handler();
1487 if (!win
->m_hasVMT
) return FALSE
;
1488 if (g_blockEventsOnDrag
) return FALSE
;
1489 if (g_blockEventsOnScroll
) return FALSE
;
1491 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1494 printf( "OnButtonRelease from " );
1495 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1496 printf( win->GetClassInfo()->GetClassName() );
1500 wxEventType event_type
= wxEVT_NULL
;
1502 switch (gdk_event
->button
)
1504 case 1: event_type
= wxEVT_LEFT_UP
; break;
1505 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1506 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1507 default: return FALSE
;
1510 wxMouseEvent
event( event_type
);
1511 InitMouseEvent( win
, event
, gdk_event
);
1513 AdjustEventButtonState(event
);
1515 // same wxListBox hack as above
1516 win
->FixUpMouseEvent(widget
, event
.m_x
, event
.m_y
);
1518 if ( !g_captureWindow
)
1519 win
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
);
1521 if (win
->GetEventHandler()->ProcessEvent( event
))
1523 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1530 //-----------------------------------------------------------------------------
1531 // "motion_notify_event"
1532 //-----------------------------------------------------------------------------
1534 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
,
1535 GdkEventMotion
*gdk_event
,
1541 wxapp_install_idle_handler();
1543 if (!win
->m_hasVMT
) return FALSE
;
1544 if (g_blockEventsOnDrag
) return FALSE
;
1545 if (g_blockEventsOnScroll
) return FALSE
;
1547 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1549 if (gdk_event
->is_hint
)
1553 GdkModifierType state
;
1554 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1560 printf( "OnMotion from " );
1561 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1562 printf( win->GetClassInfo()->GetClassName() );
1566 wxMouseEvent
event( wxEVT_MOTION
);
1567 InitMouseEvent(win
, event
, gdk_event
);
1569 if ( g_captureWindow
)
1571 // synthetize a mouse enter or leave event if needed
1572 GdkWindow
*winUnderMouse
= gdk_window_at_pointer(NULL
, NULL
);
1573 bool hasMouse
= winUnderMouse
== gdk_event
->window
;
1574 if ( hasMouse
!= g_captureWindowHasMouse
)
1576 // the mouse changed window
1577 g_captureWindowHasMouse
= hasMouse
;
1579 wxMouseEvent
event(g_captureWindowHasMouse
? wxEVT_ENTER_WINDOW
1580 : wxEVT_LEAVE_WINDOW
);
1581 InitMouseEvent(win
, event
, gdk_event
);
1582 event
.SetEventObject(win
);
1583 win
->GetEventHandler()->ProcessEvent(event
);
1588 win
= FindWindowForMouseEvent(win
, event
.m_x
, event
.m_y
);
1591 if (win
->GetEventHandler()->ProcessEvent( event
))
1593 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1600 //-----------------------------------------------------------------------------
1602 //-----------------------------------------------------------------------------
1604 // send the wxChildFocusEvent and wxFocusEvent, common code of
1605 // gtk_window_focus_in_callback() and SetFocus()
1606 static bool DoSendFocusEvents(wxWindow
*win
)
1608 // Notify the parent keeping track of focus for the kbd navigation
1609 // purposes that we got it.
1610 wxChildFocusEvent
eventChildFocus(win
);
1611 (void)win
->GetEventHandler()->ProcessEvent(eventChildFocus
);
1613 wxFocusEvent
eventFocus(wxEVT_SET_FOCUS
, win
->GetId());
1614 eventFocus
.SetEventObject(win
);
1616 return win
->GetEventHandler()->ProcessEvent(eventFocus
);
1619 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
,
1620 GdkEvent
*WXUNUSED(event
),
1626 wxapp_install_idle_handler();
1628 if (!win
->m_hasVMT
) return FALSE
;
1629 if (g_blockEventsOnDrag
) return FALSE
;
1631 switch ( g_sendActivateEvent
)
1634 // we've got focus from outside, synthetize wxActivateEvent
1635 g_sendActivateEvent
= 1;
1639 // another our window just lost focus, it was already ours before
1640 // - don't send any wxActivateEvent
1641 g_sendActivateEvent
= -1;
1646 g_focusWindow
= win
;
1648 wxLogTrace(TRACE_FOCUS
,
1649 _T("%s: focus in"), win
->GetName().c_str());
1653 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1657 // caret needs to be informed about focus change
1658 wxCaret
*caret
= win
->GetCaret();
1661 caret
->OnSetFocus();
1663 #endif // wxUSE_CARET
1665 g_activeFrameLostFocus
= FALSE
;
1667 wxWindowGTK
*active
= wxGetTopLevelParent(win
);
1668 if ( active
!= g_activeFrame
)
1670 if ( g_activeFrame
)
1672 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame
);
1673 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
1674 event
.SetEventObject(g_activeFrame
);
1675 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1678 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active
);
1679 g_activeFrame
= active
;
1680 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId());
1681 event
.SetEventObject(g_activeFrame
);
1682 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1684 // Don't send focus events in addition to activate
1685 // if (win == g_activeFrame)
1689 // does the window itself think that it has the focus?
1690 if ( !win
->m_hasFocus
)
1692 // not yet, notify it
1693 win
->m_hasFocus
= TRUE
;
1695 if ( DoSendFocusEvents(win
) )
1697 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1705 //-----------------------------------------------------------------------------
1706 // "focus_out_event"
1707 //-----------------------------------------------------------------------------
1709 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEventFocus
*gdk_event
, wxWindowGTK
*win
)
1714 wxapp_install_idle_handler();
1716 if (!win
->m_hasVMT
) return FALSE
;
1717 if (g_blockEventsOnDrag
) return FALSE
;
1719 wxLogTrace( TRACE_FOCUS
,
1720 _T("%s: focus out"), win
->GetName().c_str() );
1722 if ( !g_activeFrameLostFocus
&& g_activeFrame
)
1724 // VZ: commenting this out because it does happen (although not easy
1725 // to reproduce, I only see it when using wxMiniFrame and not
1726 // always) and makes using Mahogany quite annoying
1728 wxASSERT_MSG( wxGetTopLevelParent(win
) == g_activeFrame
,
1729 wxT("unfocusing window that hasn't gained focus properly") );
1732 g_activeFrameLostFocus
= TRUE
;
1735 // if the focus goes out of our app alltogether, OnIdle() will send
1736 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1737 // g_sendActivateEvent to -1
1738 g_sendActivateEvent
= 0;
1740 wxWindowGTK
*winFocus
= wxFindFocusedChild(win
);
1744 g_focusWindow
= (wxWindowGTK
*)NULL
;
1752 // caret needs to be informed about focus change
1753 wxCaret
*caret
= win
->GetCaret();
1756 caret
->OnKillFocus();
1758 #endif // wxUSE_CARET
1760 // don't send the window a kill focus event if it thinks that it doesn't
1761 // have focus already
1762 if ( win
->m_hasFocus
)
1764 win
->m_hasFocus
= FALSE
;
1766 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1767 event
.SetEventObject( win
);
1769 if (win
->GetEventHandler()->ProcessEvent( event
))
1771 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1779 //-----------------------------------------------------------------------------
1780 // "enter_notify_event"
1781 //-----------------------------------------------------------------------------
1784 gint
gtk_window_enter_callback( GtkWidget
*widget
,
1785 GdkEventCrossing
*gdk_event
,
1791 wxapp_install_idle_handler();
1793 if (!win
->m_hasVMT
) return FALSE
;
1794 if (g_blockEventsOnDrag
) return FALSE
;
1796 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1800 GdkModifierType state
= (GdkModifierType
)0;
1802 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1804 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1805 InitMouseEvent(win
, event
, gdk_event
);
1806 wxPoint pt
= win
->GetClientAreaOrigin();
1807 event
.m_x
= x
+ pt
.x
;
1808 event
.m_y
= y
+ pt
.y
;
1810 if (win
->GetEventHandler()->ProcessEvent( event
))
1812 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1819 //-----------------------------------------------------------------------------
1820 // "leave_notify_event"
1821 //-----------------------------------------------------------------------------
1823 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1828 wxapp_install_idle_handler();
1830 if (!win
->m_hasVMT
) return FALSE
;
1831 if (g_blockEventsOnDrag
) return FALSE
;
1833 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1835 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1836 event
.SetTimestamp( gdk_event
->time
);
1837 event
.SetEventObject( win
);
1841 GdkModifierType state
= (GdkModifierType
)0;
1843 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1845 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
) != 0;
1846 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
) != 0;
1847 event
.m_altDown
= (state
& GDK_MOD1_MASK
) != 0;
1848 event
.m_metaDown
= (state
& GDK_MOD2_MASK
) != 0;
1849 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
) != 0;
1850 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
) != 0;
1851 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
) != 0;
1853 wxPoint pt
= win
->GetClientAreaOrigin();
1854 event
.m_x
= x
+ pt
.x
;
1855 event
.m_y
= y
+ pt
.y
;
1857 if (win
->GetEventHandler()->ProcessEvent( event
))
1859 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1866 //-----------------------------------------------------------------------------
1867 // "value_changed" from m_vAdjust
1868 //-----------------------------------------------------------------------------
1870 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
,
1877 wxapp_install_idle_handler();
1879 if (g_blockEventsOnDrag
) return;
1881 if (!win
->m_hasVMT
) return;
1883 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1884 if (fabs(diff
) < 0.2) return;
1886 win
->m_oldVerticalPos
= adjust
->value
;
1888 GtkScrolledWindow
*sw
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1889 wxEventType command
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->vscrollbar
));
1891 int value
= (int)(adjust
->value
+0.5);
1893 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1894 event
.SetEventObject( win
);
1895 win
->GetEventHandler()->ProcessEvent( event
);
1898 //-----------------------------------------------------------------------------
1899 // "value_changed" from m_hAdjust
1900 //-----------------------------------------------------------------------------
1902 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
,
1909 wxapp_install_idle_handler();
1911 if (g_blockEventsOnDrag
) return;
1912 if (!win
->m_hasVMT
) return;
1914 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1915 if (fabs(diff
) < 0.2) return;
1917 GtkScrolledWindow
*sw
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1918 wxEventType command
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->hscrollbar
));
1920 win
->m_oldHorizontalPos
= adjust
->value
;
1922 int value
= (int)(adjust
->value
+0.5);
1924 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1925 event
.SetEventObject( win
);
1926 win
->GetEventHandler()->ProcessEvent( event
);
1929 //-----------------------------------------------------------------------------
1930 // "button_press_event" from scrollbar
1931 //-----------------------------------------------------------------------------
1933 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1934 GdkEventButton
*gdk_event
,
1940 wxapp_install_idle_handler();
1943 g_blockEventsOnScroll
= TRUE
;
1945 // FIXME: there is no 'slider' field in GTK+ 2.0 any more
1947 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1953 //-----------------------------------------------------------------------------
1954 // "button_release_event" from scrollbar
1955 //-----------------------------------------------------------------------------
1957 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1958 GdkEventButton
*WXUNUSED(gdk_event
),
1963 // don't test here as we can release the mouse while being over
1964 // a different window than the slider
1966 // if (gdk_event->window != widget->slider) return FALSE;
1968 g_blockEventsOnScroll
= FALSE
;
1970 if (win
->m_isScrolling
)
1972 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
1976 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1977 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1979 value
= (int)(win
->m_hAdjust
->value
+0.5);
1982 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1984 value
= (int)(win
->m_vAdjust
->value
+0.5);
1988 wxScrollWinEvent
event( command
, value
, dir
);
1989 event
.SetEventObject( win
);
1990 win
->GetEventHandler()->ProcessEvent( event
);
1993 win
->m_isScrolling
= FALSE
;
1998 // ----------------------------------------------------------------------------
1999 // this wxWindowBase function is implemented here (in platform-specific file)
2000 // because it is static and so couldn't be made virtual
2001 // ----------------------------------------------------------------------------
2003 wxWindow
*wxWindowBase::FindFocus()
2005 // the cast is necessary when we compile in wxUniversal mode
2006 return (wxWindow
*)g_focusWindow
;
2009 //-----------------------------------------------------------------------------
2011 //-----------------------------------------------------------------------------
2013 // VZ: Robert commented the code using out so it generates warnings: should
2014 // be either fixed or removed completely
2017 static void gtk_window_destroy_callback( GtkWidget
* widget
, wxWindow
*win
)
2019 wxWindowDestroyEvent
event(win
);
2020 win
->GetEventHandler()->ProcessEvent(event
);
2025 //-----------------------------------------------------------------------------
2026 // "realize" from m_widget
2027 //-----------------------------------------------------------------------------
2029 /* We cannot set colours and fonts before the widget has
2030 been realized, so we do this directly after realization. */
2033 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
2038 wxapp_install_idle_handler();
2040 if (win
->m_delayedBackgroundColour
)
2041 win
->GtkSetBackgroundColour( win
->GetBackgroundColour() );
2043 if (win
->m_delayedForegroundColour
)
2044 win
->GtkSetForegroundColour( win
->GetForegroundColour() );
2046 wxWindowCreateEvent
event( win
);
2047 event
.SetEventObject( win
);
2048 win
->GetEventHandler()->ProcessEvent( event
);
2053 //-----------------------------------------------------------------------------
2055 //-----------------------------------------------------------------------------
2058 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
2059 GtkAllocation
*WXUNUSED(alloc
),
2063 wxapp_install_idle_handler();
2065 if (!win
->m_hasScrolling
) return;
2067 int client_width
= 0;
2068 int client_height
= 0;
2069 win
->GetClientSize( &client_width
, &client_height
);
2070 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
2073 win
->m_oldClientWidth
= client_width
;
2074 win
->m_oldClientHeight
= client_height
;
2076 if (!win
->m_nativeSizeEvent
)
2078 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
2079 event
.SetEventObject( win
);
2080 win
->GetEventHandler()->ProcessEvent( event
);
2086 #define WXUNUSED_UNLESS_XIM(param) param
2088 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2091 /* Resize XIM window */
2094 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2095 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
2096 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2099 wxapp_install_idle_handler();
2105 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
2109 gdk_window_get_size (widget
->window
, &width
, &height
);
2110 win
->m_icattr
->preedit_area
.width
= width
;
2111 win
->m_icattr
->preedit_area
.height
= height
;
2112 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2117 //-----------------------------------------------------------------------------
2118 // "realize" from m_wxwindow
2119 //-----------------------------------------------------------------------------
2121 /* Initialize XIM support */
2124 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2125 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2128 wxapp_install_idle_handler();
2131 if (win
->m_ic
) return FALSE
;
2132 if (!widget
) return FALSE
;
2133 if (!gdk_im_ready()) return FALSE
;
2135 win
->m_icattr
= gdk_ic_attr_new();
2136 if (!win
->m_icattr
) return FALSE
;
2140 GdkColormap
*colormap
;
2141 GdkICAttr
*attr
= win
->m_icattr
;
2142 unsigned attrmask
= GDK_IC_ALL_REQ
;
2144 GdkIMStyle supported_style
= (GdkIMStyle
)
2145 (GDK_IM_PREEDIT_NONE
|
2146 GDK_IM_PREEDIT_NOTHING
|
2147 GDK_IM_PREEDIT_POSITION
|
2148 GDK_IM_STATUS_NONE
|
2149 GDK_IM_STATUS_NOTHING
);
2151 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2152 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2154 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2155 attr
->client_window
= widget
->window
;
2157 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2158 gtk_widget_get_default_colormap ())
2160 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2161 attr
->preedit_colormap
= colormap
;
2164 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2165 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2166 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2167 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2169 switch (style
& GDK_IM_PREEDIT_MASK
)
2171 case GDK_IM_PREEDIT_POSITION
:
2172 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2174 g_warning ("over-the-spot style requires fontset");
2178 gdk_window_get_size (widget
->window
, &width
, &height
);
2180 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2181 attr
->spot_location
.x
= 0;
2182 attr
->spot_location
.y
= height
;
2183 attr
->preedit_area
.x
= 0;
2184 attr
->preedit_area
.y
= 0;
2185 attr
->preedit_area
.width
= width
;
2186 attr
->preedit_area
.height
= height
;
2187 attr
->preedit_fontset
= widget
->style
->font
;
2192 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2194 if (win
->m_ic
== NULL
)
2195 g_warning ("Can't create input context.");
2198 mask
= gdk_window_get_events (widget
->window
);
2199 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2200 gdk_window_set_events (widget
->window
, mask
);
2202 if (GTK_WIDGET_HAS_FOCUS(widget
))
2203 gdk_im_begin (win
->m_ic
, widget
->window
);
2210 //-----------------------------------------------------------------------------
2211 // InsertChild for wxWindowGTK.
2212 //-----------------------------------------------------------------------------
2214 /* Callback for wxWindowGTK. This very strange beast has to be used because
2215 * C++ has no virtual methods in a constructor. We have to emulate a
2216 * virtual function here as wxNotebook requires a different way to insert
2217 * a child in it. I had opted for creating a wxNotebookPage window class
2218 * which would have made this superfluous (such in the MDI window system),
2219 * but no-one was listening to me... */
2221 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child
)
2223 /* the window might have been scrolled already, do we
2224 have to adapt the position */
2225 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2226 child
->m_x
+= pizza
->xoffset
;
2227 child
->m_y
+= pizza
->yoffset
;
2229 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2230 GTK_WIDGET(child
->m_widget
),
2237 //-----------------------------------------------------------------------------
2239 //-----------------------------------------------------------------------------
2241 wxWindow
*wxGetActiveWindow()
2243 return wxWindow::FindFocus();
2246 //-----------------------------------------------------------------------------
2248 //-----------------------------------------------------------------------------
2250 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
2252 #ifdef __WXUNIVERSAL__
2253 IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
)
2255 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2256 #endif // __WXUNIVERSAL__/__WXGTK__
2258 void wxWindowGTK::Init()
2264 m_widget
= (GtkWidget
*) NULL
;
2265 m_wxwindow
= (GtkWidget
*) NULL
;
2266 m_focusWidget
= (GtkWidget
*) NULL
;
2276 m_needParent
= TRUE
;
2277 m_isBeingDeleted
= FALSE
;
2280 m_nativeSizeEvent
= FALSE
;
2282 m_hasScrolling
= FALSE
;
2283 m_isScrolling
= FALSE
;
2285 m_hAdjust
= (GtkAdjustment
*) NULL
;
2286 m_vAdjust
= (GtkAdjustment
*) NULL
;
2287 m_oldHorizontalPos
= 0.0;
2288 m_oldVerticalPos
= 0.0;
2291 m_widgetStyle
= (GtkStyle
*) NULL
;
2293 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2295 m_acceptsFocus
= FALSE
;
2298 m_clipPaintRegion
= FALSE
;
2300 m_cursor
= *wxSTANDARD_CURSOR
;
2302 m_delayedForegroundColour
= FALSE
;
2303 m_delayedBackgroundColour
= FALSE
;
2306 m_ic
= (GdkIC
*) NULL
;
2307 m_icattr
= (GdkICAttr
*) NULL
;
2311 wxWindowGTK::wxWindowGTK()
2316 wxWindowGTK::wxWindowGTK( wxWindow
*parent
,
2321 const wxString
&name
)
2325 Create( parent
, id
, pos
, size
, style
, name
);
2328 bool wxWindowGTK::Create( wxWindow
*parent
,
2333 const wxString
&name
)
2335 if (!PreCreation( parent
, pos
, size
) ||
2336 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2338 wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
2342 m_insertCallback
= wxInsertChildInWindow
;
2344 // always needed for background clearing
2345 m_delayedBackgroundColour
= TRUE
;
2347 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2348 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2350 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2352 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2353 scroll_class
->scrollbar_spacing
= 0;
2355 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2357 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2358 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2360 m_wxwindow
= gtk_pizza_new();
2362 #ifndef __WXUNIVERSAL__
2363 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2365 if (HasFlag(wxRAISED_BORDER
))
2367 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2369 else if (HasFlag(wxSUNKEN_BORDER
))
2371 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2373 else if (HasFlag(wxSIMPLE_BORDER
))
2375 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2379 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2381 #endif // __WXUNIVERSAL__
2383 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2385 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2386 m_acceptsFocus
= TRUE
;
2388 // I _really_ don't want scrollbars in the beginning
2389 m_vAdjust
->lower
= 0.0;
2390 m_vAdjust
->upper
= 1.0;
2391 m_vAdjust
->value
= 0.0;
2392 m_vAdjust
->step_increment
= 1.0;
2393 m_vAdjust
->page_increment
= 1.0;
2394 m_vAdjust
->page_size
= 5.0;
2395 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2396 m_hAdjust
->lower
= 0.0;
2397 m_hAdjust
->upper
= 1.0;
2398 m_hAdjust
->value
= 0.0;
2399 m_hAdjust
->step_increment
= 1.0;
2400 m_hAdjust
->page_increment
= 1.0;
2401 m_hAdjust
->page_size
= 5.0;
2402 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2404 // these handlers block mouse events to any window during scrolling such as
2405 // motion events and prevent GTK and wxWindows from fighting over where the
2408 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2409 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2411 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2412 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2414 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2415 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2417 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2418 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2420 // these handlers get notified when screen updates are required either when
2421 // scrolling or when the window size (and therefore scrollbar configuration)
2424 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2425 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2426 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2427 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2429 gtk_widget_show( m_wxwindow
);
2432 m_parent
->DoAddChild( this );
2434 m_focusWidget
= m_wxwindow
;
2443 wxWindowGTK::~wxWindowGTK()
2445 if (g_focusWindow
== this)
2446 g_focusWindow
= NULL
;
2448 if (g_activeFrame
== this)
2449 g_activeFrame
= NULL
;
2451 if ( g_delayedFocus
== this )
2452 g_delayedFocus
= NULL
;
2454 m_isBeingDeleted
= TRUE
;
2463 m_parent
->RemoveChild( this );
2467 gdk_ic_destroy (m_ic
);
2469 gdk_ic_attr_destroy (m_icattr
);
2474 #if DISABLE_STYLE_IF_BROKEN_THEME
2475 // don't delete if it's a pixmap theme style
2476 if (!m_widgetStyle
->engine_data
)
2477 gtk_style_unref( m_widgetStyle
);
2479 m_widgetStyle
= (GtkStyle
*) NULL
;
2484 gtk_widget_destroy( m_wxwindow
);
2485 m_wxwindow
= (GtkWidget
*) NULL
;
2490 gtk_widget_destroy( m_widget
);
2491 m_widget
= (GtkWidget
*) NULL
;
2495 bool wxWindowGTK::PreCreation( wxWindowGTK
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2497 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2499 // This turns -1 into 30 so that a minimal window is
2500 // visible even although -1,-1 has been given as the
2501 // size of the window. the same trick is used in other
2502 // ports and should make debugging easier.
2503 m_width
= WidthDefault(size
.x
) ;
2504 m_height
= HeightDefault(size
.y
);
2509 // some reasonable defaults
2514 m_x
= (gdk_screen_width () - m_width
) / 2;
2515 if (m_x
< 10) m_x
= 10;
2519 m_y
= (gdk_screen_height () - m_height
) / 2;
2520 if (m_y
< 10) m_y
= 10;
2527 void wxWindowGTK::PostCreation()
2529 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2535 // these get reported to wxWindows -> wxPaintEvent
2537 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2539 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2540 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2543 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2544 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2546 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2548 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2549 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2552 gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow
), HasFlag( wxNO_FULL_REPAINT_ON_RESIZE
) );
2556 // these are called when the "sunken" or "raised" borders are drawn
2557 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2558 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2561 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2562 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2568 if (m_focusWidget
== NULL
)
2569 m_focusWidget
= m_widget
;
2571 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event",
2572 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2574 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event",
2575 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2577 // connect to the various key and mouse handlers
2579 GtkWidget
*connect_widget
= GetConnectWidget();
2581 ConnectWidget( connect_widget
);
2583 /* We cannot set colours, fonts and cursors before the widget has
2584 been realized, so we do this directly after realization */
2585 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2586 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2590 // Catch native resize events
2591 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2592 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2594 // Initialize XIM support
2595 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2596 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2598 // And resize XIM window
2599 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2600 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2603 if (!GTK_IS_COMBO(m_widget
))
2605 // This is needed if we want to add our windows into native
2606 // GTK control, such as the toolbar. With this callback, the
2607 // toolbar gets to know the correct size (the one set by the
2608 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2609 // when moving to GTK 2.0.
2610 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2611 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2617 void wxWindowGTK::ConnectWidget( GtkWidget
*widget
)
2619 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2620 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2622 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2623 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2625 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2626 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2628 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2629 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2631 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2632 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2634 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2635 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2637 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2638 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2640 // This keeps crashing on me. RR.
2642 // gtk_signal_connect( GTK_OBJECT(widget), "destroy",
2643 // GTK_SIGNAL_FUNC(gtk_window_destroy_callback), (gpointer)this );
2646 bool wxWindowGTK::Destroy()
2648 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2652 return wxWindowBase::Destroy();
2655 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
)
2657 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2660 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2662 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2663 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") );
2666 printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
2669 if (m_resizing
) return; /* I don't like recursions */
2672 int currentX
, currentY
;
2673 GetPosition(¤tX
, ¤tY
);
2678 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
2680 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2682 /* don't set the size for children of wxNotebook, just take the values. */
2690 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2691 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2693 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2694 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2698 m_x
= x
+ pizza
->xoffset
;
2699 m_y
= y
+ pizza
->yoffset
;
2701 if (width
!= -1) m_width
= width
;
2702 if (height
!= -1) m_height
= height
;
2704 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2706 if (width
== -1) m_width
= 80;
2709 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2711 if (height
== -1) m_height
= 26;
2714 int minWidth
= GetMinWidth(),
2715 minHeight
= GetMinHeight(),
2716 maxWidth
= GetMaxWidth(),
2717 maxHeight
= GetMaxHeight();
2719 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
2720 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
2721 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
2722 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
2725 int bottom_border
= 0;
2728 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2730 /* the default button has a border around it */
2736 DoMoveWindow( m_x
-border
,
2739 m_height
+border
+bottom_border
);
2744 /* Sometimes the client area changes size without the
2745 whole windows's size changing, but if the whole
2746 windows's size doesn't change, no wxSizeEvent will
2747 normally be sent. Here we add an extra test if
2748 the client test has been changed and this will
2750 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2754 wxPrintf( "OnSize sent from " );
2755 if (GetClassInfo() && GetClassInfo()->GetClassName())
2756 wxPrintf( GetClassInfo()->GetClassName() );
2757 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2760 if (!m_nativeSizeEvent
)
2762 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2763 event
.SetEventObject( this );
2764 GetEventHandler()->ProcessEvent( event
);
2770 void wxWindowGTK::OnInternalIdle()
2772 // Update invalidated regions.
2775 // Synthetize activate events.
2776 if ( g_sendActivateEvent
!= -1 )
2778 bool activate
= g_sendActivateEvent
!= 0;
2781 g_sendActivateEvent
= -1;
2783 wxTheApp
->SetActive(activate
, (wxWindow
*)g_focusWindowLast
);
2786 if ( g_activeFrameLostFocus
)
2788 if ( g_activeFrame
)
2790 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame
);
2791 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
2792 event
.SetEventObject(g_activeFrame
);
2793 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
2794 g_activeFrame
= NULL
;
2796 g_activeFrameLostFocus
= FALSE
;
2799 wxCursor cursor
= m_cursor
;
2800 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2804 /* I now set the cursor anew in every OnInternalIdle call
2805 as setting the cursor in a parent window also effects the
2806 windows above so that checking for the current cursor is
2811 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2813 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2815 if (!g_globalCursor
.Ok())
2816 cursor
= *wxSTANDARD_CURSOR
;
2818 window
= m_widget
->window
;
2819 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2820 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2826 GdkWindow
*window
= m_widget
->window
;
2827 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2828 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2836 void wxWindowGTK::DoGetSize( int *width
, int *height
) const
2838 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2840 if (width
) (*width
) = m_width
;
2841 if (height
) (*height
) = m_height
;
2844 void wxWindowGTK::DoSetClientSize( int width
, int height
)
2846 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2850 SetSize( width
, height
);
2857 #ifndef __WXUNIVERSAL__
2858 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2860 /* when using GTK 1.2 we set the shadow border size to 2 */
2864 if (HasFlag(wxSIMPLE_BORDER
))
2866 /* when using GTK 1.2 we set the simple border size to 1 */
2870 #endif // __WXUNIVERSAL__
2874 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2876 GtkRequisition vscroll_req
;
2877 vscroll_req
.width
= 2;
2878 vscroll_req
.height
= 2;
2879 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2880 (scroll_window
->vscrollbar
, &vscroll_req
);
2882 GtkRequisition hscroll_req
;
2883 hscroll_req
.width
= 2;
2884 hscroll_req
.height
= 2;
2885 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2886 (scroll_window
->hscrollbar
, &hscroll_req
);
2888 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2890 if (scroll_window
->vscrollbar_visible
)
2892 dw
+= vscroll_req
.width
;
2893 dw
+= scroll_class
->scrollbar_spacing
;
2896 if (scroll_window
->hscrollbar_visible
)
2898 dh
+= hscroll_req
.height
;
2899 dh
+= scroll_class
->scrollbar_spacing
;
2903 SetSize( width
+dw
, height
+dh
);
2907 void wxWindowGTK::DoGetClientSize( int *width
, int *height
) const
2909 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2913 if (width
) (*width
) = m_width
;
2914 if (height
) (*height
) = m_height
;
2921 #ifndef __WXUNIVERSAL__
2922 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2924 /* when using GTK 1.2 we set the shadow border size to 2 */
2928 if (HasFlag(wxSIMPLE_BORDER
))
2930 /* when using GTK 1.2 we set the simple border size to 1 */
2934 #endif // __WXUNIVERSAL__
2938 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2940 GtkRequisition vscroll_req
;
2941 vscroll_req
.width
= 2;
2942 vscroll_req
.height
= 2;
2943 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2944 (scroll_window
->vscrollbar
, &vscroll_req
);
2946 GtkRequisition hscroll_req
;
2947 hscroll_req
.width
= 2;
2948 hscroll_req
.height
= 2;
2949 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2950 (scroll_window
->hscrollbar
, &hscroll_req
);
2952 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2954 if (scroll_window
->vscrollbar_visible
)
2956 dw
+= vscroll_req
.width
;
2957 dw
+= scroll_class
->scrollbar_spacing
;
2960 if (scroll_window
->hscrollbar_visible
)
2962 dh
+= hscroll_req
.height
;
2963 dh
+= scroll_class
->scrollbar_spacing
;
2967 if (width
) (*width
) = m_width
- dw
;
2968 if (height
) (*height
) = m_height
- dh
;
2972 printf( "GetClientSize, name %s ", GetName().c_str() );
2973 if (width) printf( " width = %d", (*width) );
2974 if (height) printf( " height = %d", (*height) );
2979 void wxWindowGTK::DoGetPosition( int *x
, int *y
) const
2981 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2985 if (m_parent
&& m_parent
->m_wxwindow
)
2987 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2988 dx
= pizza
->xoffset
;
2989 dy
= pizza
->yoffset
;
2992 if (x
) (*x
) = m_x
- dx
;
2993 if (y
) (*y
) = m_y
- dy
;
2996 void wxWindowGTK::DoClientToScreen( int *x
, int *y
) const
2998 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3000 if (!m_widget
->window
) return;
3002 GdkWindow
*source
= (GdkWindow
*) NULL
;
3004 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3006 source
= m_widget
->window
;
3010 gdk_window_get_origin( source
, &org_x
, &org_y
);
3014 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3016 org_x
+= m_widget
->allocation
.x
;
3017 org_y
+= m_widget
->allocation
.y
;
3025 void wxWindowGTK::DoScreenToClient( int *x
, int *y
) const
3027 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3029 if (!m_widget
->window
) return;
3031 GdkWindow
*source
= (GdkWindow
*) NULL
;
3033 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3035 source
= m_widget
->window
;
3039 gdk_window_get_origin( source
, &org_x
, &org_y
);
3043 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3045 org_x
+= m_widget
->allocation
.x
;
3046 org_y
+= m_widget
->allocation
.y
;
3054 bool wxWindowGTK::Show( bool show
)
3056 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3058 if (!wxWindowBase::Show(show
))
3065 gtk_widget_show( m_widget
);
3067 gtk_widget_hide( m_widget
);
3072 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
)
3074 win
->OnParentEnable(enable
);
3076 // Recurse, so that children have the opportunity to Do The Right Thing
3077 // and reset colours that have been messed up by a parent's (really ancestor's)
3079 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
3081 node
= node
->GetNext() )
3083 wxWindow
*child
= node
->GetData();
3084 if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
)))
3085 wxWindowNotifyEnable(child
, enable
);
3089 bool wxWindowGTK::Enable( bool enable
)
3091 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3093 if (!wxWindowBase::Enable(enable
))
3099 gtk_widget_set_sensitive( m_widget
, enable
);
3101 gtk_widget_set_sensitive( m_wxwindow
, enable
);
3103 wxWindowNotifyEnable(this, enable
);
3108 int wxWindowGTK::GetCharHeight() const
3110 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
3112 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
3114 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3116 return font
->ascent
+ font
->descent
;
3119 int wxWindowGTK::GetCharWidth() const
3121 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
3123 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
3125 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3127 return gdk_string_width( font
, "H" );
3130 void wxWindowGTK::GetTextExtent( const wxString
& string
,
3134 int *externalLeading
,
3135 const wxFont
*theFont
) const
3137 wxFont fontToUse
= m_font
;
3138 if (theFont
) fontToUse
= *theFont
;
3140 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
3142 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
3143 if (x
) (*x
) = gdk_string_width( font
, wxGTK_CONV( string
) );
3144 if (y
) (*y
) = font
->ascent
+ font
->descent
;
3145 if (descent
) (*descent
) = font
->descent
;
3146 if (externalLeading
) (*externalLeading
) = 0; // ??
3149 void wxWindowGTK::SetFocus()
3151 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3155 // don't do anything if we already have focus
3161 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3163 gtk_widget_grab_focus (m_wxwindow
);
3168 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
3170 if (!GTK_WIDGET_REALIZED(m_widget
))
3172 // we can't set the focus to the widget now so we remember that
3173 // it should be focused and will do it later, during the idle
3174 // time, as soon as we can
3175 wxLogTrace(TRACE_FOCUS
,
3176 _T("Delaying setting focus to %s(%s)"),
3177 GetClassInfo()->GetClassName(), GetLabel().c_str());
3179 g_delayedFocus
= this;
3183 wxLogTrace(TRACE_FOCUS
,
3184 _T("Setting focus to %s(%s)"),
3185 GetClassInfo()->GetClassName(), GetLabel().c_str());
3187 gtk_widget_grab_focus (m_widget
);
3190 else if (GTK_IS_CONTAINER(m_widget
))
3192 SET_CONTAINER_FOCUS( m_widget
, GTK_DIR_TAB_FORWARD
);
3196 wxLogTrace(TRACE_FOCUS
,
3197 _T("Can't set focus to %s(%s)"),
3198 GetClassInfo()->GetClassName(), GetLabel().c_str());
3203 bool wxWindowGTK::AcceptsFocus() const
3205 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3208 bool wxWindowGTK::Reparent( wxWindowBase
*newParentBase
)
3210 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3212 wxWindowGTK
*oldParent
= m_parent
,
3213 *newParent
= (wxWindowGTK
*)newParentBase
;
3215 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3217 if ( !wxWindowBase::Reparent(newParent
) )
3220 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3222 /* prevent GTK from deleting the widget arbitrarily */
3223 gtk_widget_ref( m_widget
);
3227 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3230 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3234 /* insert GTK representation */
3235 (*(newParent
->m_insertCallback
))(newParent
, this);
3238 /* reverse: prevent GTK from deleting the widget arbitrarily */
3239 gtk_widget_unref( m_widget
);
3244 void wxWindowGTK::DoAddChild(wxWindowGTK
*child
)
3246 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3248 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3250 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3255 /* insert GTK representation */
3256 (*m_insertCallback
)(this, child
);
3259 void wxWindowGTK::Raise()
3261 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3263 if (!m_widget
->window
) return;
3265 gdk_window_raise( m_widget
->window
);
3268 void wxWindowGTK::Lower()
3270 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3272 if (!m_widget
->window
) return;
3274 gdk_window_lower( m_widget
->window
);
3277 bool wxWindowGTK::SetCursor( const wxCursor
&cursor
)
3279 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3281 if (cursor
== m_cursor
)
3285 wxapp_install_idle_handler();
3287 if (cursor
== wxNullCursor
)
3288 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3290 return wxWindowBase::SetCursor( cursor
);
3293 void wxWindowGTK::WarpPointer( int x
, int y
)
3295 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3297 // We provide this function ourselves as it is
3298 // missing in GDK (top of this file).
3300 GdkWindow
*window
= (GdkWindow
*) NULL
;
3302 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3304 window
= GetConnectWidget()->window
;
3307 gdk_window_warp_pointer( window
, x
, y
);
3311 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect
*rect
)
3313 if (!m_widget
) return;
3314 if (!m_widget
->window
) return;
3318 wxapp_install_idle_handler();
3320 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3324 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3325 m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
3329 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3330 m_clearRegion
.Clear();
3331 m_clearRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height
);
3339 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3340 m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
3344 GdkRectangle gdk_rect
;
3345 gdk_rect
.x
= rect
->x
;
3346 gdk_rect
.y
= rect
->y
;
3347 gdk_rect
.width
= rect
->width
;
3348 gdk_rect
.height
= rect
->height
;
3349 gtk_widget_draw( m_widget
, &gdk_rect
);
3356 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3357 m_updateRegion
.Clear();
3358 m_updateRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height
);
3362 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3370 GdkRectangle gdk_rect
;
3371 gdk_rect
.x
= rect
->x
;
3372 gdk_rect
.y
= rect
->y
;
3373 gdk_rect
.width
= rect
->width
;
3374 gdk_rect
.height
= rect
->height
;
3375 gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, &gdk_rect
, TRUE
);
3379 gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, NULL
, TRUE
);
3385 void wxWindowGTK::Update()
3390 void wxWindowGTK::GtkUpdate()
3393 if (m_wxwindow
&& GTK_PIZZA(m_wxwindow
)->bin_window
)
3394 gdk_window_process_updates( GTK_PIZZA(m_wxwindow
)->bin_window
, FALSE
);
3397 if (!m_updateRegion
.IsEmpty())
3398 GtkSendPaintEvents();
3401 void wxWindowGTK::GtkSendPaintEvents()
3405 m_clearRegion
.Clear();
3406 m_updateRegion
.Clear();
3410 // widget to draw on
3411 GtkPizza
*pizza
= GTK_PIZZA (m_wxwindow
);
3413 // Clip to paint region in wxClientDC
3414 m_clipPaintRegion
= TRUE
;
3417 if (GetThemeEnabled())
3419 // find ancestor from which to steal background
3420 wxWindow
*parent
= GetParent();
3421 while (parent
&& !parent
->IsTopLevel())
3422 parent
= parent
->GetParent();
3424 parent
= (wxWindow
*)this;
3426 wxRegionIterator
upd( m_updateRegion
);
3430 rect
.x
= upd
.GetX();
3431 rect
.y
= upd
.GetY();
3432 rect
.width
= upd
.GetWidth();
3433 rect
.height
= upd
.GetHeight();
3435 gtk_paint_flat_box( parent
->m_widget
->style
,
3450 if (!m_clearRegion
.IsEmpty()) // Always send an erase event under GTK 1.2
3453 wxWindowDC
dc( (wxWindow
*)this );
3454 if (m_clearRegion
.IsEmpty())
3455 dc
.SetClippingRegion( m_updateRegion
);
3457 dc
.SetClippingRegion( m_clearRegion
);
3459 wxEraseEvent
erase_event( GetId(), &dc
);
3460 erase_event
.SetEventObject( this );
3462 if (!GetEventHandler()->ProcessEvent(erase_event
))
3467 g_eraseGC
= gdk_gc_new( pizza
->bin_window
);
3468 gdk_gc_set_fill( g_eraseGC
, GDK_SOLID
);
3470 gdk_gc_set_foreground( g_eraseGC
, m_backgroundColour
.GetColor() );
3472 wxRegionIterator
upd( m_clearRegion
);
3475 gdk_draw_rectangle( pizza
->bin_window
, g_eraseGC
, 1,
3476 upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
3481 m_clearRegion
.Clear();
3484 wxNcPaintEvent
nc_paint_event( GetId() );
3485 nc_paint_event
.SetEventObject( this );
3486 GetEventHandler()->ProcessEvent( nc_paint_event
);
3488 wxPaintEvent
paint_event( GetId() );
3489 paint_event
.SetEventObject( this );
3490 GetEventHandler()->ProcessEvent( paint_event
);
3492 m_clipPaintRegion
= FALSE
;
3494 #ifndef __WXUNIVERSAL__
3496 // The following code will result in all window-less widgets
3497 // being redrawn because the wxWindows class is allowed to
3498 // paint over the window-less widgets.
3500 GList
*children
= pizza
->children
;
3503 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
3504 children
= children
->next
;
3506 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
3507 GTK_WIDGET_DRAWABLE (child
->widget
))
3509 // Get intersection of widget area and update region
3510 wxRegion
region( m_updateRegion
);
3512 GdkEventExpose gdk_event
;
3513 gdk_event
.type
= GDK_EXPOSE
;
3514 gdk_event
.window
= pizza
->bin_window
;
3515 gdk_event
.count
= 0;
3517 wxRegionIterator
upd( m_updateRegion
);
3521 rect
.x
= upd
.GetX();
3522 rect
.y
= upd
.GetY();
3523 rect
.width
= upd
.GetWidth();
3524 rect
.height
= upd
.GetHeight();
3526 if (gtk_widget_intersect (child
->widget
, &rect
, &gdk_event
.area
))
3528 gtk_widget_event (child
->widget
, (GdkEvent
*) &gdk_event
);
3538 m_updateRegion
.Clear();
3541 void wxWindowGTK::Clear()
3543 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3545 if (m_wxwindow
&& m_wxwindow
->window
)
3547 m_clearRegion
.Clear();
3548 wxSize
size( GetClientSize() );
3549 m_clearRegion
.Union( 0,0,size
.x
,size
.y
);
3551 // Better do this in idle?
3557 void wxWindowGTK::DoSetToolTip( wxToolTip
*tip
)
3559 wxWindowBase::DoSetToolTip(tip
);
3562 m_tooltip
->Apply( (wxWindow
*)this );
3565 void wxWindowGTK::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3567 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3569 #endif // wxUSE_TOOLTIPS
3571 void wxWindowGTK::GtkSetBackgroundColour( const wxColour
&colour
)
3573 GdkWindow
*window
= (GdkWindow
*) NULL
;
3575 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3577 window
= GetConnectWidget()->window
;
3581 // We need the pixel value e.g. for background clearing.
3582 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3586 // wxMSW doesn't clear the window here, either.
3587 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3593 bool wxWindowGTK::SetBackgroundColour( const wxColour
&colour
)
3595 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3597 if (!wxWindowBase::SetBackgroundColour(colour
))
3600 GdkWindow
*window
= (GdkWindow
*) NULL
;
3602 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3604 window
= GetConnectWidget()->window
;
3608 // indicate that a new style has been set
3609 // but it couldn't get applied as the
3610 // widget hasn't been realized yet.
3611 m_delayedBackgroundColour
= TRUE
;
3616 GtkSetBackgroundColour( colour
);
3622 void wxWindowGTK::GtkSetForegroundColour( const wxColour
&colour
)
3624 GdkWindow
*window
= (GdkWindow
*) NULL
;
3626 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3628 window
= GetConnectWidget()->window
;
3635 bool wxWindowGTK::SetForegroundColour( const wxColour
&colour
)
3637 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3639 if (!wxWindowBase::SetForegroundColour(colour
))
3641 // don't leave if the GTK widget has just
3643 if (!m_delayedForegroundColour
) return FALSE
;
3646 GdkWindow
*window
= (GdkWindow
*) NULL
;
3648 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3650 window
= GetConnectWidget()->window
;
3654 // indicate that a new style has been set
3655 // but it couldn't get applied as the
3656 // widget hasn't been realized yet.
3657 m_delayedForegroundColour
= TRUE
;
3661 GtkSetForegroundColour( colour
);
3667 GtkStyle
*wxWindowGTK::GetWidgetStyle()
3671 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3673 // FIXME: no more klass in 2.0
3675 remake
->klass
= m_widgetStyle
->klass
;
3678 gtk_style_unref( m_widgetStyle
);
3679 m_widgetStyle
= remake
;
3683 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3686 def
= gtk_widget_get_default_style();
3688 m_widgetStyle
= gtk_style_copy( def
);
3690 // FIXME: no more klass in 2.0
3692 m_widgetStyle
->klass
= def
->klass
;
3696 return m_widgetStyle
;
3699 void wxWindowGTK::SetWidgetStyle()
3701 #if DISABLE_STYLE_IF_BROKEN_THEME
3702 if (m_widget
->style
->engine_data
)
3704 static bool s_warningPrinted
= FALSE
;
3705 if (!s_warningPrinted
)
3707 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3708 s_warningPrinted
= TRUE
;
3710 m_widgetStyle
= m_widget
->style
;
3715 GtkStyle
*style
= GetWidgetStyle();
3717 if (m_font
!= wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT
))
3719 SET_STYLE_FONT(style
, m_font
.GetInternalFont( 1.0 ));
3722 if (m_foregroundColour
.Ok())
3724 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3725 if (m_foregroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT
))
3727 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3728 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3729 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3733 // Try to restore the gtk default style. This is still a little
3734 // oversimplified for what is probably really needed here for controls
3735 // other than buttons, but is better than not being able to (re)set a
3736 // control's foreground colour to *wxBLACK -- RL
3737 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3740 def
= gtk_widget_get_default_style();
3742 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3743 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3744 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3748 if (m_backgroundColour
.Ok())
3750 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3751 if (m_backgroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
))
3753 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3754 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3755 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3756 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3757 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3758 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3759 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3760 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3764 // Try to restore the gtk default style. This is still a little
3765 // oversimplified for what is probably really needed here for controls
3766 // other than buttons, but is better than not being able to (re)set a
3767 // control's background colour to default grey and means resetting a
3768 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3770 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3773 def
= gtk_widget_get_default_style();
3775 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3776 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3777 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3778 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3779 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3780 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3781 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3782 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3787 void wxWindowGTK::ApplyWidgetStyle()
3791 //-----------------------------------------------------------------------------
3792 // Pop-up menu stuff
3793 //-----------------------------------------------------------------------------
3795 #if wxUSE_MENUS_NATIVE
3798 void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3800 *is_waiting
= FALSE
;
3803 static void SetInvokingWindow( wxMenu
*menu
, wxWindowGTK
*win
)
3805 menu
->SetInvokingWindow( win
);
3806 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3809 wxMenuItem
*menuitem
= node
->GetData();
3810 if (menuitem
->IsSubMenu())
3812 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3815 node
= node
->GetNext();
3819 // used to pass the coordinates from wxWindowGTK::DoPopupMenu() to
3820 // wxPopupMenuPositionCallback()
3822 // should be safe even in the MT case as the user can hardly popup 2 menus
3823 // simultaneously, can he?
3824 static gint gs_pop_x
= 0;
3825 static gint gs_pop_y
= 0;
3827 extern "C" void wxPopupMenuPositionCallback( GtkMenu
*menu
,
3830 gboolean
* WXUNUSED(whatever
),
3832 gpointer
WXUNUSED(user_data
) )
3834 // ensure that the menu appears entirely on screen
3836 gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
);
3838 wxSize sizeScreen
= wxGetDisplaySize();
3840 gint xmax
= sizeScreen
.x
- req
.width
,
3841 ymax
= sizeScreen
.y
- req
.height
;
3843 *x
= gs_pop_x
< xmax
? gs_pop_x
: xmax
;
3844 *y
= gs_pop_y
< ymax
? gs_pop_y
: ymax
;
3847 bool wxWindowGTK::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3849 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3851 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3853 SetInvokingWindow( menu
, this );
3859 ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3861 bool is_waiting
= TRUE
;
3863 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
),
3865 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
),
3866 (gpointer
)&is_waiting
);
3869 GTK_MENU(menu
->m_menu
),
3870 (GtkWidget
*) NULL
, // parent menu shell
3871 (GtkWidget
*) NULL
, // parent menu item
3872 wxPopupMenuPositionCallback
, // function to position it
3873 NULL
, // client data
3874 0, // button used to activate it
3875 gs_timeLastClick
// the time of activation
3880 while (gtk_events_pending())
3881 gtk_main_iteration();
3887 #endif // wxUSE_MENUS_NATIVE
3889 #if wxUSE_DRAG_AND_DROP
3891 void wxWindowGTK::SetDropTarget( wxDropTarget
*dropTarget
)
3893 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3895 GtkWidget
*dnd_widget
= GetConnectWidget();
3897 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3899 if (m_dropTarget
) delete m_dropTarget
;
3900 m_dropTarget
= dropTarget
;
3902 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3905 #endif // wxUSE_DRAG_AND_DROP
3907 GtkWidget
* wxWindowGTK::GetConnectWidget()
3909 GtkWidget
*connect_widget
= m_widget
;
3910 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3912 return connect_widget
;
3915 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow
*window
)
3918 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3920 return (window
== m_widget
->window
);
3923 bool wxWindowGTK::SetFont( const wxFont
&font
)
3925 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3927 if (!wxWindowBase::SetFont(font
))
3932 wxColour sysbg
= wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE
);
3933 if ( sysbg
== m_backgroundColour
)
3935 m_backgroundColour
= wxNullColour
;
3937 m_backgroundColour
= sysbg
;
3947 void wxWindowGTK::DoCaptureMouse()
3949 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3951 GdkWindow
*window
= (GdkWindow
*) NULL
;
3953 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3955 window
= GetConnectWidget()->window
;
3957 wxCHECK_RET( window
, _T("CaptureMouse() failed") );
3959 wxCursor
* cursor
= & m_cursor
;
3961 cursor
= wxSTANDARD_CURSOR
;
3963 gdk_pointer_grab( window
, FALSE
,
3965 (GDK_BUTTON_PRESS_MASK
|
3966 GDK_BUTTON_RELEASE_MASK
|
3967 GDK_POINTER_MOTION_HINT_MASK
|
3968 GDK_POINTER_MOTION_MASK
),
3970 cursor
->GetCursor(),
3971 (guint32
)GDK_CURRENT_TIME
);
3972 g_captureWindow
= this;
3973 g_captureWindowHasMouse
= TRUE
;
3976 void wxWindowGTK::DoReleaseMouse()
3978 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3980 wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") );
3982 g_captureWindow
= (wxWindowGTK
*) NULL
;
3984 GdkWindow
*window
= (GdkWindow
*) NULL
;
3986 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3988 window
= GetConnectWidget()->window
;
3993 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3997 wxWindow
*wxWindowBase::GetCapture()
3999 return (wxWindow
*)g_captureWindow
;
4002 bool wxWindowGTK::IsRetained() const
4007 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
,
4008 int range
, bool refresh
)
4010 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4012 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4014 m_hasScrolling
= TRUE
;
4016 if (orient
== wxHORIZONTAL
)
4018 float fpos
= (float)pos
;
4019 float frange
= (float)range
;
4020 float fthumb
= (float)thumbVisible
;
4021 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
4022 if (fpos
< 0.0) fpos
= 0.0;
4024 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
4025 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
4027 SetScrollPos( orient
, pos
, refresh
);
4031 m_oldHorizontalPos
= fpos
;
4033 m_hAdjust
->lower
= 0.0;
4034 m_hAdjust
->upper
= frange
;
4035 m_hAdjust
->value
= fpos
;
4036 m_hAdjust
->step_increment
= 1.0;
4037 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
4038 m_hAdjust
->page_size
= fthumb
;
4042 float fpos
= (float)pos
;
4043 float frange
= (float)range
;
4044 float fthumb
= (float)thumbVisible
;
4045 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
4046 if (fpos
< 0.0) fpos
= 0.0;
4048 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
4049 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
4051 SetScrollPos( orient
, pos
, refresh
);
4055 m_oldVerticalPos
= fpos
;
4057 m_vAdjust
->lower
= 0.0;
4058 m_vAdjust
->upper
= frange
;
4059 m_vAdjust
->value
= fpos
;
4060 m_vAdjust
->step_increment
= 1.0;
4061 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
4062 m_vAdjust
->page_size
= fthumb
;
4065 if (orient
== wxHORIZONTAL
)
4066 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
4068 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
4071 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
4073 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4075 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4077 if (orient
== wxHORIZONTAL
)
4079 float fpos
= (float)pos
;
4080 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
4081 if (fpos
< 0.0) fpos
= 0.0;
4082 m_oldHorizontalPos
= fpos
;
4084 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
4085 m_hAdjust
->value
= fpos
;
4089 float fpos
= (float)pos
;
4090 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
4091 if (fpos
< 0.0) fpos
= 0.0;
4092 m_oldVerticalPos
= fpos
;
4094 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
4095 m_vAdjust
->value
= fpos
;
4098 if (m_wxwindow
->window
)
4100 if (orient
== wxHORIZONTAL
)
4102 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
4103 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
4105 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
4107 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
4108 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
4112 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
4113 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4115 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
4117 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
4118 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4123 int wxWindowGTK::GetScrollThumb( int orient
) const
4125 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4127 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4129 if (orient
== wxHORIZONTAL
)
4130 return (int)(m_hAdjust
->page_size
+0.5);
4132 return (int)(m_vAdjust
->page_size
+0.5);
4135 int wxWindowGTK::GetScrollPos( int orient
) const
4137 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4139 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4141 if (orient
== wxHORIZONTAL
)
4142 return (int)(m_hAdjust
->value
+0.5);
4144 return (int)(m_vAdjust
->value
+0.5);
4147 int wxWindowGTK::GetScrollRange( int orient
) const
4149 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4151 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4153 if (orient
== wxHORIZONTAL
)
4154 return (int)(m_hAdjust
->upper
+0.5);
4156 return (int)(m_vAdjust
->upper
+0.5);
4159 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
4161 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4163 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4165 // No scrolling requested.
4166 if ((dx
== 0) && (dy
== 0)) return;
4169 if (!m_updateRegion
.IsEmpty())
4171 m_updateRegion
.Offset( dx
, dy
);
4175 GetClientSize( &cw
, &ch
);
4176 m_updateRegion
.Intersect( 0, 0, cw
, ch
);
4179 if (!m_clearRegion
.IsEmpty())
4181 m_clearRegion
.Offset( dx
, dy
);
4185 GetClientSize( &cw
, &ch
);
4186 m_clearRegion
.Intersect( 0, 0, cw
, ch
);
4188 m_clipPaintRegion
= TRUE
;
4190 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
4192 m_clipPaintRegion
= FALSE
;
4195 gdk_window_scroll( GTK_PIZZA(m_wxwindow
)->bin_window
, dx
, dy
);
4197 GTK_PIZZA(m_wxwindow
)->xoffset
+= dx
;
4198 GTK_PIZZA(m_wxwindow
)->yoffset
+= dy
;
4205 // Find the wxWindow at the current mouse position, also returning the mouse
4207 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
4209 pt
= wxGetMousePosition();
4210 wxWindow
* found
= wxFindWindowAtPoint(pt
);
4214 // Get the current mouse position.
4215 wxPoint
wxGetMousePosition()
4217 /* This crashes when used within wxHelpContext,
4218 so we have to use the X-specific implementation below.
4220 GdkModifierType *mask;
4221 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
4223 return wxPoint(x, y);
4227 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
4229 return wxPoint(-999, -999);
4231 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
4232 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
4233 Window rootReturn
, childReturn
;
4234 int rootX
, rootY
, winX
, winY
;
4235 unsigned int maskReturn
;
4237 XQueryPointer (display
,
4241 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
4242 return wxPoint(rootX
, rootY
);
4246 // ----------------------------------------------------------------------------
4248 // ----------------------------------------------------------------------------
4250 class wxWinModule
: public wxModule
4257 DECLARE_DYNAMIC_CLASS(wxWinModule
)
4260 IMPLEMENT_DYNAMIC_CLASS(wxWinModule
, wxModule
)
4262 bool wxWinModule::OnInit()
4264 // g_eraseGC = gdk_gc_new( GDK_ROOT_PARENT() );
4265 // gdk_gc_set_fill( g_eraseGC, GDK_SOLID );
4270 void wxWinModule::OnExit()
4273 gdk_gc_unref( g_eraseGC
);