1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/window.cpp
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #define XWarpPointer XWARPPOINTER
20 #include "wx/window.h"
21 #include "wx/dcclient.h"
24 #include "wx/layout.h"
26 #include "wx/dialog.h"
27 #include "wx/msgdlg.h"
28 #include "wx/module.h"
30 #if wxUSE_DRAG_AND_DROP
35 #include "wx/tooltip.h"
43 #include "wx/textctrl.h"
47 #include "wx/statusbr.h"
49 #include "wx/settings.h"
53 #include "wx/thread.h"
58 #include "wx/gtk/private.h"
59 #include <gdk/gdkprivate.h>
60 #include <gdk/gdkkeysyms.h>
64 #include <gtk/gtkprivate.h>
66 #include "wx/gtk/win_gtk.h"
69 #define SET_CONTAINER_FOCUS(w, d) gtk_widget_child_focus((w), (d))
71 #define SET_CONTAINER_FOCUS(w, d) gtk_container_focus(GTK_CONTAINER(w), (d))
81 extern GtkContainerClass
*pizza_parent_class
;
84 //-----------------------------------------------------------------------------
85 // documentation on internals
86 //-----------------------------------------------------------------------------
89 I have been asked several times about writing some documentation about
90 the GTK port of wxWindows, especially its internal structures. Obviously,
91 you cannot understand wxGTK without knowing a little about the GTK, but
92 some more information about what the wxWindow, which is the base class
93 for all other window classes, does seems required as well.
97 What does wxWindow do? It contains the common interface for the following
98 jobs of its descendants:
100 1) Define the rudimentary behaviour common to all window classes, such as
101 resizing, intercepting user input (so as to make it possible to use these
102 events for special purposes in a derived class), window names etc.
104 2) Provide the possibility to contain and manage children, if the derived
105 class is allowed to contain children, which holds true for those window
106 classes which do not display a native GTK widget. To name them, these
107 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
108 work classes are a special case and are handled a bit differently from
109 the rest. The same holds true for the wxNotebook class.
111 3) Provide the possibility to draw into a client area of a window. This,
112 too, only holds true for classes that do not display a native GTK widget
115 4) Provide the entire mechanism for scrolling widgets. This actual inter-
116 face for this is usually in wxScrolledWindow, but the GTK implementation
119 5) A multitude of helper or extra methods for special purposes, such as
120 Drag'n'Drop, managing validators etc.
122 6) Display a border (sunken, raised, simple or none).
124 Normally one might expect, that one wxWindows window would always correspond
125 to one GTK widget. Under GTK, there is no such allround widget that has all
126 the functionality. Moreover, the GTK defines a client area as a different
127 widget from the actual widget you are handling. Last but not least some
128 special classes (e.g. wxFrame) handle different categories of widgets and
129 still have the possibility to draw something in the client area.
130 It was therefore required to write a special purpose GTK widget, that would
131 represent a client area in the sense of wxWindows capable to do the jobs
132 2), 3) and 4). I have written this class and it resides in win_gtk.c of
135 All windows must have a widget, with which they interact with other under-
136 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
137 thw wxWindow class has a member variable called m_widget which holds a
138 pointer to this widget. When the window class represents a GTK native widget,
139 this is (in most cases) the only GTK widget the class manages. E.g. the
140 wxStatitText class handles only a GtkLabel widget a pointer to which you
141 can find in m_widget (defined in wxWindow)
143 When the class has a client area for drawing into and for containing children
144 it has to handle the client area widget (of the type GtkPizza, defined in
145 win_gtk.c), but there could be any number of widgets, handled by a class
146 The common rule for all windows is only, that the widget that interacts with
147 the rest of GTK must be referenced in m_widget and all other widgets must be
148 children of this widget on the GTK level. The top-most widget, which also
149 represents the client area, must be in the m_wxwindow field and must be of
152 As I said, the window classes that display a GTK native widget only have
153 one widget, so in the case of e.g. the wxButton class m_widget holds a
154 pointer to a GtkButton widget. But windows with client areas (for drawing
155 and children) have a m_widget field that is a pointer to a GtkScrolled-
156 Window and a m_wxwindow field that is pointer to a GtkPizza and this
157 one is (in the GTK sense) a child of the GtkScrolledWindow.
159 If the m_wxwindow field is set, then all input to this widget is inter-
160 cepted and sent to the wxWindows class. If not, all input to the widget
161 that gets pointed to by m_widget gets intercepted and sent to the class.
165 The design of scrolling in wxWindows is markedly different from that offered
166 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
167 clicking on a scrollbar belonging to scrolled window will inevitably move
168 the window. In wxWindows, the scrollbar will only emit an event, send this
169 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
170 which actually moves the window and its subchildren. Note that GtkPizza
171 memorizes how much it has been scrolled but that wxWindows forgets this
172 so that the two coordinates systems have to be kept in synch. This is done
173 in various places using the pizza->xoffset and pizza->yoffset values.
177 Singularily the most broken code in GTK is the code that is supposes to
178 inform subwindows (child windows) about new positions. Very often, duplicate
179 events are sent without changes in size or position, equally often no
180 events are sent at all (All this is due to a bug in the GtkContainer code
181 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
182 GTK's own system and it simply waits for size events for toplevel windows
183 and then iterates down the respective size events to all window. This has
184 the disadvantage, that windows might get size events before the GTK widget
185 actually has the reported size. This doesn't normally pose any problem, but
186 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
187 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
188 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
189 window that is used for OpenGl output really has that size (as reported by
194 If someone at some point of time feels the immense desire to have a look at,
195 change or attempt to optimse the Refresh() logic, this person will need an
196 intimate understanding of what a "draw" and what an "expose" events are and
197 what there are used for, in particular when used in connection with GTK's
198 own windowless widgets. Beware.
202 Cursors, too, have been a constant source of pleasure. The main difficulty
203 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
204 for the parent. To prevent this from doing too much harm, I use idle time
205 to set the cursor over and over again, starting from the toplevel windows
206 and ending with the youngest generation (speaking of parent and child windows).
207 Also don't forget that cursors (like much else) are connected to GdkWindows,
208 not GtkWidgets and that the "window" field of a GtkWidget might very well
209 point to the GdkWindow of the parent widget (-> "window less widget") and
210 that the two obviously have very different meanings.
214 //-----------------------------------------------------------------------------
216 //-----------------------------------------------------------------------------
218 extern wxList wxPendingDelete
;
219 extern bool g_blockEventsOnDrag
;
220 extern bool g_blockEventsOnScroll
;
221 extern wxCursor g_globalCursor
;
223 static GdkGC
*g_eraseGC
= NULL
;
225 // mouse capture state: the window which has it and if the mouse is currently
227 static wxWindowGTK
*g_captureWindow
= (wxWindowGTK
*) NULL
;
228 static bool g_captureWindowHasMouse
= FALSE
;
230 /* extern */ wxWindowGTK
*g_focusWindow
= (wxWindowGTK
*) NULL
;
232 // the last window which had the focus - this is normally never NULL (except
233 // if we never had focus at all) as even when g_focusWindow is NULL it still
234 // keeps its previous value
235 static wxWindowGTK
*g_focusWindowLast
= (wxWindowGTK
*) NULL
;
237 // the frame that is currently active (i.e. its child has focus). It is
238 // used to generate wxActivateEvents
239 static wxWindowGTK
*g_activeFrame
= (wxWindowGTK
*) NULL
;
240 static bool g_activeFrameLostFocus
= FALSE
;
242 // If a window get the focus set but has not been realized
243 // yet, defer setting the focus to idle time.
244 wxWindowGTK
*g_delayedFocus
= (wxWindowGTK
*) NULL
;
246 // if we detect that the app has got/lost the focus, we set this variable to
247 // either TRUE or FALSE and an activate event will be sent during the next
248 // OnIdle() call and it is reset to -1: this value means that we shouldn't
249 // send any activate events at all
250 static int g_sendActivateEvent
= -1;
252 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
253 the last click here */
254 static guint32 gs_timeLastClick
= 0;
256 extern bool g_mainThreadLocked
;
258 //-----------------------------------------------------------------------------
260 //-----------------------------------------------------------------------------
263 #define DISABLE_STYLE_IF_BROKEN_THEME 1
269 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
271 # define DEBUG_MAIN_THREAD
274 #define DEBUG_MAIN_THREAD
277 //-----------------------------------------------------------------------------
278 // missing gdk functions
279 //-----------------------------------------------------------------------------
282 gdk_window_warp_pointer (GdkWindow
*window
,
287 GdkWindowPrivate
*priv
;
291 window
= GDK_ROOT_PARENT();
294 if (!GDK_WINDOW_DESTROYED(window
))
296 XWarpPointer (GDK_WINDOW_XDISPLAY(window
),
297 None
, /* not source window -> move from anywhere */
298 GDK_WINDOW_XID(window
), /* dest window */
299 0, 0, 0, 0, /* not source window -> move from anywhere */
303 priv
= (GdkWindowPrivate
*) window
;
305 if (!priv
->destroyed
)
307 XWarpPointer (priv
->xdisplay
,
308 None
, /* not source window -> move from anywhere */
309 priv
->xwindow
, /* dest window */
310 0, 0, 0, 0, /* not source window -> move from anywhere */
316 //-----------------------------------------------------------------------------
318 //-----------------------------------------------------------------------------
320 extern void wxapp_install_idle_handler();
321 extern bool g_isIdle
;
323 //-----------------------------------------------------------------------------
324 // local code (see below)
325 //-----------------------------------------------------------------------------
327 // returns the child of win which currently has focus or NULL if not found
329 // Note: can't be static, needed by textctrl.cpp.
330 wxWindow
*wxFindFocusedChild(wxWindowGTK
*win
)
332 wxWindow
*winFocus
= wxWindowGTK::FindFocus();
334 return (wxWindow
*)NULL
;
336 if ( winFocus
== win
)
337 return (wxWindow
*)win
;
339 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
341 node
= node
->GetNext() )
343 wxWindow
*child
= wxFindFocusedChild(node
->GetData());
348 return (wxWindow
*)NULL
;
351 static void draw_frame( GtkWidget
*widget
, wxWindowGTK
*win
)
353 // wxUniversal widgets draw the borders and scrollbars themselves
354 #ifndef __WXUNIVERSAL__
361 if (win
->m_hasScrolling
)
363 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
365 GtkRequisition vscroll_req
;
366 vscroll_req
.width
= 2;
367 vscroll_req
.height
= 2;
368 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
369 (scroll_window
->vscrollbar
, &vscroll_req
);
371 GtkRequisition hscroll_req
;
372 hscroll_req
.width
= 2;
373 hscroll_req
.height
= 2;
374 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
375 (scroll_window
->hscrollbar
, &hscroll_req
);
377 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) );
379 if (scroll_window
->vscrollbar_visible
)
381 dw
+= vscroll_req
.width
;
382 dw
+= scroll_class
->scrollbar_spacing
;
385 if (scroll_window
->hscrollbar_visible
)
387 dh
+= hscroll_req
.height
;
388 dh
+= scroll_class
->scrollbar_spacing
;
394 if (GTK_WIDGET_NO_WINDOW (widget
))
396 dx
+= widget
->allocation
.x
;
397 dy
+= widget
->allocation
.y
;
400 if (win
->HasFlag(wxRAISED_BORDER
))
402 gtk_draw_shadow( widget
->style
,
407 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
411 if (win
->HasFlag(wxSUNKEN_BORDER
))
413 gtk_draw_shadow( widget
->style
,
418 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
422 if (win
->HasFlag(wxSIMPLE_BORDER
))
425 gc
= gdk_gc_new( widget
->window
);
426 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
427 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
429 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
433 #endif // __WXUNIVERSAL__
436 //-----------------------------------------------------------------------------
437 // "expose_event" of m_widget
438 //-----------------------------------------------------------------------------
440 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindowGTK
*win
)
442 if (gdk_event
->count
> 0) return FALSE
;
444 draw_frame( widget
, win
);
448 (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
);
454 //-----------------------------------------------------------------------------
455 // "draw" of m_widget
456 //-----------------------------------------------------------------------------
460 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindowGTK
*win
)
462 draw_frame( widget
, win
);
467 //-----------------------------------------------------------------------------
468 // "size_request" of m_widget
469 //-----------------------------------------------------------------------------
471 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
474 win
->GetSize( &w
, &h
);
478 requisition
->height
= h
;
479 requisition
->width
= w
;
482 //-----------------------------------------------------------------------------
483 // "expose_event" of m_wxwindow
484 //-----------------------------------------------------------------------------
486 static int gtk_window_expose_callback( GtkWidget
*widget
,
487 GdkEventExpose
*gdk_event
,
493 wxapp_install_idle_handler();
498 wxPrintf( wxT("OnExpose from ") );
499 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
500 wxPrintf( win
->GetClassInfo()->GetClassName() );
501 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event
->area
.x
,
502 (int)gdk_event
->area
.y
,
503 (int)gdk_event
->area
.width
,
504 (int)gdk_event
->area
.height
);
508 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
510 gdk_event
->area
.width
,
511 gdk_event
->area
.height
);
512 win
->m_clearRegion
.Union( gdk_event
->area
.x
,
514 gdk_event
->area
.width
,
515 gdk_event
->area
.height
);
517 // Actual redrawing takes place in idle time.
522 (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
);
529 //-----------------------------------------------------------------------------
530 // "event" of m_wxwindow
531 //-----------------------------------------------------------------------------
533 // GTK thinks it is clever and filters out a certain amount of "unneeded"
534 // expose events. We need them, of course, so we override the main event
535 // procedure in GtkWidget by giving our own handler for all system events.
536 // There, we look for expose events ourselves whereas all other events are
539 gint
gtk_window_event_event_callback( GtkWidget
*widget
,
540 GdkEventExpose
*event
,
543 if (event
->type
== GDK_EXPOSE
)
545 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
552 //-----------------------------------------------------------------------------
553 // "draw" of m_wxwindow
554 //-----------------------------------------------------------------------------
558 // This callback is a complete replacement of the gtk_pizza_draw() function,
559 // which is disabled.
561 static void gtk_window_draw_callback( GtkWidget
*widget
,
568 wxapp_install_idle_handler();
570 // The wxNO_FULL_REPAINT_ON_RESIZE flag only works if
571 // there are no child windows.
572 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
573 (win
->GetChildren().GetCount() == 0))
581 wxPrintf( wxT("OnDraw from ") );
582 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
583 wxPrintf( win
->GetClassInfo()->GetClassName() );
584 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect
->x
,
591 #ifndef __WXUNIVERSAL__
592 GtkPizza
*pizza
= GTK_PIZZA (widget
);
594 if (win
->GetThemeEnabled())
596 wxWindow
*parent
= win
->GetParent();
597 while (parent
&& !parent
->IsTopLevel())
598 parent
= parent
->GetParent();
602 gtk_paint_flat_box (parent
->m_widget
->style
,
613 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
614 (pizza
->clear_on_draw
))
616 gdk_window_clear_area( pizza
->bin_window
,
617 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
621 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
623 // Actual redrawing takes place in idle time.
627 #ifndef __WXUNIVERSAL__
628 // Redraw child widgets
629 GList
*children
= pizza
->children
;
632 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
633 children
= children
->next
;
635 GdkRectangle child_area
;
636 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
638 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
646 //-----------------------------------------------------------------------------
647 // "key_press_event" from any window
648 //-----------------------------------------------------------------------------
650 // set WXTRACE to this to see the key event codes on the console
651 #define TRACE_KEYS _T("keyevent")
653 // translates an X key symbol to WXK_XXX value
655 // if isChar is true it means that the value returned will be used for EVT_CHAR
656 // event and then we choose the logical WXK_XXX, i.e. '/' for GDK_KP_Divide,
657 // for example, while if it is false it means that the value is going to be
658 // used for KEY_DOWN/UP events and then we translate GDK_KP_Divide to
660 static long wxTranslateKeySymToWXKey(KeySym keysym
, bool isChar
)
666 // Shift, Control and Alt don't generate the CHAR events at all
669 key_code
= isChar
? 0 : WXK_SHIFT
;
673 key_code
= isChar
? 0 : WXK_CONTROL
;
681 key_code
= isChar
? 0 : WXK_ALT
;
684 // neither do the toggle modifies
685 case GDK_Scroll_Lock
:
686 key_code
= isChar
? 0 : WXK_SCROLL
;
690 key_code
= isChar
? 0 : WXK_CAPITAL
;
694 key_code
= isChar
? 0 : WXK_NUMLOCK
;
698 // various other special keys
711 case GDK_ISO_Left_Tab
:
718 key_code
= WXK_RETURN
;
722 key_code
= WXK_CLEAR
;
726 key_code
= WXK_PAUSE
;
730 key_code
= WXK_SELECT
;
734 key_code
= WXK_PRINT
;
738 key_code
= WXK_EXECUTE
;
742 key_code
= WXK_ESCAPE
;
745 // cursor and other extended keyboard keys
747 key_code
= WXK_DELETE
;
763 key_code
= WXK_RIGHT
;
770 case GDK_Prior
: // == GDK_Page_Up
771 key_code
= WXK_PRIOR
;
774 case GDK_Next
: // == GDK_Page_Down
787 key_code
= WXK_INSERT
;
802 key_code
= (isChar
? '0' : WXK_NUMPAD0
) + keysym
- GDK_KP_0
;
806 key_code
= isChar
? ' ' : WXK_NUMPAD_SPACE
;
810 key_code
= isChar
? WXK_TAB
: WXK_NUMPAD_TAB
;
814 key_code
= isChar
? WXK_RETURN
: WXK_NUMPAD_ENTER
;
818 key_code
= isChar
? WXK_F1
: WXK_NUMPAD_F1
;
822 key_code
= isChar
? WXK_F2
: WXK_NUMPAD_F2
;
826 key_code
= isChar
? WXK_F3
: WXK_NUMPAD_F3
;
830 key_code
= isChar
? WXK_F4
: WXK_NUMPAD_F4
;
834 key_code
= isChar
? WXK_HOME
: WXK_NUMPAD_HOME
;
838 key_code
= isChar
? WXK_LEFT
: WXK_NUMPAD_LEFT
;
842 key_code
= isChar
? WXK_UP
: WXK_NUMPAD_UP
;
846 key_code
= isChar
? WXK_RIGHT
: WXK_NUMPAD_RIGHT
;
850 key_code
= isChar
? WXK_DOWN
: WXK_NUMPAD_DOWN
;
853 case GDK_KP_Prior
: // == GDK_KP_Page_Up
854 key_code
= isChar
? WXK_PRIOR
: WXK_NUMPAD_PRIOR
;
857 case GDK_KP_Next
: // == GDK_KP_Page_Down
858 key_code
= isChar
? WXK_NEXT
: WXK_NUMPAD_NEXT
;
862 key_code
= isChar
? WXK_END
: WXK_NUMPAD_END
;
866 key_code
= isChar
? WXK_HOME
: WXK_NUMPAD_BEGIN
;
870 key_code
= isChar
? WXK_INSERT
: WXK_NUMPAD_INSERT
;
874 key_code
= isChar
? WXK_DELETE
: WXK_NUMPAD_DELETE
;
878 key_code
= isChar
? '=' : WXK_NUMPAD_EQUAL
;
881 case GDK_KP_Multiply
:
882 key_code
= isChar
? '*' : WXK_NUMPAD_MULTIPLY
;
886 key_code
= isChar
? '+' : WXK_NUMPAD_ADD
;
889 case GDK_KP_Separator
:
890 // FIXME: what is this?
891 key_code
= isChar
? '.' : WXK_NUMPAD_SEPARATOR
;
894 case GDK_KP_Subtract
:
895 key_code
= isChar
? '-' : WXK_NUMPAD_SUBTRACT
;
899 key_code
= isChar
? '.' : WXK_NUMPAD_DECIMAL
;
903 key_code
= isChar
? '/' : WXK_NUMPAD_DIVIDE
;
920 key_code
= WXK_F1
+ keysym
- GDK_F1
;
930 static inline bool wxIsAsciiKeysym(KeySym ks
)
936 wxTranslateGTKKeyEventToWx(wxKeyEvent
& event
,
938 GdkEventKey
*gdk_event
)
940 // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string
941 // but only event->keyval which is quite useless to us, so remember
942 // the last character from GDK_KEY_PRESS and reuse it as last resort
944 // NB: should be MT-safe as we're always called from the main thread only
949 } s_lastKeyPress
= { 0, 0 };
951 KeySym keysym
= gdk_event
->keyval
;
953 wxLogTrace(TRACE_KEYS
, _T("Key %s event: keysym = %d"),
954 event
.GetEventType() == wxEVT_KEY_UP
? _T("release")
958 long key_code
= wxTranslateKeySymToWXKey(keysym
, FALSE
/* !isChar */);
962 // do we have the translation or is it a plain ASCII character?
963 if ( (gdk_event
->length
== 1) || wxIsAsciiKeysym(keysym
) )
965 // we should use keysym if it is ASCII as X does some translations
966 // like "I pressed while Control is down" => "Ctrl-I" == "TAB"
967 // which we don't want here (but which we do use for OnChar())
968 if ( !wxIsAsciiKeysym(keysym
) )
970 keysym
= (KeySym
)gdk_event
->string
[0];
973 // we want to always get the same key code when the same key is
974 // pressed regardless of the state of the modifies, i.e. on a
975 // standard US keyboard pressing '5' or '%' ('5' key with
976 // Shift) should result in the same key code in OnKeyDown():
977 // '5' (although OnChar() will get either '5' or '%').
979 // to do it we first translate keysym to keycode (== scan code)
980 // and then back but always using the lower register
981 Display
*dpy
= (Display
*)wxGetDisplay();
982 KeyCode keycode
= XKeysymToKeycode(dpy
, keysym
);
984 wxLogTrace(TRACE_KEYS
, _T("\t-> keycode %d"), keycode
);
986 KeySym keysymNormalized
= XKeycodeToKeysym(dpy
, keycode
, 0);
988 // use the normalized, i.e. lower register, keysym if we've
990 key_code
= keysymNormalized
? keysymNormalized
: keysym
;
992 // as explained above, we want to have lower register key codes
993 // normally but for the letter keys we want to have the upper ones
995 // NB: don't use XConvertCase() here, we want to do it for letters
997 key_code
= toupper(key_code
);
999 else // non ASCII key, what to do?
1001 // by default, ignore it
1004 // but if we have cached information from the last KEY_PRESS
1005 if ( gdk_event
->type
== GDK_KEY_RELEASE
)
1008 if ( keysym
== s_lastKeyPress
.keysym
)
1010 key_code
= s_lastKeyPress
.keycode
;
1015 if ( gdk_event
->type
== GDK_KEY_PRESS
)
1017 // remember it to be reused for KEY_UP event later
1018 s_lastKeyPress
.keysym
= keysym
;
1019 s_lastKeyPress
.keycode
= key_code
;
1023 wxLogTrace(TRACE_KEYS
, _T("\t-> wxKeyCode %d"), key_code
);
1025 // sending unknown key events doesn't really make sense
1029 // now fill all the other fields
1032 GdkModifierType state
;
1033 if (gdk_event
->window
)
1034 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1036 event
.SetTimestamp( gdk_event
->time
);
1037 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
) != 0;
1038 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
) != 0;
1039 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
) != 0;
1040 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
) != 0;
1041 event
.m_keyCode
= key_code
;
1042 event
.m_scanCode
= gdk_event
->keyval
;
1043 event
.m_rawCode
= (wxUint32
) gdk_event
->keyval
;
1044 event
.m_rawFlags
= 0;
1047 event
.SetEventObject( win
);
1052 static gint
gtk_window_key_press_callback( GtkWidget
*widget
,
1053 GdkEventKey
*gdk_event
,
1059 wxapp_install_idle_handler();
1063 if (g_blockEventsOnDrag
)
1066 wxKeyEvent
event( wxEVT_KEY_DOWN
);
1067 if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) )
1069 // unknown key pressed, ignore (the event would be useless anyhow)
1073 bool ret
= win
->GetEventHandler()->ProcessEvent( event
);
1078 wxWindowGTK
*ancestor
= win
;
1081 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
1084 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
1085 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
1088 if (ancestor
->IsTopLevel())
1090 ancestor
= ancestor
->GetParent();
1093 #endif // wxUSE_ACCEL
1095 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
1096 will only be sent if it is not in an accelerator table. */
1099 KeySym keysym
= gdk_event
->keyval
;
1100 long key_code
= wxTranslateKeySymToWXKey(keysym
, TRUE
/* isChar */);
1103 if ( gdk_event
->length
== 1 )
1105 key_code
= (unsigned char)gdk_event
->string
[0];
1107 else if ( wxIsAsciiKeysym(keysym
) )
1110 key_code
= (unsigned char)keysym
;
1116 wxLogTrace(TRACE_KEYS
, _T("Char event: %ld"), key_code
);
1118 // reuse the same event object, just change its type and use the
1119 // translated keycode instead of the raw one
1120 event
.SetEventType(wxEVT_CHAR
);
1121 event
.m_keyCode
= key_code
;
1123 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1127 /* win is a control: tab can be propagated up */
1129 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
1130 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
1131 // have this style, yet choose not to process this particular TAB in which
1132 // case TAB must still work as a navigational character
1134 !win
->HasFlag(wxTE_PROCESS_TAB
) &&
1136 win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
1138 wxNavigationKeyEvent new_event
;
1139 new_event
.SetEventObject( win
->GetParent() );
1140 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
1141 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
1142 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1143 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
1144 new_event
.SetCurrentFocus( win
);
1145 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
1148 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
1150 (gdk_event
->keyval
== GDK_Escape
) )
1152 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
1153 new_event
.SetEventObject( win
);
1154 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
1158 #if 0 // (GTK_MINOR_VERSION > 0)
1159 /* Pressing F10 will activate the menu bar of the top frame. */
1161 (gdk_event
->keyval
== GDK_F10
) )
1163 wxWindowGTK
*ancestor
= win
;
1166 if (wxIsKindOf(ancestor
,wxFrame
))
1168 wxFrame
*frame
= (wxFrame
*) ancestor
;
1169 wxMenuBar
*menubar
= frame
->GetMenuBar();
1172 wxNode
*node
= menubar
->GetMenus().First();
1175 wxMenu
*firstMenu
= (wxMenu
*) node
->Data();
1176 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu
->m_owner
) );
1182 ancestor
= ancestor
->GetParent();
1189 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1196 //-----------------------------------------------------------------------------
1197 // "key_release_event" from any window
1198 //-----------------------------------------------------------------------------
1200 static gint
gtk_window_key_release_callback( GtkWidget
*widget
,
1201 GdkEventKey
*gdk_event
,
1207 wxapp_install_idle_handler();
1212 if (g_blockEventsOnDrag
)
1215 wxKeyEvent
event( wxEVT_KEY_UP
);
1216 if ( !wxTranslateGTKKeyEventToWx(event
, win
, gdk_event
) )
1218 // unknown key pressed, ignore (the event would be useless anyhow
1222 if ( !win
->GetEventHandler()->ProcessEvent( event
) )
1225 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1229 // ============================================================================
1231 // ============================================================================
1233 // init wxMouseEvent with the info from gdk_event
1234 #define InitMouseEvent(win, event, gdk_event) \
1236 event.SetTimestamp( gdk_event->time ); \
1237 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
1238 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
1239 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
1240 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
1241 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
1242 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
1243 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
1245 wxPoint pt = win->GetClientAreaOrigin(); \
1246 event.m_x = (wxCoord)gdk_event->x - pt.x; \
1247 event.m_y = (wxCoord)gdk_event->y - pt.y; \
1250 // ----------------------------------------------------------------------------
1251 // mouse event processing helper
1252 // ----------------------------------------------------------------------------
1254 static void AdjustEventButtonState(wxMouseEvent
& event
)
1256 // GDK reports the old state of the button for a button press event, but
1257 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1258 // for a LEFT_DOWN event, not FALSE, so we will invert
1259 // left/right/middleDown for the corresponding click events
1261 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1262 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1263 (event
.GetEventType() == wxEVT_LEFT_UP
))
1265 event
.m_leftDown
= !event
.m_leftDown
;
1269 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1270 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1271 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1273 event
.m_middleDown
= !event
.m_middleDown
;
1277 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1278 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1279 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1281 event
.m_rightDown
= !event
.m_rightDown
;
1286 //-----------------------------------------------------------------------------
1287 // "button_press_event"
1288 //-----------------------------------------------------------------------------
1290 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1295 wxapp_install_idle_handler();
1298 wxPrintf( wxT("1) OnButtonPress from ") );
1299 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1300 wxPrintf( win->GetClassInfo()->GetClassName() );
1301 wxPrintf( wxT(".\n") );
1303 if (!win
->m_hasVMT
) return FALSE
;
1304 if (g_blockEventsOnDrag
) return TRUE
;
1305 if (g_blockEventsOnScroll
) return TRUE
;
1307 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1309 if (win
->m_wxwindow
&& (g_focusWindow
!= win
) && win
->AcceptsFocus())
1311 gtk_widget_grab_focus( win
->m_wxwindow
);
1313 wxPrintf( wxT("GrabFocus from ") );
1314 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1315 wxPrintf( win->GetClassInfo()->GetClassName() );
1316 wxPrintf( wxT(".\n") );
1320 wxEventType event_type
= wxEVT_NULL
;
1322 if (gdk_event
->button
== 1)
1324 switch (gdk_event
->type
)
1326 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1327 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1331 else if (gdk_event
->button
== 2)
1333 switch (gdk_event
->type
)
1335 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1336 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1340 else if (gdk_event
->button
== 3)
1342 switch (gdk_event
->type
)
1344 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1345 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1350 if ( event_type
== wxEVT_NULL
)
1352 // unknown mouse button or click type
1356 wxMouseEvent
event( event_type
);
1357 InitMouseEvent( win
, event
, gdk_event
);
1359 AdjustEventButtonState(event
);
1361 // wxListBox actually get mouse events from the item
1363 if (win
->m_isListBox
)
1365 event
.m_x
+= widget
->allocation
.x
;
1366 event
.m_y
+= widget
->allocation
.y
;
1369 // Some control don't have their own X window and thus cannot get
1372 if (!g_captureWindow
)
1374 wxCoord x
= event
.m_x
;
1375 wxCoord y
= event
.m_y
;
1376 if (win
->m_wxwindow
)
1378 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1379 x
+= pizza
->xoffset
;
1380 y
+= pizza
->yoffset
;
1383 wxNode
*node
= win
->GetChildren().First();
1386 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1388 node
= node
->Next();
1389 if (!child
->IsShown())
1392 if (child
->m_isStaticBox
)
1394 // wxStaticBox is transparent in the box itself
1395 int xx1
= child
->m_x
;
1396 int yy1
= child
->m_y
;
1397 int xx2
= child
->m_x
+ child
->m_width
;
1398 int yy2
= child
->m_x
+ child
->m_height
;
1401 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1403 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1405 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1407 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1410 event
.m_x
-= child
->m_x
;
1411 event
.m_y
-= child
->m_y
;
1418 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1419 (child
->m_x
<= x
) &&
1420 (child
->m_y
<= y
) &&
1421 (child
->m_x
+child
->m_width
>= x
) &&
1422 (child
->m_y
+child
->m_height
>= y
))
1425 event
.m_x
-= child
->m_x
;
1426 event
.m_y
-= child
->m_y
;
1433 event
.SetEventObject( win
);
1435 gs_timeLastClick
= gdk_event
->time
;
1438 wxPrintf( wxT("2) OnButtonPress from ") );
1439 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1440 wxPrintf( win->GetClassInfo()->GetClassName() );
1441 wxPrintf( wxT(".\n") );
1444 if (win
->GetEventHandler()->ProcessEvent( event
))
1446 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1453 //-----------------------------------------------------------------------------
1454 // "button_release_event"
1455 //-----------------------------------------------------------------------------
1457 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1462 wxapp_install_idle_handler();
1464 if (!win
->m_hasVMT
) return FALSE
;
1465 if (g_blockEventsOnDrag
) return FALSE
;
1466 if (g_blockEventsOnScroll
) return FALSE
;
1468 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1471 printf( "OnButtonRelease from " );
1472 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1473 printf( win->GetClassInfo()->GetClassName() );
1477 wxEventType event_type
= wxEVT_NULL
;
1479 switch (gdk_event
->button
)
1481 case 1: event_type
= wxEVT_LEFT_UP
; break;
1482 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1483 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1484 default: return FALSE
;
1487 wxMouseEvent
event( event_type
);
1488 InitMouseEvent( win
, event
, gdk_event
);
1490 AdjustEventButtonState(event
);
1492 // wxListBox actually get mouse events from the item
1494 if (win
->m_isListBox
)
1496 event
.m_x
+= widget
->allocation
.x
;
1497 event
.m_y
+= widget
->allocation
.y
;
1500 // Some control don't have their own X window and thus cannot get
1503 if (!g_captureWindow
)
1505 wxCoord x
= event
.m_x
;
1506 wxCoord y
= event
.m_y
;
1507 if (win
->m_wxwindow
)
1509 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1510 x
+= pizza
->xoffset
;
1511 y
+= pizza
->yoffset
;
1514 wxNode
*node
= win
->GetChildren().First();
1517 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1519 node
= node
->Next();
1520 if (!child
->IsShown())
1523 if (child
->m_isStaticBox
)
1525 // wxStaticBox is transparent in the box itself
1526 int xx1
= child
->m_x
;
1527 int yy1
= child
->m_y
;
1528 int xx2
= child
->m_x
+ child
->m_width
;
1529 int yy2
= child
->m_x
+ child
->m_height
;
1532 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1534 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1536 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1538 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1541 event
.m_x
-= child
->m_x
;
1542 event
.m_y
-= child
->m_y
;
1549 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1550 (child
->m_x
<= x
) &&
1551 (child
->m_y
<= y
) &&
1552 (child
->m_x
+child
->m_width
>= x
) &&
1553 (child
->m_y
+child
->m_height
>= y
))
1556 event
.m_x
-= child
->m_x
;
1557 event
.m_y
-= child
->m_y
;
1564 event
.SetEventObject( win
);
1566 if (win
->GetEventHandler()->ProcessEvent( event
))
1568 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1575 //-----------------------------------------------------------------------------
1576 // "motion_notify_event"
1577 //-----------------------------------------------------------------------------
1579 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
,
1580 GdkEventMotion
*gdk_event
,
1586 wxapp_install_idle_handler();
1588 if (!win
->m_hasVMT
) return FALSE
;
1589 if (g_blockEventsOnDrag
) return FALSE
;
1590 if (g_blockEventsOnScroll
) return FALSE
;
1592 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1594 if (gdk_event
->is_hint
)
1598 GdkModifierType state
;
1599 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1605 printf( "OnMotion from " );
1606 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1607 printf( win->GetClassInfo()->GetClassName() );
1611 wxMouseEvent
event( wxEVT_MOTION
);
1612 InitMouseEvent(win
, event
, gdk_event
);
1614 if ( g_captureWindow
)
1616 // synthetize a mouse enter or leave event if needed
1617 GdkWindow
*winUnderMouse
= gdk_window_at_pointer(NULL
, NULL
);
1618 bool hasMouse
= winUnderMouse
== gdk_event
->window
;
1619 if ( hasMouse
!= g_captureWindowHasMouse
)
1621 // the mouse changed window
1622 g_captureWindowHasMouse
= hasMouse
;
1624 wxMouseEvent
event(g_captureWindowHasMouse
? wxEVT_ENTER_WINDOW
1625 : wxEVT_LEAVE_WINDOW
);
1626 InitMouseEvent(win
, event
, gdk_event
);
1627 event
.SetEventObject(win
);
1628 win
->GetEventHandler()->ProcessEvent(event
);
1633 // Some control don't have their own X window and thus cannot get
1636 wxCoord x
= event
.m_x
;
1637 wxCoord y
= event
.m_y
;
1638 if (win
->m_wxwindow
)
1640 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1641 x
+= pizza
->xoffset
;
1642 y
+= pizza
->yoffset
;
1645 wxNode
*node
= win
->GetChildren().First();
1648 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1650 node
= node
->Next();
1651 if (!child
->IsShown())
1654 if (child
->m_isStaticBox
)
1656 // wxStaticBox is transparent in the box itself
1657 int xx1
= child
->m_x
;
1658 int yy1
= child
->m_y
;
1659 int xx2
= child
->m_x
+ child
->m_width
;
1660 int yy2
= child
->m_x
+ child
->m_height
;
1663 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1665 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1667 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1669 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1672 event
.m_x
-= child
->m_x
;
1673 event
.m_y
-= child
->m_y
;
1680 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1681 (child
->m_x
<= x
) &&
1682 (child
->m_y
<= y
) &&
1683 (child
->m_x
+child
->m_width
>= x
) &&
1684 (child
->m_y
+child
->m_height
>= y
))
1687 event
.m_x
-= child
->m_x
;
1688 event
.m_y
-= child
->m_y
;
1695 event
.SetEventObject( win
);
1697 if (win
->GetEventHandler()->ProcessEvent( event
))
1699 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1706 //-----------------------------------------------------------------------------
1708 //-----------------------------------------------------------------------------
1710 // send the wxChildFocusEvent and wxFocusEvent, common code of
1711 // gtk_window_focus_in_callback() and SetFocus()
1712 static bool DoSendFocusEvents(wxWindow
*win
)
1714 // Notify the parent keeping track of focus for the kbd navigation
1715 // purposes that we got it.
1716 wxChildFocusEvent
eventChildFocus(win
);
1717 (void)win
->GetEventHandler()->ProcessEvent(eventChildFocus
);
1719 wxFocusEvent
eventFocus(wxEVT_SET_FOCUS
, win
->GetId());
1720 eventFocus
.SetEventObject(win
);
1722 return win
->GetEventHandler()->ProcessEvent(eventFocus
);
1725 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
,
1726 GdkEvent
*WXUNUSED(event
),
1732 wxapp_install_idle_handler();
1734 if (!win
->m_hasVMT
) return FALSE
;
1735 if (g_blockEventsOnDrag
) return FALSE
;
1737 switch ( g_sendActivateEvent
)
1740 // we've got focus from outside, synthetize wxActivateEvent
1741 g_sendActivateEvent
= 1;
1745 // another our window just lost focus, it was already ours before
1746 // - don't send any wxActivateEvent
1747 g_sendActivateEvent
= -1;
1752 g_focusWindow
= win
;
1755 printf( "OnSetFocus 2 from %s\n", win
->GetName().c_str() );
1760 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1764 // caret needs to be informed about focus change
1765 wxCaret
*caret
= win
->GetCaret();
1768 caret
->OnSetFocus();
1770 #endif // wxUSE_CARET
1772 g_activeFrameLostFocus
= FALSE
;
1774 wxWindowGTK
*active
= wxGetTopLevelParent(win
);
1775 if ( active
!= g_activeFrame
)
1777 if ( g_activeFrame
)
1779 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame
);
1780 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
1781 event
.SetEventObject(g_activeFrame
);
1782 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1785 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active
);
1786 g_activeFrame
= active
;
1787 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId());
1788 event
.SetEventObject(g_activeFrame
);
1789 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1791 // Don't send focus events in addition to activate
1792 // if (win == g_activeFrame)
1796 if ( DoSendFocusEvents(win
) )
1798 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1805 //-----------------------------------------------------------------------------
1806 // "focus_out_event"
1807 //-----------------------------------------------------------------------------
1809 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEventFocus
*gdk_event
, wxWindowGTK
*win
)
1814 wxapp_install_idle_handler();
1816 if (!win
->m_hasVMT
) return FALSE
;
1817 if (g_blockEventsOnDrag
) return FALSE
;
1820 wxLogDebug( wxT("OnKillFocus from %s"), win
->GetName().c_str() );
1823 if ( !g_activeFrameLostFocus
&& g_activeFrame
)
1825 // VZ: commenting this out because it does happen (although not easy
1826 // to reproduce, I only see it when using wxMiniFrame and not
1827 // always) and makes using Mahogany quite annoying
1829 wxASSERT_MSG( wxGetTopLevelParent(win
) == g_activeFrame
,
1830 wxT("unfocusing window that hasn't gained focus properly") )
1833 g_activeFrameLostFocus
= TRUE
;
1836 // if the focus goes out of our app alltogether, OnIdle() will send
1837 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1838 // g_sendActivateEvent to -1
1839 g_sendActivateEvent
= 0;
1841 wxWindowGTK
*winFocus
= wxFindFocusedChild(win
);
1845 g_focusWindow
= (wxWindowGTK
*)NULL
;
1853 // caret needs to be informed about focus change
1854 wxCaret
*caret
= win
->GetCaret();
1857 caret
->OnKillFocus();
1859 #endif // wxUSE_CARET
1861 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1862 event
.SetEventObject( win
);
1864 if (win
->GetEventHandler()->ProcessEvent( event
))
1866 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1873 //-----------------------------------------------------------------------------
1874 // "enter_notify_event"
1875 //-----------------------------------------------------------------------------
1877 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1882 wxapp_install_idle_handler();
1884 if (!win
->m_hasVMT
) return FALSE
;
1885 if (g_blockEventsOnDrag
) return FALSE
;
1887 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1889 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1890 event
.SetTimestamp( gdk_event
->time
);
1891 event
.SetEventObject( win
);
1895 GdkModifierType state
= (GdkModifierType
)0;
1897 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1899 InitMouseEvent(win
, event
, gdk_event
);
1900 wxPoint pt
= win
->GetClientAreaOrigin();
1901 event
.m_x
= x
+ pt
.x
;
1902 event
.m_y
= y
+ pt
.y
;
1904 if (win
->GetEventHandler()->ProcessEvent( event
))
1906 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1913 //-----------------------------------------------------------------------------
1914 // "leave_notify_event"
1915 //-----------------------------------------------------------------------------
1917 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1922 wxapp_install_idle_handler();
1924 if (!win
->m_hasVMT
) return FALSE
;
1925 if (g_blockEventsOnDrag
) return FALSE
;
1927 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1929 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1930 event
.SetTimestamp( gdk_event
->time
);
1931 event
.SetEventObject( win
);
1935 GdkModifierType state
= (GdkModifierType
)0;
1937 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1939 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
) != 0;
1940 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
) != 0;
1941 event
.m_altDown
= (state
& GDK_MOD1_MASK
) != 0;
1942 event
.m_metaDown
= (state
& GDK_MOD2_MASK
) != 0;
1943 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
) != 0;
1944 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
) != 0;
1945 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
) != 0;
1947 wxPoint pt
= win
->GetClientAreaOrigin();
1948 event
.m_x
= x
+ pt
.x
;
1949 event
.m_y
= y
+ pt
.y
;
1951 if (win
->GetEventHandler()->ProcessEvent( event
))
1953 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1960 //-----------------------------------------------------------------------------
1961 // "value_changed" from m_vAdjust
1962 //-----------------------------------------------------------------------------
1964 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
,
1971 wxapp_install_idle_handler();
1973 if (g_blockEventsOnDrag
) return;
1975 if (!win
->m_hasVMT
) return;
1977 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1978 if (fabs(diff
) < 0.2) return;
1980 win
->m_oldVerticalPos
= adjust
->value
;
1982 GtkScrolledWindow
*sw
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1983 wxEventType command
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->vscrollbar
));
1985 int value
= (int)(adjust
->value
+0.5);
1987 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1988 event
.SetEventObject( win
);
1989 win
->GetEventHandler()->ProcessEvent( event
);
1992 //-----------------------------------------------------------------------------
1993 // "value_changed" from m_hAdjust
1994 //-----------------------------------------------------------------------------
1996 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
,
2003 wxapp_install_idle_handler();
2005 if (g_blockEventsOnDrag
) return;
2006 if (!win
->m_hasVMT
) return;
2008 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
2009 if (fabs(diff
) < 0.2) return;
2011 GtkScrolledWindow
*sw
= GTK_SCROLLED_WINDOW(win
->m_widget
);
2012 wxEventType command
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(sw
->hscrollbar
));
2014 win
->m_oldHorizontalPos
= adjust
->value
;
2016 int value
= (int)(adjust
->value
+0.5);
2018 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
2019 event
.SetEventObject( win
);
2020 win
->GetEventHandler()->ProcessEvent( event
);
2023 //-----------------------------------------------------------------------------
2024 // "button_press_event" from scrollbar
2025 //-----------------------------------------------------------------------------
2027 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
2028 GdkEventButton
*gdk_event
,
2034 wxapp_install_idle_handler();
2037 g_blockEventsOnScroll
= TRUE
;
2039 // FIXME: there is no 'slider' field in GTK+ 2.0 any more
2041 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
2047 //-----------------------------------------------------------------------------
2048 // "button_release_event" from scrollbar
2049 //-----------------------------------------------------------------------------
2051 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
2052 GdkEventButton
*WXUNUSED(gdk_event
),
2057 // don't test here as we can release the mouse while being over
2058 // a different window than the slider
2060 // if (gdk_event->window != widget->slider) return FALSE;
2062 g_blockEventsOnScroll
= FALSE
;
2064 if (win
->m_isScrolling
)
2066 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
2070 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
2071 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
2073 value
= (int)(win
->m_hAdjust
->value
+0.5);
2076 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
2078 value
= (int)(win
->m_vAdjust
->value
+0.5);
2082 wxScrollWinEvent
event( command
, value
, dir
);
2083 event
.SetEventObject( win
);
2084 win
->GetEventHandler()->ProcessEvent( event
);
2087 win
->m_isScrolling
= FALSE
;
2092 // ----------------------------------------------------------------------------
2093 // this wxWindowBase function is implemented here (in platform-specific file)
2094 // because it is static and so couldn't be made virtual
2095 // ----------------------------------------------------------------------------
2097 wxWindow
*wxWindowBase::FindFocus()
2099 // the cast is necessary when we compile in wxUniversal mode
2100 return (wxWindow
*)g_focusWindow
;
2103 //-----------------------------------------------------------------------------
2104 // "realize" from m_widget
2105 //-----------------------------------------------------------------------------
2107 /* We cannot set colours and fonts before the widget has
2108 been realized, so we do this directly after realization. */
2111 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
2116 wxapp_install_idle_handler();
2118 if (win
->m_delayedBackgroundColour
)
2119 win
->GtkSetBackgroundColour( win
->GetBackgroundColour() );
2121 if (win
->m_delayedForegroundColour
)
2122 win
->GtkSetForegroundColour( win
->GetForegroundColour() );
2124 wxWindowCreateEvent
event( win
);
2125 event
.SetEventObject( win
);
2126 win
->GetEventHandler()->ProcessEvent( event
);
2131 //-----------------------------------------------------------------------------
2133 //-----------------------------------------------------------------------------
2136 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
2137 GtkAllocation
*WXUNUSED(alloc
),
2141 wxapp_install_idle_handler();
2143 if (!win
->m_hasScrolling
) return;
2145 int client_width
= 0;
2146 int client_height
= 0;
2147 win
->GetClientSize( &client_width
, &client_height
);
2148 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
2151 win
->m_oldClientWidth
= client_width
;
2152 win
->m_oldClientHeight
= client_height
;
2154 if (!win
->m_nativeSizeEvent
)
2156 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
2157 event
.SetEventObject( win
);
2158 win
->GetEventHandler()->ProcessEvent( event
);
2164 #define WXUNUSED_UNLESS_XIM(param) param
2166 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2169 /* Resize XIM window */
2172 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2173 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
2174 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2177 wxapp_install_idle_handler();
2183 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
2187 gdk_window_get_size (widget
->window
, &width
, &height
);
2188 win
->m_icattr
->preedit_area
.width
= width
;
2189 win
->m_icattr
->preedit_area
.height
= height
;
2190 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2195 //-----------------------------------------------------------------------------
2196 // "realize" from m_wxwindow
2197 //-----------------------------------------------------------------------------
2199 /* Initialize XIM support */
2202 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2203 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2206 wxapp_install_idle_handler();
2209 if (win
->m_ic
) return FALSE
;
2210 if (!widget
) return FALSE
;
2211 if (!gdk_im_ready()) return FALSE
;
2213 win
->m_icattr
= gdk_ic_attr_new();
2214 if (!win
->m_icattr
) return FALSE
;
2218 GdkColormap
*colormap
;
2219 GdkICAttr
*attr
= win
->m_icattr
;
2220 unsigned attrmask
= GDK_IC_ALL_REQ
;
2222 GdkIMStyle supported_style
= (GdkIMStyle
)
2223 (GDK_IM_PREEDIT_NONE
|
2224 GDK_IM_PREEDIT_NOTHING
|
2225 GDK_IM_PREEDIT_POSITION
|
2226 GDK_IM_STATUS_NONE
|
2227 GDK_IM_STATUS_NOTHING
);
2229 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2230 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2232 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2233 attr
->client_window
= widget
->window
;
2235 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2236 gtk_widget_get_default_colormap ())
2238 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2239 attr
->preedit_colormap
= colormap
;
2242 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2243 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2244 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2245 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2247 switch (style
& GDK_IM_PREEDIT_MASK
)
2249 case GDK_IM_PREEDIT_POSITION
:
2250 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2252 g_warning ("over-the-spot style requires fontset");
2256 gdk_window_get_size (widget
->window
, &width
, &height
);
2258 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2259 attr
->spot_location
.x
= 0;
2260 attr
->spot_location
.y
= height
;
2261 attr
->preedit_area
.x
= 0;
2262 attr
->preedit_area
.y
= 0;
2263 attr
->preedit_area
.width
= width
;
2264 attr
->preedit_area
.height
= height
;
2265 attr
->preedit_fontset
= widget
->style
->font
;
2270 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2272 if (win
->m_ic
== NULL
)
2273 g_warning ("Can't create input context.");
2276 mask
= gdk_window_get_events (widget
->window
);
2277 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2278 gdk_window_set_events (widget
->window
, mask
);
2280 if (GTK_WIDGET_HAS_FOCUS(widget
))
2281 gdk_im_begin (win
->m_ic
, widget
->window
);
2288 //-----------------------------------------------------------------------------
2289 // InsertChild for wxWindowGTK.
2290 //-----------------------------------------------------------------------------
2292 /* Callback for wxWindowGTK. This very strange beast has to be used because
2293 * C++ has no virtual methods in a constructor. We have to emulate a
2294 * virtual function here as wxNotebook requires a different way to insert
2295 * a child in it. I had opted for creating a wxNotebookPage window class
2296 * which would have made this superfluous (such in the MDI window system),
2297 * but no-one was listening to me... */
2299 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child
)
2301 /* the window might have been scrolled already, do we
2302 have to adapt the position */
2303 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2304 child
->m_x
+= pizza
->xoffset
;
2305 child
->m_y
+= pizza
->yoffset
;
2307 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2308 GTK_WIDGET(child
->m_widget
),
2315 //-----------------------------------------------------------------------------
2317 //-----------------------------------------------------------------------------
2319 wxWindow
*wxGetActiveWindow()
2321 // the cast is necessary when we compile in wxUniversal mode
2322 return (wxWindow
*)g_focusWindow
;
2325 //-----------------------------------------------------------------------------
2327 //-----------------------------------------------------------------------------
2329 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
2331 #ifdef __WXUNIVERSAL__
2332 IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
)
2334 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2335 #endif // __WXUNIVERSAL__/__WXGTK__
2337 void wxWindowGTK::Init()
2343 m_widget
= (GtkWidget
*) NULL
;
2344 m_wxwindow
= (GtkWidget
*) NULL
;
2345 m_focusWidget
= (GtkWidget
*) NULL
;
2355 m_needParent
= TRUE
;
2356 m_isBeingDeleted
= FALSE
;
2359 m_nativeSizeEvent
= FALSE
;
2361 m_hasScrolling
= FALSE
;
2362 m_isScrolling
= FALSE
;
2364 m_hAdjust
= (GtkAdjustment
*) NULL
;
2365 m_vAdjust
= (GtkAdjustment
*) NULL
;
2366 m_oldHorizontalPos
= 0.0;
2367 m_oldVerticalPos
= 0.0;
2370 m_widgetStyle
= (GtkStyle
*) NULL
;
2372 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2374 m_isStaticBox
= FALSE
;
2375 m_isRadioButton
= FALSE
;
2376 m_isListBox
= FALSE
;
2378 m_acceptsFocus
= FALSE
;
2380 m_clipPaintRegion
= FALSE
;
2382 m_cursor
= *wxSTANDARD_CURSOR
;
2384 m_delayedForegroundColour
= FALSE
;
2385 m_delayedBackgroundColour
= FALSE
;
2388 m_ic
= (GdkIC
*) NULL
;
2389 m_icattr
= (GdkICAttr
*) NULL
;
2393 wxWindowGTK::wxWindowGTK()
2398 wxWindowGTK::wxWindowGTK( wxWindow
*parent
,
2403 const wxString
&name
)
2407 Create( parent
, id
, pos
, size
, style
, name
);
2410 bool wxWindowGTK::Create( wxWindow
*parent
,
2415 const wxString
&name
)
2417 if (!PreCreation( parent
, pos
, size
) ||
2418 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2420 wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
2424 m_insertCallback
= wxInsertChildInWindow
;
2426 // always needed for background clearing
2427 m_delayedBackgroundColour
= TRUE
;
2429 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2430 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2432 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2434 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2435 scroll_class
->scrollbar_spacing
= 0;
2437 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2439 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2440 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2442 m_wxwindow
= gtk_pizza_new();
2444 #ifndef __WXUNIVERSAL__
2445 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2447 if (HasFlag(wxRAISED_BORDER
))
2449 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2451 else if (HasFlag(wxSUNKEN_BORDER
))
2453 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2455 else if (HasFlag(wxSIMPLE_BORDER
))
2457 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2461 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2463 #endif // __WXUNIVERSAL__
2465 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2467 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2468 m_acceptsFocus
= TRUE
;
2470 // I _really_ don't want scrollbars in the beginning
2471 m_vAdjust
->lower
= 0.0;
2472 m_vAdjust
->upper
= 1.0;
2473 m_vAdjust
->value
= 0.0;
2474 m_vAdjust
->step_increment
= 1.0;
2475 m_vAdjust
->page_increment
= 1.0;
2476 m_vAdjust
->page_size
= 5.0;
2477 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2478 m_hAdjust
->lower
= 0.0;
2479 m_hAdjust
->upper
= 1.0;
2480 m_hAdjust
->value
= 0.0;
2481 m_hAdjust
->step_increment
= 1.0;
2482 m_hAdjust
->page_increment
= 1.0;
2483 m_hAdjust
->page_size
= 5.0;
2484 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2486 // these handlers block mouse events to any window during scrolling such as
2487 // motion events and prevent GTK and wxWindows from fighting over where the
2490 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2491 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2493 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2494 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2496 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2497 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2499 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2500 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2502 // these handlers get notified when screen updates are required either when
2503 // scrolling or when the window size (and therefore scrollbar configuration)
2506 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2507 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2508 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2509 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2511 gtk_widget_show( m_wxwindow
);
2514 m_parent
->DoAddChild( this );
2516 m_focusWidget
= m_wxwindow
;
2525 wxWindowGTK::~wxWindowGTK()
2527 if (g_focusWindow
== this)
2528 g_focusWindow
= NULL
;
2530 if (g_activeFrame
== this)
2531 g_activeFrame
= NULL
;
2533 if ( g_delayedFocus
== this )
2534 g_delayedFocus
= NULL
;
2536 m_isBeingDeleted
= TRUE
;
2545 m_parent
->RemoveChild( this );
2549 gdk_ic_destroy (m_ic
);
2551 gdk_ic_attr_destroy (m_icattr
);
2556 #if DISABLE_STYLE_IF_BROKEN_THEME
2557 // don't delete if it's a pixmap theme style
2558 if (!m_widgetStyle
->engine_data
)
2559 gtk_style_unref( m_widgetStyle
);
2561 m_widgetStyle
= (GtkStyle
*) NULL
;
2566 gtk_widget_destroy( m_wxwindow
);
2567 m_wxwindow
= (GtkWidget
*) NULL
;
2572 gtk_widget_destroy( m_widget
);
2573 m_widget
= (GtkWidget
*) NULL
;
2577 bool wxWindowGTK::PreCreation( wxWindowGTK
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2579 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2581 /* this turns -1 into 20 so that a minimal window is
2582 visible even although -1,-1 has been given as the
2583 size of the window. the same trick is used in other
2584 ports and should make debugging easier */
2585 m_width
= WidthDefault(size
.x
);
2586 m_height
= HeightDefault(size
.y
);
2591 /* some reasonable defaults */
2596 m_x
= (gdk_screen_width () - m_width
) / 2;
2597 if (m_x
< 10) m_x
= 10;
2601 m_y
= (gdk_screen_height () - m_height
) / 2;
2602 if (m_y
< 10) m_y
= 10;
2609 void wxWindowGTK::PostCreation()
2611 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2617 // these get reported to wxWindows -> wxPaintEvent
2619 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2621 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2622 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2625 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2626 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2628 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2630 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2631 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2634 gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow
), HasFlag( wxNO_FULL_REPAINT_ON_RESIZE
) );
2638 // these are called when the "sunken" or "raised" borders are drawn
2639 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2640 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2643 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2644 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2650 if (m_focusWidget
== NULL
)
2651 m_focusWidget
= m_widget
;
2653 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event",
2654 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2656 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event",
2657 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2659 // connect to the various key and mouse handlers
2661 GtkWidget
*connect_widget
= GetConnectWidget();
2663 ConnectWidget( connect_widget
);
2665 /* We cannot set colours, fonts and cursors before the widget has
2666 been realized, so we do this directly after realization */
2667 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2668 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2672 // Catch native resize events
2673 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2674 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2676 // Initialize XIM support
2677 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2678 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2680 // And resize XIM window
2681 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2682 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2685 if (!GTK_IS_COMBO(m_widget
))
2687 // This is needed if we want to add our windows into native
2688 // GTK control, such as the toolbar. With this callback, the
2689 // toolbar gets to know the correct size (the one set by the
2690 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2691 // when moving to GTK 2.0.
2692 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2693 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2699 void wxWindowGTK::ConnectWidget( GtkWidget
*widget
)
2701 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2702 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2704 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2705 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2707 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2708 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2710 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2711 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2713 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2714 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2716 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2717 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2719 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2720 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2723 bool wxWindowGTK::Destroy()
2725 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2729 return wxWindowBase::Destroy();
2732 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
)
2734 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2737 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2739 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2740 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") );
2743 printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
2746 if (m_resizing
) return; /* I don't like recursions */
2749 int currentX
, currentY
;
2750 GetPosition(¤tX
, ¤tY
);
2755 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
2757 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2759 /* don't set the size for children of wxNotebook, just take the values. */
2767 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2768 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2770 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2771 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2772 if (width
!= -1) m_width
= width
;
2773 if (height
!= -1) m_height
= height
;
2777 m_x
= x
+ pizza
->xoffset
;
2778 m_y
= y
+ pizza
->yoffset
;
2783 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2785 if (width
== -1) m_width
= 80;
2788 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2790 if (height
== -1) m_height
= 26;
2793 int minWidth
= GetMinWidth(),
2794 minHeight
= GetMinHeight(),
2795 maxWidth
= GetMaxWidth(),
2796 maxHeight
= GetMaxHeight();
2798 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
2799 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
2800 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
2801 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
2804 int bottom_border
= 0;
2807 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2809 /* the default button has a border around it */
2815 DoMoveWindow( m_x
-border
,
2818 m_height
+border
+bottom_border
);
2823 /* Sometimes the client area changes size without the
2824 whole windows's size changing, but if the whole
2825 windows's size doesn't change, no wxSizeEvent will
2826 normally be sent. Here we add an extra test if
2827 the client test has been changed and this will
2829 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2833 wxPrintf( "OnSize sent from " );
2834 if (GetClassInfo() && GetClassInfo()->GetClassName())
2835 wxPrintf( GetClassInfo()->GetClassName() );
2836 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2839 if (!m_nativeSizeEvent
)
2841 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2842 event
.SetEventObject( this );
2843 GetEventHandler()->ProcessEvent( event
);
2849 void wxWindowGTK::OnInternalIdle()
2851 // Update invalidated regions.
2854 // Synthetize activate events.
2855 if ( g_sendActivateEvent
!= -1 )
2857 bool activate
= g_sendActivateEvent
!= 0;
2860 g_sendActivateEvent
= -1;
2862 wxTheApp
->SetActive(activate
, (wxWindow
*)g_focusWindowLast
);
2865 if ( g_activeFrameLostFocus
)
2867 if ( g_activeFrame
)
2869 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame
);
2870 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
2871 event
.SetEventObject(g_activeFrame
);
2872 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
2873 g_activeFrame
= NULL
;
2875 g_activeFrameLostFocus
= FALSE
;
2878 wxCursor cursor
= m_cursor
;
2879 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2883 /* I now set the cursor anew in every OnInternalIdle call
2884 as setting the cursor in a parent window also effects the
2885 windows above so that checking for the current cursor is
2890 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2892 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2894 if (!g_globalCursor
.Ok())
2895 cursor
= *wxSTANDARD_CURSOR
;
2897 window
= m_widget
->window
;
2898 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2899 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2905 GdkWindow
*window
= m_widget
->window
;
2906 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2907 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2915 void wxWindowGTK::DoGetSize( int *width
, int *height
) const
2917 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2919 if (width
) (*width
) = m_width
;
2920 if (height
) (*height
) = m_height
;
2923 void wxWindowGTK::DoSetClientSize( int width
, int height
)
2925 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2929 SetSize( width
, height
);
2936 #ifndef __WXUNIVERSAL__
2937 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2939 /* when using GTK 1.2 we set the shadow border size to 2 */
2943 if (HasFlag(wxSIMPLE_BORDER
))
2945 /* when using GTK 1.2 we set the simple border size to 1 */
2949 #endif // __WXUNIVERSAL__
2953 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2955 GtkRequisition vscroll_req
;
2956 vscroll_req
.width
= 2;
2957 vscroll_req
.height
= 2;
2958 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2959 (scroll_window
->vscrollbar
, &vscroll_req
);
2961 GtkRequisition hscroll_req
;
2962 hscroll_req
.width
= 2;
2963 hscroll_req
.height
= 2;
2964 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2965 (scroll_window
->hscrollbar
, &hscroll_req
);
2967 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2969 if (scroll_window
->vscrollbar_visible
)
2971 dw
+= vscroll_req
.width
;
2972 dw
+= scroll_class
->scrollbar_spacing
;
2975 if (scroll_window
->hscrollbar_visible
)
2977 dh
+= hscroll_req
.height
;
2978 dh
+= scroll_class
->scrollbar_spacing
;
2982 SetSize( width
+dw
, height
+dh
);
2986 void wxWindowGTK::DoGetClientSize( int *width
, int *height
) const
2988 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2992 if (width
) (*width
) = m_width
;
2993 if (height
) (*height
) = m_height
;
3000 #ifndef __WXUNIVERSAL__
3001 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
3003 /* when using GTK 1.2 we set the shadow border size to 2 */
3007 if (HasFlag(wxSIMPLE_BORDER
))
3009 /* when using GTK 1.2 we set the simple border size to 1 */
3013 #endif // __WXUNIVERSAL__
3017 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
3019 GtkRequisition vscroll_req
;
3020 vscroll_req
.width
= 2;
3021 vscroll_req
.height
= 2;
3022 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
3023 (scroll_window
->vscrollbar
, &vscroll_req
);
3025 GtkRequisition hscroll_req
;
3026 hscroll_req
.width
= 2;
3027 hscroll_req
.height
= 2;
3028 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
3029 (scroll_window
->hscrollbar
, &hscroll_req
);
3031 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
3033 if (scroll_window
->vscrollbar_visible
)
3035 dw
+= vscroll_req
.width
;
3036 dw
+= scroll_class
->scrollbar_spacing
;
3039 if (scroll_window
->hscrollbar_visible
)
3041 dh
+= hscroll_req
.height
;
3042 dh
+= scroll_class
->scrollbar_spacing
;
3046 if (width
) (*width
) = m_width
- dw
;
3047 if (height
) (*height
) = m_height
- dh
;
3051 printf( "GetClientSize, name %s ", GetName().c_str() );
3052 if (width) printf( " width = %d", (*width) );
3053 if (height) printf( " height = %d", (*height) );
3058 void wxWindowGTK::DoGetPosition( int *x
, int *y
) const
3060 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3064 if (m_parent
&& m_parent
->m_wxwindow
)
3066 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
3067 dx
= pizza
->xoffset
;
3068 dy
= pizza
->yoffset
;
3071 if (x
) (*x
) = m_x
- dx
;
3072 if (y
) (*y
) = m_y
- dy
;
3075 void wxWindowGTK::DoClientToScreen( int *x
, int *y
) const
3077 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3079 if (!m_widget
->window
) return;
3081 GdkWindow
*source
= (GdkWindow
*) NULL
;
3083 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3085 source
= m_widget
->window
;
3089 gdk_window_get_origin( source
, &org_x
, &org_y
);
3093 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3095 org_x
+= m_widget
->allocation
.x
;
3096 org_y
+= m_widget
->allocation
.y
;
3104 void wxWindowGTK::DoScreenToClient( int *x
, int *y
) const
3106 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3108 if (!m_widget
->window
) return;
3110 GdkWindow
*source
= (GdkWindow
*) NULL
;
3112 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3114 source
= m_widget
->window
;
3118 gdk_window_get_origin( source
, &org_x
, &org_y
);
3122 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3124 org_x
+= m_widget
->allocation
.x
;
3125 org_y
+= m_widget
->allocation
.y
;
3133 bool wxWindowGTK::Show( bool show
)
3135 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3137 if (!wxWindowBase::Show(show
))
3144 gtk_widget_show( m_widget
);
3146 gtk_widget_hide( m_widget
);
3151 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
)
3153 win
->OnParentEnable(enable
);
3155 // Recurse, so that children have the opportunity to Do The Right Thing
3156 // and reset colours that have been messed up by a parent's (really ancestor's)
3158 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
3160 node
= node
->GetNext() )
3162 wxWindow
*child
= node
->GetData();
3163 if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
)))
3164 wxWindowNotifyEnable(child
, enable
);
3168 bool wxWindowGTK::Enable( bool enable
)
3170 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3172 if (!wxWindowBase::Enable(enable
))
3178 gtk_widget_set_sensitive( m_widget
, enable
);
3180 gtk_widget_set_sensitive( m_wxwindow
, enable
);
3182 wxWindowNotifyEnable(this, enable
);
3187 int wxWindowGTK::GetCharHeight() const
3189 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
3191 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
3193 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3195 return font
->ascent
+ font
->descent
;
3198 int wxWindowGTK::GetCharWidth() const
3200 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
3202 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
3204 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3206 return gdk_string_width( font
, "H" );
3209 void wxWindowGTK::GetTextExtent( const wxString
& string
,
3213 int *externalLeading
,
3214 const wxFont
*theFont
) const
3216 wxFont fontToUse
= m_font
;
3217 if (theFont
) fontToUse
= *theFont
;
3219 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
3221 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
3222 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
3223 if (y
) (*y
) = font
->ascent
+ font
->descent
;
3224 if (descent
) (*descent
) = font
->descent
;
3225 if (externalLeading
) (*externalLeading
) = 0; // ??
3228 void wxWindowGTK::SetFocus()
3230 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3234 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3236 gtk_widget_grab_focus (m_wxwindow
);
3241 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
3243 if (!GTK_WIDGET_REALIZED(m_widget
))
3245 wxLogTrace(_T("focus"),
3246 _T("Delaying setting focus to %s(%s)\n"),
3247 GetClassInfo()->GetClassName(), GetLabel().c_str());
3249 g_delayedFocus
= this;
3253 wxLogTrace(_T("focus"),
3254 _T("Setting focus to %s(%s)\n"),
3255 GetClassInfo()->GetClassName(), GetLabel().c_str());
3257 gtk_widget_grab_focus (m_widget
);
3260 else if (GTK_IS_CONTAINER(m_widget
))
3262 SET_CONTAINER_FOCUS( m_widget
, GTK_DIR_TAB_FORWARD
);
3270 (void)DoSendFocusEvents((wxWindow
*)this);
3273 bool wxWindowGTK::AcceptsFocus() const
3275 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3278 bool wxWindowGTK::Reparent( wxWindowBase
*newParentBase
)
3280 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3282 wxWindowGTK
*oldParent
= m_parent
,
3283 *newParent
= (wxWindowGTK
*)newParentBase
;
3285 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3287 if ( !wxWindowBase::Reparent(newParent
) )
3290 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3292 /* prevent GTK from deleting the widget arbitrarily */
3293 gtk_widget_ref( m_widget
);
3297 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3300 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3304 /* insert GTK representation */
3305 (*(newParent
->m_insertCallback
))(newParent
, this);
3308 /* reverse: prevent GTK from deleting the widget arbitrarily */
3309 gtk_widget_unref( m_widget
);
3314 void wxWindowGTK::DoAddChild(wxWindowGTK
*child
)
3316 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3318 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3320 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3325 /* insert GTK representation */
3326 (*m_insertCallback
)(this, child
);
3329 void wxWindowGTK::Raise()
3331 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3333 if (!m_widget
->window
) return;
3335 gdk_window_raise( m_widget
->window
);
3338 void wxWindowGTK::Lower()
3340 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3342 if (!m_widget
->window
) return;
3344 gdk_window_lower( m_widget
->window
);
3347 bool wxWindowGTK::SetCursor( const wxCursor
&cursor
)
3349 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3351 if (cursor
== m_cursor
)
3355 wxapp_install_idle_handler();
3357 if (cursor
== wxNullCursor
)
3358 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3360 return wxWindowBase::SetCursor( cursor
);
3363 void wxWindowGTK::WarpPointer( int x
, int y
)
3365 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3367 // We provide this function ourselves as it is
3368 // missing in GDK (top of this file).
3370 GdkWindow
*window
= (GdkWindow
*) NULL
;
3372 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3374 window
= GetConnectWidget()->window
;
3377 gdk_window_warp_pointer( window
, x
, y
);
3380 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect
*rect
)
3382 if (!m_widget
) return;
3383 if (!m_widget
->window
) return;
3387 wxapp_install_idle_handler();
3389 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3393 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3394 m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
3398 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3399 m_clearRegion
.Clear();
3400 m_clearRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height
);
3408 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3409 m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
3413 GdkRectangle gdk_rect
;
3414 gdk_rect
.x
= rect
->x
;
3415 gdk_rect
.y
= rect
->y
;
3416 gdk_rect
.width
= rect
->width
;
3417 gdk_rect
.height
= rect
->height
;
3418 gtk_widget_draw( m_widget
, &gdk_rect
);
3425 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3426 m_updateRegion
.Clear();
3427 m_updateRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height
);
3431 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3439 GdkRectangle gdk_rect
;
3440 gdk_rect
.x
= rect
->x
;
3441 gdk_rect
.y
= rect
->y
;
3442 gdk_rect
.width
= rect
->width
;
3443 gdk_rect
.height
= rect
->height
;
3444 gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, &gdk_rect
, TRUE
);
3448 gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, NULL
, TRUE
);
3454 void wxWindowGTK::Update()
3459 void wxWindowGTK::GtkUpdate()
3462 if (m_wxwindow
&& GTK_PIZZA(m_wxwindow
)->bin_window
)
3463 gdk_window_process_updates( GTK_PIZZA(m_wxwindow
)->bin_window
, FALSE
);
3466 if (!m_updateRegion
.IsEmpty())
3467 GtkSendPaintEvents();
3470 void wxWindowGTK::GtkSendPaintEvents()
3474 m_clearRegion
.Clear();
3475 m_updateRegion
.Clear();
3479 // widget to draw on
3480 GtkPizza
*pizza
= GTK_PIZZA (m_wxwindow
);
3482 // Clip to paint region in wxClientDC
3483 m_clipPaintRegion
= TRUE
;
3485 if (GetThemeEnabled())
3487 // find ancestor from which to steal background
3488 wxWindow
*parent
= GetParent();
3489 while (parent
&& !parent
->IsTopLevel())
3490 parent
= parent
->GetParent();
3492 parent
= (wxWindow
*)this;
3494 wxRegionIterator
upd( m_updateRegion
);
3498 rect
.x
= upd
.GetX();
3499 rect
.y
= upd
.GetY();
3500 rect
.width
= upd
.GetWidth();
3501 rect
.height
= upd
.GetHeight();
3503 gtk_paint_flat_box( parent
->m_widget
->style
,
3516 // if (!m_clearRegion.IsEmpty()) // always send an erase event
3518 wxWindowDC
dc( (wxWindow
*)this );
3519 dc
.SetClippingRegion( m_clearRegion
);
3521 wxEraseEvent
erase_event( GetId(), &dc
);
3522 erase_event
.SetEventObject( this );
3524 if (!GetEventHandler()->ProcessEvent(erase_event
))
3528 g_eraseGC
= gdk_gc_new( pizza
->bin_window
);
3529 gdk_gc_set_fill( g_eraseGC
, GDK_SOLID
);
3531 gdk_gc_set_foreground( g_eraseGC
, m_backgroundColour
.GetColor() );
3533 wxRegionIterator
upd( m_clearRegion
);
3536 gdk_draw_rectangle( pizza
->bin_window
, g_eraseGC
, 1,
3537 upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
3541 m_clearRegion
.Clear();
3544 wxNcPaintEvent
nc_paint_event( GetId() );
3545 nc_paint_event
.SetEventObject( this );
3546 GetEventHandler()->ProcessEvent( nc_paint_event
);
3548 wxPaintEvent
paint_event( GetId() );
3549 paint_event
.SetEventObject( this );
3550 GetEventHandler()->ProcessEvent( paint_event
);
3552 m_clipPaintRegion
= FALSE
;
3554 #ifndef __WXUNIVERSAL__
3556 // The following code will result in all window-less widgets
3557 // being redrawn because the wxWindows class is allowed to
3558 // paint over the window-less widgets.
3560 GList
*children
= pizza
->children
;
3563 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
3564 children
= children
->next
;
3566 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
3567 GTK_WIDGET_DRAWABLE (child
->widget
))
3569 // Get intersection of widget area and update region
3570 wxRegion
region( m_updateRegion
);
3572 GdkEventExpose gdk_event
;
3573 gdk_event
.type
= GDK_EXPOSE
;
3574 gdk_event
.window
= pizza
->bin_window
;
3575 gdk_event
.count
= 0;
3577 wxRegionIterator
upd( m_updateRegion
);
3581 rect
.x
= upd
.GetX();
3582 rect
.y
= upd
.GetY();
3583 rect
.width
= upd
.GetWidth();
3584 rect
.height
= upd
.GetHeight();
3586 if (gtk_widget_intersect (child
->widget
, &rect
, &gdk_event
.area
))
3588 gtk_widget_event (child
->widget
, (GdkEvent
*) &gdk_event
);
3598 m_updateRegion
.Clear();
3601 void wxWindowGTK::Clear()
3603 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3605 if (m_wxwindow
&& m_wxwindow
->window
)
3607 m_clearRegion
.Clear();
3608 wxSize
size( GetClientSize() );
3609 m_clearRegion
.Union( 0,0,size
.x
,size
.y
);
3611 // Better do this in idle?
3617 void wxWindowGTK::DoSetToolTip( wxToolTip
*tip
)
3619 wxWindowBase::DoSetToolTip(tip
);
3622 m_tooltip
->Apply( (wxWindow
*)this );
3625 void wxWindowGTK::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3627 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3629 #endif // wxUSE_TOOLTIPS
3631 void wxWindowGTK::GtkSetBackgroundColour( const wxColour
&colour
)
3633 GdkWindow
*window
= (GdkWindow
*) NULL
;
3635 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3637 window
= GetConnectWidget()->window
;
3641 // We need the pixel value e.g. for background clearing.
3642 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3646 // wxMSW doesn't clear the window here, either.
3647 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3653 bool wxWindowGTK::SetBackgroundColour( const wxColour
&colour
)
3655 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3657 if (!wxWindowBase::SetBackgroundColour(colour
))
3660 GdkWindow
*window
= (GdkWindow
*) NULL
;
3662 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3664 window
= GetConnectWidget()->window
;
3668 // indicate that a new style has been set
3669 // but it couldn't get applied as the
3670 // widget hasn't been realized yet.
3671 m_delayedBackgroundColour
= TRUE
;
3676 GtkSetBackgroundColour( colour
);
3682 void wxWindowGTK::GtkSetForegroundColour( const wxColour
&colour
)
3684 GdkWindow
*window
= (GdkWindow
*) NULL
;
3686 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3688 window
= GetConnectWidget()->window
;
3695 bool wxWindowGTK::SetForegroundColour( const wxColour
&colour
)
3697 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3699 if (!wxWindowBase::SetForegroundColour(colour
))
3701 // don't leave if the GTK widget has just
3703 if (!m_delayedForegroundColour
) return FALSE
;
3706 GdkWindow
*window
= (GdkWindow
*) NULL
;
3708 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3710 window
= GetConnectWidget()->window
;
3714 // indicate that a new style has been set
3715 // but it couldn't get applied as the
3716 // widget hasn't been realized yet.
3717 m_delayedForegroundColour
= TRUE
;
3721 GtkSetForegroundColour( colour
);
3727 GtkStyle
*wxWindowGTK::GetWidgetStyle()
3731 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3733 // FIXME: no more klass in 2.0
3735 remake
->klass
= m_widgetStyle
->klass
;
3738 gtk_style_unref( m_widgetStyle
);
3739 m_widgetStyle
= remake
;
3743 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3746 def
= gtk_widget_get_default_style();
3748 m_widgetStyle
= gtk_style_copy( def
);
3750 // FIXME: no more klass in 2.0
3752 m_widgetStyle
->klass
= def
->klass
;
3756 return m_widgetStyle
;
3759 void wxWindowGTK::SetWidgetStyle()
3761 #if DISABLE_STYLE_IF_BROKEN_THEME
3762 if (m_widget
->style
->engine_data
)
3764 static bool s_warningPrinted
= FALSE
;
3765 if (!s_warningPrinted
)
3767 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3768 s_warningPrinted
= TRUE
;
3770 m_widgetStyle
= m_widget
->style
;
3775 GtkStyle
*style
= GetWidgetStyle();
3777 if (m_font
!= wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT
))
3779 SET_STYLE_FONT(style
, m_font
.GetInternalFont( 1.0 ));
3782 if (m_foregroundColour
.Ok())
3784 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3785 if (m_foregroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT
))
3787 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3788 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3789 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3793 // Try to restore the gtk default style. This is still a little
3794 // oversimplified for what is probably really needed here for controls
3795 // other than buttons, but is better than not being able to (re)set a
3796 // control's foreground colour to *wxBLACK -- RL
3797 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3800 def
= gtk_widget_get_default_style();
3802 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3803 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3804 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3808 if (m_backgroundColour
.Ok())
3810 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3811 if (m_backgroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
))
3813 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3814 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3815 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3816 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3817 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3818 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3819 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3820 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3824 // Try to restore the gtk default style. This is still a little
3825 // oversimplified for what is probably really needed here for controls
3826 // other than buttons, but is better than not being able to (re)set a
3827 // control's background colour to default grey and means resetting a
3828 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3830 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3833 def
= gtk_widget_get_default_style();
3835 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3836 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3837 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3838 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3839 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3840 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3841 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3842 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3847 void wxWindowGTK::ApplyWidgetStyle()
3851 //-----------------------------------------------------------------------------
3852 // Pop-up menu stuff
3853 //-----------------------------------------------------------------------------
3855 #if wxUSE_MENUS_NATIVE
3858 void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3860 *is_waiting
= FALSE
;
3863 static void SetInvokingWindow( wxMenu
*menu
, wxWindowGTK
*win
)
3865 menu
->SetInvokingWindow( win
);
3866 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3869 wxMenuItem
*menuitem
= node
->GetData();
3870 if (menuitem
->IsSubMenu())
3872 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3875 node
= node
->GetNext();
3879 // used to pass the coordinates from wxWindowGTK::DoPopupMenu() to
3880 // wxPopupMenuPositionCallback()
3882 // should be safe even in the MT case as the user can hardly popup 2 menus
3883 // simultaneously, can he?
3884 static gint gs_pop_x
= 0;
3885 static gint gs_pop_y
= 0;
3887 extern "C" void wxPopupMenuPositionCallback( GtkMenu
*menu
,
3890 gboolean
* WXUNUSED(whatever
),
3892 gpointer
WXUNUSED(user_data
) )
3894 // ensure that the menu appears entirely on screen
3896 gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
);
3898 wxSize sizeScreen
= wxGetDisplaySize();
3900 gint xmax
= sizeScreen
.x
- req
.width
,
3901 ymax
= sizeScreen
.y
- req
.height
;
3903 *x
= gs_pop_x
< xmax
? gs_pop_x
: xmax
;
3904 *y
= gs_pop_y
< ymax
? gs_pop_y
: ymax
;
3907 bool wxWindowGTK::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3909 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3911 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3913 SetInvokingWindow( menu
, this );
3919 ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3921 bool is_waiting
= TRUE
;
3923 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
),
3925 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
),
3926 (gpointer
)&is_waiting
);
3929 GTK_MENU(menu
->m_menu
),
3930 (GtkWidget
*) NULL
, // parent menu shell
3931 (GtkWidget
*) NULL
, // parent menu item
3932 wxPopupMenuPositionCallback
, // function to position it
3933 NULL
, // client data
3934 0, // button used to activate it
3935 gs_timeLastClick
// the time of activation
3940 while (gtk_events_pending())
3941 gtk_main_iteration();
3947 #endif // wxUSE_MENUS_NATIVE
3949 #if wxUSE_DRAG_AND_DROP
3951 void wxWindowGTK::SetDropTarget( wxDropTarget
*dropTarget
)
3953 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3955 GtkWidget
*dnd_widget
= GetConnectWidget();
3957 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3959 if (m_dropTarget
) delete m_dropTarget
;
3960 m_dropTarget
= dropTarget
;
3962 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3965 #endif // wxUSE_DRAG_AND_DROP
3967 GtkWidget
* wxWindowGTK::GetConnectWidget()
3969 GtkWidget
*connect_widget
= m_widget
;
3970 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3972 return connect_widget
;
3975 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow
*window
)
3978 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3980 return (window
== m_widget
->window
);
3983 bool wxWindowGTK::SetFont( const wxFont
&font
)
3985 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3987 if (!wxWindowBase::SetFont(font
))
3992 wxColour sysbg
= wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE
);
3993 if ( sysbg
== m_backgroundColour
)
3995 m_backgroundColour
= wxNullColour
;
3997 m_backgroundColour
= sysbg
;
4007 void wxWindowGTK::DoCaptureMouse()
4009 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4011 GdkWindow
*window
= (GdkWindow
*) NULL
;
4013 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
4015 window
= GetConnectWidget()->window
;
4017 wxCHECK_RET( window
, _T("CaptureMouse() failed") );
4019 wxCursor
* cursor
= & m_cursor
;
4021 cursor
= wxSTANDARD_CURSOR
;
4023 gdk_pointer_grab( window
, FALSE
,
4025 (GDK_BUTTON_PRESS_MASK
|
4026 GDK_BUTTON_RELEASE_MASK
|
4027 GDK_POINTER_MOTION_HINT_MASK
|
4028 GDK_POINTER_MOTION_MASK
),
4030 cursor
->GetCursor(),
4031 (guint32
)GDK_CURRENT_TIME
);
4032 g_captureWindow
= this;
4033 g_captureWindowHasMouse
= TRUE
;
4036 void wxWindowGTK::DoReleaseMouse()
4038 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4040 wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") );
4042 g_captureWindow
= (wxWindowGTK
*) NULL
;
4044 GdkWindow
*window
= (GdkWindow
*) NULL
;
4046 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
4048 window
= GetConnectWidget()->window
;
4053 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
4057 wxWindow
*wxWindowBase::GetCapture()
4059 return (wxWindow
*)g_captureWindow
;
4062 bool wxWindowGTK::IsRetained() const
4067 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
,
4068 int range
, bool refresh
)
4070 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4072 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4074 m_hasScrolling
= TRUE
;
4076 if (orient
== wxHORIZONTAL
)
4078 float fpos
= (float)pos
;
4079 float frange
= (float)range
;
4080 float fthumb
= (float)thumbVisible
;
4081 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
4082 if (fpos
< 0.0) fpos
= 0.0;
4084 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
4085 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
4087 SetScrollPos( orient
, pos
, refresh
);
4091 m_oldHorizontalPos
= fpos
;
4093 m_hAdjust
->lower
= 0.0;
4094 m_hAdjust
->upper
= frange
;
4095 m_hAdjust
->value
= fpos
;
4096 m_hAdjust
->step_increment
= 1.0;
4097 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
4098 m_hAdjust
->page_size
= fthumb
;
4102 float fpos
= (float)pos
;
4103 float frange
= (float)range
;
4104 float fthumb
= (float)thumbVisible
;
4105 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
4106 if (fpos
< 0.0) fpos
= 0.0;
4108 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
4109 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
4111 SetScrollPos( orient
, pos
, refresh
);
4115 m_oldVerticalPos
= fpos
;
4117 m_vAdjust
->lower
= 0.0;
4118 m_vAdjust
->upper
= frange
;
4119 m_vAdjust
->value
= fpos
;
4120 m_vAdjust
->step_increment
= 1.0;
4121 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
4122 m_vAdjust
->page_size
= fthumb
;
4125 if (orient
== wxHORIZONTAL
)
4126 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
4128 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
4131 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
4133 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4135 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4137 if (orient
== wxHORIZONTAL
)
4139 float fpos
= (float)pos
;
4140 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
4141 if (fpos
< 0.0) fpos
= 0.0;
4142 m_oldHorizontalPos
= fpos
;
4144 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
4145 m_hAdjust
->value
= fpos
;
4149 float fpos
= (float)pos
;
4150 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
4151 if (fpos
< 0.0) fpos
= 0.0;
4152 m_oldVerticalPos
= fpos
;
4154 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
4155 m_vAdjust
->value
= fpos
;
4158 if (m_wxwindow
->window
)
4160 if (orient
== wxHORIZONTAL
)
4162 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
4163 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
4165 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
4167 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
4168 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
4172 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
4173 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4175 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
4177 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
4178 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4183 int wxWindowGTK::GetScrollThumb( int orient
) const
4185 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4187 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4189 if (orient
== wxHORIZONTAL
)
4190 return (int)(m_hAdjust
->page_size
+0.5);
4192 return (int)(m_vAdjust
->page_size
+0.5);
4195 int wxWindowGTK::GetScrollPos( int orient
) const
4197 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4199 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4201 if (orient
== wxHORIZONTAL
)
4202 return (int)(m_hAdjust
->value
+0.5);
4204 return (int)(m_vAdjust
->value
+0.5);
4207 int wxWindowGTK::GetScrollRange( int orient
) const
4209 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4211 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4213 if (orient
== wxHORIZONTAL
)
4214 return (int)(m_hAdjust
->upper
+0.5);
4216 return (int)(m_vAdjust
->upper
+0.5);
4219 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
4221 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4223 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4225 // No scrolling requested.
4226 if ((dx
== 0) && (dy
== 0)) return;
4229 if (!m_updateRegion
.IsEmpty())
4231 m_updateRegion
.Offset( dx
, dy
);
4235 GetClientSize( &cw
, &ch
);
4236 m_updateRegion
.Intersect( 0, 0, cw
, ch
);
4239 if (!m_clearRegion
.IsEmpty())
4241 m_clearRegion
.Offset( dx
, dy
);
4245 GetClientSize( &cw
, &ch
);
4246 m_clearRegion
.Intersect( 0, 0, cw
, ch
);
4248 m_clipPaintRegion
= TRUE
;
4250 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
4252 m_clipPaintRegion
= FALSE
;
4255 gdk_window_scroll( GTK_PIZZA(m_wxwindow
)->bin_window
, dx
, dy
);
4257 GTK_PIZZA(m_wxwindow
)->xoffset
+= dx
;
4258 GTK_PIZZA(m_wxwindow
)->yoffset
+= dy
;
4265 // Find the wxWindow at the current mouse position, also returning the mouse
4267 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
4269 pt
= wxGetMousePosition();
4270 wxWindow
* found
= wxFindWindowAtPoint(pt
);
4274 // Get the current mouse position.
4275 wxPoint
wxGetMousePosition()
4277 /* This crashes when used within wxHelpContext,
4278 so we have to use the X-specific implementation below.
4280 GdkModifierType *mask;
4281 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
4283 return wxPoint(x, y);
4287 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
4289 return wxPoint(-999, -999);
4291 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
4292 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
4293 Window rootReturn
, childReturn
;
4294 int rootX
, rootY
, winX
, winY
;
4295 unsigned int maskReturn
;
4297 XQueryPointer (display
,
4301 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
4302 return wxPoint(rootX
, rootY
);
4306 // ----------------------------------------------------------------------------
4308 // ----------------------------------------------------------------------------
4310 class wxWinModule
: public wxModule
4317 DECLARE_DYNAMIC_CLASS(wxWinModule
)
4320 IMPLEMENT_DYNAMIC_CLASS(wxWinModule
, wxModule
)
4322 bool wxWinModule::OnInit()
4324 // g_eraseGC = gdk_gc_new( GDK_ROOT_PARENT() );
4325 // gdk_gc_set_fill( g_eraseGC, GDK_SOLID );
4330 void wxWinModule::OnExit()
4333 gdk_gc_unref( g_eraseGC
);