1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/window.cpp
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #define XWarpPointer XWARPPOINTER
20 #include "wx/window.h"
21 #include "wx/dcclient.h"
24 #include "wx/layout.h"
26 #include "wx/dialog.h"
27 #include "wx/msgdlg.h"
28 #include "wx/module.h"
30 #if wxUSE_DRAG_AND_DROP
35 #include "wx/tooltip.h"
43 #include "wx/textctrl.h"
47 #include "wx/statusbr.h"
49 #include "wx/settings.h"
53 #include "wx/thread.h"
58 #include "wx/gtk/private.h"
59 #include <gdk/gdkprivate.h>
60 #include <gdk/gdkkeysyms.h>
64 #include <gtk/gtkprivate.h>
66 #include "wx/gtk/win_gtk.h"
69 #define SET_CONTAINER_FOCUS(w, d) gtk_widget_child_focus((w), (d))
71 #define SET_CONTAINER_FOCUS(w, d) gtk_container_focus(GTK_CONTAINER(w), (d))
81 extern GtkContainerClass
*pizza_parent_class
;
84 //-----------------------------------------------------------------------------
85 // documentation on internals
86 //-----------------------------------------------------------------------------
89 I have been asked several times about writing some documentation about
90 the GTK port of wxWindows, especially its internal structures. Obviously,
91 you cannot understand wxGTK without knowing a little about the GTK, but
92 some more information about what the wxWindow, which is the base class
93 for all other window classes, does seems required as well.
97 What does wxWindow do? It contains the common interface for the following
98 jobs of its descendants:
100 1) Define the rudimentary behaviour common to all window classes, such as
101 resizing, intercepting user input (so as to make it possible to use these
102 events for special purposes in a derived class), window names etc.
104 2) Provide the possibility to contain and manage children, if the derived
105 class is allowed to contain children, which holds true for those window
106 classes which do not display a native GTK widget. To name them, these
107 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
108 work classes are a special case and are handled a bit differently from
109 the rest. The same holds true for the wxNotebook class.
111 3) Provide the possibility to draw into a client area of a window. This,
112 too, only holds true for classes that do not display a native GTK widget
115 4) Provide the entire mechanism for scrolling widgets. This actual inter-
116 face for this is usually in wxScrolledWindow, but the GTK implementation
119 5) A multitude of helper or extra methods for special purposes, such as
120 Drag'n'Drop, managing validators etc.
122 6) Display a border (sunken, raised, simple or none).
124 Normally one might expect, that one wxWindows window would always correspond
125 to one GTK widget. Under GTK, there is no such allround widget that has all
126 the functionality. Moreover, the GTK defines a client area as a different
127 widget from the actual widget you are handling. Last but not least some
128 special classes (e.g. wxFrame) handle different categories of widgets and
129 still have the possibility to draw something in the client area.
130 It was therefore required to write a special purpose GTK widget, that would
131 represent a client area in the sense of wxWindows capable to do the jobs
132 2), 3) and 4). I have written this class and it resides in win_gtk.c of
135 All windows must have a widget, with which they interact with other under-
136 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
137 thw wxWindow class has a member variable called m_widget which holds a
138 pointer to this widget. When the window class represents a GTK native widget,
139 this is (in most cases) the only GTK widget the class manages. E.g. the
140 wxStatitText class handles only a GtkLabel widget a pointer to which you
141 can find in m_widget (defined in wxWindow)
143 When the class has a client area for drawing into and for containing children
144 it has to handle the client area widget (of the type GtkPizza, defined in
145 win_gtk.c), but there could be any number of widgets, handled by a class
146 The common rule for all windows is only, that the widget that interacts with
147 the rest of GTK must be referenced in m_widget and all other widgets must be
148 children of this widget on the GTK level. The top-most widget, which also
149 represents the client area, must be in the m_wxwindow field and must be of
152 As I said, the window classes that display a GTK native widget only have
153 one widget, so in the case of e.g. the wxButton class m_widget holds a
154 pointer to a GtkButton widget. But windows with client areas (for drawing
155 and children) have a m_widget field that is a pointer to a GtkScrolled-
156 Window and a m_wxwindow field that is pointer to a GtkPizza and this
157 one is (in the GTK sense) a child of the GtkScrolledWindow.
159 If the m_wxwindow field is set, then all input to this widget is inter-
160 cepted and sent to the wxWindows class. If not, all input to the widget
161 that gets pointed to by m_widget gets intercepted and sent to the class.
165 The design of scrolling in wxWindows is markedly different from that offered
166 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
167 clicking on a scrollbar belonging to scrolled window will inevitably move
168 the window. In wxWindows, the scrollbar will only emit an event, send this
169 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
170 which actually moves the window and its subchildren. Note that GtkPizza
171 memorizes how much it has been scrolled but that wxWindows forgets this
172 so that the two coordinates systems have to be kept in synch. This is done
173 in various places using the pizza->xoffset and pizza->yoffset values.
177 Singularily the most broken code in GTK is the code that is supposes to
178 inform subwindows (child windows) about new positions. Very often, duplicate
179 events are sent without changes in size or position, equally often no
180 events are sent at all (All this is due to a bug in the GtkContainer code
181 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
182 GTK's own system and it simply waits for size events for toplevel windows
183 and then iterates down the respective size events to all window. This has
184 the disadvantage, that windows might get size events before the GTK widget
185 actually has the reported size. This doesn't normally pose any problem, but
186 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
187 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
188 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
189 window that is used for OpenGl output really has that size (as reported by
194 If someone at some point of time feels the immense desire to have a look at,
195 change or attempt to optimse the Refresh() logic, this person will need an
196 intimate understanding of what a "draw" and what an "expose" events are and
197 what there are used for, in particular when used in connection with GTK's
198 own windowless widgets. Beware.
202 Cursors, too, have been a constant source of pleasure. The main difficulty
203 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
204 for the parent. To prevent this from doing too much harm, I use idle time
205 to set the cursor over and over again, starting from the toplevel windows
206 and ending with the youngest generation (speaking of parent and child windows).
207 Also don't forget that cursors (like much else) are connected to GdkWindows,
208 not GtkWidgets and that the "window" field of a GtkWidget might very well
209 point to the GdkWindow of the parent widget (-> "window less widget") and
210 that the two obviously have very different meanings.
214 //-----------------------------------------------------------------------------
216 //-----------------------------------------------------------------------------
218 extern wxList wxPendingDelete
;
219 extern bool g_blockEventsOnDrag
;
220 extern bool g_blockEventsOnScroll
;
221 extern wxCursor g_globalCursor
;
223 static GdkGC
*g_eraseGC
= NULL
;
225 // mouse capture state: the window which has it and if the mouse is currently
227 static wxWindowGTK
*g_captureWindow
= (wxWindowGTK
*) NULL
;
228 static bool g_captureWindowHasMouse
= FALSE
;
230 /* extern */ wxWindowGTK
*g_focusWindow
= (wxWindowGTK
*) NULL
;
232 // the last window which had the focus - this is normally never NULL (except
233 // if we never had focus at all) as even when g_focusWindow is NULL it still
234 // keeps its previous value
235 static wxWindowGTK
*g_focusWindowLast
= (wxWindowGTK
*)NULL
;
237 // the frame that is currently active (i.e. its child has focus). It is
238 // used to generate wxActivateEvents
239 static wxWindowGTK
*g_activeFrame
= (wxWindowGTK
*)NULL
;
240 static bool g_activeFrameLostFocus
= FALSE
;
242 // if we detect that the app has got/lost the focus, we set this variable to
243 // either TRUE or FALSE and an activate event will be sent during the next
244 // OnIdle() call and it is reset to -1: this value means that we shouldn't
245 // send any activate events at all
246 static int g_sendActivateEvent
= -1;
248 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
249 the last click here */
250 static guint32 gs_timeLastClick
= 0;
252 extern bool g_mainThreadLocked
;
254 //-----------------------------------------------------------------------------
256 //-----------------------------------------------------------------------------
259 #define DISABLE_STYLE_IF_BROKEN_THEME 1
265 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
267 # define DEBUG_MAIN_THREAD
270 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
271 GdkEvent
*WXUNUSED(event
),
272 const wxChar
*WXUNUSED(name
) )
275 static bool s_done = FALSE;
278 wxLog::AddTraceMask("focus");
281 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
287 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
289 // suppress warnings about gtk_debug_focus_in_callback being unused with
294 tmp
+= wxT(" FROM ");
297 wxChar
*s
= new wxChar
[tmp
.Length()+1];
301 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
302 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
307 #define DEBUG_MAIN_THREAD
310 //-----------------------------------------------------------------------------
311 // missing gdk functions
312 //-----------------------------------------------------------------------------
315 gdk_window_warp_pointer (GdkWindow
*window
,
320 GdkWindowPrivate
*priv
;
324 window
= GDK_ROOT_PARENT();
327 if (!GDK_WINDOW_DESTROYED(window
))
329 XWarpPointer (GDK_WINDOW_XDISPLAY(window
),
330 None
, /* not source window -> move from anywhere */
331 GDK_WINDOW_XID(window
), /* dest window */
332 0, 0, 0, 0, /* not source window -> move from anywhere */
336 priv
= (GdkWindowPrivate
*) window
;
338 if (!priv
->destroyed
)
340 XWarpPointer (priv
->xdisplay
,
341 None
, /* not source window -> move from anywhere */
342 priv
->xwindow
, /* dest window */
343 0, 0, 0, 0, /* not source window -> move from anywhere */
349 //-----------------------------------------------------------------------------
351 //-----------------------------------------------------------------------------
353 extern void wxapp_install_idle_handler();
354 extern bool g_isIdle
;
356 //-----------------------------------------------------------------------------
357 // local code (see below)
358 //-----------------------------------------------------------------------------
360 // returns the child of win which currently has focus or NULL if not found
362 // Note: can't be static, needed by textctrl.cpp.
363 wxWindow
*wxFindFocusedChild(wxWindowGTK
*win
)
365 wxWindow
*winFocus
= wxWindowGTK::FindFocus();
367 return (wxWindow
*)NULL
;
369 if ( winFocus
== win
)
370 return (wxWindow
*)win
;
372 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
374 node
= node
->GetNext() )
376 wxWindow
*child
= wxFindFocusedChild(node
->GetData());
381 return (wxWindow
*)NULL
;
384 // Returns toplevel grandparent of given window:
385 static wxWindowGTK
* wxGetTopLevelParent(wxWindowGTK
*win
)
387 wxWindowGTK
*p
= win
;
388 while (p
&& !p
->IsTopLevel())
393 static void draw_frame( GtkWidget
*widget
, wxWindowGTK
*win
)
395 // wxUniversal widgets draw the borders and scrollbars themselves
396 #ifndef __WXUNIVERSAL__
403 if (win
->m_hasScrolling
)
405 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
407 GtkRequisition vscroll_req
;
408 vscroll_req
.width
= 2;
409 vscroll_req
.height
= 2;
410 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
411 (scroll_window
->vscrollbar
, &vscroll_req
);
413 GtkRequisition hscroll_req
;
414 hscroll_req
.width
= 2;
415 hscroll_req
.height
= 2;
416 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
417 (scroll_window
->hscrollbar
, &hscroll_req
);
419 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) );
421 if (scroll_window
->vscrollbar_visible
)
423 dw
+= vscroll_req
.width
;
424 dw
+= scroll_class
->scrollbar_spacing
;
427 if (scroll_window
->hscrollbar_visible
)
429 dh
+= hscroll_req
.height
;
430 dh
+= scroll_class
->scrollbar_spacing
;
436 if (GTK_WIDGET_NO_WINDOW (widget
))
438 dx
+= widget
->allocation
.x
;
439 dy
+= widget
->allocation
.y
;
442 if (win
->HasFlag(wxRAISED_BORDER
))
444 gtk_draw_shadow( widget
->style
,
449 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
453 if (win
->HasFlag(wxSUNKEN_BORDER
))
455 gtk_draw_shadow( widget
->style
,
460 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
464 if (win
->HasFlag(wxSIMPLE_BORDER
))
467 gc
= gdk_gc_new( widget
->window
);
468 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
469 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
471 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
475 #endif // __WXUNIVERSAL__
478 //-----------------------------------------------------------------------------
479 // "expose_event" of m_widget
480 //-----------------------------------------------------------------------------
482 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindowGTK
*win
)
484 if (gdk_event
->count
> 0) return FALSE
;
486 draw_frame( widget
, win
);
490 (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
);
496 //-----------------------------------------------------------------------------
497 // "draw" of m_widget
498 //-----------------------------------------------------------------------------
502 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindowGTK
*win
)
504 draw_frame( widget
, win
);
509 //-----------------------------------------------------------------------------
510 // "size_request" of m_widget
511 //-----------------------------------------------------------------------------
513 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
516 win
->GetSize( &w
, &h
);
520 requisition
->height
= h
;
521 requisition
->width
= w
;
524 //-----------------------------------------------------------------------------
525 // "expose_event" of m_wxwindow
526 //-----------------------------------------------------------------------------
528 static int gtk_window_expose_callback( GtkWidget
*widget
,
529 GdkEventExpose
*gdk_event
,
535 wxapp_install_idle_handler();
538 if (win->GetName() == wxT("panel"))
540 wxPrintf( wxT("OnExpose from ") );
541 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
542 wxPrintf( win->GetClassInfo()->GetClassName() );
543 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
544 (int)gdk_event->area.y,
545 (int)gdk_event->area.width,
546 (int)gdk_event->area.height );
550 #ifndef __WXUNIVERSAL__
551 GtkPizza
*pizza
= GTK_PIZZA (widget
);
553 if (win
->GetThemeEnabled())
555 wxWindow
*parent
= win
->GetParent();
556 while (parent
&& !parent
->IsTopLevel())
557 parent
= parent
->GetParent();
561 gtk_paint_flat_box (parent
->m_widget
->style
,
572 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
574 gdk_event
->area
.width
,
575 gdk_event
->area
.height
);
577 // Actual redrawing takes place in idle time.
582 (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
);
589 //-----------------------------------------------------------------------------
590 // "event" of m_wxwindow
591 //-----------------------------------------------------------------------------
593 // GTK thinks it is clever and filters out a certain amount of "unneeded"
594 // expose events. We need them, of course, so we override the main event
595 // procedure in GtkWidget by giving our own handler for all system events.
596 // There, we look for expose events ourselves whereas all other events are
599 gint
gtk_window_event_event_callback( GtkWidget
*widget
,
600 GdkEventExpose
*event
,
603 if (event
->type
== GDK_EXPOSE
)
605 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
612 //-----------------------------------------------------------------------------
613 // "draw" of m_wxwindow
614 //-----------------------------------------------------------------------------
618 // This callback is a complete replacement of the gtk_pizza_draw() function,
619 // which is disabled.
621 static void gtk_window_draw_callback( GtkWidget
*widget
,
628 wxapp_install_idle_handler();
630 // The wxNO_FULL_REPAINT_ON_RESIZE flag only works if
631 // there are no child windows.
632 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
633 (win
->GetChildren().GetCount() == 0))
639 if (win->GetName() == wxT("panel"))
641 wxPrintf( wxT("OnDraw from ") );
642 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
643 wxPrintf( win->GetClassInfo()->GetClassName() );
644 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
651 #ifndef __WXUNIVERSAL__
652 GtkPizza
*pizza
= GTK_PIZZA (widget
);
654 if (win
->GetThemeEnabled())
656 wxWindow
*parent
= win
->GetParent();
657 while (parent
&& !parent
->IsTopLevel())
658 parent
= parent
->GetParent();
662 gtk_paint_flat_box (parent
->m_widget
->style
,
673 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
674 (pizza
->clear_on_draw
))
676 gdk_window_clear_area( pizza
->bin_window
,
677 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
681 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
683 // Actual redrawing takes place in idle time.
687 #ifndef __WXUNIVERSAL__
688 // Redraw child widgets
689 GList
*children
= pizza
->children
;
692 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
693 children
= children
->next
;
695 GdkRectangle child_area
;
696 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
698 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
706 //-----------------------------------------------------------------------------
707 // "key_press_event" from any window
708 //-----------------------------------------------------------------------------
710 // set WXTRACE to this to see the key event codes on the console
711 #define TRACE_KEYS _T("keyevent")
713 // translates an X key symbol to WXK_XXX value
715 // if isChar is true it means that the value returned will be used for EVT_CHAR
716 // event and then we choose the logical WXK_XXX, i.e. '/' for GDK_KP_Divide,
717 // for example, while if it is false it means that the value is going to be
718 // used for KEY_DOWN/UP events and then we translate GDK_KP_Divide to
720 static long wxTranslateKeySymToWXKey(KeySym keysym
, bool isChar
)
726 // Shift, Control and Alt don't generate the CHAR events at all
729 key_code
= isChar
? 0 : WXK_SHIFT
;
733 key_code
= isChar
? 0 : WXK_CONTROL
;
741 key_code
= isChar
? 0 : WXK_ALT
;
744 // neither do the toggle modifies
745 case GDK_Scroll_Lock
:
746 key_code
= isChar
? 0 : WXK_SCROLL
;
750 key_code
= isChar
? 0 : WXK_CAPITAL
;
754 key_code
= isChar
? 0 : WXK_NUMLOCK
;
758 // various other special keys
771 case GDK_ISO_Left_Tab
:
778 key_code
= WXK_RETURN
;
782 key_code
= WXK_CLEAR
;
786 key_code
= WXK_PAUSE
;
790 key_code
= WXK_SELECT
;
794 key_code
= WXK_PRINT
;
798 key_code
= WXK_EXECUTE
;
802 key_code
= WXK_ESCAPE
;
805 // cursor and other extended keyboard keys
807 key_code
= WXK_DELETE
;
823 key_code
= WXK_RIGHT
;
830 case GDK_Prior
: // == GDK_Page_Up
831 key_code
= WXK_PRIOR
;
834 case GDK_Next
: // == GDK_Page_Down
847 key_code
= WXK_INSERT
;
862 key_code
= (isChar
? '0' : WXK_NUMPAD0
) + keysym
- GDK_KP_0
;
866 key_code
= isChar
? ' ' : WXK_NUMPAD_SPACE
;
870 key_code
= isChar
? WXK_TAB
: WXK_NUMPAD_TAB
;
874 key_code
= isChar
? WXK_RETURN
: WXK_NUMPAD_ENTER
;
878 key_code
= isChar
? WXK_F1
: WXK_NUMPAD_F1
;
882 key_code
= isChar
? WXK_F2
: WXK_NUMPAD_F2
;
886 key_code
= isChar
? WXK_F3
: WXK_NUMPAD_F3
;
890 key_code
= isChar
? WXK_F4
: WXK_NUMPAD_F4
;
894 key_code
= isChar
? WXK_HOME
: WXK_NUMPAD_HOME
;
898 key_code
= isChar
? WXK_LEFT
: WXK_NUMPAD_LEFT
;
902 key_code
= isChar
? WXK_UP
: WXK_NUMPAD_UP
;
906 key_code
= isChar
? WXK_RIGHT
: WXK_NUMPAD_RIGHT
;
910 key_code
= isChar
? WXK_DOWN
: WXK_NUMPAD_DOWN
;
913 case GDK_KP_Prior
: // == GDK_KP_Page_Up
914 key_code
= isChar
? WXK_PRIOR
: WXK_NUMPAD_PRIOR
;
917 case GDK_KP_Next
: // == GDK_KP_Page_Down
918 key_code
= isChar
? WXK_NEXT
: WXK_NUMPAD_NEXT
;
922 key_code
= isChar
? WXK_END
: WXK_NUMPAD_END
;
926 key_code
= isChar
? WXK_HOME
: WXK_NUMPAD_BEGIN
;
930 key_code
= isChar
? WXK_INSERT
: WXK_NUMPAD_INSERT
;
934 key_code
= isChar
? WXK_DELETE
: WXK_NUMPAD_DELETE
;
938 key_code
= isChar
? '=' : WXK_NUMPAD_EQUAL
;
941 case GDK_KP_Multiply
:
942 key_code
= isChar
? '*' : WXK_NUMPAD_MULTIPLY
;
946 key_code
= isChar
? '+' : WXK_NUMPAD_ADD
;
949 case GDK_KP_Separator
:
950 // FIXME: what is this?
951 key_code
= isChar
? '.' : WXK_NUMPAD_SEPARATOR
;
954 case GDK_KP_Subtract
:
955 key_code
= isChar
? '-' : WXK_NUMPAD_SUBTRACT
;
959 key_code
= isChar
? '.' : WXK_NUMPAD_DECIMAL
;
963 key_code
= isChar
? '/' : WXK_NUMPAD_DIVIDE
;
980 key_code
= WXK_F1
+ keysym
- GDK_F1
;
990 static inline bool wxIsAsciiKeysym(KeySym ks
)
996 wxTranslateGTKKeyEventToWx(wxKeyEvent
& event
,
998 GdkEventKey
*gdk_event
)
1000 // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string
1001 // but only event->keyval which is quite useless to us, so remember
1002 // the last character from GDK_KEY_PRESS and reuse it as last resort
1004 // NB: should be MT-safe as we're always called from the main thread only
1009 } s_lastKeyPress
= { 0, 0 };
1011 KeySym keysym
= gdk_event
->keyval
;
1013 wxLogTrace(TRACE_KEYS
, _T("Key %s event: keysym = %d"),
1014 event
.GetEventType() == wxEVT_KEY_UP
? _T("release")
1018 long key_code
= wxTranslateKeySymToWXKey(keysym
, FALSE
/* !isChar */);
1022 // do we have the translation or is it a plain ASCII character?
1023 if ( (gdk_event
->length
== 1) || wxIsAsciiKeysym(keysym
) )
1025 // we should use keysym if it is ASCII as X does some translations
1026 // like "I pressed while Control is down" => "Ctrl-I" == "TAB"
1027 // which we don't want here (but which we do use for OnChar())
1028 if ( !wxIsAsciiKeysym(keysym
) )
1030 keysym
= (KeySym
)gdk_event
->string
[0];
1033 // we want to always get the same key code when the same key is
1034 // pressed regardless of the state of the modifies, i.e. on a
1035 // standard US keyboard pressing '5' or '%' ('5' key with
1036 // Shift) should result in the same key code in OnKeyDown():
1037 // '5' (although OnChar() will get either '5' or '%').
1039 // to do it we first translate keysym to keycode (== scan code)
1040 // and then back but always using the lower register
1041 Display
*dpy
= (Display
*)wxGetDisplay();
1042 KeyCode keycode
= XKeysymToKeycode(dpy
, keysym
);
1044 wxLogTrace(TRACE_KEYS
, _T("\t-> keycode %d"), keycode
);
1046 KeySym keysymNormalized
= XKeycodeToKeysym(dpy
, keycode
, 0);
1048 // use the normalized, i.e. lower register, keysym if we've
1050 key_code
= keysymNormalized
? keysymNormalized
: keysym
;
1052 // as explained above, we want to have lower register key codes
1053 // normally but for the letter keys we want to have the upper ones
1055 // NB: don't use XConvertCase() here, we want to do it for letters
1057 key_code
= toupper(key_code
);
1059 else // non ASCII key, what to do?
1061 // by default, ignore it
1064 // but if we have cached information from the last KEY_PRESS
1065 if ( gdk_event
->type
== GDK_KEY_RELEASE
)
1068 if ( keysym
== s_lastKeyPress
.keysym
)
1070 key_code
= s_lastKeyPress
.keycode
;
1075 if ( gdk_event
->type
== GDK_KEY_PRESS
)
1077 // remember it to be reused for KEY_UP event later
1078 s_lastKeyPress
.keysym
= keysym
;
1079 s_lastKeyPress
.keycode
= key_code
;
1083 wxLogTrace(TRACE_KEYS
, _T("\t-> wxKeyCode %d"), key_code
);
1085 // sending unknown key events doesn't really make sense
1089 // now fill all the other fields
1092 GdkModifierType state
;
1093 if (gdk_event
->window
)
1094 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1096 event
.SetTimestamp( gdk_event
->time
);
1097 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
) != 0;
1098 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
) != 0;
1099 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
) != 0;
1100 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
) != 0;
1101 event
.m_keyCode
= key_code
;
1102 event
.m_scanCode
= gdk_event
->keyval
;
1103 event
.m_rawCode
= (wxUint32
) gdk_event
->keyval
;
1104 event
.m_rawFlags
= 0;
1107 event
.SetEventObject( win
);
1112 static gint
gtk_window_key_press_callback( GtkWidget
*widget
,
1113 GdkEventKey
*gdk_event
,
1119 wxapp_install_idle_handler();
1123 if (g_blockEventsOnDrag
)
1126 wxKeyEvent
event( wxEVT_KEY_DOWN
);
1127 if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) )
1129 // unknown key pressed, ignore (the event would be useless anyhow)
1133 bool ret
= win
->GetEventHandler()->ProcessEvent( event
);
1138 wxWindowGTK
*ancestor
= win
;
1141 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
1144 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
1145 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
1148 if (ancestor
->IsTopLevel())
1150 ancestor
= ancestor
->GetParent();
1153 #endif // wxUSE_ACCEL
1155 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
1156 will only be sent if it is not in an accelerator table. */
1159 KeySym keysym
= gdk_event
->keyval
;
1160 long key_code
= wxTranslateKeySymToWXKey(keysym
, TRUE
/* isChar */);
1163 if ( gdk_event
->length
== 1 )
1165 key_code
= (unsigned char)gdk_event
->string
[0];
1167 else if ( wxIsAsciiKeysym(keysym
) )
1170 key_code
= (unsigned char)keysym
;
1176 wxLogTrace(TRACE_KEYS
, _T("Char event: %ld"), key_code
);
1178 // reuse the same event object, just change its type and use the
1179 // translated keycode instead of the raw one
1180 event
.SetEventType(wxEVT_CHAR
);
1181 event
.m_keyCode
= key_code
;
1183 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1187 /* win is a control: tab can be propagated up */
1189 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
1190 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
1191 // have this style, yet choose not to process this particular TAB in which
1192 // case TAB must still work as a navigational character
1194 !win
->HasFlag(wxTE_PROCESS_TAB
) &&
1196 win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
1198 wxNavigationKeyEvent new_event
;
1199 new_event
.SetEventObject( win
->GetParent() );
1200 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
1201 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
1202 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1203 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
1204 new_event
.SetCurrentFocus( win
);
1205 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
1208 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
1210 (gdk_event
->keyval
== GDK_Escape
) )
1212 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
1213 new_event
.SetEventObject( win
);
1214 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
1218 #if 0 // (GTK_MINOR_VERSION > 0)
1219 /* Pressing F10 will activate the menu bar of the top frame. */
1221 (gdk_event
->keyval
== GDK_F10
) )
1223 wxWindowGTK
*ancestor
= win
;
1226 if (wxIsKindOf(ancestor
,wxFrame
))
1228 wxFrame
*frame
= (wxFrame
*) ancestor
;
1229 wxMenuBar
*menubar
= frame
->GetMenuBar();
1232 wxNode
*node
= menubar
->GetMenus().First();
1235 wxMenu
*firstMenu
= (wxMenu
*) node
->Data();
1236 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu
->m_owner
) );
1242 ancestor
= ancestor
->GetParent();
1249 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1256 //-----------------------------------------------------------------------------
1257 // "key_release_event" from any window
1258 //-----------------------------------------------------------------------------
1260 static gint
gtk_window_key_release_callback( GtkWidget
*widget
,
1261 GdkEventKey
*gdk_event
,
1267 wxapp_install_idle_handler();
1272 if (g_blockEventsOnDrag
)
1275 wxKeyEvent
event( wxEVT_KEY_UP
);
1276 if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) )
1278 // unknown key pressed, ignore (the event would be useless anyhow
1282 if ( !win
->GetEventHandler()->ProcessEvent( event
) )
1285 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1289 // ============================================================================
1291 // ============================================================================
1293 // init wxMouseEvent with the info from gdk_event
1294 #define InitMouseEvent(win, event, gdk_event) \
1296 event.SetTimestamp( gdk_event->time ); \
1297 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
1298 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
1299 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
1300 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
1301 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
1302 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
1303 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
1305 wxPoint pt = win->GetClientAreaOrigin(); \
1306 event.m_x = (wxCoord)gdk_event->x - pt.x; \
1307 event.m_y = (wxCoord)gdk_event->y - pt.y; \
1310 // ----------------------------------------------------------------------------
1311 // mouse event processing helper
1312 // ----------------------------------------------------------------------------
1314 static void AdjustEventButtonState(wxMouseEvent
& event
)
1316 // GDK reports the old state of the button for a button press event, but
1317 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1318 // for a LEFT_DOWN event, not FALSE, so we will invert
1319 // left/right/middleDown for the corresponding click events
1321 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1322 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1323 (event
.GetEventType() == wxEVT_LEFT_UP
))
1325 event
.m_leftDown
= !event
.m_leftDown
;
1329 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1330 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1331 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1333 event
.m_middleDown
= !event
.m_middleDown
;
1337 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1338 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1339 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1341 event
.m_rightDown
= !event
.m_rightDown
;
1346 //-----------------------------------------------------------------------------
1347 // "button_press_event"
1348 //-----------------------------------------------------------------------------
1350 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1355 wxapp_install_idle_handler();
1358 wxPrintf( wxT("1) OnButtonPress from ") );
1359 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1360 wxPrintf( win->GetClassInfo()->GetClassName() );
1361 wxPrintf( wxT(".\n") );
1363 if (!win
->m_hasVMT
) return FALSE
;
1364 if (g_blockEventsOnDrag
) return TRUE
;
1365 if (g_blockEventsOnScroll
) return TRUE
;
1367 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1369 if (win
->m_wxwindow
&& (g_focusWindow
!= win
) && win
->AcceptsFocus())
1371 gtk_widget_grab_focus( win
->m_wxwindow
);
1373 wxPrintf( wxT("GrabFocus from ") );
1374 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1375 wxPrintf( win->GetClassInfo()->GetClassName() );
1376 wxPrintf( wxT(".\n") );
1380 wxEventType event_type
= wxEVT_NULL
;
1382 if (gdk_event
->button
== 1)
1384 switch (gdk_event
->type
)
1386 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1387 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1391 else if (gdk_event
->button
== 2)
1393 switch (gdk_event
->type
)
1395 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1396 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1400 else if (gdk_event
->button
== 3)
1402 switch (gdk_event
->type
)
1404 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1405 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1410 if ( event_type
== wxEVT_NULL
)
1412 // unknown mouse button or click type
1416 wxMouseEvent
event( event_type
);
1417 InitMouseEvent( win
, event
, gdk_event
);
1419 AdjustEventButtonState(event
);
1421 // wxListBox actually get mouse events from the item
1423 if (win
->m_isListBox
)
1425 event
.m_x
+= widget
->allocation
.x
;
1426 event
.m_y
+= widget
->allocation
.y
;
1429 // Some control don't have their own X window and thus cannot get
1432 if (!g_captureWindow
)
1434 wxCoord x
= event
.m_x
;
1435 wxCoord y
= event
.m_y
;
1436 if (win
->m_wxwindow
)
1438 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1439 x
+= pizza
->xoffset
;
1440 y
+= pizza
->yoffset
;
1443 wxNode
*node
= win
->GetChildren().First();
1446 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1448 node
= node
->Next();
1449 if (!child
->IsShown())
1452 if (child
->m_isStaticBox
)
1454 // wxStaticBox is transparent in the box itself
1455 int xx1
= child
->m_x
;
1456 int yy1
= child
->m_y
;
1457 int xx2
= child
->m_x
+ child
->m_width
;
1458 int yy2
= child
->m_x
+ child
->m_height
;
1461 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1463 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1465 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1467 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1470 event
.m_x
-= child
->m_x
;
1471 event
.m_y
-= child
->m_y
;
1478 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1479 (child
->m_x
<= x
) &&
1480 (child
->m_y
<= y
) &&
1481 (child
->m_x
+child
->m_width
>= x
) &&
1482 (child
->m_y
+child
->m_height
>= y
))
1485 event
.m_x
-= child
->m_x
;
1486 event
.m_y
-= child
->m_y
;
1493 event
.SetEventObject( win
);
1495 gs_timeLastClick
= gdk_event
->time
;
1498 wxPrintf( wxT("2) OnButtonPress from ") );
1499 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1500 wxPrintf( win->GetClassInfo()->GetClassName() );
1501 wxPrintf( wxT(".\n") );
1504 if (win
->GetEventHandler()->ProcessEvent( event
))
1506 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1513 //-----------------------------------------------------------------------------
1514 // "button_release_event"
1515 //-----------------------------------------------------------------------------
1517 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1522 wxapp_install_idle_handler();
1524 if (!win
->m_hasVMT
) return FALSE
;
1525 if (g_blockEventsOnDrag
) return FALSE
;
1526 if (g_blockEventsOnScroll
) return FALSE
;
1528 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1531 printf( "OnButtonRelease from " );
1532 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1533 printf( win->GetClassInfo()->GetClassName() );
1537 wxEventType event_type
= wxEVT_NULL
;
1539 switch (gdk_event
->button
)
1541 case 1: event_type
= wxEVT_LEFT_UP
; break;
1542 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1543 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1544 default: return FALSE
;
1547 wxMouseEvent
event( event_type
);
1548 InitMouseEvent( win
, event
, gdk_event
);
1550 AdjustEventButtonState(event
);
1552 // wxListBox actually get mouse events from the item
1554 if (win
->m_isListBox
)
1556 event
.m_x
+= widget
->allocation
.x
;
1557 event
.m_y
+= widget
->allocation
.y
;
1560 // Some control don't have their own X window and thus cannot get
1563 if (!g_captureWindow
)
1565 wxCoord x
= event
.m_x
;
1566 wxCoord y
= event
.m_y
;
1567 if (win
->m_wxwindow
)
1569 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1570 x
+= pizza
->xoffset
;
1571 y
+= pizza
->yoffset
;
1574 wxNode
*node
= win
->GetChildren().First();
1577 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1579 node
= node
->Next();
1580 if (!child
->IsShown())
1583 if (child
->m_isStaticBox
)
1585 // wxStaticBox is transparent in the box itself
1586 int xx1
= child
->m_x
;
1587 int yy1
= child
->m_y
;
1588 int xx2
= child
->m_x
+ child
->m_width
;
1589 int yy2
= child
->m_x
+ child
->m_height
;
1592 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1594 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1596 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1598 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1601 event
.m_x
-= child
->m_x
;
1602 event
.m_y
-= child
->m_y
;
1609 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1610 (child
->m_x
<= x
) &&
1611 (child
->m_y
<= y
) &&
1612 (child
->m_x
+child
->m_width
>= x
) &&
1613 (child
->m_y
+child
->m_height
>= y
))
1616 event
.m_x
-= child
->m_x
;
1617 event
.m_y
-= child
->m_y
;
1624 event
.SetEventObject( win
);
1626 if (win
->GetEventHandler()->ProcessEvent( event
))
1628 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1635 //-----------------------------------------------------------------------------
1636 // "motion_notify_event"
1637 //-----------------------------------------------------------------------------
1639 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
,
1640 GdkEventMotion
*gdk_event
,
1646 wxapp_install_idle_handler();
1648 if (!win
->m_hasVMT
) return FALSE
;
1649 if (g_blockEventsOnDrag
) return FALSE
;
1650 if (g_blockEventsOnScroll
) return FALSE
;
1652 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1654 if (gdk_event
->is_hint
)
1658 GdkModifierType state
;
1659 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1665 printf( "OnMotion from " );
1666 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1667 printf( win->GetClassInfo()->GetClassName() );
1671 wxMouseEvent
event( wxEVT_MOTION
);
1672 InitMouseEvent(win
, event
, gdk_event
);
1674 if ( g_captureWindow
)
1676 // synthetize a mouse enter or leave event if needed
1677 GdkWindow
*winUnderMouse
= gdk_window_at_pointer(NULL
, NULL
);
1678 bool hasMouse
= winUnderMouse
== gdk_event
->window
;
1679 if ( hasMouse
!= g_captureWindowHasMouse
)
1681 // the mouse changed window
1682 g_captureWindowHasMouse
= hasMouse
;
1684 wxMouseEvent
event(g_captureWindowHasMouse
? wxEVT_ENTER_WINDOW
1685 : wxEVT_LEAVE_WINDOW
);
1686 InitMouseEvent(win
, event
, gdk_event
);
1687 event
.SetEventObject(win
);
1688 win
->GetEventHandler()->ProcessEvent(event
);
1693 // Some control don't have their own X window and thus cannot get
1696 wxCoord x
= event
.m_x
;
1697 wxCoord y
= event
.m_y
;
1698 if (win
->m_wxwindow
)
1700 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1701 x
+= pizza
->xoffset
;
1702 y
+= pizza
->yoffset
;
1705 wxNode
*node
= win
->GetChildren().First();
1708 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1710 node
= node
->Next();
1711 if (!child
->IsShown())
1714 if (child
->m_isStaticBox
)
1716 // wxStaticBox is transparent in the box itself
1717 int xx1
= child
->m_x
;
1718 int yy1
= child
->m_y
;
1719 int xx2
= child
->m_x
+ child
->m_width
;
1720 int yy2
= child
->m_x
+ child
->m_height
;
1723 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1725 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1727 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1729 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1732 event
.m_x
-= child
->m_x
;
1733 event
.m_y
-= child
->m_y
;
1740 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1741 (child
->m_x
<= x
) &&
1742 (child
->m_y
<= y
) &&
1743 (child
->m_x
+child
->m_width
>= x
) &&
1744 (child
->m_y
+child
->m_height
>= y
))
1747 event
.m_x
-= child
->m_x
;
1748 event
.m_y
-= child
->m_y
;
1755 event
.SetEventObject( win
);
1757 if (win
->GetEventHandler()->ProcessEvent( event
))
1759 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1766 //-----------------------------------------------------------------------------
1768 //-----------------------------------------------------------------------------
1770 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
,
1771 GdkEvent
*WXUNUSED(event
),
1777 wxapp_install_idle_handler();
1779 if (!win
->m_hasVMT
) return FALSE
;
1780 if (g_blockEventsOnDrag
) return FALSE
;
1782 switch ( g_sendActivateEvent
)
1785 // we've got focus from outside, synthetize wxActivateEvent
1786 g_sendActivateEvent
= 1;
1790 // another our window just lost focus, it was already ours before
1791 // - don't send any wxActivateEvent
1792 g_sendActivateEvent
= -1;
1797 g_focusWindow
= win
;
1800 wxLogDebug( wxT("OnSetFocus from %s\n"), win
->GetName().c_str() );
1803 // notify the parent keeping track of focus for the kbd navigation
1804 // purposes that we got it
1805 wxChildFocusEvent
eventFocus(win
);
1806 (void)win
->GetEventHandler()->ProcessEvent(eventFocus
);
1810 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1814 // caret needs to be informed about focus change
1815 wxCaret
*caret
= win
->GetCaret();
1818 caret
->OnSetFocus();
1820 #endif // wxUSE_CARET
1822 wxWindowGTK
*active
= wxGetTopLevelParent(win
);
1823 if ( active
!= g_activeFrame
)
1825 if ( g_activeFrame
)
1827 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame
);
1828 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
1829 event
.SetEventObject(g_activeFrame
);
1830 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1833 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active
);
1834 g_activeFrame
= active
;
1835 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId());
1836 event
.SetEventObject(g_activeFrame
);
1837 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1839 g_activeFrameLostFocus
= FALSE
;
1842 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1843 event
.SetEventObject( win
);
1845 if (win
->GetEventHandler()->ProcessEvent( event
))
1847 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1855 //-----------------------------------------------------------------------------
1856 // "focus_out_event"
1857 //-----------------------------------------------------------------------------
1859 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEventFocus
*gdk_event
, wxWindowGTK
*win
)
1864 wxapp_install_idle_handler();
1866 if (!win
->m_hasVMT
) return FALSE
;
1867 if (g_blockEventsOnDrag
) return FALSE
;
1870 wxLogDebug( wxT("OnKillFocus from %s"), win
->GetName().c_str() );
1873 if ( !g_activeFrameLostFocus
&& g_activeFrame
)
1875 // VZ: commenting this out because it does happen (although not easy
1876 // to reproduce, I only see it when using wxMiniFrame and not
1877 // always) and makes using Mahogany quite annoying
1879 wxASSERT_MSG( wxGetTopLevelParent(win
) == g_activeFrame
,
1880 wxT("unfocusing window that hasn't gained focus properly") )
1883 g_activeFrameLostFocus
= TRUE
;
1886 // if the focus goes out of our app alltogether, OnIdle() will send
1887 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1888 // g_sendActivateEvent to -1
1889 g_sendActivateEvent
= 0;
1891 wxWindowGTK
*winFocus
= wxFindFocusedChild(win
);
1895 g_focusWindow
= (wxWindowGTK
*)NULL
;
1903 // caret needs to be informed about focus change
1904 wxCaret
*caret
= win
->GetCaret();
1907 caret
->OnKillFocus();
1909 #endif // wxUSE_CARET
1911 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1912 event
.SetEventObject( win
);
1914 if (win
->GetEventHandler()->ProcessEvent( event
))
1916 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1923 //-----------------------------------------------------------------------------
1924 // "enter_notify_event"
1925 //-----------------------------------------------------------------------------
1927 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1932 wxapp_install_idle_handler();
1934 if (!win
->m_hasVMT
) return FALSE
;
1935 if (g_blockEventsOnDrag
) return FALSE
;
1937 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1939 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1940 event
.SetTimestamp( gdk_event
->time
);
1941 event
.SetEventObject( win
);
1945 GdkModifierType state
= (GdkModifierType
)0;
1947 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1949 InitMouseEvent(win
, event
, gdk_event
);
1950 wxPoint pt
= win
->GetClientAreaOrigin();
1951 event
.m_x
= x
+ pt
.x
;
1952 event
.m_y
= y
+ pt
.y
;
1954 if (win
->GetEventHandler()->ProcessEvent( event
))
1956 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1963 //-----------------------------------------------------------------------------
1964 // "leave_notify_event"
1965 //-----------------------------------------------------------------------------
1967 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1972 wxapp_install_idle_handler();
1974 if (!win
->m_hasVMT
) return FALSE
;
1975 if (g_blockEventsOnDrag
) return FALSE
;
1977 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1979 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1980 event
.SetTimestamp( gdk_event
->time
);
1981 event
.SetEventObject( win
);
1985 GdkModifierType state
= (GdkModifierType
)0;
1987 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1989 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
) != 0;
1990 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
) != 0;
1991 event
.m_altDown
= (state
& GDK_MOD1_MASK
) != 0;
1992 event
.m_metaDown
= (state
& GDK_MOD2_MASK
) != 0;
1993 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
) != 0;
1994 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
) != 0;
1995 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
) != 0;
1997 wxPoint pt
= win
->GetClientAreaOrigin();
1998 event
.m_x
= x
+ pt
.x
;
1999 event
.m_y
= y
+ pt
.y
;
2001 if (win
->GetEventHandler()->ProcessEvent( event
))
2003 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
2010 //-----------------------------------------------------------------------------
2011 // "value_changed" from m_vAdjust
2012 //-----------------------------------------------------------------------------
2014 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
,
2021 wxapp_install_idle_handler();
2023 if (g_blockEventsOnDrag
) return;
2025 if (!win
->m_hasVMT
) return;
2027 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
2028 if (fabs(diff
) < 0.2) return;
2030 win
->m_oldVerticalPos
= adjust
->value
;
2032 wxEventType command
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(win
->m_widget
));
2034 int value
= (int)(adjust
->value
+0.5);
2036 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
2037 event
.SetEventObject( win
);
2038 win
->GetEventHandler()->ProcessEvent( event
);
2041 //-----------------------------------------------------------------------------
2042 // "value_changed" from m_hAdjust
2043 //-----------------------------------------------------------------------------
2045 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
,
2052 wxapp_install_idle_handler();
2054 if (g_blockEventsOnDrag
) return;
2055 if (!win
->m_hasVMT
) return;
2057 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
2058 if (fabs(diff
) < 0.2) return;
2060 wxEventType command
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(win
->m_widget
));
2062 win
->m_oldHorizontalPos
= adjust
->value
;
2064 int value
= (int)(adjust
->value
+0.5);
2066 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
2067 event
.SetEventObject( win
);
2068 win
->GetEventHandler()->ProcessEvent( event
);
2071 //-----------------------------------------------------------------------------
2072 // "button_press_event" from scrollbar
2073 //-----------------------------------------------------------------------------
2075 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
2076 GdkEventButton
*gdk_event
,
2082 wxapp_install_idle_handler();
2085 g_blockEventsOnScroll
= TRUE
;
2087 // FIXME: there is no 'slider' field in GTK+ 2.0 any more
2089 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
2095 //-----------------------------------------------------------------------------
2096 // "button_release_event" from scrollbar
2097 //-----------------------------------------------------------------------------
2099 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
2100 GdkEventButton
*WXUNUSED(gdk_event
),
2105 // don't test here as we can release the mouse while being over
2106 // a different window than the slider
2108 // if (gdk_event->window != widget->slider) return FALSE;
2110 g_blockEventsOnScroll
= FALSE
;
2112 if (win
->m_isScrolling
)
2114 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
2118 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
2119 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
2121 value
= (int)(win
->m_hAdjust
->value
+0.5);
2124 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
2126 value
= (int)(win
->m_vAdjust
->value
+0.5);
2130 wxScrollWinEvent
event( command
, value
, dir
);
2131 event
.SetEventObject( win
);
2132 win
->GetEventHandler()->ProcessEvent( event
);
2135 win
->m_isScrolling
= FALSE
;
2140 // ----------------------------------------------------------------------------
2141 // this wxWindowBase function is implemented here (in platform-specific file)
2142 // because it is static and so couldn't be made virtual
2143 // ----------------------------------------------------------------------------
2145 wxWindow
*wxWindowBase::FindFocus()
2147 // the cast is necessary when we compile in wxUniversal mode
2148 return (wxWindow
*)g_focusWindow
;
2151 //-----------------------------------------------------------------------------
2152 // "realize" from m_widget
2153 //-----------------------------------------------------------------------------
2155 /* We cannot set colours and fonts before the widget has
2156 been realized, so we do this directly after realization. */
2159 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
2164 wxapp_install_idle_handler();
2166 if (win
->m_delayedBackgroundColour
)
2167 win
->SetBackgroundColour( win
->GetBackgroundColour() );
2169 if (win
->m_delayedForegroundColour
)
2170 win
->SetForegroundColour( win
->GetForegroundColour() );
2172 wxWindowCreateEvent
event( win
);
2173 event
.SetEventObject( win
);
2174 win
->GetEventHandler()->ProcessEvent( event
);
2179 //-----------------------------------------------------------------------------
2181 //-----------------------------------------------------------------------------
2184 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
2185 GtkAllocation
*WXUNUSED(alloc
),
2189 wxapp_install_idle_handler();
2191 if (!win
->m_hasScrolling
) return;
2193 int client_width
= 0;
2194 int client_height
= 0;
2195 win
->GetClientSize( &client_width
, &client_height
);
2196 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
2199 win
->m_oldClientWidth
= client_width
;
2200 win
->m_oldClientHeight
= client_height
;
2202 if (!win
->m_nativeSizeEvent
)
2204 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
2205 event
.SetEventObject( win
);
2206 win
->GetEventHandler()->ProcessEvent( event
);
2212 #define WXUNUSED_UNLESS_XIM(param) param
2214 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2217 /* Resize XIM window */
2220 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2221 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
2222 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2225 wxapp_install_idle_handler();
2231 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
2235 gdk_window_get_size (widget
->window
, &width
, &height
);
2236 win
->m_icattr
->preedit_area
.width
= width
;
2237 win
->m_icattr
->preedit_area
.height
= height
;
2238 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2243 //-----------------------------------------------------------------------------
2244 // "realize" from m_wxwindow
2245 //-----------------------------------------------------------------------------
2247 /* Initialize XIM support */
2250 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2251 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2254 wxapp_install_idle_handler();
2257 if (win
->m_ic
) return FALSE
;
2258 if (!widget
) return FALSE
;
2259 if (!gdk_im_ready()) return FALSE
;
2261 win
->m_icattr
= gdk_ic_attr_new();
2262 if (!win
->m_icattr
) return FALSE
;
2266 GdkColormap
*colormap
;
2267 GdkICAttr
*attr
= win
->m_icattr
;
2268 unsigned attrmask
= GDK_IC_ALL_REQ
;
2270 GdkIMStyle supported_style
= (GdkIMStyle
)
2271 (GDK_IM_PREEDIT_NONE
|
2272 GDK_IM_PREEDIT_NOTHING
|
2273 GDK_IM_PREEDIT_POSITION
|
2274 GDK_IM_STATUS_NONE
|
2275 GDK_IM_STATUS_NOTHING
);
2277 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2278 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2280 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2281 attr
->client_window
= widget
->window
;
2283 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2284 gtk_widget_get_default_colormap ())
2286 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2287 attr
->preedit_colormap
= colormap
;
2290 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2291 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2292 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2293 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2295 switch (style
& GDK_IM_PREEDIT_MASK
)
2297 case GDK_IM_PREEDIT_POSITION
:
2298 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2300 g_warning ("over-the-spot style requires fontset");
2304 gdk_window_get_size (widget
->window
, &width
, &height
);
2306 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2307 attr
->spot_location
.x
= 0;
2308 attr
->spot_location
.y
= height
;
2309 attr
->preedit_area
.x
= 0;
2310 attr
->preedit_area
.y
= 0;
2311 attr
->preedit_area
.width
= width
;
2312 attr
->preedit_area
.height
= height
;
2313 attr
->preedit_fontset
= widget
->style
->font
;
2318 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2320 if (win
->m_ic
== NULL
)
2321 g_warning ("Can't create input context.");
2324 mask
= gdk_window_get_events (widget
->window
);
2325 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2326 gdk_window_set_events (widget
->window
, mask
);
2328 if (GTK_WIDGET_HAS_FOCUS(widget
))
2329 gdk_im_begin (win
->m_ic
, widget
->window
);
2336 //-----------------------------------------------------------------------------
2337 // InsertChild for wxWindowGTK.
2338 //-----------------------------------------------------------------------------
2340 /* Callback for wxWindowGTK. This very strange beast has to be used because
2341 * C++ has no virtual methods in a constructor. We have to emulate a
2342 * virtual function here as wxNotebook requires a different way to insert
2343 * a child in it. I had opted for creating a wxNotebookPage window class
2344 * which would have made this superfluous (such in the MDI window system),
2345 * but no-one was listening to me... */
2347 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child
)
2349 /* the window might have been scrolled already, do we
2350 have to adapt the position */
2351 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2352 child
->m_x
+= pizza
->xoffset
;
2353 child
->m_y
+= pizza
->yoffset
;
2355 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2356 GTK_WIDGET(child
->m_widget
),
2363 //-----------------------------------------------------------------------------
2365 //-----------------------------------------------------------------------------
2367 wxWindow
*wxGetActiveWindow()
2369 // the cast is necessary when we compile in wxUniversal mode
2370 return (wxWindow
*)g_focusWindow
;
2373 //-----------------------------------------------------------------------------
2375 //-----------------------------------------------------------------------------
2377 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
2379 #ifdef __WXUNIVERSAL__
2380 IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
)
2382 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2383 #endif // __WXUNIVERSAL__/__WXGTK__
2385 void wxWindowGTK::Init()
2391 m_widget
= (GtkWidget
*) NULL
;
2392 m_wxwindow
= (GtkWidget
*) NULL
;
2393 m_focusWidget
= (GtkWidget
*) NULL
;
2403 m_needParent
= TRUE
;
2404 m_isBeingDeleted
= FALSE
;
2407 m_nativeSizeEvent
= FALSE
;
2409 m_hasScrolling
= FALSE
;
2410 m_isScrolling
= FALSE
;
2412 m_hAdjust
= (GtkAdjustment
*) NULL
;
2413 m_vAdjust
= (GtkAdjustment
*) NULL
;
2414 m_oldHorizontalPos
= 0.0;
2415 m_oldVerticalPos
= 0.0;
2418 m_widgetStyle
= (GtkStyle
*) NULL
;
2420 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2422 m_isStaticBox
= FALSE
;
2423 m_isRadioButton
= FALSE
;
2424 m_isListBox
= FALSE
;
2426 m_acceptsFocus
= FALSE
;
2428 m_clipPaintRegion
= FALSE
;
2430 m_cursor
= *wxSTANDARD_CURSOR
;
2432 m_delayedForegroundColour
= FALSE
;
2433 m_delayedBackgroundColour
= FALSE
;
2436 m_ic
= (GdkIC
*) NULL
;
2437 m_icattr
= (GdkICAttr
*) NULL
;
2441 wxWindowGTK::wxWindowGTK()
2446 wxWindowGTK::wxWindowGTK( wxWindow
*parent
,
2451 const wxString
&name
)
2455 Create( parent
, id
, pos
, size
, style
, name
);
2458 bool wxWindowGTK::Create( wxWindow
*parent
,
2463 const wxString
&name
)
2465 if (!PreCreation( parent
, pos
, size
) ||
2466 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2468 wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
2472 m_insertCallback
= wxInsertChildInWindow
;
2474 // always needed for background clearing
2475 m_delayedBackgroundColour
= TRUE
;
2477 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2478 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2480 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2482 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2483 scroll_class
->scrollbar_spacing
= 0;
2485 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2487 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2488 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2490 m_wxwindow
= gtk_pizza_new();
2492 #ifndef __WXUNIVERSAL__
2493 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2495 if (HasFlag(wxRAISED_BORDER
))
2497 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2499 else if (HasFlag(wxSUNKEN_BORDER
))
2501 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2503 else if (HasFlag(wxSIMPLE_BORDER
))
2505 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2509 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2511 #endif // __WXUNIVERSAL__
2513 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2515 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2516 m_acceptsFocus
= TRUE
;
2518 // I _really_ don't want scrollbars in the beginning
2519 m_vAdjust
->lower
= 0.0;
2520 m_vAdjust
->upper
= 1.0;
2521 m_vAdjust
->value
= 0.0;
2522 m_vAdjust
->step_increment
= 1.0;
2523 m_vAdjust
->page_increment
= 1.0;
2524 m_vAdjust
->page_size
= 5.0;
2525 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2526 m_hAdjust
->lower
= 0.0;
2527 m_hAdjust
->upper
= 1.0;
2528 m_hAdjust
->value
= 0.0;
2529 m_hAdjust
->step_increment
= 1.0;
2530 m_hAdjust
->page_increment
= 1.0;
2531 m_hAdjust
->page_size
= 5.0;
2532 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2534 // these handlers block mouse events to any window during scrolling such as
2535 // motion events and prevent GTK and wxWindows from fighting over where the
2538 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2539 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2541 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2542 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2544 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2545 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2547 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2548 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2550 // these handlers get notified when screen updates are required either when
2551 // scrolling or when the window size (and therefore scrollbar configuration)
2554 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2555 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2556 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2557 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2559 gtk_widget_show( m_wxwindow
);
2562 m_parent
->DoAddChild( this );
2564 m_focusWidget
= m_wxwindow
;
2573 wxWindowGTK::~wxWindowGTK()
2575 if (g_focusWindow
== this)
2576 g_focusWindow
= NULL
;
2578 if (g_activeFrame
== this)
2579 g_activeFrame
= NULL
;
2581 m_isBeingDeleted
= TRUE
;
2590 m_parent
->RemoveChild( this );
2594 gdk_ic_destroy (m_ic
);
2596 gdk_ic_attr_destroy (m_icattr
);
2601 #if DISABLE_STYLE_IF_BROKEN_THEME
2602 // don't delete if it's a pixmap theme style
2603 if (!m_widgetStyle
->engine_data
)
2604 gtk_style_unref( m_widgetStyle
);
2606 m_widgetStyle
= (GtkStyle
*) NULL
;
2611 gtk_widget_destroy( m_wxwindow
);
2612 m_wxwindow
= (GtkWidget
*) NULL
;
2617 gtk_widget_destroy( m_widget
);
2618 m_widget
= (GtkWidget
*) NULL
;
2622 bool wxWindowGTK::PreCreation( wxWindowGTK
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2624 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2626 /* this turns -1 into 20 so that a minimal window is
2627 visible even although -1,-1 has been given as the
2628 size of the window. the same trick is used in other
2629 ports and should make debugging easier */
2630 m_width
= WidthDefault(size
.x
);
2631 m_height
= HeightDefault(size
.y
);
2636 /* some reasonable defaults */
2641 m_x
= (gdk_screen_width () - m_width
) / 2;
2642 if (m_x
< 10) m_x
= 10;
2646 m_y
= (gdk_screen_height () - m_height
) / 2;
2647 if (m_y
< 10) m_y
= 10;
2654 void wxWindowGTK::PostCreation()
2656 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2662 // these get reported to wxWindows -> wxPaintEvent
2664 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2666 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2667 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2670 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2671 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2673 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2675 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2676 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2679 gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow
), HasFlag( wxNO_FULL_REPAINT_ON_RESIZE
) );
2683 // these are called when the "sunken" or "raised" borders are drawn
2684 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2685 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2688 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2689 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2695 if (m_focusWidget
== NULL
)
2696 m_focusWidget
= m_widget
;
2698 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event",
2699 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2701 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event",
2702 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2704 // connect to the various key and mouse handlers
2706 GtkWidget
*connect_widget
= GetConnectWidget();
2708 ConnectWidget( connect_widget
);
2710 /* We cannot set colours, fonts and cursors before the widget has
2711 been realized, so we do this directly after realization */
2712 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2713 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2717 // Catch native resize events
2718 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2719 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2721 // Initialize XIM support
2722 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2723 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2725 // And resize XIM window
2726 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2727 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2730 if (!GTK_IS_COMBO(m_widget
))
2732 // This is needed if we want to add our windows into native
2733 // GTK control, such as the toolbar. With this callback, the
2734 // toolbar gets to know the correct size (the one set by the
2735 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2736 // when moving to GTK 2.0.
2737 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2738 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2744 void wxWindowGTK::ConnectWidget( GtkWidget
*widget
)
2746 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2747 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2749 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2750 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2752 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2753 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2755 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2756 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2758 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2759 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2761 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2762 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2764 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2765 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2768 bool wxWindowGTK::Destroy()
2770 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2774 return wxWindowBase::Destroy();
2777 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
)
2779 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2782 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2784 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2785 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") );
2788 printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
2791 if (m_resizing
) return; /* I don't like recursions */
2794 int currentX
, currentY
;
2795 GetPosition(¤tX
, ¤tY
);
2800 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
2802 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2804 /* don't set the size for children of wxNotebook, just take the values. */
2812 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2813 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2815 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2816 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2817 if (width
!= -1) m_width
= width
;
2818 if (height
!= -1) m_height
= height
;
2822 m_x
= x
+ pizza
->xoffset
;
2823 m_y
= y
+ pizza
->yoffset
;
2828 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2830 if (width
== -1) m_width
= 80;
2833 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2835 if (height
== -1) m_height
= 26;
2838 int minWidth
= GetMinWidth(),
2839 minHeight
= GetMinHeight(),
2840 maxWidth
= GetMaxWidth(),
2841 maxHeight
= GetMaxHeight();
2843 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
2844 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
2845 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
2846 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
2849 int bottom_border
= 0;
2852 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2854 /* the default button has a border around it */
2860 DoMoveWindow( m_x
-border
,
2863 m_height
+border
+bottom_border
);
2868 /* Sometimes the client area changes size without the
2869 whole windows's size changing, but if the whole
2870 windows's size doesn't change, no wxSizeEvent will
2871 normally be sent. Here we add an extra test if
2872 the client test has been changed and this will
2874 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2878 wxPrintf( "OnSize sent from " );
2879 if (GetClassInfo() && GetClassInfo()->GetClassName())
2880 wxPrintf( GetClassInfo()->GetClassName() );
2881 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2884 if (!m_nativeSizeEvent
)
2886 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2887 event
.SetEventObject( this );
2888 GetEventHandler()->ProcessEvent( event
);
2894 void wxWindowGTK::OnInternalIdle()
2896 // Update invalidated regions.
2899 // Synthetize activate events.
2900 if ( g_sendActivateEvent
!= -1 )
2902 bool activate
= g_sendActivateEvent
!= 0;
2905 g_sendActivateEvent
= -1;
2907 wxTheApp
->SetActive(activate
, (wxWindow
*)g_focusWindowLast
);
2910 if ( g_activeFrameLostFocus
)
2912 if ( g_activeFrame
)
2914 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame
);
2915 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
2916 event
.SetEventObject(g_activeFrame
);
2917 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
2918 g_activeFrame
= NULL
;
2920 g_activeFrameLostFocus
= FALSE
;
2923 wxCursor cursor
= m_cursor
;
2924 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2928 /* I now set the cursor anew in every OnInternalIdle call
2929 as setting the cursor in a parent window also effects the
2930 windows above so that checking for the current cursor is
2935 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2937 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2939 if (!g_globalCursor
.Ok())
2940 cursor
= *wxSTANDARD_CURSOR
;
2942 window
= m_widget
->window
;
2943 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2944 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2950 GdkWindow
*window
= m_widget
->window
;
2951 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2952 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2960 void wxWindowGTK::DoGetSize( int *width
, int *height
) const
2962 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2964 if (width
) (*width
) = m_width
;
2965 if (height
) (*height
) = m_height
;
2968 void wxWindowGTK::DoSetClientSize( int width
, int height
)
2970 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2974 SetSize( width
, height
);
2981 #ifndef __WXUNIVERSAL__
2982 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2984 /* when using GTK 1.2 we set the shadow border size to 2 */
2988 if (HasFlag(wxSIMPLE_BORDER
))
2990 /* when using GTK 1.2 we set the simple border size to 1 */
2994 #endif // __WXUNIVERSAL__
2998 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
3000 GtkRequisition vscroll_req
;
3001 vscroll_req
.width
= 2;
3002 vscroll_req
.height
= 2;
3003 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
3004 (scroll_window
->vscrollbar
, &vscroll_req
);
3006 GtkRequisition hscroll_req
;
3007 hscroll_req
.width
= 2;
3008 hscroll_req
.height
= 2;
3009 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
3010 (scroll_window
->hscrollbar
, &hscroll_req
);
3012 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
3014 if (scroll_window
->vscrollbar_visible
)
3016 dw
+= vscroll_req
.width
;
3017 dw
+= scroll_class
->scrollbar_spacing
;
3020 if (scroll_window
->hscrollbar_visible
)
3022 dh
+= hscroll_req
.height
;
3023 dh
+= scroll_class
->scrollbar_spacing
;
3027 SetSize( width
+dw
, height
+dh
);
3031 void wxWindowGTK::DoGetClientSize( int *width
, int *height
) const
3033 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3037 if (width
) (*width
) = m_width
;
3038 if (height
) (*height
) = m_height
;
3045 #ifndef __WXUNIVERSAL__
3046 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
3048 /* when using GTK 1.2 we set the shadow border size to 2 */
3052 if (HasFlag(wxSIMPLE_BORDER
))
3054 /* when using GTK 1.2 we set the simple border size to 1 */
3058 #endif // __WXUNIVERSAL__
3062 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
3064 GtkRequisition vscroll_req
;
3065 vscroll_req
.width
= 2;
3066 vscroll_req
.height
= 2;
3067 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
3068 (scroll_window
->vscrollbar
, &vscroll_req
);
3070 GtkRequisition hscroll_req
;
3071 hscroll_req
.width
= 2;
3072 hscroll_req
.height
= 2;
3073 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
3074 (scroll_window
->hscrollbar
, &hscroll_req
);
3076 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
3078 if (scroll_window
->vscrollbar_visible
)
3080 dw
+= vscroll_req
.width
;
3081 dw
+= scroll_class
->scrollbar_spacing
;
3084 if (scroll_window
->hscrollbar_visible
)
3086 dh
+= hscroll_req
.height
;
3087 dh
+= scroll_class
->scrollbar_spacing
;
3091 if (width
) (*width
) = m_width
- dw
;
3092 if (height
) (*height
) = m_height
- dh
;
3096 printf( "GetClientSize, name %s ", GetName().c_str() );
3097 if (width) printf( " width = %d", (*width) );
3098 if (height) printf( " height = %d", (*height) );
3103 void wxWindowGTK::DoGetPosition( int *x
, int *y
) const
3105 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3109 if (m_parent
&& m_parent
->m_wxwindow
)
3111 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
3112 dx
= pizza
->xoffset
;
3113 dy
= pizza
->yoffset
;
3116 if (x
) (*x
) = m_x
- dx
;
3117 if (y
) (*y
) = m_y
- dy
;
3120 void wxWindowGTK::DoClientToScreen( int *x
, int *y
) const
3122 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3124 if (!m_widget
->window
) return;
3126 GdkWindow
*source
= (GdkWindow
*) NULL
;
3128 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3130 source
= m_widget
->window
;
3134 gdk_window_get_origin( source
, &org_x
, &org_y
);
3138 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3140 org_x
+= m_widget
->allocation
.x
;
3141 org_y
+= m_widget
->allocation
.y
;
3149 void wxWindowGTK::DoScreenToClient( int *x
, int *y
) const
3151 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3153 if (!m_widget
->window
) return;
3155 GdkWindow
*source
= (GdkWindow
*) NULL
;
3157 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3159 source
= m_widget
->window
;
3163 gdk_window_get_origin( source
, &org_x
, &org_y
);
3167 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3169 org_x
+= m_widget
->allocation
.x
;
3170 org_y
+= m_widget
->allocation
.y
;
3178 bool wxWindowGTK::Show( bool show
)
3180 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3182 if (!wxWindowBase::Show(show
))
3189 gtk_widget_show( m_widget
);
3191 gtk_widget_hide( m_widget
);
3196 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
)
3198 win
->OnParentEnable(enable
);
3200 // Recurse, so that children have the opportunity to Do The Right Thing
3201 // and reset colours that have been messed up by a parent's (really ancestor's)
3203 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
3205 node
= node
->GetNext() )
3207 wxWindow
*child
= node
->GetData();
3208 if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
)))
3209 wxWindowNotifyEnable(child
, enable
);
3213 bool wxWindowGTK::Enable( bool enable
)
3215 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3217 if (!wxWindowBase::Enable(enable
))
3223 gtk_widget_set_sensitive( m_widget
, enable
);
3225 gtk_widget_set_sensitive( m_wxwindow
, enable
);
3227 wxWindowNotifyEnable(this, enable
);
3232 int wxWindowGTK::GetCharHeight() const
3234 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
3236 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
3238 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3240 return font
->ascent
+ font
->descent
;
3243 int wxWindowGTK::GetCharWidth() const
3245 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
3247 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
3249 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3251 return gdk_string_width( font
, "H" );
3254 void wxWindowGTK::GetTextExtent( const wxString
& string
,
3258 int *externalLeading
,
3259 const wxFont
*theFont
) const
3261 wxFont fontToUse
= m_font
;
3262 if (theFont
) fontToUse
= *theFont
;
3264 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
3266 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
3267 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
3268 if (y
) (*y
) = font
->ascent
+ font
->descent
;
3269 if (descent
) (*descent
) = font
->descent
;
3270 if (externalLeading
) (*externalLeading
) = 0; // ??
3273 void wxWindowGTK::SetFocus()
3275 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3278 wxPrintf( "SetFocus from " );
3279 if (GetClassInfo() && GetClassInfo()->GetClassName())
3280 wxPrintf( GetClassInfo()->GetClassName() );
3286 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3288 gtk_widget_grab_focus (m_wxwindow
);
3293 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
3295 gtk_widget_grab_focus (m_widget
);
3297 else if (GTK_IS_CONTAINER(m_widget
))
3299 SET_CONTAINER_FOCUS( m_widget
, GTK_DIR_TAB_FORWARD
);
3308 bool wxWindowGTK::AcceptsFocus() const
3310 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3313 bool wxWindowGTK::Reparent( wxWindowBase
*newParentBase
)
3315 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3317 wxWindowGTK
*oldParent
= m_parent
,
3318 *newParent
= (wxWindowGTK
*)newParentBase
;
3320 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3322 if ( !wxWindowBase::Reparent(newParent
) )
3325 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3327 /* prevent GTK from deleting the widget arbitrarily */
3328 gtk_widget_ref( m_widget
);
3332 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3335 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3339 /* insert GTK representation */
3340 (*(newParent
->m_insertCallback
))(newParent
, this);
3343 /* reverse: prevent GTK from deleting the widget arbitrarily */
3344 gtk_widget_unref( m_widget
);
3349 void wxWindowGTK::DoAddChild(wxWindowGTK
*child
)
3351 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3353 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3355 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3360 /* insert GTK representation */
3361 (*m_insertCallback
)(this, child
);
3364 void wxWindowGTK::Raise()
3366 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3368 if (!m_widget
->window
) return;
3370 gdk_window_raise( m_widget
->window
);
3373 void wxWindowGTK::Lower()
3375 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3377 if (!m_widget
->window
) return;
3379 gdk_window_lower( m_widget
->window
);
3382 bool wxWindowGTK::SetCursor( const wxCursor
&cursor
)
3384 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3386 if (cursor
== m_cursor
)
3390 wxapp_install_idle_handler();
3392 if (cursor
== wxNullCursor
)
3393 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3395 return wxWindowBase::SetCursor( cursor
);
3398 void wxWindowGTK::WarpPointer( int x
, int y
)
3400 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3402 // We provide this function ourselves as it is
3403 // missing in GDK (top of this file).
3405 GdkWindow
*window
= (GdkWindow
*) NULL
;
3407 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3409 window
= GetConnectWidget()->window
;
3412 gdk_window_warp_pointer( window
, x
, y
);
3415 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect
*rect
)
3417 if (!m_widget
) return;
3418 if (!m_widget
->window
) return;
3421 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3425 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3426 m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
3430 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3431 m_clearRegion
.Clear();
3432 m_clearRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height
);
3440 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3441 m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
3445 GdkRectangle gdk_rect
;
3446 gdk_rect
.x
= rect
->x
;
3447 gdk_rect
.y
= rect
->y
;
3448 gdk_rect
.width
= rect
->width
;
3449 gdk_rect
.height
= rect
->height
;
3450 gtk_widget_draw( m_widget
, &gdk_rect
);
3457 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3458 m_updateRegion
.Clear();
3459 m_updateRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height
);
3463 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3471 GdkRectangle gdk_rect
;
3472 gdk_rect
.x
= rect
->x
;
3473 gdk_rect
.y
= rect
->y
;
3474 gdk_rect
.width
= rect
->width
;
3475 gdk_rect
.height
= rect
->height
;
3476 gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, &gdk_rect
, TRUE
);
3480 gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, NULL
, TRUE
);
3486 void wxWindowGTK::Update()
3489 if (m_wxwindow
&& GTK_PIZZA(m_wxwindow
)->bin_window
)
3490 gdk_window_process_updates( GTK_PIZZA(m_wxwindow
)->bin_window
, FALSE
);
3493 if (!m_updateRegion
.IsEmpty())
3494 GtkSendPaintEvents();
3497 void wxWindowGTK::GtkSendPaintEvents()
3501 m_clearRegion
.Clear();
3502 m_updateRegion
.Clear();
3506 m_clipPaintRegion
= TRUE
;
3508 // if (!m_clearRegion.IsEmpty()) // always send an erase event
3510 wxWindowDC
dc( (wxWindow
*)this );
3511 dc
.SetClippingRegion( m_clearRegion
);
3513 wxEraseEvent
erase_event( GetId(), &dc
);
3514 erase_event
.SetEventObject( this );
3516 if (!GetEventHandler()->ProcessEvent(erase_event
))
3520 g_eraseGC
= gdk_gc_new( GTK_PIZZA(m_wxwindow
)->bin_window
);
3521 gdk_gc_set_fill( g_eraseGC
, GDK_SOLID
);
3523 gdk_gc_set_foreground( g_eraseGC
, m_backgroundColour
.GetColor() );
3525 wxRegionIterator
upd( m_clearRegion
);
3528 gdk_draw_rectangle( GTK_PIZZA(m_wxwindow
)->bin_window
, g_eraseGC
, 1,
3529 upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
3533 m_clearRegion
.Clear();
3536 wxNcPaintEvent
nc_paint_event( GetId() );
3537 nc_paint_event
.SetEventObject( this );
3538 GetEventHandler()->ProcessEvent( nc_paint_event
);
3540 wxPaintEvent
paint_event( GetId() );
3541 paint_event
.SetEventObject( this );
3542 GetEventHandler()->ProcessEvent( paint_event
);
3544 m_clipPaintRegion
= FALSE
;
3546 #ifndef __WXUNIVERSAL__
3548 // The following code will result in all window-less widgets
3549 // being redrawn because the wxWindows class is allowed to
3550 // paint over the window-less widgets.
3552 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
3554 GList
*children
= pizza
->children
;
3557 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
3558 children
= children
->next
;
3560 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
3561 GTK_WIDGET_DRAWABLE (child
->widget
))
3563 // Get intersection of widget area and update region
3564 wxRegion
region( m_updateRegion
);
3566 GdkEventExpose gdk_event
;
3567 gdk_event
.type
= GDK_EXPOSE
;
3568 gdk_event
.window
= pizza
->bin_window
;
3569 gdk_event
.count
= 0;
3571 wxRegionIterator
upd( m_updateRegion
);
3575 rect
.x
= upd
.GetX();
3576 rect
.y
= upd
.GetY();
3577 rect
.width
= upd
.GetWidth();
3578 rect
.height
= upd
.GetHeight();
3580 if (gtk_widget_intersect (child
->widget
, &rect
, &gdk_event
.area
))
3582 gtk_widget_event (child
->widget
, (GdkEvent
*) &gdk_event
);
3592 m_updateRegion
.Clear();
3595 void wxWindowGTK::Clear()
3597 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3599 if (!m_widget
->window
) return;
3601 if (m_wxwindow
&& m_wxwindow
->window
)
3603 gdk_window_clear( m_wxwindow
->window
);
3608 void wxWindowGTK::DoSetToolTip( wxToolTip
*tip
)
3610 wxWindowBase::DoSetToolTip(tip
);
3613 m_tooltip
->Apply( (wxWindow
*)this );
3616 void wxWindowGTK::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3618 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3620 #endif // wxUSE_TOOLTIPS
3622 bool wxWindowGTK::SetBackgroundColour( const wxColour
&colour
)
3624 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3626 if (!wxWindowBase::SetBackgroundColour(colour
))
3628 // don't leave if the GTK widget has just
3630 if (!m_delayedBackgroundColour
) return FALSE
;
3633 GdkWindow
*window
= (GdkWindow
*) NULL
;
3635 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3637 window
= GetConnectWidget()->window
;
3641 // indicate that a new style has been set
3642 // but it couldn't get applied as the
3643 // widget hasn't been realized yet.
3644 m_delayedBackgroundColour
= TRUE
;
3649 // We need the pixel value e.g. for background clearing.
3650 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3654 (m_wxwindow
->window
) &&
3655 (m_backgroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
)))
3657 /* wxMSW doesn't clear the window here. I don't do that either to
3658 provide compatibility. call Clear() to do the job. */
3660 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3668 bool wxWindowGTK::SetForegroundColour( const wxColour
&colour
)
3670 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3672 if (!wxWindowBase::SetForegroundColour(colour
))
3674 // don't leave if the GTK widget has just
3676 if (!m_delayedForegroundColour
) return FALSE
;
3679 GdkWindow
*window
= (GdkWindow
*) NULL
;
3681 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3683 window
= GetConnectWidget()->window
;
3687 // indicate that a new style has been set
3688 // but it couldn't get applied as the
3689 // widget hasn't been realized yet.
3690 m_delayedForegroundColour
= TRUE
;
3698 GtkStyle
*wxWindowGTK::GetWidgetStyle()
3702 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3704 // FIXME: no more klass in 2.0
3706 remake
->klass
= m_widgetStyle
->klass
;
3709 gtk_style_unref( m_widgetStyle
);
3710 m_widgetStyle
= remake
;
3714 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3717 def
= gtk_widget_get_default_style();
3719 m_widgetStyle
= gtk_style_copy( def
);
3721 // FIXME: no more klass in 2.0
3723 m_widgetStyle
->klass
= def
->klass
;
3727 return m_widgetStyle
;
3730 void wxWindowGTK::SetWidgetStyle()
3732 #if DISABLE_STYLE_IF_BROKEN_THEME
3733 if (m_widget
->style
->engine_data
)
3735 static bool s_warningPrinted
= FALSE
;
3736 if (!s_warningPrinted
)
3738 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3739 s_warningPrinted
= TRUE
;
3741 m_widgetStyle
= m_widget
->style
;
3746 GtkStyle
*style
= GetWidgetStyle();
3748 if (m_font
!= wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT
))
3750 SET_STYLE_FONT(style
, m_font
.GetInternalFont( 1.0 ));
3753 if (m_foregroundColour
.Ok())
3755 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3756 if (m_foregroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT
))
3758 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3759 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3760 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.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 foreground colour to *wxBLACK -- RL
3768 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3771 def
= gtk_widget_get_default_style();
3773 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3774 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3775 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3779 if (m_backgroundColour
.Ok())
3781 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3782 if (m_backgroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
))
3784 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3785 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3786 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3787 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3788 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3789 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3790 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3791 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3795 // Try to restore the gtk default style. This is still a little
3796 // oversimplified for what is probably really needed here for controls
3797 // other than buttons, but is better than not being able to (re)set a
3798 // control's background colour to default grey and means resetting a
3799 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3801 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3804 def
= gtk_widget_get_default_style();
3806 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3807 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3808 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3809 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3810 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3811 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3812 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3813 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3818 void wxWindowGTK::ApplyWidgetStyle()
3822 //-----------------------------------------------------------------------------
3823 // Pop-up menu stuff
3824 //-----------------------------------------------------------------------------
3826 #if wxUSE_MENUS_NATIVE
3829 void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3831 *is_waiting
= FALSE
;
3834 static void SetInvokingWindow( wxMenu
*menu
, wxWindowGTK
*win
)
3836 menu
->SetInvokingWindow( win
);
3837 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3840 wxMenuItem
*menuitem
= node
->GetData();
3841 if (menuitem
->IsSubMenu())
3843 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3846 node
= node
->GetNext();
3850 // used to pass the coordinates from wxWindowGTK::DoPopupMenu() to
3851 // wxPopupMenuPositionCallback()
3853 // should be safe even in the MT case as the user can hardly popup 2 menus
3854 // simultaneously, can he?
3855 static gint gs_pop_x
= 0;
3856 static gint gs_pop_y
= 0;
3858 extern "C" void wxPopupMenuPositionCallback( GtkMenu
*menu
,
3861 gboolean
* WXUNUSED(whatever
),
3863 gpointer
WXUNUSED(user_data
) )
3865 // ensure that the menu appears entirely on screen
3867 gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
);
3869 wxSize sizeScreen
= wxGetDisplaySize();
3871 gint xmax
= sizeScreen
.x
- req
.width
,
3872 ymax
= sizeScreen
.y
- req
.height
;
3874 *x
= gs_pop_x
< xmax
? gs_pop_x
: xmax
;
3875 *y
= gs_pop_y
< ymax
? gs_pop_y
: ymax
;
3878 bool wxWindowGTK::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3880 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3882 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3884 SetInvokingWindow( menu
, this );
3890 ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3892 bool is_waiting
= TRUE
;
3894 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
),
3896 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
),
3897 (gpointer
)&is_waiting
);
3900 GTK_MENU(menu
->m_menu
),
3901 (GtkWidget
*) NULL
, // parent menu shell
3902 (GtkWidget
*) NULL
, // parent menu item
3903 wxPopupMenuPositionCallback
, // function to position it
3904 NULL
, // client data
3905 0, // button used to activate it
3906 gs_timeLastClick
// the time of activation
3911 while (gtk_events_pending())
3912 gtk_main_iteration();
3918 #endif // wxUSE_MENUS_NATIVE
3920 #if wxUSE_DRAG_AND_DROP
3922 void wxWindowGTK::SetDropTarget( wxDropTarget
*dropTarget
)
3924 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3926 GtkWidget
*dnd_widget
= GetConnectWidget();
3928 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3930 if (m_dropTarget
) delete m_dropTarget
;
3931 m_dropTarget
= dropTarget
;
3933 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3936 #endif // wxUSE_DRAG_AND_DROP
3938 GtkWidget
* wxWindowGTK::GetConnectWidget()
3940 GtkWidget
*connect_widget
= m_widget
;
3941 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3943 return connect_widget
;
3946 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow
*window
)
3949 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3951 return (window
== m_widget
->window
);
3954 bool wxWindowGTK::SetFont( const wxFont
&font
)
3956 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3958 if (!wxWindowBase::SetFont(font
))
3963 wxColour sysbg
= wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE
);
3964 if ( sysbg
== m_backgroundColour
)
3966 m_backgroundColour
= wxNullColour
;
3968 m_backgroundColour
= sysbg
;
3978 void wxWindowGTK::DoCaptureMouse()
3980 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3982 GdkWindow
*window
= (GdkWindow
*) NULL
;
3984 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3986 window
= GetConnectWidget()->window
;
3988 wxCHECK_RET( window
, _T("CaptureMouse() failed") );
3990 wxCursor
* cursor
= & m_cursor
;
3992 cursor
= wxSTANDARD_CURSOR
;
3994 gdk_pointer_grab( window
, FALSE
,
3996 (GDK_BUTTON_PRESS_MASK
|
3997 GDK_BUTTON_RELEASE_MASK
|
3998 GDK_POINTER_MOTION_HINT_MASK
|
3999 GDK_POINTER_MOTION_MASK
),
4001 cursor
->GetCursor(),
4002 (guint32
)GDK_CURRENT_TIME
);
4003 g_captureWindow
= this;
4004 g_captureWindowHasMouse
= TRUE
;
4007 void wxWindowGTK::DoReleaseMouse()
4009 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4011 wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") );
4013 g_captureWindow
= (wxWindowGTK
*) NULL
;
4015 GdkWindow
*window
= (GdkWindow
*) NULL
;
4017 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
4019 window
= GetConnectWidget()->window
;
4024 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
4028 wxWindow
*wxWindowBase::GetCapture()
4030 return (wxWindow
*)g_captureWindow
;
4033 bool wxWindowGTK::IsRetained() const
4038 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
,
4039 int range
, bool refresh
)
4041 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4043 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4045 m_hasScrolling
= TRUE
;
4047 if (orient
== wxHORIZONTAL
)
4049 float fpos
= (float)pos
;
4050 float frange
= (float)range
;
4051 float fthumb
= (float)thumbVisible
;
4052 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
4053 if (fpos
< 0.0) fpos
= 0.0;
4055 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
4056 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
4058 SetScrollPos( orient
, pos
, refresh
);
4062 m_oldHorizontalPos
= fpos
;
4064 m_hAdjust
->lower
= 0.0;
4065 m_hAdjust
->upper
= frange
;
4066 m_hAdjust
->value
= fpos
;
4067 m_hAdjust
->step_increment
= 1.0;
4068 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
4069 m_hAdjust
->page_size
= fthumb
;
4073 float fpos
= (float)pos
;
4074 float frange
= (float)range
;
4075 float fthumb
= (float)thumbVisible
;
4076 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
4077 if (fpos
< 0.0) fpos
= 0.0;
4079 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
4080 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
4082 SetScrollPos( orient
, pos
, refresh
);
4086 m_oldVerticalPos
= fpos
;
4088 m_vAdjust
->lower
= 0.0;
4089 m_vAdjust
->upper
= frange
;
4090 m_vAdjust
->value
= fpos
;
4091 m_vAdjust
->step_increment
= 1.0;
4092 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
4093 m_vAdjust
->page_size
= fthumb
;
4096 if (orient
== wxHORIZONTAL
)
4097 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
4099 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
4102 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
4104 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4106 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4108 if (orient
== wxHORIZONTAL
)
4110 float fpos
= (float)pos
;
4111 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
4112 if (fpos
< 0.0) fpos
= 0.0;
4113 m_oldHorizontalPos
= fpos
;
4115 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
4116 m_hAdjust
->value
= fpos
;
4120 float fpos
= (float)pos
;
4121 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
4122 if (fpos
< 0.0) fpos
= 0.0;
4123 m_oldVerticalPos
= fpos
;
4125 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
4126 m_vAdjust
->value
= fpos
;
4129 if (m_wxwindow
->window
)
4131 if (orient
== wxHORIZONTAL
)
4133 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
4134 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
4136 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
4138 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
4139 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
4143 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
4144 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4146 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
4148 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
4149 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4154 int wxWindowGTK::GetScrollThumb( int orient
) const
4156 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4158 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4160 if (orient
== wxHORIZONTAL
)
4161 return (int)(m_hAdjust
->page_size
+0.5);
4163 return (int)(m_vAdjust
->page_size
+0.5);
4166 int wxWindowGTK::GetScrollPos( int orient
) const
4168 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4170 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4172 if (orient
== wxHORIZONTAL
)
4173 return (int)(m_hAdjust
->value
+0.5);
4175 return (int)(m_vAdjust
->value
+0.5);
4178 int wxWindowGTK::GetScrollRange( int orient
) const
4180 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4182 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4184 if (orient
== wxHORIZONTAL
)
4185 return (int)(m_hAdjust
->upper
+0.5);
4187 return (int)(m_vAdjust
->upper
+0.5);
4190 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
4192 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4194 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4196 // No scrolling requested.
4197 if ((dx
== 0) && (dy
== 0)) return;
4200 if (!m_updateRegion
.IsEmpty())
4202 m_updateRegion
.Offset( dx
, dy
);
4206 GetClientSize( &cw
, &ch
);
4207 m_updateRegion
.Intersect( 0, 0, cw
, ch
);
4210 if (!m_clearRegion
.IsEmpty())
4212 m_clearRegion
.Offset( dx
, dy
);
4216 GetClientSize( &cw
, &ch
);
4217 m_clearRegion
.Intersect( 0, 0, cw
, ch
);
4220 m_clipPaintRegion
= TRUE
;
4222 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
4224 m_clipPaintRegion
= FALSE
;
4227 gdk_window_scroll( GTK_PIZZA(m_wxwindow
)->bin_window
, dx
, dy
);
4229 GTK_PIZZA(m_wxwindow
)->xoffset
+= dx
;
4230 GTK_PIZZA(m_wxwindow
)->yoffset
+= dy
;
4237 // Find the wxWindow at the current mouse position, also returning the mouse
4239 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
4241 pt
= wxGetMousePosition();
4242 wxWindow
* found
= wxFindWindowAtPoint(pt
);
4246 // Get the current mouse position.
4247 wxPoint
wxGetMousePosition()
4249 /* This crashes when used within wxHelpContext,
4250 so we have to use the X-specific implementation below.
4252 GdkModifierType *mask;
4253 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
4255 return wxPoint(x, y);
4259 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
4261 return wxPoint(-999, -999);
4263 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
4264 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
4265 Window rootReturn
, childReturn
;
4266 int rootX
, rootY
, winX
, winY
;
4267 unsigned int maskReturn
;
4269 XQueryPointer (display
,
4273 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
4274 return wxPoint(rootX
, rootY
);
4278 // ----------------------------------------------------------------------------
4280 // ----------------------------------------------------------------------------
4282 class wxWinModule
: public wxModule
4289 DECLARE_DYNAMIC_CLASS(wxWinModule
)
4292 IMPLEMENT_DYNAMIC_CLASS(wxWinModule
, wxModule
)
4294 bool wxWinModule::OnInit()
4296 // g_eraseGC = gdk_gc_new( GDK_ROOT_PARENT() );
4297 // gdk_gc_set_fill( g_eraseGC, GDK_SOLID );
4302 void wxWinModule::OnExit()
4305 gdk_gc_unref( g_eraseGC
);