1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/window.cpp
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #define XWarpPointer XWARPPOINTER
20 #include "wx/window.h"
21 #include "wx/dcclient.h"
24 #include "wx/layout.h"
26 #include "wx/dialog.h"
27 #include "wx/msgdlg.h"
28 #include "wx/module.h"
30 #if wxUSE_DRAG_AND_DROP
35 #include "wx/tooltip.h"
43 #include "wx/textctrl.h"
47 #include "wx/statusbr.h"
49 #include "wx/settings.h"
53 #include "wx/thread.h"
58 #include "wx/gtk/private.h"
59 #include <gdk/gdkprivate.h>
60 #include <gdk/gdkkeysyms.h>
64 #include <gtk/gtkprivate.h>
66 #include "wx/gtk/win_gtk.h"
69 #define SET_CONTAINER_FOCUS(w, d) gtk_widget_child_focus((w), (d))
71 #define SET_CONTAINER_FOCUS(w, d) gtk_container_focus(GTK_CONTAINER(w), (d))
81 extern GtkContainerClass
*pizza_parent_class
;
84 //-----------------------------------------------------------------------------
85 // documentation on internals
86 //-----------------------------------------------------------------------------
89 I have been asked several times about writing some documentation about
90 the GTK port of wxWindows, especially its internal structures. Obviously,
91 you cannot understand wxGTK without knowing a little about the GTK, but
92 some more information about what the wxWindow, which is the base class
93 for all other window classes, does seems required as well.
97 What does wxWindow do? It contains the common interface for the following
98 jobs of its descendants:
100 1) Define the rudimentary behaviour common to all window classes, such as
101 resizing, intercepting user input (so as to make it possible to use these
102 events for special purposes in a derived class), window names etc.
104 2) Provide the possibility to contain and manage children, if the derived
105 class is allowed to contain children, which holds true for those window
106 classes which do not display a native GTK widget. To name them, these
107 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
108 work classes are a special case and are handled a bit differently from
109 the rest. The same holds true for the wxNotebook class.
111 3) Provide the possibility to draw into a client area of a window. This,
112 too, only holds true for classes that do not display a native GTK widget
115 4) Provide the entire mechanism for scrolling widgets. This actual inter-
116 face for this is usually in wxScrolledWindow, but the GTK implementation
119 5) A multitude of helper or extra methods for special purposes, such as
120 Drag'n'Drop, managing validators etc.
122 6) Display a border (sunken, raised, simple or none).
124 Normally one might expect, that one wxWindows window would always correspond
125 to one GTK widget. Under GTK, there is no such allround widget that has all
126 the functionality. Moreover, the GTK defines a client area as a different
127 widget from the actual widget you are handling. Last but not least some
128 special classes (e.g. wxFrame) handle different categories of widgets and
129 still have the possibility to draw something in the client area.
130 It was therefore required to write a special purpose GTK widget, that would
131 represent a client area in the sense of wxWindows capable to do the jobs
132 2), 3) and 4). I have written this class and it resides in win_gtk.c of
135 All windows must have a widget, with which they interact with other under-
136 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
137 thw wxWindow class has a member variable called m_widget which holds a
138 pointer to this widget. When the window class represents a GTK native widget,
139 this is (in most cases) the only GTK widget the class manages. E.g. the
140 wxStatitText class handles only a GtkLabel widget a pointer to which you
141 can find in m_widget (defined in wxWindow)
143 When the class has a client area for drawing into and for containing children
144 it has to handle the client area widget (of the type GtkPizza, defined in
145 win_gtk.c), but there could be any number of widgets, handled by a class
146 The common rule for all windows is only, that the widget that interacts with
147 the rest of GTK must be referenced in m_widget and all other widgets must be
148 children of this widget on the GTK level. The top-most widget, which also
149 represents the client area, must be in the m_wxwindow field and must be of
152 As I said, the window classes that display a GTK native widget only have
153 one widget, so in the case of e.g. the wxButton class m_widget holds a
154 pointer to a GtkButton widget. But windows with client areas (for drawing
155 and children) have a m_widget field that is a pointer to a GtkScrolled-
156 Window and a m_wxwindow field that is pointer to a GtkPizza and this
157 one is (in the GTK sense) a child of the GtkScrolledWindow.
159 If the m_wxwindow field is set, then all input to this widget is inter-
160 cepted and sent to the wxWindows class. If not, all input to the widget
161 that gets pointed to by m_widget gets intercepted and sent to the class.
165 The design of scrolling in wxWindows is markedly different from that offered
166 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
167 clicking on a scrollbar belonging to scrolled window will inevitably move
168 the window. In wxWindows, the scrollbar will only emit an event, send this
169 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
170 which actually moves the window and its subchildren. Note that GtkPizza
171 memorizes how much it has been scrolled but that wxWindows forgets this
172 so that the two coordinates systems have to be kept in synch. This is done
173 in various places using the pizza->xoffset and pizza->yoffset values.
177 Singularily the most broken code in GTK is the code that is supposes to
178 inform subwindows (child windows) about new positions. Very often, duplicate
179 events are sent without changes in size or position, equally often no
180 events are sent at all (All this is due to a bug in the GtkContainer code
181 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
182 GTK's own system and it simply waits for size events for toplevel windows
183 and then iterates down the respective size events to all window. This has
184 the disadvantage, that windows might get size events before the GTK widget
185 actually has the reported size. This doesn't normally pose any problem, but
186 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
187 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
188 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
189 window that is used for OpenGl output really has that size (as reported by
194 If someone at some point of time feels the immense desire to have a look at,
195 change or attempt to optimse the Refresh() logic, this person will need an
196 intimate understanding of what a "draw" and what an "expose" events are and
197 what there are used for, in particular when used in connection with GTK's
198 own windowless widgets. Beware.
202 Cursors, too, have been a constant source of pleasure. The main difficulty
203 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
204 for the parent. To prevent this from doing too much harm, I use idle time
205 to set the cursor over and over again, starting from the toplevel windows
206 and ending with the youngest generation (speaking of parent and child windows).
207 Also don't forget that cursors (like much else) are connected to GdkWindows,
208 not GtkWidgets and that the "window" field of a GtkWidget might very well
209 point to the GdkWindow of the parent widget (-> "window less widget") and
210 that the two obviously have very different meanings.
214 //-----------------------------------------------------------------------------
216 //-----------------------------------------------------------------------------
218 extern wxList wxPendingDelete
;
219 extern bool g_blockEventsOnDrag
;
220 extern bool g_blockEventsOnScroll
;
221 extern wxCursor g_globalCursor
;
223 static GdkGC
*g_eraseGC
= NULL
;
225 // mouse capture state: the window which has it and if the mouse is currently
227 static wxWindowGTK
*g_captureWindow
= (wxWindowGTK
*) NULL
;
228 static bool g_captureWindowHasMouse
= FALSE
;
230 /* extern */ wxWindowGTK
*g_focusWindow
= (wxWindowGTK
*) NULL
;
232 // the last window which had the focus - this is normally never NULL (except
233 // if we never had focus at all) as even when g_focusWindow is NULL it still
234 // keeps its previous value
235 static wxWindowGTK
*g_focusWindowLast
= (wxWindowGTK
*) NULL
;
237 // the frame that is currently active (i.e. its child has focus). It is
238 // used to generate wxActivateEvents
239 static wxWindowGTK
*g_activeFrame
= (wxWindowGTK
*) NULL
;
240 static bool g_activeFrameLostFocus
= FALSE
;
242 // If a window get the focus set but has not been realized
243 // yet, defer setting the focus to idle time.
244 wxWindowGTK
*g_delayedFocus
= (wxWindowGTK
*) NULL
;
246 // if we detect that the app has got/lost the focus, we set this variable to
247 // either TRUE or FALSE and an activate event will be sent during the next
248 // OnIdle() call and it is reset to -1: this value means that we shouldn't
249 // send any activate events at all
250 static int g_sendActivateEvent
= -1;
252 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
253 the last click here */
254 static guint32 gs_timeLastClick
= 0;
256 extern bool g_mainThreadLocked
;
258 //-----------------------------------------------------------------------------
260 //-----------------------------------------------------------------------------
263 #define DISABLE_STYLE_IF_BROKEN_THEME 1
269 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
271 # define DEBUG_MAIN_THREAD
274 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
275 GdkEvent
*WXUNUSED(event
),
276 const wxChar
*WXUNUSED(name
) )
279 static bool s_done = FALSE;
282 wxLog::AddTraceMask("focus");
285 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
291 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
293 // suppress warnings about gtk_debug_focus_in_callback being unused with
298 tmp
+= wxT(" FROM ");
301 wxChar
*s
= new wxChar
[tmp
.Length()+1];
305 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
306 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
311 #define DEBUG_MAIN_THREAD
314 //-----------------------------------------------------------------------------
315 // missing gdk functions
316 //-----------------------------------------------------------------------------
319 gdk_window_warp_pointer (GdkWindow
*window
,
324 GdkWindowPrivate
*priv
;
328 window
= GDK_ROOT_PARENT();
331 if (!GDK_WINDOW_DESTROYED(window
))
333 XWarpPointer (GDK_WINDOW_XDISPLAY(window
),
334 None
, /* not source window -> move from anywhere */
335 GDK_WINDOW_XID(window
), /* dest window */
336 0, 0, 0, 0, /* not source window -> move from anywhere */
340 priv
= (GdkWindowPrivate
*) window
;
342 if (!priv
->destroyed
)
344 XWarpPointer (priv
->xdisplay
,
345 None
, /* not source window -> move from anywhere */
346 priv
->xwindow
, /* dest window */
347 0, 0, 0, 0, /* not source window -> move from anywhere */
353 //-----------------------------------------------------------------------------
355 //-----------------------------------------------------------------------------
357 extern void wxapp_install_idle_handler();
358 extern bool g_isIdle
;
360 //-----------------------------------------------------------------------------
361 // local code (see below)
362 //-----------------------------------------------------------------------------
364 // returns the child of win which currently has focus or NULL if not found
366 // Note: can't be static, needed by textctrl.cpp.
367 wxWindow
*wxFindFocusedChild(wxWindowGTK
*win
)
369 wxWindow
*winFocus
= wxWindowGTK::FindFocus();
371 return (wxWindow
*)NULL
;
373 if ( winFocus
== win
)
374 return (wxWindow
*)win
;
376 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
378 node
= node
->GetNext() )
380 wxWindow
*child
= wxFindFocusedChild(node
->GetData());
385 return (wxWindow
*)NULL
;
388 // Returns toplevel grandparent of given window:
389 static wxWindowGTK
* wxGetTopLevelParent(wxWindowGTK
*win
)
391 wxWindowGTK
*p
= win
;
392 while (p
&& !p
->IsTopLevel())
397 static void draw_frame( GtkWidget
*widget
, wxWindowGTK
*win
)
399 // wxUniversal widgets draw the borders and scrollbars themselves
400 #ifndef __WXUNIVERSAL__
407 if (win
->m_hasScrolling
)
409 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
411 GtkRequisition vscroll_req
;
412 vscroll_req
.width
= 2;
413 vscroll_req
.height
= 2;
414 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
415 (scroll_window
->vscrollbar
, &vscroll_req
);
417 GtkRequisition hscroll_req
;
418 hscroll_req
.width
= 2;
419 hscroll_req
.height
= 2;
420 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
421 (scroll_window
->hscrollbar
, &hscroll_req
);
423 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) );
425 if (scroll_window
->vscrollbar_visible
)
427 dw
+= vscroll_req
.width
;
428 dw
+= scroll_class
->scrollbar_spacing
;
431 if (scroll_window
->hscrollbar_visible
)
433 dh
+= hscroll_req
.height
;
434 dh
+= scroll_class
->scrollbar_spacing
;
440 if (GTK_WIDGET_NO_WINDOW (widget
))
442 dx
+= widget
->allocation
.x
;
443 dy
+= widget
->allocation
.y
;
446 if (win
->HasFlag(wxRAISED_BORDER
))
448 gtk_draw_shadow( widget
->style
,
453 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
457 if (win
->HasFlag(wxSUNKEN_BORDER
))
459 gtk_draw_shadow( widget
->style
,
464 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
468 if (win
->HasFlag(wxSIMPLE_BORDER
))
471 gc
= gdk_gc_new( widget
->window
);
472 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
473 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
475 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
479 #endif // __WXUNIVERSAL__
482 //-----------------------------------------------------------------------------
483 // "expose_event" of m_widget
484 //-----------------------------------------------------------------------------
486 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindowGTK
*win
)
488 if (gdk_event
->count
> 0) return FALSE
;
490 draw_frame( widget
, win
);
494 (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
);
500 //-----------------------------------------------------------------------------
501 // "draw" of m_widget
502 //-----------------------------------------------------------------------------
506 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindowGTK
*win
)
508 draw_frame( widget
, win
);
513 //-----------------------------------------------------------------------------
514 // "size_request" of m_widget
515 //-----------------------------------------------------------------------------
517 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
520 win
->GetSize( &w
, &h
);
524 requisition
->height
= h
;
525 requisition
->width
= w
;
528 //-----------------------------------------------------------------------------
529 // "expose_event" of m_wxwindow
530 //-----------------------------------------------------------------------------
532 static int gtk_window_expose_callback( GtkWidget
*widget
,
533 GdkEventExpose
*gdk_event
,
539 wxapp_install_idle_handler();
544 wxPrintf( wxT("OnExpose from ") );
545 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
546 wxPrintf( win
->GetClassInfo()->GetClassName() );
547 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event
->area
.x
,
548 (int)gdk_event
->area
.y
,
549 (int)gdk_event
->area
.width
,
550 (int)gdk_event
->area
.height
);
554 #ifndef __WXUNIVERSAL__
555 GtkPizza
*pizza
= GTK_PIZZA (widget
);
557 if (win
->GetThemeEnabled())
559 wxWindow
*parent
= win
->GetParent();
560 while (parent
&& !parent
->IsTopLevel())
561 parent
= parent
->GetParent();
565 gtk_paint_flat_box (parent
->m_widget
->style
,
576 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
578 gdk_event
->area
.width
,
579 gdk_event
->area
.height
);
581 // Actual redrawing takes place in idle time.
586 (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
);
593 //-----------------------------------------------------------------------------
594 // "event" of m_wxwindow
595 //-----------------------------------------------------------------------------
597 // GTK thinks it is clever and filters out a certain amount of "unneeded"
598 // expose events. We need them, of course, so we override the main event
599 // procedure in GtkWidget by giving our own handler for all system events.
600 // There, we look for expose events ourselves whereas all other events are
603 gint
gtk_window_event_event_callback( GtkWidget
*widget
,
604 GdkEventExpose
*event
,
607 if (event
->type
== GDK_EXPOSE
)
609 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
616 //-----------------------------------------------------------------------------
617 // "draw" of m_wxwindow
618 //-----------------------------------------------------------------------------
622 // This callback is a complete replacement of the gtk_pizza_draw() function,
623 // which is disabled.
625 static void gtk_window_draw_callback( GtkWidget
*widget
,
632 wxapp_install_idle_handler();
634 // The wxNO_FULL_REPAINT_ON_RESIZE flag only works if
635 // there are no child windows.
636 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
637 (win
->GetChildren().GetCount() == 0))
645 wxPrintf( wxT("OnDraw from ") );
646 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
647 wxPrintf( win
->GetClassInfo()->GetClassName() );
648 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect
->x
,
655 #ifndef __WXUNIVERSAL__
656 GtkPizza
*pizza
= GTK_PIZZA (widget
);
658 if (win
->GetThemeEnabled())
660 wxWindow
*parent
= win
->GetParent();
661 while (parent
&& !parent
->IsTopLevel())
662 parent
= parent
->GetParent();
666 gtk_paint_flat_box (parent
->m_widget
->style
,
677 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
678 (pizza
->clear_on_draw
))
680 gdk_window_clear_area( pizza
->bin_window
,
681 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
685 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
687 // Actual redrawing takes place in idle time.
691 #ifndef __WXUNIVERSAL__
692 // Redraw child widgets
693 GList
*children
= pizza
->children
;
696 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
697 children
= children
->next
;
699 GdkRectangle child_area
;
700 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
702 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
710 //-----------------------------------------------------------------------------
711 // "key_press_event" from any window
712 //-----------------------------------------------------------------------------
714 // set WXTRACE to this to see the key event codes on the console
715 #define TRACE_KEYS _T("keyevent")
717 // translates an X key symbol to WXK_XXX value
719 // if isChar is true it means that the value returned will be used for EVT_CHAR
720 // event and then we choose the logical WXK_XXX, i.e. '/' for GDK_KP_Divide,
721 // for example, while if it is false it means that the value is going to be
722 // used for KEY_DOWN/UP events and then we translate GDK_KP_Divide to
724 static long wxTranslateKeySymToWXKey(KeySym keysym
, bool isChar
)
730 // Shift, Control and Alt don't generate the CHAR events at all
733 key_code
= isChar
? 0 : WXK_SHIFT
;
737 key_code
= isChar
? 0 : WXK_CONTROL
;
745 key_code
= isChar
? 0 : WXK_ALT
;
748 // neither do the toggle modifies
749 case GDK_Scroll_Lock
:
750 key_code
= isChar
? 0 : WXK_SCROLL
;
754 key_code
= isChar
? 0 : WXK_CAPITAL
;
758 key_code
= isChar
? 0 : WXK_NUMLOCK
;
762 // various other special keys
775 case GDK_ISO_Left_Tab
:
782 key_code
= WXK_RETURN
;
786 key_code
= WXK_CLEAR
;
790 key_code
= WXK_PAUSE
;
794 key_code
= WXK_SELECT
;
798 key_code
= WXK_PRINT
;
802 key_code
= WXK_EXECUTE
;
806 key_code
= WXK_ESCAPE
;
809 // cursor and other extended keyboard keys
811 key_code
= WXK_DELETE
;
827 key_code
= WXK_RIGHT
;
834 case GDK_Prior
: // == GDK_Page_Up
835 key_code
= WXK_PRIOR
;
838 case GDK_Next
: // == GDK_Page_Down
851 key_code
= WXK_INSERT
;
866 key_code
= (isChar
? '0' : WXK_NUMPAD0
) + keysym
- GDK_KP_0
;
870 key_code
= isChar
? ' ' : WXK_NUMPAD_SPACE
;
874 key_code
= isChar
? WXK_TAB
: WXK_NUMPAD_TAB
;
878 key_code
= isChar
? WXK_RETURN
: WXK_NUMPAD_ENTER
;
882 key_code
= isChar
? WXK_F1
: WXK_NUMPAD_F1
;
886 key_code
= isChar
? WXK_F2
: WXK_NUMPAD_F2
;
890 key_code
= isChar
? WXK_F3
: WXK_NUMPAD_F3
;
894 key_code
= isChar
? WXK_F4
: WXK_NUMPAD_F4
;
898 key_code
= isChar
? WXK_HOME
: WXK_NUMPAD_HOME
;
902 key_code
= isChar
? WXK_LEFT
: WXK_NUMPAD_LEFT
;
906 key_code
= isChar
? WXK_UP
: WXK_NUMPAD_UP
;
910 key_code
= isChar
? WXK_RIGHT
: WXK_NUMPAD_RIGHT
;
914 key_code
= isChar
? WXK_DOWN
: WXK_NUMPAD_DOWN
;
917 case GDK_KP_Prior
: // == GDK_KP_Page_Up
918 key_code
= isChar
? WXK_PRIOR
: WXK_NUMPAD_PRIOR
;
921 case GDK_KP_Next
: // == GDK_KP_Page_Down
922 key_code
= isChar
? WXK_NEXT
: WXK_NUMPAD_NEXT
;
926 key_code
= isChar
? WXK_END
: WXK_NUMPAD_END
;
930 key_code
= isChar
? WXK_HOME
: WXK_NUMPAD_BEGIN
;
934 key_code
= isChar
? WXK_INSERT
: WXK_NUMPAD_INSERT
;
938 key_code
= isChar
? WXK_DELETE
: WXK_NUMPAD_DELETE
;
942 key_code
= isChar
? '=' : WXK_NUMPAD_EQUAL
;
945 case GDK_KP_Multiply
:
946 key_code
= isChar
? '*' : WXK_NUMPAD_MULTIPLY
;
950 key_code
= isChar
? '+' : WXK_NUMPAD_ADD
;
953 case GDK_KP_Separator
:
954 // FIXME: what is this?
955 key_code
= isChar
? '.' : WXK_NUMPAD_SEPARATOR
;
958 case GDK_KP_Subtract
:
959 key_code
= isChar
? '-' : WXK_NUMPAD_SUBTRACT
;
963 key_code
= isChar
? '.' : WXK_NUMPAD_DECIMAL
;
967 key_code
= isChar
? '/' : WXK_NUMPAD_DIVIDE
;
984 key_code
= WXK_F1
+ keysym
- GDK_F1
;
994 static inline bool wxIsAsciiKeysym(KeySym ks
)
1000 wxTranslateGTKKeyEventToWx(wxKeyEvent
& event
,
1002 GdkEventKey
*gdk_event
)
1004 // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string
1005 // but only event->keyval which is quite useless to us, so remember
1006 // the last character from GDK_KEY_PRESS and reuse it as last resort
1008 // NB: should be MT-safe as we're always called from the main thread only
1013 } s_lastKeyPress
= { 0, 0 };
1015 KeySym keysym
= gdk_event
->keyval
;
1017 wxLogTrace(TRACE_KEYS
, _T("Key %s event: keysym = %d"),
1018 event
.GetEventType() == wxEVT_KEY_UP
? _T("release")
1022 long key_code
= wxTranslateKeySymToWXKey(keysym
, FALSE
/* !isChar */);
1026 // do we have the translation or is it a plain ASCII character?
1027 if ( (gdk_event
->length
== 1) || wxIsAsciiKeysym(keysym
) )
1029 // we should use keysym if it is ASCII as X does some translations
1030 // like "I pressed while Control is down" => "Ctrl-I" == "TAB"
1031 // which we don't want here (but which we do use for OnChar())
1032 if ( !wxIsAsciiKeysym(keysym
) )
1034 keysym
= (KeySym
)gdk_event
->string
[0];
1037 // we want to always get the same key code when the same key is
1038 // pressed regardless of the state of the modifies, i.e. on a
1039 // standard US keyboard pressing '5' or '%' ('5' key with
1040 // Shift) should result in the same key code in OnKeyDown():
1041 // '5' (although OnChar() will get either '5' or '%').
1043 // to do it we first translate keysym to keycode (== scan code)
1044 // and then back but always using the lower register
1045 Display
*dpy
= (Display
*)wxGetDisplay();
1046 KeyCode keycode
= XKeysymToKeycode(dpy
, keysym
);
1048 wxLogTrace(TRACE_KEYS
, _T("\t-> keycode %d"), keycode
);
1050 KeySym keysymNormalized
= XKeycodeToKeysym(dpy
, keycode
, 0);
1052 // use the normalized, i.e. lower register, keysym if we've
1054 key_code
= keysymNormalized
? keysymNormalized
: keysym
;
1056 // as explained above, we want to have lower register key codes
1057 // normally but for the letter keys we want to have the upper ones
1059 // NB: don't use XConvertCase() here, we want to do it for letters
1061 key_code
= toupper(key_code
);
1063 else // non ASCII key, what to do?
1065 // by default, ignore it
1068 // but if we have cached information from the last KEY_PRESS
1069 if ( gdk_event
->type
== GDK_KEY_RELEASE
)
1072 if ( keysym
== s_lastKeyPress
.keysym
)
1074 key_code
= s_lastKeyPress
.keycode
;
1079 if ( gdk_event
->type
== GDK_KEY_PRESS
)
1081 // remember it to be reused for KEY_UP event later
1082 s_lastKeyPress
.keysym
= keysym
;
1083 s_lastKeyPress
.keycode
= key_code
;
1087 wxLogTrace(TRACE_KEYS
, _T("\t-> wxKeyCode %d"), key_code
);
1089 // sending unknown key events doesn't really make sense
1093 // now fill all the other fields
1096 GdkModifierType state
;
1097 if (gdk_event
->window
)
1098 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1100 event
.SetTimestamp( gdk_event
->time
);
1101 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
) != 0;
1102 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
) != 0;
1103 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
) != 0;
1104 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
) != 0;
1105 event
.m_keyCode
= key_code
;
1106 event
.m_scanCode
= gdk_event
->keyval
;
1107 event
.m_rawCode
= (wxUint32
) gdk_event
->keyval
;
1108 event
.m_rawFlags
= 0;
1111 event
.SetEventObject( win
);
1116 static gint
gtk_window_key_press_callback( GtkWidget
*widget
,
1117 GdkEventKey
*gdk_event
,
1123 wxapp_install_idle_handler();
1127 if (g_blockEventsOnDrag
)
1130 wxKeyEvent
event( wxEVT_KEY_DOWN
);
1131 if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) )
1133 // unknown key pressed, ignore (the event would be useless anyhow)
1137 bool ret
= win
->GetEventHandler()->ProcessEvent( event
);
1142 wxWindowGTK
*ancestor
= win
;
1145 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
1148 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
1149 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
1152 if (ancestor
->IsTopLevel())
1154 ancestor
= ancestor
->GetParent();
1157 #endif // wxUSE_ACCEL
1159 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
1160 will only be sent if it is not in an accelerator table. */
1163 KeySym keysym
= gdk_event
->keyval
;
1164 long key_code
= wxTranslateKeySymToWXKey(keysym
, TRUE
/* isChar */);
1167 if ( gdk_event
->length
== 1 )
1169 key_code
= (unsigned char)gdk_event
->string
[0];
1171 else if ( wxIsAsciiKeysym(keysym
) )
1174 key_code
= (unsigned char)keysym
;
1180 wxLogTrace(TRACE_KEYS
, _T("Char event: %ld"), key_code
);
1182 // reuse the same event object, just change its type and use the
1183 // translated keycode instead of the raw one
1184 event
.SetEventType(wxEVT_CHAR
);
1185 event
.m_keyCode
= key_code
;
1187 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1191 /* win is a control: tab can be propagated up */
1193 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
1194 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
1195 // have this style, yet choose not to process this particular TAB in which
1196 // case TAB must still work as a navigational character
1198 !win
->HasFlag(wxTE_PROCESS_TAB
) &&
1200 win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
1202 wxNavigationKeyEvent new_event
;
1203 new_event
.SetEventObject( win
->GetParent() );
1204 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
1205 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
1206 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1207 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
1208 new_event
.SetCurrentFocus( win
);
1209 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
1212 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
1214 (gdk_event
->keyval
== GDK_Escape
) )
1216 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
1217 new_event
.SetEventObject( win
);
1218 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
1222 #if 0 // (GTK_MINOR_VERSION > 0)
1223 /* Pressing F10 will activate the menu bar of the top frame. */
1225 (gdk_event
->keyval
== GDK_F10
) )
1227 wxWindowGTK
*ancestor
= win
;
1230 if (wxIsKindOf(ancestor
,wxFrame
))
1232 wxFrame
*frame
= (wxFrame
*) ancestor
;
1233 wxMenuBar
*menubar
= frame
->GetMenuBar();
1236 wxNode
*node
= menubar
->GetMenus().First();
1239 wxMenu
*firstMenu
= (wxMenu
*) node
->Data();
1240 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu
->m_owner
) );
1246 ancestor
= ancestor
->GetParent();
1253 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1260 //-----------------------------------------------------------------------------
1261 // "key_release_event" from any window
1262 //-----------------------------------------------------------------------------
1264 static gint
gtk_window_key_release_callback( GtkWidget
*widget
,
1265 GdkEventKey
*gdk_event
,
1271 wxapp_install_idle_handler();
1276 if (g_blockEventsOnDrag
)
1279 wxKeyEvent
event( wxEVT_KEY_UP
);
1280 if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) )
1282 // unknown key pressed, ignore (the event would be useless anyhow
1286 if ( !win
->GetEventHandler()->ProcessEvent( event
) )
1289 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1293 // ============================================================================
1295 // ============================================================================
1297 // init wxMouseEvent with the info from gdk_event
1298 #define InitMouseEvent(win, event, gdk_event) \
1300 event.SetTimestamp( gdk_event->time ); \
1301 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
1302 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
1303 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
1304 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
1305 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
1306 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
1307 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
1309 wxPoint pt = win->GetClientAreaOrigin(); \
1310 event.m_x = (wxCoord)gdk_event->x - pt.x; \
1311 event.m_y = (wxCoord)gdk_event->y - pt.y; \
1314 // ----------------------------------------------------------------------------
1315 // mouse event processing helper
1316 // ----------------------------------------------------------------------------
1318 static void AdjustEventButtonState(wxMouseEvent
& event
)
1320 // GDK reports the old state of the button for a button press event, but
1321 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1322 // for a LEFT_DOWN event, not FALSE, so we will invert
1323 // left/right/middleDown for the corresponding click events
1325 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1326 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1327 (event
.GetEventType() == wxEVT_LEFT_UP
))
1329 event
.m_leftDown
= !event
.m_leftDown
;
1333 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1334 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1335 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1337 event
.m_middleDown
= !event
.m_middleDown
;
1341 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1342 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1343 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1345 event
.m_rightDown
= !event
.m_rightDown
;
1350 //-----------------------------------------------------------------------------
1351 // "button_press_event"
1352 //-----------------------------------------------------------------------------
1354 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1359 wxapp_install_idle_handler();
1362 wxPrintf( wxT("1) OnButtonPress from ") );
1363 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1364 wxPrintf( win->GetClassInfo()->GetClassName() );
1365 wxPrintf( wxT(".\n") );
1367 if (!win
->m_hasVMT
) return FALSE
;
1368 if (g_blockEventsOnDrag
) return TRUE
;
1369 if (g_blockEventsOnScroll
) return TRUE
;
1371 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1373 if (win
->m_wxwindow
&& (g_focusWindow
!= win
) && win
->AcceptsFocus())
1375 gtk_widget_grab_focus( win
->m_wxwindow
);
1377 wxPrintf( wxT("GrabFocus from ") );
1378 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1379 wxPrintf( win->GetClassInfo()->GetClassName() );
1380 wxPrintf( wxT(".\n") );
1384 wxEventType event_type
= wxEVT_NULL
;
1386 if (gdk_event
->button
== 1)
1388 switch (gdk_event
->type
)
1390 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1391 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1395 else if (gdk_event
->button
== 2)
1397 switch (gdk_event
->type
)
1399 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1400 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1404 else if (gdk_event
->button
== 3)
1406 switch (gdk_event
->type
)
1408 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1409 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1414 if ( event_type
== wxEVT_NULL
)
1416 // unknown mouse button or click type
1420 wxMouseEvent
event( event_type
);
1421 InitMouseEvent( win
, event
, gdk_event
);
1423 AdjustEventButtonState(event
);
1425 // wxListBox actually get mouse events from the item
1427 if (win
->m_isListBox
)
1429 event
.m_x
+= widget
->allocation
.x
;
1430 event
.m_y
+= widget
->allocation
.y
;
1433 // Some control don't have their own X window and thus cannot get
1436 if (!g_captureWindow
)
1438 wxCoord x
= event
.m_x
;
1439 wxCoord y
= event
.m_y
;
1440 if (win
->m_wxwindow
)
1442 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1443 x
+= pizza
->xoffset
;
1444 y
+= pizza
->yoffset
;
1447 wxNode
*node
= win
->GetChildren().First();
1450 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1452 node
= node
->Next();
1453 if (!child
->IsShown())
1456 if (child
->m_isStaticBox
)
1458 // wxStaticBox is transparent in the box itself
1459 int xx1
= child
->m_x
;
1460 int yy1
= child
->m_y
;
1461 int xx2
= child
->m_x
+ child
->m_width
;
1462 int yy2
= child
->m_x
+ child
->m_height
;
1465 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1467 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1469 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1471 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1474 event
.m_x
-= child
->m_x
;
1475 event
.m_y
-= child
->m_y
;
1482 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1483 (child
->m_x
<= x
) &&
1484 (child
->m_y
<= y
) &&
1485 (child
->m_x
+child
->m_width
>= x
) &&
1486 (child
->m_y
+child
->m_height
>= y
))
1489 event
.m_x
-= child
->m_x
;
1490 event
.m_y
-= child
->m_y
;
1497 event
.SetEventObject( win
);
1499 gs_timeLastClick
= gdk_event
->time
;
1502 wxPrintf( wxT("2) OnButtonPress from ") );
1503 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1504 wxPrintf( win->GetClassInfo()->GetClassName() );
1505 wxPrintf( wxT(".\n") );
1508 if (win
->GetEventHandler()->ProcessEvent( event
))
1510 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1517 //-----------------------------------------------------------------------------
1518 // "button_release_event"
1519 //-----------------------------------------------------------------------------
1521 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1526 wxapp_install_idle_handler();
1528 if (!win
->m_hasVMT
) return FALSE
;
1529 if (g_blockEventsOnDrag
) return FALSE
;
1530 if (g_blockEventsOnScroll
) return FALSE
;
1532 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1535 printf( "OnButtonRelease from " );
1536 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1537 printf( win->GetClassInfo()->GetClassName() );
1541 wxEventType event_type
= wxEVT_NULL
;
1543 switch (gdk_event
->button
)
1545 case 1: event_type
= wxEVT_LEFT_UP
; break;
1546 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1547 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1548 default: return FALSE
;
1551 wxMouseEvent
event( event_type
);
1552 InitMouseEvent( win
, event
, gdk_event
);
1554 AdjustEventButtonState(event
);
1556 // wxListBox actually get mouse events from the item
1558 if (win
->m_isListBox
)
1560 event
.m_x
+= widget
->allocation
.x
;
1561 event
.m_y
+= widget
->allocation
.y
;
1564 // Some control don't have their own X window and thus cannot get
1567 if (!g_captureWindow
)
1569 wxCoord x
= event
.m_x
;
1570 wxCoord y
= event
.m_y
;
1571 if (win
->m_wxwindow
)
1573 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1574 x
+= pizza
->xoffset
;
1575 y
+= pizza
->yoffset
;
1578 wxNode
*node
= win
->GetChildren().First();
1581 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1583 node
= node
->Next();
1584 if (!child
->IsShown())
1587 if (child
->m_isStaticBox
)
1589 // wxStaticBox is transparent in the box itself
1590 int xx1
= child
->m_x
;
1591 int yy1
= child
->m_y
;
1592 int xx2
= child
->m_x
+ child
->m_width
;
1593 int yy2
= child
->m_x
+ child
->m_height
;
1596 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1598 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1600 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1602 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1605 event
.m_x
-= child
->m_x
;
1606 event
.m_y
-= child
->m_y
;
1613 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1614 (child
->m_x
<= x
) &&
1615 (child
->m_y
<= y
) &&
1616 (child
->m_x
+child
->m_width
>= x
) &&
1617 (child
->m_y
+child
->m_height
>= y
))
1620 event
.m_x
-= child
->m_x
;
1621 event
.m_y
-= child
->m_y
;
1628 event
.SetEventObject( win
);
1630 if (win
->GetEventHandler()->ProcessEvent( event
))
1632 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1639 //-----------------------------------------------------------------------------
1640 // "motion_notify_event"
1641 //-----------------------------------------------------------------------------
1643 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
,
1644 GdkEventMotion
*gdk_event
,
1650 wxapp_install_idle_handler();
1652 if (!win
->m_hasVMT
) return FALSE
;
1653 if (g_blockEventsOnDrag
) return FALSE
;
1654 if (g_blockEventsOnScroll
) return FALSE
;
1656 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1658 if (gdk_event
->is_hint
)
1662 GdkModifierType state
;
1663 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1669 printf( "OnMotion from " );
1670 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1671 printf( win->GetClassInfo()->GetClassName() );
1675 wxMouseEvent
event( wxEVT_MOTION
);
1676 InitMouseEvent(win
, event
, gdk_event
);
1678 if ( g_captureWindow
)
1680 // synthetize a mouse enter or leave event if needed
1681 GdkWindow
*winUnderMouse
= gdk_window_at_pointer(NULL
, NULL
);
1682 bool hasMouse
= winUnderMouse
== gdk_event
->window
;
1683 if ( hasMouse
!= g_captureWindowHasMouse
)
1685 // the mouse changed window
1686 g_captureWindowHasMouse
= hasMouse
;
1688 wxMouseEvent
event(g_captureWindowHasMouse
? wxEVT_ENTER_WINDOW
1689 : wxEVT_LEAVE_WINDOW
);
1690 InitMouseEvent(win
, event
, gdk_event
);
1691 event
.SetEventObject(win
);
1692 win
->GetEventHandler()->ProcessEvent(event
);
1697 // Some control don't have their own X window and thus cannot get
1700 wxCoord x
= event
.m_x
;
1701 wxCoord y
= event
.m_y
;
1702 if (win
->m_wxwindow
)
1704 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1705 x
+= pizza
->xoffset
;
1706 y
+= pizza
->yoffset
;
1709 wxNode
*node
= win
->GetChildren().First();
1712 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1714 node
= node
->Next();
1715 if (!child
->IsShown())
1718 if (child
->m_isStaticBox
)
1720 // wxStaticBox is transparent in the box itself
1721 int xx1
= child
->m_x
;
1722 int yy1
= child
->m_y
;
1723 int xx2
= child
->m_x
+ child
->m_width
;
1724 int yy2
= child
->m_x
+ child
->m_height
;
1727 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1729 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1731 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1733 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1736 event
.m_x
-= child
->m_x
;
1737 event
.m_y
-= child
->m_y
;
1744 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1745 (child
->m_x
<= x
) &&
1746 (child
->m_y
<= y
) &&
1747 (child
->m_x
+child
->m_width
>= x
) &&
1748 (child
->m_y
+child
->m_height
>= y
))
1751 event
.m_x
-= child
->m_x
;
1752 event
.m_y
-= child
->m_y
;
1759 event
.SetEventObject( win
);
1761 if (win
->GetEventHandler()->ProcessEvent( event
))
1763 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1770 //-----------------------------------------------------------------------------
1772 //-----------------------------------------------------------------------------
1774 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
,
1775 GdkEvent
*WXUNUSED(event
),
1781 wxapp_install_idle_handler();
1783 if (!win
->m_hasVMT
) return FALSE
;
1784 if (g_blockEventsOnDrag
) return FALSE
;
1786 switch ( g_sendActivateEvent
)
1789 // we've got focus from outside, synthetize wxActivateEvent
1790 g_sendActivateEvent
= 1;
1794 // another our window just lost focus, it was already ours before
1795 // - don't send any wxActivateEvent
1796 g_sendActivateEvent
= -1;
1801 g_focusWindow
= win
;
1804 printf( "OnSetFocus 2 from %s\n", win
->GetName().c_str() );
1807 // Notify the parent keeping track of focus for the kbd navigation
1808 // purposes that we got it.
1809 wxChildFocusEvent
eventFocus(win
);
1810 (void)win
->GetEventHandler()->ProcessEvent(eventFocus
);
1814 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1818 // caret needs to be informed about focus change
1819 wxCaret
*caret
= win
->GetCaret();
1822 caret
->OnSetFocus();
1824 #endif // wxUSE_CARET
1826 g_activeFrameLostFocus
= FALSE
;
1828 wxWindowGTK
*active
= wxGetTopLevelParent(win
);
1829 if ( active
!= g_activeFrame
)
1831 if ( g_activeFrame
)
1833 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame
);
1834 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
1835 event
.SetEventObject(g_activeFrame
);
1836 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1839 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active
);
1840 g_activeFrame
= active
;
1841 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId());
1842 event
.SetEventObject(g_activeFrame
);
1843 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1845 // Don't send focus events in addition to activate
1846 // if (win == g_activeFrame)
1851 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1852 event
.SetEventObject( win
);
1854 if (win
->GetEventHandler()->ProcessEvent( event
))
1856 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1863 //-----------------------------------------------------------------------------
1864 // "focus_out_event"
1865 //-----------------------------------------------------------------------------
1867 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEventFocus
*gdk_event
, wxWindowGTK
*win
)
1872 wxapp_install_idle_handler();
1874 if (!win
->m_hasVMT
) return FALSE
;
1875 if (g_blockEventsOnDrag
) return FALSE
;
1878 wxLogDebug( wxT("OnKillFocus from %s"), win
->GetName().c_str() );
1881 if ( !g_activeFrameLostFocus
&& g_activeFrame
)
1883 // VZ: commenting this out because it does happen (although not easy
1884 // to reproduce, I only see it when using wxMiniFrame and not
1885 // always) and makes using Mahogany quite annoying
1887 wxASSERT_MSG( wxGetTopLevelParent(win
) == g_activeFrame
,
1888 wxT("unfocusing window that hasn't gained focus properly") )
1891 g_activeFrameLostFocus
= TRUE
;
1894 // if the focus goes out of our app alltogether, OnIdle() will send
1895 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1896 // g_sendActivateEvent to -1
1897 g_sendActivateEvent
= 0;
1899 wxWindowGTK
*winFocus
= wxFindFocusedChild(win
);
1903 g_focusWindow
= (wxWindowGTK
*)NULL
;
1911 // caret needs to be informed about focus change
1912 wxCaret
*caret
= win
->GetCaret();
1915 caret
->OnKillFocus();
1917 #endif // wxUSE_CARET
1919 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1920 event
.SetEventObject( win
);
1922 if (win
->GetEventHandler()->ProcessEvent( event
))
1924 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1931 //-----------------------------------------------------------------------------
1932 // "enter_notify_event"
1933 //-----------------------------------------------------------------------------
1935 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1940 wxapp_install_idle_handler();
1942 if (!win
->m_hasVMT
) return FALSE
;
1943 if (g_blockEventsOnDrag
) return FALSE
;
1945 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1947 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1948 event
.SetTimestamp( gdk_event
->time
);
1949 event
.SetEventObject( win
);
1953 GdkModifierType state
= (GdkModifierType
)0;
1955 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1957 InitMouseEvent(win
, event
, gdk_event
);
1958 wxPoint pt
= win
->GetClientAreaOrigin();
1959 event
.m_x
= x
+ pt
.x
;
1960 event
.m_y
= y
+ pt
.y
;
1962 if (win
->GetEventHandler()->ProcessEvent( event
))
1964 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1971 //-----------------------------------------------------------------------------
1972 // "leave_notify_event"
1973 //-----------------------------------------------------------------------------
1975 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1980 wxapp_install_idle_handler();
1982 if (!win
->m_hasVMT
) return FALSE
;
1983 if (g_blockEventsOnDrag
) return FALSE
;
1985 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1987 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1988 event
.SetTimestamp( gdk_event
->time
);
1989 event
.SetEventObject( win
);
1993 GdkModifierType state
= (GdkModifierType
)0;
1995 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1997 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
) != 0;
1998 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
) != 0;
1999 event
.m_altDown
= (state
& GDK_MOD1_MASK
) != 0;
2000 event
.m_metaDown
= (state
& GDK_MOD2_MASK
) != 0;
2001 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
) != 0;
2002 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
) != 0;
2003 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
) != 0;
2005 wxPoint pt
= win
->GetClientAreaOrigin();
2006 event
.m_x
= x
+ pt
.x
;
2007 event
.m_y
= y
+ pt
.y
;
2009 if (win
->GetEventHandler()->ProcessEvent( event
))
2011 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
2018 //-----------------------------------------------------------------------------
2019 // "value_changed" from m_vAdjust
2020 //-----------------------------------------------------------------------------
2022 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
,
2029 wxapp_install_idle_handler();
2031 if (g_blockEventsOnDrag
) return;
2033 if (!win
->m_hasVMT
) return;
2035 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
2036 if (fabs(diff
) < 0.2) return;
2038 win
->m_oldVerticalPos
= adjust
->value
;
2040 wxEventType command
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(win
->m_widget
));
2042 int value
= (int)(adjust
->value
+0.5);
2044 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
2045 event
.SetEventObject( win
);
2046 win
->GetEventHandler()->ProcessEvent( event
);
2049 //-----------------------------------------------------------------------------
2050 // "value_changed" from m_hAdjust
2051 //-----------------------------------------------------------------------------
2053 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
,
2060 wxapp_install_idle_handler();
2062 if (g_blockEventsOnDrag
) return;
2063 if (!win
->m_hasVMT
) return;
2065 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
2066 if (fabs(diff
) < 0.2) return;
2068 wxEventType command
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(win
->m_widget
));
2070 win
->m_oldHorizontalPos
= adjust
->value
;
2072 int value
= (int)(adjust
->value
+0.5);
2074 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
2075 event
.SetEventObject( win
);
2076 win
->GetEventHandler()->ProcessEvent( event
);
2079 //-----------------------------------------------------------------------------
2080 // "button_press_event" from scrollbar
2081 //-----------------------------------------------------------------------------
2083 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
2084 GdkEventButton
*gdk_event
,
2090 wxapp_install_idle_handler();
2093 g_blockEventsOnScroll
= TRUE
;
2095 // FIXME: there is no 'slider' field in GTK+ 2.0 any more
2097 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
2103 //-----------------------------------------------------------------------------
2104 // "button_release_event" from scrollbar
2105 //-----------------------------------------------------------------------------
2107 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
2108 GdkEventButton
*WXUNUSED(gdk_event
),
2113 // don't test here as we can release the mouse while being over
2114 // a different window than the slider
2116 // if (gdk_event->window != widget->slider) return FALSE;
2118 g_blockEventsOnScroll
= FALSE
;
2120 if (win
->m_isScrolling
)
2122 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
2126 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
2127 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
2129 value
= (int)(win
->m_hAdjust
->value
+0.5);
2132 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
2134 value
= (int)(win
->m_vAdjust
->value
+0.5);
2138 wxScrollWinEvent
event( command
, value
, dir
);
2139 event
.SetEventObject( win
);
2140 win
->GetEventHandler()->ProcessEvent( event
);
2143 win
->m_isScrolling
= FALSE
;
2148 // ----------------------------------------------------------------------------
2149 // this wxWindowBase function is implemented here (in platform-specific file)
2150 // because it is static and so couldn't be made virtual
2151 // ----------------------------------------------------------------------------
2153 wxWindow
*wxWindowBase::FindFocus()
2155 // the cast is necessary when we compile in wxUniversal mode
2156 return (wxWindow
*)g_focusWindow
;
2159 //-----------------------------------------------------------------------------
2160 // "realize" from m_widget
2161 //-----------------------------------------------------------------------------
2163 /* We cannot set colours and fonts before the widget has
2164 been realized, so we do this directly after realization. */
2167 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
2172 wxapp_install_idle_handler();
2174 if (win
->m_delayedBackgroundColour
)
2175 win
->GtkSetBackgroundColour( win
->GetBackgroundColour() );
2177 if (win
->m_delayedForegroundColour
)
2178 win
->GtkSetForegroundColour( win
->GetForegroundColour() );
2180 wxWindowCreateEvent
event( win
);
2181 event
.SetEventObject( win
);
2182 win
->GetEventHandler()->ProcessEvent( event
);
2187 //-----------------------------------------------------------------------------
2189 //-----------------------------------------------------------------------------
2192 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
2193 GtkAllocation
*WXUNUSED(alloc
),
2197 wxapp_install_idle_handler();
2199 if (!win
->m_hasScrolling
) return;
2201 int client_width
= 0;
2202 int client_height
= 0;
2203 win
->GetClientSize( &client_width
, &client_height
);
2204 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
2207 win
->m_oldClientWidth
= client_width
;
2208 win
->m_oldClientHeight
= client_height
;
2210 if (!win
->m_nativeSizeEvent
)
2212 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
2213 event
.SetEventObject( win
);
2214 win
->GetEventHandler()->ProcessEvent( event
);
2220 #define WXUNUSED_UNLESS_XIM(param) param
2222 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2225 /* Resize XIM window */
2228 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2229 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
2230 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2233 wxapp_install_idle_handler();
2239 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
2243 gdk_window_get_size (widget
->window
, &width
, &height
);
2244 win
->m_icattr
->preedit_area
.width
= width
;
2245 win
->m_icattr
->preedit_area
.height
= height
;
2246 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2251 //-----------------------------------------------------------------------------
2252 // "realize" from m_wxwindow
2253 //-----------------------------------------------------------------------------
2255 /* Initialize XIM support */
2258 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2259 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2262 wxapp_install_idle_handler();
2265 if (win
->m_ic
) return FALSE
;
2266 if (!widget
) return FALSE
;
2267 if (!gdk_im_ready()) return FALSE
;
2269 win
->m_icattr
= gdk_ic_attr_new();
2270 if (!win
->m_icattr
) return FALSE
;
2274 GdkColormap
*colormap
;
2275 GdkICAttr
*attr
= win
->m_icattr
;
2276 unsigned attrmask
= GDK_IC_ALL_REQ
;
2278 GdkIMStyle supported_style
= (GdkIMStyle
)
2279 (GDK_IM_PREEDIT_NONE
|
2280 GDK_IM_PREEDIT_NOTHING
|
2281 GDK_IM_PREEDIT_POSITION
|
2282 GDK_IM_STATUS_NONE
|
2283 GDK_IM_STATUS_NOTHING
);
2285 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2286 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2288 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2289 attr
->client_window
= widget
->window
;
2291 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2292 gtk_widget_get_default_colormap ())
2294 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2295 attr
->preedit_colormap
= colormap
;
2298 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2299 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2300 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2301 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2303 switch (style
& GDK_IM_PREEDIT_MASK
)
2305 case GDK_IM_PREEDIT_POSITION
:
2306 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2308 g_warning ("over-the-spot style requires fontset");
2312 gdk_window_get_size (widget
->window
, &width
, &height
);
2314 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2315 attr
->spot_location
.x
= 0;
2316 attr
->spot_location
.y
= height
;
2317 attr
->preedit_area
.x
= 0;
2318 attr
->preedit_area
.y
= 0;
2319 attr
->preedit_area
.width
= width
;
2320 attr
->preedit_area
.height
= height
;
2321 attr
->preedit_fontset
= widget
->style
->font
;
2326 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2328 if (win
->m_ic
== NULL
)
2329 g_warning ("Can't create input context.");
2332 mask
= gdk_window_get_events (widget
->window
);
2333 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2334 gdk_window_set_events (widget
->window
, mask
);
2336 if (GTK_WIDGET_HAS_FOCUS(widget
))
2337 gdk_im_begin (win
->m_ic
, widget
->window
);
2344 //-----------------------------------------------------------------------------
2345 // InsertChild for wxWindowGTK.
2346 //-----------------------------------------------------------------------------
2348 /* Callback for wxWindowGTK. This very strange beast has to be used because
2349 * C++ has no virtual methods in a constructor. We have to emulate a
2350 * virtual function here as wxNotebook requires a different way to insert
2351 * a child in it. I had opted for creating a wxNotebookPage window class
2352 * which would have made this superfluous (such in the MDI window system),
2353 * but no-one was listening to me... */
2355 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child
)
2357 /* the window might have been scrolled already, do we
2358 have to adapt the position */
2359 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2360 child
->m_x
+= pizza
->xoffset
;
2361 child
->m_y
+= pizza
->yoffset
;
2363 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2364 GTK_WIDGET(child
->m_widget
),
2371 //-----------------------------------------------------------------------------
2373 //-----------------------------------------------------------------------------
2375 wxWindow
*wxGetActiveWindow()
2377 // the cast is necessary when we compile in wxUniversal mode
2378 return (wxWindow
*)g_focusWindow
;
2381 //-----------------------------------------------------------------------------
2383 //-----------------------------------------------------------------------------
2385 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
2387 #ifdef __WXUNIVERSAL__
2388 IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
)
2390 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2391 #endif // __WXUNIVERSAL__/__WXGTK__
2393 void wxWindowGTK::Init()
2399 m_widget
= (GtkWidget
*) NULL
;
2400 m_wxwindow
= (GtkWidget
*) NULL
;
2401 m_focusWidget
= (GtkWidget
*) NULL
;
2411 m_needParent
= TRUE
;
2412 m_isBeingDeleted
= FALSE
;
2415 m_nativeSizeEvent
= FALSE
;
2417 m_hasScrolling
= FALSE
;
2418 m_isScrolling
= FALSE
;
2420 m_hAdjust
= (GtkAdjustment
*) NULL
;
2421 m_vAdjust
= (GtkAdjustment
*) NULL
;
2422 m_oldHorizontalPos
= 0.0;
2423 m_oldVerticalPos
= 0.0;
2426 m_widgetStyle
= (GtkStyle
*) NULL
;
2428 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2430 m_isStaticBox
= FALSE
;
2431 m_isRadioButton
= FALSE
;
2432 m_isListBox
= FALSE
;
2434 m_acceptsFocus
= FALSE
;
2436 m_clipPaintRegion
= FALSE
;
2438 m_cursor
= *wxSTANDARD_CURSOR
;
2440 m_delayedForegroundColour
= FALSE
;
2441 m_delayedBackgroundColour
= FALSE
;
2444 m_ic
= (GdkIC
*) NULL
;
2445 m_icattr
= (GdkICAttr
*) NULL
;
2449 wxWindowGTK::wxWindowGTK()
2454 wxWindowGTK::wxWindowGTK( wxWindow
*parent
,
2459 const wxString
&name
)
2463 Create( parent
, id
, pos
, size
, style
, name
);
2466 bool wxWindowGTK::Create( wxWindow
*parent
,
2471 const wxString
&name
)
2473 if (!PreCreation( parent
, pos
, size
) ||
2474 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2476 wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
2480 m_insertCallback
= wxInsertChildInWindow
;
2482 // always needed for background clearing
2483 m_delayedBackgroundColour
= TRUE
;
2485 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2486 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2488 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2490 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2491 scroll_class
->scrollbar_spacing
= 0;
2493 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2495 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2496 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2498 m_wxwindow
= gtk_pizza_new();
2500 #ifndef __WXUNIVERSAL__
2501 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2503 if (HasFlag(wxRAISED_BORDER
))
2505 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2507 else if (HasFlag(wxSUNKEN_BORDER
))
2509 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2511 else if (HasFlag(wxSIMPLE_BORDER
))
2513 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2517 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2519 #endif // __WXUNIVERSAL__
2521 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2523 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2524 m_acceptsFocus
= TRUE
;
2526 // I _really_ don't want scrollbars in the beginning
2527 m_vAdjust
->lower
= 0.0;
2528 m_vAdjust
->upper
= 1.0;
2529 m_vAdjust
->value
= 0.0;
2530 m_vAdjust
->step_increment
= 1.0;
2531 m_vAdjust
->page_increment
= 1.0;
2532 m_vAdjust
->page_size
= 5.0;
2533 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2534 m_hAdjust
->lower
= 0.0;
2535 m_hAdjust
->upper
= 1.0;
2536 m_hAdjust
->value
= 0.0;
2537 m_hAdjust
->step_increment
= 1.0;
2538 m_hAdjust
->page_increment
= 1.0;
2539 m_hAdjust
->page_size
= 5.0;
2540 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2542 // these handlers block mouse events to any window during scrolling such as
2543 // motion events and prevent GTK and wxWindows from fighting over where the
2546 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2547 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2549 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2550 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2552 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2553 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2555 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2556 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2558 // these handlers get notified when screen updates are required either when
2559 // scrolling or when the window size (and therefore scrollbar configuration)
2562 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2563 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2564 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2565 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2567 gtk_widget_show( m_wxwindow
);
2570 m_parent
->DoAddChild( this );
2572 m_focusWidget
= m_wxwindow
;
2581 wxWindowGTK::~wxWindowGTK()
2583 if (g_focusWindow
== this)
2584 g_focusWindow
= NULL
;
2586 if (g_activeFrame
== this)
2587 g_activeFrame
= NULL
;
2589 m_isBeingDeleted
= TRUE
;
2598 m_parent
->RemoveChild( this );
2602 gdk_ic_destroy (m_ic
);
2604 gdk_ic_attr_destroy (m_icattr
);
2609 #if DISABLE_STYLE_IF_BROKEN_THEME
2610 // don't delete if it's a pixmap theme style
2611 if (!m_widgetStyle
->engine_data
)
2612 gtk_style_unref( m_widgetStyle
);
2614 m_widgetStyle
= (GtkStyle
*) NULL
;
2619 gtk_widget_destroy( m_wxwindow
);
2620 m_wxwindow
= (GtkWidget
*) NULL
;
2625 gtk_widget_destroy( m_widget
);
2626 m_widget
= (GtkWidget
*) NULL
;
2630 bool wxWindowGTK::PreCreation( wxWindowGTK
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2632 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2634 /* this turns -1 into 20 so that a minimal window is
2635 visible even although -1,-1 has been given as the
2636 size of the window. the same trick is used in other
2637 ports and should make debugging easier */
2638 m_width
= WidthDefault(size
.x
);
2639 m_height
= HeightDefault(size
.y
);
2644 /* some reasonable defaults */
2649 m_x
= (gdk_screen_width () - m_width
) / 2;
2650 if (m_x
< 10) m_x
= 10;
2654 m_y
= (gdk_screen_height () - m_height
) / 2;
2655 if (m_y
< 10) m_y
= 10;
2662 void wxWindowGTK::PostCreation()
2664 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2670 // these get reported to wxWindows -> wxPaintEvent
2672 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2674 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2675 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2678 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2679 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2681 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2683 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2684 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2687 gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow
), HasFlag( wxNO_FULL_REPAINT_ON_RESIZE
) );
2691 // these are called when the "sunken" or "raised" borders are drawn
2692 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2693 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2696 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2697 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2703 if (m_focusWidget
== NULL
)
2704 m_focusWidget
= m_widget
;
2706 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event",
2707 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2709 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event",
2710 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2712 // connect to the various key and mouse handlers
2714 GtkWidget
*connect_widget
= GetConnectWidget();
2716 ConnectWidget( connect_widget
);
2718 /* We cannot set colours, fonts and cursors before the widget has
2719 been realized, so we do this directly after realization */
2720 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2721 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2725 // Catch native resize events
2726 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2727 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2729 // Initialize XIM support
2730 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2731 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2733 // And resize XIM window
2734 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2735 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2738 if (!GTK_IS_COMBO(m_widget
))
2740 // This is needed if we want to add our windows into native
2741 // GTK control, such as the toolbar. With this callback, the
2742 // toolbar gets to know the correct size (the one set by the
2743 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2744 // when moving to GTK 2.0.
2745 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2746 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2752 void wxWindowGTK::ConnectWidget( GtkWidget
*widget
)
2754 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2755 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2757 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2758 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2760 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2761 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2763 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2764 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2766 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2767 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2769 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2770 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2772 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2773 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2776 bool wxWindowGTK::Destroy()
2778 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2782 return wxWindowBase::Destroy();
2785 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
)
2787 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2790 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2792 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2793 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") );
2796 printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
2799 if (m_resizing
) return; /* I don't like recursions */
2802 int currentX
, currentY
;
2803 GetPosition(¤tX
, ¤tY
);
2808 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
2810 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2812 /* don't set the size for children of wxNotebook, just take the values. */
2820 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2821 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2823 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2824 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2825 if (width
!= -1) m_width
= width
;
2826 if (height
!= -1) m_height
= height
;
2830 m_x
= x
+ pizza
->xoffset
;
2831 m_y
= y
+ pizza
->yoffset
;
2836 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2838 if (width
== -1) m_width
= 80;
2841 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2843 if (height
== -1) m_height
= 26;
2846 int minWidth
= GetMinWidth(),
2847 minHeight
= GetMinHeight(),
2848 maxWidth
= GetMaxWidth(),
2849 maxHeight
= GetMaxHeight();
2851 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
2852 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
2853 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
2854 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
2857 int bottom_border
= 0;
2860 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2862 /* the default button has a border around it */
2868 DoMoveWindow( m_x
-border
,
2871 m_height
+border
+bottom_border
);
2876 /* Sometimes the client area changes size without the
2877 whole windows's size changing, but if the whole
2878 windows's size doesn't change, no wxSizeEvent will
2879 normally be sent. Here we add an extra test if
2880 the client test has been changed and this will
2882 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2886 wxPrintf( "OnSize sent from " );
2887 if (GetClassInfo() && GetClassInfo()->GetClassName())
2888 wxPrintf( GetClassInfo()->GetClassName() );
2889 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2892 if (!m_nativeSizeEvent
)
2894 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2895 event
.SetEventObject( this );
2896 GetEventHandler()->ProcessEvent( event
);
2902 void wxWindowGTK::OnInternalIdle()
2904 // Update invalidated regions.
2907 // Synthetize activate events.
2908 if ( g_sendActivateEvent
!= -1 )
2910 bool activate
= g_sendActivateEvent
!= 0;
2913 g_sendActivateEvent
= -1;
2915 wxTheApp
->SetActive(activate
, (wxWindow
*)g_focusWindowLast
);
2918 if ( g_activeFrameLostFocus
)
2920 if ( g_activeFrame
)
2922 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame
);
2923 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
2924 event
.SetEventObject(g_activeFrame
);
2925 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
2926 g_activeFrame
= NULL
;
2928 g_activeFrameLostFocus
= FALSE
;
2931 if (g_delayedFocus
== this)
2933 if (GTK_WIDGET_REALIZED(m_widget
))
2935 gtk_widget_grab_focus( m_widget
);
2936 g_delayedFocus
= NULL
;
2940 wxCursor cursor
= m_cursor
;
2941 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2945 /* I now set the cursor anew in every OnInternalIdle call
2946 as setting the cursor in a parent window also effects the
2947 windows above so that checking for the current cursor is
2952 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2954 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2956 if (!g_globalCursor
.Ok())
2957 cursor
= *wxSTANDARD_CURSOR
;
2959 window
= m_widget
->window
;
2960 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2961 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2967 GdkWindow
*window
= m_widget
->window
;
2968 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2969 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2977 void wxWindowGTK::DoGetSize( int *width
, int *height
) const
2979 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2981 if (width
) (*width
) = m_width
;
2982 if (height
) (*height
) = m_height
;
2985 void wxWindowGTK::DoSetClientSize( int width
, int height
)
2987 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2991 SetSize( width
, height
);
2998 #ifndef __WXUNIVERSAL__
2999 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
3001 /* when using GTK 1.2 we set the shadow border size to 2 */
3005 if (HasFlag(wxSIMPLE_BORDER
))
3007 /* when using GTK 1.2 we set the simple border size to 1 */
3011 #endif // __WXUNIVERSAL__
3015 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
3017 GtkRequisition vscroll_req
;
3018 vscroll_req
.width
= 2;
3019 vscroll_req
.height
= 2;
3020 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
3021 (scroll_window
->vscrollbar
, &vscroll_req
);
3023 GtkRequisition hscroll_req
;
3024 hscroll_req
.width
= 2;
3025 hscroll_req
.height
= 2;
3026 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
3027 (scroll_window
->hscrollbar
, &hscroll_req
);
3029 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
3031 if (scroll_window
->vscrollbar_visible
)
3033 dw
+= vscroll_req
.width
;
3034 dw
+= scroll_class
->scrollbar_spacing
;
3037 if (scroll_window
->hscrollbar_visible
)
3039 dh
+= hscroll_req
.height
;
3040 dh
+= scroll_class
->scrollbar_spacing
;
3044 SetSize( width
+dw
, height
+dh
);
3048 void wxWindowGTK::DoGetClientSize( int *width
, int *height
) const
3050 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3054 if (width
) (*width
) = m_width
;
3055 if (height
) (*height
) = m_height
;
3062 #ifndef __WXUNIVERSAL__
3063 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
3065 /* when using GTK 1.2 we set the shadow border size to 2 */
3069 if (HasFlag(wxSIMPLE_BORDER
))
3071 /* when using GTK 1.2 we set the simple border size to 1 */
3075 #endif // __WXUNIVERSAL__
3079 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
3081 GtkRequisition vscroll_req
;
3082 vscroll_req
.width
= 2;
3083 vscroll_req
.height
= 2;
3084 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
3085 (scroll_window
->vscrollbar
, &vscroll_req
);
3087 GtkRequisition hscroll_req
;
3088 hscroll_req
.width
= 2;
3089 hscroll_req
.height
= 2;
3090 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
3091 (scroll_window
->hscrollbar
, &hscroll_req
);
3093 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
3095 if (scroll_window
->vscrollbar_visible
)
3097 dw
+= vscroll_req
.width
;
3098 dw
+= scroll_class
->scrollbar_spacing
;
3101 if (scroll_window
->hscrollbar_visible
)
3103 dh
+= hscroll_req
.height
;
3104 dh
+= scroll_class
->scrollbar_spacing
;
3108 if (width
) (*width
) = m_width
- dw
;
3109 if (height
) (*height
) = m_height
- dh
;
3113 printf( "GetClientSize, name %s ", GetName().c_str() );
3114 if (width) printf( " width = %d", (*width) );
3115 if (height) printf( " height = %d", (*height) );
3120 void wxWindowGTK::DoGetPosition( int *x
, int *y
) const
3122 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3126 if (m_parent
&& m_parent
->m_wxwindow
)
3128 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
3129 dx
= pizza
->xoffset
;
3130 dy
= pizza
->yoffset
;
3133 if (x
) (*x
) = m_x
- dx
;
3134 if (y
) (*y
) = m_y
- dy
;
3137 void wxWindowGTK::DoClientToScreen( int *x
, int *y
) const
3139 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3141 if (!m_widget
->window
) return;
3143 GdkWindow
*source
= (GdkWindow
*) NULL
;
3145 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3147 source
= m_widget
->window
;
3151 gdk_window_get_origin( source
, &org_x
, &org_y
);
3155 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3157 org_x
+= m_widget
->allocation
.x
;
3158 org_y
+= m_widget
->allocation
.y
;
3166 void wxWindowGTK::DoScreenToClient( int *x
, int *y
) const
3168 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3170 if (!m_widget
->window
) return;
3172 GdkWindow
*source
= (GdkWindow
*) NULL
;
3174 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3176 source
= m_widget
->window
;
3180 gdk_window_get_origin( source
, &org_x
, &org_y
);
3184 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3186 org_x
+= m_widget
->allocation
.x
;
3187 org_y
+= m_widget
->allocation
.y
;
3195 bool wxWindowGTK::Show( bool show
)
3197 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3199 if (!wxWindowBase::Show(show
))
3206 gtk_widget_show( m_widget
);
3208 gtk_widget_hide( m_widget
);
3213 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
)
3215 win
->OnParentEnable(enable
);
3217 // Recurse, so that children have the opportunity to Do The Right Thing
3218 // and reset colours that have been messed up by a parent's (really ancestor's)
3220 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
3222 node
= node
->GetNext() )
3224 wxWindow
*child
= node
->GetData();
3225 if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
)))
3226 wxWindowNotifyEnable(child
, enable
);
3230 bool wxWindowGTK::Enable( bool enable
)
3232 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3234 if (!wxWindowBase::Enable(enable
))
3240 gtk_widget_set_sensitive( m_widget
, enable
);
3242 gtk_widget_set_sensitive( m_wxwindow
, enable
);
3244 wxWindowNotifyEnable(this, enable
);
3249 int wxWindowGTK::GetCharHeight() const
3251 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
3253 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
3255 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3257 return font
->ascent
+ font
->descent
;
3260 int wxWindowGTK::GetCharWidth() const
3262 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
3264 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
3266 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3268 return gdk_string_width( font
, "H" );
3271 void wxWindowGTK::GetTextExtent( const wxString
& string
,
3275 int *externalLeading
,
3276 const wxFont
*theFont
) const
3278 wxFont fontToUse
= m_font
;
3279 if (theFont
) fontToUse
= *theFont
;
3281 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
3283 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
3284 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
3285 if (y
) (*y
) = font
->ascent
+ font
->descent
;
3286 if (descent
) (*descent
) = font
->descent
;
3287 if (externalLeading
) (*externalLeading
) = 0; // ??
3290 void wxWindowGTK::SetFocus()
3292 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3296 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3298 gtk_widget_grab_focus (m_wxwindow
);
3303 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
3305 if (!GTK_WIDGET_REALIZED(m_widget
))
3306 g_delayedFocus
= this;
3308 gtk_widget_grab_focus (m_widget
);
3310 else if (GTK_IS_CONTAINER(m_widget
))
3312 SET_CONTAINER_FOCUS( m_widget
, GTK_DIR_TAB_FORWARD
);
3321 bool wxWindowGTK::AcceptsFocus() const
3323 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3326 bool wxWindowGTK::Reparent( wxWindowBase
*newParentBase
)
3328 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3330 wxWindowGTK
*oldParent
= m_parent
,
3331 *newParent
= (wxWindowGTK
*)newParentBase
;
3333 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3335 if ( !wxWindowBase::Reparent(newParent
) )
3338 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3340 /* prevent GTK from deleting the widget arbitrarily */
3341 gtk_widget_ref( m_widget
);
3345 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3348 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3352 /* insert GTK representation */
3353 (*(newParent
->m_insertCallback
))(newParent
, this);
3356 /* reverse: prevent GTK from deleting the widget arbitrarily */
3357 gtk_widget_unref( m_widget
);
3362 void wxWindowGTK::DoAddChild(wxWindowGTK
*child
)
3364 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3366 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3368 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3373 /* insert GTK representation */
3374 (*m_insertCallback
)(this, child
);
3377 void wxWindowGTK::Raise()
3379 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3381 if (!m_widget
->window
) return;
3383 gdk_window_raise( m_widget
->window
);
3386 void wxWindowGTK::Lower()
3388 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3390 if (!m_widget
->window
) return;
3392 gdk_window_lower( m_widget
->window
);
3395 bool wxWindowGTK::SetCursor( const wxCursor
&cursor
)
3397 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3399 if (cursor
== m_cursor
)
3403 wxapp_install_idle_handler();
3405 if (cursor
== wxNullCursor
)
3406 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3408 return wxWindowBase::SetCursor( cursor
);
3411 void wxWindowGTK::WarpPointer( int x
, int y
)
3413 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3415 // We provide this function ourselves as it is
3416 // missing in GDK (top of this file).
3418 GdkWindow
*window
= (GdkWindow
*) NULL
;
3420 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3422 window
= GetConnectWidget()->window
;
3425 gdk_window_warp_pointer( window
, x
, y
);
3428 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect
*rect
)
3430 if (!m_widget
) return;
3431 if (!m_widget
->window
) return;
3435 wxapp_install_idle_handler();
3437 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3441 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3442 m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
3446 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3447 m_clearRegion
.Clear();
3448 m_clearRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height
);
3456 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3457 m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
3461 GdkRectangle gdk_rect
;
3462 gdk_rect
.x
= rect
->x
;
3463 gdk_rect
.y
= rect
->y
;
3464 gdk_rect
.width
= rect
->width
;
3465 gdk_rect
.height
= rect
->height
;
3466 gtk_widget_draw( m_widget
, &gdk_rect
);
3473 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3474 m_updateRegion
.Clear();
3475 m_updateRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height
);
3479 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3487 GdkRectangle gdk_rect
;
3488 gdk_rect
.x
= rect
->x
;
3489 gdk_rect
.y
= rect
->y
;
3490 gdk_rect
.width
= rect
->width
;
3491 gdk_rect
.height
= rect
->height
;
3492 gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, &gdk_rect
, TRUE
);
3496 gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, NULL
, TRUE
);
3502 void wxWindowGTK::Update()
3505 if (m_wxwindow
&& GTK_PIZZA(m_wxwindow
)->bin_window
)
3506 gdk_window_process_updates( GTK_PIZZA(m_wxwindow
)->bin_window
, FALSE
);
3509 if (!m_updateRegion
.IsEmpty())
3510 GtkSendPaintEvents();
3513 void wxWindowGTK::GtkSendPaintEvents()
3517 m_clearRegion
.Clear();
3518 m_updateRegion
.Clear();
3522 m_clipPaintRegion
= TRUE
;
3524 // if (!m_clearRegion.IsEmpty()) // always send an erase event
3526 wxWindowDC
dc( (wxWindow
*)this );
3527 dc
.SetClippingRegion( m_clearRegion
);
3529 wxEraseEvent
erase_event( GetId(), &dc
);
3530 erase_event
.SetEventObject( this );
3532 if (!GetEventHandler()->ProcessEvent(erase_event
))
3536 g_eraseGC
= gdk_gc_new( GTK_PIZZA(m_wxwindow
)->bin_window
);
3537 gdk_gc_set_fill( g_eraseGC
, GDK_SOLID
);
3539 gdk_gc_set_foreground( g_eraseGC
, m_backgroundColour
.GetColor() );
3541 wxRegionIterator
upd( m_clearRegion
);
3544 gdk_draw_rectangle( GTK_PIZZA(m_wxwindow
)->bin_window
, g_eraseGC
, 1,
3545 upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
3549 m_clearRegion
.Clear();
3552 wxNcPaintEvent
nc_paint_event( GetId() );
3553 nc_paint_event
.SetEventObject( this );
3554 GetEventHandler()->ProcessEvent( nc_paint_event
);
3556 wxPaintEvent
paint_event( GetId() );
3557 paint_event
.SetEventObject( this );
3558 GetEventHandler()->ProcessEvent( paint_event
);
3560 m_clipPaintRegion
= FALSE
;
3562 #ifndef __WXUNIVERSAL__
3564 // The following code will result in all window-less widgets
3565 // being redrawn because the wxWindows class is allowed to
3566 // paint over the window-less widgets.
3568 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
3570 GList
*children
= pizza
->children
;
3573 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
3574 children
= children
->next
;
3576 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
3577 GTK_WIDGET_DRAWABLE (child
->widget
))
3579 // Get intersection of widget area and update region
3580 wxRegion
region( m_updateRegion
);
3582 GdkEventExpose gdk_event
;
3583 gdk_event
.type
= GDK_EXPOSE
;
3584 gdk_event
.window
= pizza
->bin_window
;
3585 gdk_event
.count
= 0;
3587 wxRegionIterator
upd( m_updateRegion
);
3591 rect
.x
= upd
.GetX();
3592 rect
.y
= upd
.GetY();
3593 rect
.width
= upd
.GetWidth();
3594 rect
.height
= upd
.GetHeight();
3596 if (gtk_widget_intersect (child
->widget
, &rect
, &gdk_event
.area
))
3598 gtk_widget_event (child
->widget
, (GdkEvent
*) &gdk_event
);
3608 m_updateRegion
.Clear();
3611 void wxWindowGTK::Clear()
3613 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3615 if (m_wxwindow
&& m_wxwindow
->window
)
3617 m_clearRegion
.Clear();
3618 wxSize
size( GetClientSize() );
3619 m_clearRegion
.Union( 0,0,size
.x
,size
.y
);
3621 // Better do this in idle?
3627 void wxWindowGTK::DoSetToolTip( wxToolTip
*tip
)
3629 wxWindowBase::DoSetToolTip(tip
);
3632 m_tooltip
->Apply( (wxWindow
*)this );
3635 void wxWindowGTK::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3637 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3639 #endif // wxUSE_TOOLTIPS
3641 void wxWindowGTK::GtkSetBackgroundColour( const wxColour
&colour
)
3643 GdkWindow
*window
= (GdkWindow
*) NULL
;
3645 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3647 window
= GetConnectWidget()->window
;
3651 // We need the pixel value e.g. for background clearing.
3652 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( 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() );
3666 bool wxWindowGTK::SetBackgroundColour( const wxColour
&colour
)
3668 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3670 if (!wxWindowBase::SetBackgroundColour(colour
))
3673 GdkWindow
*window
= (GdkWindow
*) NULL
;
3675 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3677 window
= GetConnectWidget()->window
;
3681 // indicate that a new style has been set
3682 // but it couldn't get applied as the
3683 // widget hasn't been realized yet.
3684 m_delayedBackgroundColour
= TRUE
;
3689 GtkSetBackgroundColour( colour
);
3695 void wxWindowGTK::GtkSetForegroundColour( const wxColour
&colour
)
3697 GdkWindow
*window
= (GdkWindow
*) NULL
;
3699 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3701 window
= GetConnectWidget()->window
;
3708 bool wxWindowGTK::SetForegroundColour( const wxColour
&colour
)
3710 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3712 if (!wxWindowBase::SetForegroundColour(colour
))
3714 // don't leave if the GTK widget has just
3716 if (!m_delayedForegroundColour
) return FALSE
;
3719 GdkWindow
*window
= (GdkWindow
*) NULL
;
3721 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3723 window
= GetConnectWidget()->window
;
3727 // indicate that a new style has been set
3728 // but it couldn't get applied as the
3729 // widget hasn't been realized yet.
3730 m_delayedForegroundColour
= TRUE
;
3734 GtkSetForegroundColour( colour
);
3740 GtkStyle
*wxWindowGTK::GetWidgetStyle()
3744 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3746 // FIXME: no more klass in 2.0
3748 remake
->klass
= m_widgetStyle
->klass
;
3751 gtk_style_unref( m_widgetStyle
);
3752 m_widgetStyle
= remake
;
3756 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3759 def
= gtk_widget_get_default_style();
3761 m_widgetStyle
= gtk_style_copy( def
);
3763 // FIXME: no more klass in 2.0
3765 m_widgetStyle
->klass
= def
->klass
;
3769 return m_widgetStyle
;
3772 void wxWindowGTK::SetWidgetStyle()
3774 #if DISABLE_STYLE_IF_BROKEN_THEME
3775 if (m_widget
->style
->engine_data
)
3777 static bool s_warningPrinted
= FALSE
;
3778 if (!s_warningPrinted
)
3780 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3781 s_warningPrinted
= TRUE
;
3783 m_widgetStyle
= m_widget
->style
;
3788 GtkStyle
*style
= GetWidgetStyle();
3790 if (m_font
!= wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT
))
3792 SET_STYLE_FONT(style
, m_font
.GetInternalFont( 1.0 ));
3795 if (m_foregroundColour
.Ok())
3797 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3798 if (m_foregroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT
))
3800 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3801 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3802 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3806 // Try to restore the gtk default style. This is still a little
3807 // oversimplified for what is probably really needed here for controls
3808 // other than buttons, but is better than not being able to (re)set a
3809 // control's foreground colour to *wxBLACK -- RL
3810 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3813 def
= gtk_widget_get_default_style();
3815 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3816 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3817 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3821 if (m_backgroundColour
.Ok())
3823 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3824 if (m_backgroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
))
3826 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3827 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3828 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3829 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3830 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3831 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3832 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3833 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3837 // Try to restore the gtk default style. This is still a little
3838 // oversimplified for what is probably really needed here for controls
3839 // other than buttons, but is better than not being able to (re)set a
3840 // control's background colour to default grey and means resetting a
3841 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3843 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3846 def
= gtk_widget_get_default_style();
3848 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3849 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3850 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3851 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3852 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3853 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3854 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3855 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3860 void wxWindowGTK::ApplyWidgetStyle()
3864 //-----------------------------------------------------------------------------
3865 // Pop-up menu stuff
3866 //-----------------------------------------------------------------------------
3868 #if wxUSE_MENUS_NATIVE
3871 void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3873 *is_waiting
= FALSE
;
3876 static void SetInvokingWindow( wxMenu
*menu
, wxWindowGTK
*win
)
3878 menu
->SetInvokingWindow( win
);
3879 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3882 wxMenuItem
*menuitem
= node
->GetData();
3883 if (menuitem
->IsSubMenu())
3885 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3888 node
= node
->GetNext();
3892 // used to pass the coordinates from wxWindowGTK::DoPopupMenu() to
3893 // wxPopupMenuPositionCallback()
3895 // should be safe even in the MT case as the user can hardly popup 2 menus
3896 // simultaneously, can he?
3897 static gint gs_pop_x
= 0;
3898 static gint gs_pop_y
= 0;
3900 extern "C" void wxPopupMenuPositionCallback( GtkMenu
*menu
,
3903 gboolean
* WXUNUSED(whatever
),
3905 gpointer
WXUNUSED(user_data
) )
3907 // ensure that the menu appears entirely on screen
3909 gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
);
3911 wxSize sizeScreen
= wxGetDisplaySize();
3913 gint xmax
= sizeScreen
.x
- req
.width
,
3914 ymax
= sizeScreen
.y
- req
.height
;
3916 *x
= gs_pop_x
< xmax
? gs_pop_x
: xmax
;
3917 *y
= gs_pop_y
< ymax
? gs_pop_y
: ymax
;
3920 bool wxWindowGTK::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3922 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3924 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3926 SetInvokingWindow( menu
, this );
3932 ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3934 bool is_waiting
= TRUE
;
3936 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
),
3938 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
),
3939 (gpointer
)&is_waiting
);
3942 GTK_MENU(menu
->m_menu
),
3943 (GtkWidget
*) NULL
, // parent menu shell
3944 (GtkWidget
*) NULL
, // parent menu item
3945 wxPopupMenuPositionCallback
, // function to position it
3946 NULL
, // client data
3947 0, // button used to activate it
3948 gs_timeLastClick
// the time of activation
3953 while (gtk_events_pending())
3954 gtk_main_iteration();
3960 #endif // wxUSE_MENUS_NATIVE
3962 #if wxUSE_DRAG_AND_DROP
3964 void wxWindowGTK::SetDropTarget( wxDropTarget
*dropTarget
)
3966 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3968 GtkWidget
*dnd_widget
= GetConnectWidget();
3970 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3972 if (m_dropTarget
) delete m_dropTarget
;
3973 m_dropTarget
= dropTarget
;
3975 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3978 #endif // wxUSE_DRAG_AND_DROP
3980 GtkWidget
* wxWindowGTK::GetConnectWidget()
3982 GtkWidget
*connect_widget
= m_widget
;
3983 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3985 return connect_widget
;
3988 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow
*window
)
3991 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3993 return (window
== m_widget
->window
);
3996 bool wxWindowGTK::SetFont( const wxFont
&font
)
3998 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
4000 if (!wxWindowBase::SetFont(font
))
4005 wxColour sysbg
= wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE
);
4006 if ( sysbg
== m_backgroundColour
)
4008 m_backgroundColour
= wxNullColour
;
4010 m_backgroundColour
= sysbg
;
4020 void wxWindowGTK::DoCaptureMouse()
4022 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4024 GdkWindow
*window
= (GdkWindow
*) NULL
;
4026 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
4028 window
= GetConnectWidget()->window
;
4030 wxCHECK_RET( window
, _T("CaptureMouse() failed") );
4032 wxCursor
* cursor
= & m_cursor
;
4034 cursor
= wxSTANDARD_CURSOR
;
4036 gdk_pointer_grab( window
, FALSE
,
4038 (GDK_BUTTON_PRESS_MASK
|
4039 GDK_BUTTON_RELEASE_MASK
|
4040 GDK_POINTER_MOTION_HINT_MASK
|
4041 GDK_POINTER_MOTION_MASK
),
4043 cursor
->GetCursor(),
4044 (guint32
)GDK_CURRENT_TIME
);
4045 g_captureWindow
= this;
4046 g_captureWindowHasMouse
= TRUE
;
4049 void wxWindowGTK::DoReleaseMouse()
4051 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4053 wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") );
4055 g_captureWindow
= (wxWindowGTK
*) NULL
;
4057 GdkWindow
*window
= (GdkWindow
*) NULL
;
4059 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
4061 window
= GetConnectWidget()->window
;
4066 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
4070 wxWindow
*wxWindowBase::GetCapture()
4072 return (wxWindow
*)g_captureWindow
;
4075 bool wxWindowGTK::IsRetained() const
4080 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
,
4081 int range
, bool refresh
)
4083 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4085 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4087 m_hasScrolling
= TRUE
;
4089 if (orient
== wxHORIZONTAL
)
4091 float fpos
= (float)pos
;
4092 float frange
= (float)range
;
4093 float fthumb
= (float)thumbVisible
;
4094 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
4095 if (fpos
< 0.0) fpos
= 0.0;
4097 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
4098 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
4100 SetScrollPos( orient
, pos
, refresh
);
4104 m_oldHorizontalPos
= fpos
;
4106 m_hAdjust
->lower
= 0.0;
4107 m_hAdjust
->upper
= frange
;
4108 m_hAdjust
->value
= fpos
;
4109 m_hAdjust
->step_increment
= 1.0;
4110 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
4111 m_hAdjust
->page_size
= fthumb
;
4115 float fpos
= (float)pos
;
4116 float frange
= (float)range
;
4117 float fthumb
= (float)thumbVisible
;
4118 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
4119 if (fpos
< 0.0) fpos
= 0.0;
4121 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
4122 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
4124 SetScrollPos( orient
, pos
, refresh
);
4128 m_oldVerticalPos
= fpos
;
4130 m_vAdjust
->lower
= 0.0;
4131 m_vAdjust
->upper
= frange
;
4132 m_vAdjust
->value
= fpos
;
4133 m_vAdjust
->step_increment
= 1.0;
4134 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
4135 m_vAdjust
->page_size
= fthumb
;
4138 if (orient
== wxHORIZONTAL
)
4139 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
4141 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
4144 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
4146 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4148 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4150 if (orient
== wxHORIZONTAL
)
4152 float fpos
= (float)pos
;
4153 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
4154 if (fpos
< 0.0) fpos
= 0.0;
4155 m_oldHorizontalPos
= fpos
;
4157 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
4158 m_hAdjust
->value
= fpos
;
4162 float fpos
= (float)pos
;
4163 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
4164 if (fpos
< 0.0) fpos
= 0.0;
4165 m_oldVerticalPos
= fpos
;
4167 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
4168 m_vAdjust
->value
= fpos
;
4171 if (m_wxwindow
->window
)
4173 if (orient
== wxHORIZONTAL
)
4175 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
4176 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
4178 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
4180 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
4181 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
4185 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
4186 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4188 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
4190 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
4191 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4196 int wxWindowGTK::GetScrollThumb( int orient
) const
4198 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4200 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4202 if (orient
== wxHORIZONTAL
)
4203 return (int)(m_hAdjust
->page_size
+0.5);
4205 return (int)(m_vAdjust
->page_size
+0.5);
4208 int wxWindowGTK::GetScrollPos( int orient
) const
4210 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4212 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4214 if (orient
== wxHORIZONTAL
)
4215 return (int)(m_hAdjust
->value
+0.5);
4217 return (int)(m_vAdjust
->value
+0.5);
4220 int wxWindowGTK::GetScrollRange( int orient
) const
4222 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4224 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4226 if (orient
== wxHORIZONTAL
)
4227 return (int)(m_hAdjust
->upper
+0.5);
4229 return (int)(m_vAdjust
->upper
+0.5);
4232 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
4234 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4236 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4238 // No scrolling requested.
4239 if ((dx
== 0) && (dy
== 0)) return;
4242 if (!m_updateRegion
.IsEmpty())
4244 m_updateRegion
.Offset( dx
, dy
);
4248 GetClientSize( &cw
, &ch
);
4249 m_updateRegion
.Intersect( 0, 0, cw
, ch
);
4252 if (!m_clearRegion
.IsEmpty())
4254 m_clearRegion
.Offset( dx
, dy
);
4258 GetClientSize( &cw
, &ch
);
4259 m_clearRegion
.Intersect( 0, 0, cw
, ch
);
4262 m_clipPaintRegion
= TRUE
;
4264 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
4266 m_clipPaintRegion
= FALSE
;
4269 gdk_window_scroll( GTK_PIZZA(m_wxwindow
)->bin_window
, dx
, dy
);
4271 GTK_PIZZA(m_wxwindow
)->xoffset
+= dx
;
4272 GTK_PIZZA(m_wxwindow
)->yoffset
+= dy
;
4279 // Find the wxWindow at the current mouse position, also returning the mouse
4281 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
4283 pt
= wxGetMousePosition();
4284 wxWindow
* found
= wxFindWindowAtPoint(pt
);
4288 // Get the current mouse position.
4289 wxPoint
wxGetMousePosition()
4291 /* This crashes when used within wxHelpContext,
4292 so we have to use the X-specific implementation below.
4294 GdkModifierType *mask;
4295 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
4297 return wxPoint(x, y);
4301 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
4303 return wxPoint(-999, -999);
4305 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
4306 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
4307 Window rootReturn
, childReturn
;
4308 int rootX
, rootY
, winX
, winY
;
4309 unsigned int maskReturn
;
4311 XQueryPointer (display
,
4315 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
4316 return wxPoint(rootX
, rootY
);
4320 // ----------------------------------------------------------------------------
4322 // ----------------------------------------------------------------------------
4324 class wxWinModule
: public wxModule
4331 DECLARE_DYNAMIC_CLASS(wxWinModule
)
4334 IMPLEMENT_DYNAMIC_CLASS(wxWinModule
, wxModule
)
4336 bool wxWinModule::OnInit()
4338 // g_eraseGC = gdk_gc_new( GDK_ROOT_PARENT() );
4339 // gdk_gc_set_fill( g_eraseGC, GDK_SOLID );
4344 void wxWinModule::OnExit()
4347 gdk_gc_unref( g_eraseGC
);