1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/window.cpp
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #define XWarpPointer XWARPPOINTER
20 #include "wx/window.h"
21 #include "wx/dcclient.h"
24 #include "wx/layout.h"
26 #include "wx/dialog.h"
27 #include "wx/msgdlg.h"
28 #include "wx/module.h"
30 #if wxUSE_DRAG_AND_DROP
35 #include "wx/tooltip.h"
43 #include "wx/textctrl.h"
47 #include "wx/statusbr.h"
49 #include "wx/settings.h"
53 #include "wx/thread.h"
58 #include "wx/gtk/private.h"
59 #include <gdk/gdkprivate.h>
60 #include <gdk/gdkkeysyms.h>
64 #include <gtk/gtkprivate.h>
66 #include "wx/gtk/win_gtk.h"
69 #define SET_CONTAINER_FOCUS(w, d) gtk_widget_child_focus((w), (d))
71 #define SET_CONTAINER_FOCUS(w, d) gtk_container_focus(GTK_CONTAINER(w), (d))
81 extern GtkContainerClass
*pizza_parent_class
;
84 //-----------------------------------------------------------------------------
85 // documentation on internals
86 //-----------------------------------------------------------------------------
89 I have been asked several times about writing some documentation about
90 the GTK port of wxWindows, especially its internal structures. Obviously,
91 you cannot understand wxGTK without knowing a little about the GTK, but
92 some more information about what the wxWindow, which is the base class
93 for all other window classes, does seems required as well.
97 What does wxWindow do? It contains the common interface for the following
98 jobs of its descendants:
100 1) Define the rudimentary behaviour common to all window classes, such as
101 resizing, intercepting user input (so as to make it possible to use these
102 events for special purposes in a derived class), window names etc.
104 2) Provide the possibility to contain and manage children, if the derived
105 class is allowed to contain children, which holds true for those window
106 classes which do not display a native GTK widget. To name them, these
107 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
108 work classes are a special case and are handled a bit differently from
109 the rest. The same holds true for the wxNotebook class.
111 3) Provide the possibility to draw into a client area of a window. This,
112 too, only holds true for classes that do not display a native GTK widget
115 4) Provide the entire mechanism for scrolling widgets. This actual inter-
116 face for this is usually in wxScrolledWindow, but the GTK implementation
119 5) A multitude of helper or extra methods for special purposes, such as
120 Drag'n'Drop, managing validators etc.
122 6) Display a border (sunken, raised, simple or none).
124 Normally one might expect, that one wxWindows window would always correspond
125 to one GTK widget. Under GTK, there is no such allround widget that has all
126 the functionality. Moreover, the GTK defines a client area as a different
127 widget from the actual widget you are handling. Last but not least some
128 special classes (e.g. wxFrame) handle different categories of widgets and
129 still have the possibility to draw something in the client area.
130 It was therefore required to write a special purpose GTK widget, that would
131 represent a client area in the sense of wxWindows capable to do the jobs
132 2), 3) and 4). I have written this class and it resides in win_gtk.c of
135 All windows must have a widget, with which they interact with other under-
136 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
137 thw wxWindow class has a member variable called m_widget which holds a
138 pointer to this widget. When the window class represents a GTK native widget,
139 this is (in most cases) the only GTK widget the class manages. E.g. the
140 wxStatitText class handles only a GtkLabel widget a pointer to which you
141 can find in m_widget (defined in wxWindow)
143 When the class has a client area for drawing into and for containing children
144 it has to handle the client area widget (of the type GtkPizza, defined in
145 win_gtk.c), but there could be any number of widgets, handled by a class
146 The common rule for all windows is only, that the widget that interacts with
147 the rest of GTK must be referenced in m_widget and all other widgets must be
148 children of this widget on the GTK level. The top-most widget, which also
149 represents the client area, must be in the m_wxwindow field and must be of
152 As I said, the window classes that display a GTK native widget only have
153 one widget, so in the case of e.g. the wxButton class m_widget holds a
154 pointer to a GtkButton widget. But windows with client areas (for drawing
155 and children) have a m_widget field that is a pointer to a GtkScrolled-
156 Window and a m_wxwindow field that is pointer to a GtkPizza and this
157 one is (in the GTK sense) a child of the GtkScrolledWindow.
159 If the m_wxwindow field is set, then all input to this widget is inter-
160 cepted and sent to the wxWindows class. If not, all input to the widget
161 that gets pointed to by m_widget gets intercepted and sent to the class.
165 The design of scrolling in wxWindows is markedly different from that offered
166 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
167 clicking on a scrollbar belonging to scrolled window will inevitably move
168 the window. In wxWindows, the scrollbar will only emit an event, send this
169 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
170 which actually moves the window and its subchildren. Note that GtkPizza
171 memorizes how much it has been scrolled but that wxWindows forgets this
172 so that the two coordinates systems have to be kept in synch. This is done
173 in various places using the pizza->xoffset and pizza->yoffset values.
177 Singularily the most broken code in GTK is the code that is supposes to
178 inform subwindows (child windows) about new positions. Very often, duplicate
179 events are sent without changes in size or position, equally often no
180 events are sent at all (All this is due to a bug in the GtkContainer code
181 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
182 GTK's own system and it simply waits for size events for toplevel windows
183 and then iterates down the respective size events to all window. This has
184 the disadvantage, that windows might get size events before the GTK widget
185 actually has the reported size. This doesn't normally pose any problem, but
186 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
187 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
188 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
189 window that is used for OpenGl output really has that size (as reported by
194 If someone at some point of time feels the immense desire to have a look at,
195 change or attempt to optimse the Refresh() logic, this person will need an
196 intimate understanding of what a "draw" and what an "expose" events are and
197 what there are used for, in particular when used in connection with GTK's
198 own windowless widgets. Beware.
202 Cursors, too, have been a constant source of pleasure. The main difficulty
203 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
204 for the parent. To prevent this from doing too much harm, I use idle time
205 to set the cursor over and over again, starting from the toplevel windows
206 and ending with the youngest generation (speaking of parent and child windows).
207 Also don't forget that cursors (like much else) are connected to GdkWindows,
208 not GtkWidgets and that the "window" field of a GtkWidget might very well
209 point to the GdkWindow of the parent widget (-> "window less widget") and
210 that the two obviously have very different meanings.
214 //-----------------------------------------------------------------------------
216 //-----------------------------------------------------------------------------
218 extern wxList wxPendingDelete
;
219 extern bool g_blockEventsOnDrag
;
220 extern bool g_blockEventsOnScroll
;
221 extern wxCursor g_globalCursor
;
223 static GdkGC
*g_eraseGC
= NULL
;
225 // mouse capture state: the window which has it and if the mouse is currently
227 static wxWindowGTK
*g_captureWindow
= (wxWindowGTK
*) NULL
;
228 static bool g_captureWindowHasMouse
= FALSE
;
230 /* extern */ wxWindowGTK
*g_focusWindow
= (wxWindowGTK
*) NULL
;
232 // the last window which had the focus - this is normally never NULL (except
233 // if we never had focus at all) as even when g_focusWindow is NULL it still
234 // keeps its previous value
235 static wxWindowGTK
*g_focusWindowLast
= (wxWindowGTK
*)NULL
;
237 // the frame that is currently active (i.e. its child has focus). It is
238 // used to generate wxActivateEvents
239 static wxWindowGTK
*g_activeFrame
= (wxWindowGTK
*)NULL
;
240 static bool g_activeFrameLostFocus
= FALSE
;
242 // if we detect that the app has got/lost the focus, we set this variable to
243 // either TRUE or FALSE and an activate event will be sent during the next
244 // OnIdle() call and it is reset to -1: this value means that we shouldn't
245 // send any activate events at all
246 static int g_sendActivateEvent
= -1;
248 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
249 the last click here */
250 static guint32 gs_timeLastClick
= 0;
252 extern bool g_mainThreadLocked
;
254 //-----------------------------------------------------------------------------
256 //-----------------------------------------------------------------------------
259 #define DISABLE_STYLE_IF_BROKEN_THEME 1
265 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
267 # define DEBUG_MAIN_THREAD
270 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
271 GdkEvent
*WXUNUSED(event
),
272 const wxChar
*WXUNUSED(name
) )
275 static bool s_done = FALSE;
278 wxLog::AddTraceMask("focus");
281 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
287 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
289 // suppress warnings about gtk_debug_focus_in_callback being unused with
294 tmp
+= wxT(" FROM ");
297 wxChar
*s
= new wxChar
[tmp
.Length()+1];
301 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
302 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
307 #define DEBUG_MAIN_THREAD
310 //-----------------------------------------------------------------------------
311 // missing gdk functions
312 //-----------------------------------------------------------------------------
315 gdk_window_warp_pointer (GdkWindow
*window
,
320 GdkWindowPrivate
*priv
;
324 window
= GDK_ROOT_PARENT();
327 if (!GDK_WINDOW_DESTROYED(window
))
329 XWarpPointer (GDK_WINDOW_XDISPLAY(window
),
330 None
, /* not source window -> move from anywhere */
331 GDK_WINDOW_XID(window
), /* dest window */
332 0, 0, 0, 0, /* not source window -> move from anywhere */
336 priv
= (GdkWindowPrivate
*) window
;
338 if (!priv
->destroyed
)
340 XWarpPointer (priv
->xdisplay
,
341 None
, /* not source window -> move from anywhere */
342 priv
->xwindow
, /* dest window */
343 0, 0, 0, 0, /* not source window -> move from anywhere */
349 //-----------------------------------------------------------------------------
351 //-----------------------------------------------------------------------------
353 extern void wxapp_install_idle_handler();
354 extern bool g_isIdle
;
356 //-----------------------------------------------------------------------------
357 // local code (see below)
358 //-----------------------------------------------------------------------------
360 // returns the child of win which currently has focus or NULL if not found
362 // Note: can't be static, needed by textctrl.cpp.
363 wxWindow
*wxFindFocusedChild(wxWindowGTK
*win
)
365 wxWindow
*winFocus
= wxWindowGTK::FindFocus();
367 return (wxWindow
*)NULL
;
369 if ( winFocus
== win
)
370 return (wxWindow
*)win
;
372 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
374 node
= node
->GetNext() )
376 wxWindow
*child
= wxFindFocusedChild(node
->GetData());
381 return (wxWindow
*)NULL
;
384 // Returns toplevel grandparent of given window:
385 static wxWindowGTK
* wxGetTopLevelParent(wxWindowGTK
*win
)
387 wxWindowGTK
*p
= win
;
388 while (p
&& !p
->IsTopLevel())
393 static void draw_frame( GtkWidget
*widget
, wxWindowGTK
*win
)
395 // wxUniversal widgets draw the borders and scrollbars themselves
396 #ifndef __WXUNIVERSAL__
403 if (win
->m_hasScrolling
)
405 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
407 GtkRequisition vscroll_req
;
408 vscroll_req
.width
= 2;
409 vscroll_req
.height
= 2;
410 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
411 (scroll_window
->vscrollbar
, &vscroll_req
);
413 GtkRequisition hscroll_req
;
414 hscroll_req
.width
= 2;
415 hscroll_req
.height
= 2;
416 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
417 (scroll_window
->hscrollbar
, &hscroll_req
);
419 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) );
421 if (scroll_window
->vscrollbar_visible
)
423 dw
+= vscroll_req
.width
;
424 dw
+= scroll_class
->scrollbar_spacing
;
427 if (scroll_window
->hscrollbar_visible
)
429 dh
+= hscroll_req
.height
;
430 dh
+= scroll_class
->scrollbar_spacing
;
436 if (GTK_WIDGET_NO_WINDOW (widget
))
438 dx
+= widget
->allocation
.x
;
439 dy
+= widget
->allocation
.y
;
442 if (win
->HasFlag(wxRAISED_BORDER
))
444 gtk_draw_shadow( widget
->style
,
449 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
453 if (win
->HasFlag(wxSUNKEN_BORDER
))
455 gtk_draw_shadow( widget
->style
,
460 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
464 if (win
->HasFlag(wxSIMPLE_BORDER
))
467 gc
= gdk_gc_new( widget
->window
);
468 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
469 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
471 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
475 #endif // __WXUNIVERSAL__
478 //-----------------------------------------------------------------------------
479 // "expose_event" of m_widget
480 //-----------------------------------------------------------------------------
482 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindowGTK
*win
)
484 if (gdk_event
->count
> 0) return FALSE
;
486 draw_frame( widget
, win
);
490 (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
);
496 //-----------------------------------------------------------------------------
497 // "draw" of m_widget
498 //-----------------------------------------------------------------------------
502 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindowGTK
*win
)
504 draw_frame( widget
, win
);
509 //-----------------------------------------------------------------------------
510 // key code mapping routines
511 //-----------------------------------------------------------------------------
513 static long map_to_unmodified_wx_keysym( GdkEventKey
*event
)
515 // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string
516 // but only event->keyval which is quite useless to us, so remember
517 // the last character from GDK_KEY_PRESS and resue it as last resort
519 // NB: should be MT-neutral as always called from main thread only
524 } s_lastKeyPress
= { 0, 0 };
526 KeySym keysym
= event
->keyval
;
532 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
534 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
540 case GDK_Super_R
: key_code
= WXK_ALT
; break;
541 case GDK_Menu
: key_code
= WXK_MENU
; break;
542 case GDK_Help
: key_code
= WXK_HELP
; break;
543 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
544 case GDK_ISO_Left_Tab
:
545 case GDK_Tab
: key_code
= WXK_TAB
; break;
546 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
547 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
548 case GDK_Return
: key_code
= WXK_RETURN
; break;
549 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
550 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
551 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
552 case GDK_Delete
: key_code
= WXK_DELETE
; break;
553 case GDK_Home
: key_code
= WXK_HOME
; break;
554 case GDK_Left
: key_code
= WXK_LEFT
; break;
555 case GDK_Up
: key_code
= WXK_UP
; break;
556 case GDK_Right
: key_code
= WXK_RIGHT
; break;
557 case GDK_Down
: key_code
= WXK_DOWN
; break;
558 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
559 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
560 case GDK_Next
: key_code
= WXK_NEXT
; break;
561 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
562 case GDK_End
: key_code
= WXK_END
; break;
563 case GDK_Begin
: key_code
= WXK_HOME
; break;
564 case GDK_Select
: key_code
= WXK_SELECT
; break;
565 case GDK_Print
: key_code
= WXK_PRINT
; break;
566 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
567 case GDK_Insert
: key_code
= WXK_INSERT
; break;
568 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
570 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
571 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
572 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
573 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
574 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
575 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
576 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
577 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
578 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
579 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
580 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
581 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
582 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
583 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
584 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
585 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
586 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
587 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
588 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
589 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
590 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
591 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
592 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
593 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
594 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
595 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
596 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
597 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
598 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
599 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
600 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
601 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
602 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
603 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
604 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
605 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
606 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
608 case GDK_F1
: key_code
= WXK_F1
; break;
609 case GDK_F2
: key_code
= WXK_F2
; break;
610 case GDK_F3
: key_code
= WXK_F3
; break;
611 case GDK_F4
: key_code
= WXK_F4
; break;
612 case GDK_F5
: key_code
= WXK_F5
; break;
613 case GDK_F6
: key_code
= WXK_F6
; break;
614 case GDK_F7
: key_code
= WXK_F7
; break;
615 case GDK_F8
: key_code
= WXK_F8
; break;
616 case GDK_F9
: key_code
= WXK_F9
; break;
617 case GDK_F10
: key_code
= WXK_F10
; break;
618 case GDK_F11
: key_code
= WXK_F11
; break;
619 case GDK_F12
: key_code
= WXK_F12
; break;
622 // do we have the translation?
623 if ( event
->length
== 1 )
625 keysym
= (KeySym
)event
->string
[0];
627 else if ( (keysym
& 0xFF) != keysym
)
629 // non ASCII key, what to do?
631 if ( event
->type
== GDK_KEY_RELEASE
)
633 // reuse the one from the last keypress if any
634 if ( keysym
== s_lastKeyPress
.keysym
)
636 key_code
= s_lastKeyPress
.keycode
;
643 // ignore this one, we don't know it
646 //else: ASCII key, ok
648 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
649 key_code
= upper
? upper
: keysym
;
651 if ( event
->type
== GDK_KEY_PRESS
)
653 // remember it to be reused below later
654 s_lastKeyPress
.keysym
= keysym
;
655 s_lastKeyPress
.keycode
= key_code
;
663 static long map_to_wx_keysym( GdkEventKey
*event
)
665 KeySym keysym
= event
->keyval
;
670 case GDK_Menu
: key_code
= WXK_MENU
; break;
671 case GDK_Help
: key_code
= WXK_HELP
; break;
672 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
673 case GDK_ISO_Left_Tab
:
674 case GDK_Tab
: key_code
= WXK_TAB
; break;
675 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
676 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
677 case GDK_Return
: key_code
= WXK_RETURN
; break;
678 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
679 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
680 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
681 case GDK_Delete
: key_code
= WXK_DELETE
; break;
682 case GDK_Home
: key_code
= WXK_HOME
; break;
683 case GDK_Left
: key_code
= WXK_LEFT
; break;
684 case GDK_Up
: key_code
= WXK_UP
; break;
685 case GDK_Right
: key_code
= WXK_RIGHT
; break;
686 case GDK_Down
: key_code
= WXK_DOWN
; break;
687 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
688 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
689 case GDK_Next
: key_code
= WXK_NEXT
; break;
690 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
691 case GDK_End
: key_code
= WXK_END
; break;
692 case GDK_Begin
: key_code
= WXK_HOME
; break;
693 case GDK_Select
: key_code
= WXK_SELECT
; break;
694 case GDK_Print
: key_code
= WXK_PRINT
; break;
695 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
696 case GDK_Insert
: key_code
= WXK_INSERT
; break;
697 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
699 case GDK_KP_0
: key_code
= '0'; break;
700 case GDK_KP_1
: key_code
= '1'; break;
701 case GDK_KP_2
: key_code
= '2'; break;
702 case GDK_KP_3
: key_code
= '3'; break;
703 case GDK_KP_4
: key_code
= '4'; break;
704 case GDK_KP_5
: key_code
= '5'; break;
705 case GDK_KP_6
: key_code
= '6'; break;
706 case GDK_KP_7
: key_code
= '7'; break;
707 case GDK_KP_8
: key_code
= '8'; break;
708 case GDK_KP_9
: key_code
= '9'; break;
709 case GDK_KP_Space
: key_code
= ' '; break;
710 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
711 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
712 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
713 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
714 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
715 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
716 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
717 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
718 case GDK_KP_Up
: key_code
= WXK_UP
; break;
719 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
720 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
721 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
722 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
723 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
724 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
725 case GDK_KP_End
: key_code
= WXK_END
; break;
726 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
727 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
728 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
729 case GDK_KP_Equal
: key_code
= '='; break;
730 case GDK_KP_Multiply
: key_code
= '*'; break;
731 case GDK_KP_Add
: key_code
= '+'; break;
732 case GDK_KP_Separator
: key_code
= ','; break;
733 case GDK_KP_Subtract
: key_code
= '-'; break;
734 case GDK_KP_Decimal
: key_code
= '.'; break;
735 case GDK_KP_Divide
: key_code
= '/'; break;
737 case GDK_F1
: key_code
= WXK_F1
; break;
738 case GDK_F2
: key_code
= WXK_F2
; break;
739 case GDK_F3
: key_code
= WXK_F3
; break;
740 case GDK_F4
: key_code
= WXK_F4
; break;
741 case GDK_F5
: key_code
= WXK_F5
; break;
742 case GDK_F6
: key_code
= WXK_F6
; break;
743 case GDK_F7
: key_code
= WXK_F7
; break;
744 case GDK_F8
: key_code
= WXK_F8
; break;
745 case GDK_F9
: key_code
= WXK_F9
; break;
746 case GDK_F10
: key_code
= WXK_F10
; break;
747 case GDK_F11
: key_code
= WXK_F11
; break;
748 case GDK_F12
: key_code
= WXK_F12
; break;
750 if (event
->length
== 1)
752 key_code
= (unsigned char)*event
->string
;
754 else if ((keysym
& 0xFF) == keysym
)
756 key_code
= (guint
)keysym
;
763 //-----------------------------------------------------------------------------
764 // "size_request" of m_widget
765 //-----------------------------------------------------------------------------
767 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
770 win
->GetSize( &w
, &h
);
774 requisition
->height
= h
;
775 requisition
->width
= w
;
778 //-----------------------------------------------------------------------------
779 // "expose_event" of m_wxwindow
780 //-----------------------------------------------------------------------------
782 static int gtk_window_expose_callback( GtkWidget
*widget
,
783 GdkEventExpose
*gdk_event
,
789 wxapp_install_idle_handler();
792 if (win->GetName() == wxT("panel"))
794 wxPrintf( wxT("OnExpose from ") );
795 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
796 wxPrintf( win->GetClassInfo()->GetClassName() );
797 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
798 (int)gdk_event->area.y,
799 (int)gdk_event->area.width,
800 (int)gdk_event->area.height );
804 #ifndef __WXUNIVERSAL__
805 GtkPizza
*pizza
= GTK_PIZZA (widget
);
807 if (win
->GetThemeEnabled())
809 wxWindow
*parent
= win
->GetParent();
810 while (parent
&& !parent
->IsTopLevel())
811 parent
= parent
->GetParent();
815 gtk_paint_flat_box (parent
->m_widget
->style
,
826 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
828 gdk_event
->area
.width
,
829 gdk_event
->area
.height
);
831 // Actual redrawing takes place in idle time.
836 (* GTK_WIDGET_CLASS (pizza_parent_class
)->expose_event
) (widget
, gdk_event
);
843 //-----------------------------------------------------------------------------
844 // "event" of m_wxwindow
845 //-----------------------------------------------------------------------------
847 // GTK thinks it is clever and filters out a certain amount of "unneeded"
848 // expose events. We need them, of course, so we override the main event
849 // procedure in GtkWidget by giving our own handler for all system events.
850 // There, we look for expose events ourselves whereas all other events are
853 gint
gtk_window_event_event_callback( GtkWidget
*widget
,
854 GdkEventExpose
*event
,
857 if (event
->type
== GDK_EXPOSE
)
859 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
866 //-----------------------------------------------------------------------------
867 // "draw" of m_wxwindow
868 //-----------------------------------------------------------------------------
872 // This callback is a complete replacement of the gtk_pizza_draw() function,
873 // which is disabled.
875 static void gtk_window_draw_callback( GtkWidget
*widget
,
882 wxapp_install_idle_handler();
884 // The wxNO_FULL_REPAINT_ON_RESIZE flag only works if
885 // there are no child windows.
886 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
887 (win
->GetChildren().GetCount() == 0))
893 if (win->GetName() == wxT("panel"))
895 wxPrintf( wxT("OnDraw from ") );
896 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
897 wxPrintf( win->GetClassInfo()->GetClassName() );
898 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
905 #ifndef __WXUNIVERSAL__
906 GtkPizza
*pizza
= GTK_PIZZA (widget
);
908 if (win
->GetThemeEnabled())
910 wxWindow
*parent
= win
->GetParent();
911 while (parent
&& !parent
->IsTopLevel())
912 parent
= parent
->GetParent();
916 gtk_paint_flat_box (parent
->m_widget
->style
,
927 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
928 (pizza
->clear_on_draw
))
930 gdk_window_clear_area( pizza
->bin_window
,
931 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
935 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
937 // Actual redrawing takes place in idle time.
941 #ifndef __WXUNIVERSAL__
942 // Redraw child widgets
943 GList
*children
= pizza
->children
;
946 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
947 children
= children
->next
;
949 GdkRectangle child_area
;
950 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
952 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
960 //-----------------------------------------------------------------------------
961 // "key_press_event" from any window
962 //-----------------------------------------------------------------------------
964 // turn on to see the key event codes on the console
965 #undef DEBUG_KEY_EVENTS
967 static gint
gtk_window_key_press_callback( GtkWidget
*widget
,
968 GdkEventKey
*gdk_event
,
974 wxapp_install_idle_handler();
976 if (!win
->m_hasVMT
) return FALSE
;
977 if (g_blockEventsOnDrag
) return FALSE
;
982 GdkModifierType state
;
983 if (gdk_event
->window
)
984 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
988 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
990 #ifdef DEBUG_KEY_EVENTS
991 wxPrintf(_T("Key press event: %d => %ld\n"), gdk_event
->keyval
, key_code
);
992 #endif // DEBUG_KEY_EVENTS
994 /* sending unknown key events doesn't really make sense */
998 wxKeyEvent
event( wxEVT_KEY_DOWN
);
999 event
.SetTimestamp( gdk_event
->time
);
1000 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1001 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1002 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1003 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1004 event
.m_keyCode
= key_code
;
1005 event
.m_scanCode
= gdk_event
->keyval
;
1006 event
.m_rawCode
= (wxUint32
) gdk_event
->keyval
;
1007 event
.m_rawFlags
= 0;
1010 event
.SetEventObject( win
);
1011 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1016 wxWindowGTK
*ancestor
= win
;
1019 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
1022 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
1023 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
1026 if (ancestor
->IsTopLevel())
1028 ancestor
= ancestor
->GetParent();
1031 #endif // wxUSE_ACCEL
1033 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
1034 will only be sent if it is not in an accelerator table. */
1037 key_code
= map_to_wx_keysym( gdk_event
);
1041 #ifdef DEBUG_KEY_EVENTS
1042 wxPrintf(_T("Char event: %ld\n"), key_code
);
1043 #endif // DEBUG_KEY_EVENTS
1045 // reuse the ame event object, just change its type and use the
1046 // translated keycode instead of the raw one
1047 event
.SetEventType(wxEVT_CHAR
);
1048 event
.m_keyCode
= key_code
;
1050 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1054 /* win is a control: tab can be propagated up */
1056 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
1057 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
1058 // have this style, yet choose not to process this particular TAB in which
1059 // case TAB must still work as a navigational character
1061 !win
->HasFlag(wxTE_PROCESS_TAB
) &&
1063 win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
1065 wxNavigationKeyEvent new_event
;
1066 new_event
.SetEventObject( win
->GetParent() );
1067 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
1068 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
1069 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1070 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
1071 new_event
.SetCurrentFocus( win
);
1072 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
1075 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
1077 (gdk_event
->keyval
== GDK_Escape
) )
1079 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
1080 new_event
.SetEventObject( win
);
1081 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
1085 #if 0 // (GTK_MINOR_VERSION > 0)
1086 /* Pressing F10 will activate the menu bar of the top frame. */
1088 (gdk_event
->keyval
== GDK_F10
) )
1090 wxWindowGTK
*ancestor
= win
;
1093 if (wxIsKindOf(ancestor
,wxFrame
))
1095 wxFrame
*frame
= (wxFrame
*) ancestor
;
1096 wxMenuBar
*menubar
= frame
->GetMenuBar();
1099 wxNode
*node
= menubar
->GetMenus().First();
1102 wxMenu
*firstMenu
= (wxMenu
*) node
->Data();
1103 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu
->m_owner
) );
1109 ancestor
= ancestor
->GetParent();
1116 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1123 //-----------------------------------------------------------------------------
1124 // "key_release_event" from any window
1125 //-----------------------------------------------------------------------------
1127 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindowGTK
*win
)
1132 wxapp_install_idle_handler();
1134 if (!win
->m_hasVMT
) return FALSE
;
1135 if (g_blockEventsOnDrag
) return FALSE
;
1137 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
1139 #ifdef DEBUG_KEY_EVENTS
1140 wxPrintf(_T("Key release event: %d => %ld\n"), gdk_event
->keyval
, key_code
);
1141 #endif // DEBUG_KEY_EVENTS
1143 /* sending unknown key events doesn't really make sense */
1144 if (key_code
== 0) return FALSE
;
1148 GdkModifierType state
;
1149 if (gdk_event
->window
)
1150 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1152 wxKeyEvent
event( wxEVT_KEY_UP
);
1153 event
.SetTimestamp( gdk_event
->time
);
1154 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1155 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1156 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1157 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1158 event
.m_keyCode
= key_code
;
1159 event
.m_scanCode
= gdk_event
->keyval
;
1160 event
.m_rawCode
= (wxUint32
) gdk_event
->keyval
;
1161 event
.m_rawFlags
= 0;
1164 event
.SetEventObject( win
);
1166 if (win
->GetEventHandler()->ProcessEvent( event
))
1168 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1175 // ============================================================================
1177 // ============================================================================
1179 // init wxMouseEvent with the info from gdk_event
1180 #define InitMouseEvent(win, event, gdk_event) \
1182 event.SetTimestamp( gdk_event->time ); \
1183 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
1184 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
1185 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
1186 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
1187 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
1188 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
1189 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
1191 wxPoint pt = win->GetClientAreaOrigin(); \
1192 event.m_x = (wxCoord)gdk_event->x - pt.x; \
1193 event.m_y = (wxCoord)gdk_event->y - pt.y; \
1196 // ----------------------------------------------------------------------------
1197 // mouse event processing helper
1198 // ----------------------------------------------------------------------------
1200 static void AdjustEventButtonState(wxMouseEvent
& event
)
1202 // GDK reports the old state of the button for a button press event, but
1203 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1204 // for a LEFT_DOWN event, not FALSE, so we will invert
1205 // left/right/middleDown for the corresponding click events
1207 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1208 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1209 (event
.GetEventType() == wxEVT_LEFT_UP
))
1211 event
.m_leftDown
= !event
.m_leftDown
;
1215 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1216 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1217 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1219 event
.m_middleDown
= !event
.m_middleDown
;
1223 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1224 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1225 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1227 event
.m_rightDown
= !event
.m_rightDown
;
1232 //-----------------------------------------------------------------------------
1233 // "button_press_event"
1234 //-----------------------------------------------------------------------------
1236 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1241 wxapp_install_idle_handler();
1244 wxPrintf( wxT("1) OnButtonPress from ") );
1245 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1246 wxPrintf( win->GetClassInfo()->GetClassName() );
1247 wxPrintf( wxT(".\n") );
1249 if (!win
->m_hasVMT
) return FALSE
;
1250 if (g_blockEventsOnDrag
) return TRUE
;
1251 if (g_blockEventsOnScroll
) return TRUE
;
1253 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1255 if (win
->m_wxwindow
&& (g_focusWindow
!= win
) && win
->AcceptsFocus())
1257 gtk_widget_grab_focus( win
->m_wxwindow
);
1259 wxPrintf( wxT("GrabFocus from ") );
1260 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1261 wxPrintf( win->GetClassInfo()->GetClassName() );
1262 wxPrintf( wxT(".\n") );
1266 wxEventType event_type
= wxEVT_NULL
;
1268 if (gdk_event
->button
== 1)
1270 switch (gdk_event
->type
)
1272 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1273 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1277 else if (gdk_event
->button
== 2)
1279 switch (gdk_event
->type
)
1281 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1282 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1286 else if (gdk_event
->button
== 3)
1288 switch (gdk_event
->type
)
1290 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1291 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1296 if ( event_type
== wxEVT_NULL
)
1298 // unknown mouse button or click type
1302 wxMouseEvent
event( event_type
);
1303 InitMouseEvent( win
, event
, gdk_event
);
1305 AdjustEventButtonState(event
);
1307 // wxListBox actually get mouse events from the item
1309 if (win
->m_isListBox
)
1311 event
.m_x
+= widget
->allocation
.x
;
1312 event
.m_y
+= widget
->allocation
.y
;
1315 // Some control don't have their own X window and thus cannot get
1318 if (!g_captureWindow
)
1320 wxCoord x
= event
.m_x
;
1321 wxCoord y
= event
.m_y
;
1322 if (win
->m_wxwindow
)
1324 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1325 x
+= pizza
->xoffset
;
1326 y
+= pizza
->yoffset
;
1329 wxNode
*node
= win
->GetChildren().First();
1332 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1334 node
= node
->Next();
1335 if (!child
->IsShown())
1338 if (child
->m_isStaticBox
)
1340 // wxStaticBox is transparent in the box itself
1341 int xx1
= child
->m_x
;
1342 int yy1
= child
->m_y
;
1343 int xx2
= child
->m_x
+ child
->m_width
;
1344 int yy2
= child
->m_x
+ child
->m_height
;
1347 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1349 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1351 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1353 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1356 event
.m_x
-= child
->m_x
;
1357 event
.m_y
-= child
->m_y
;
1364 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1365 (child
->m_x
<= x
) &&
1366 (child
->m_y
<= y
) &&
1367 (child
->m_x
+child
->m_width
>= x
) &&
1368 (child
->m_y
+child
->m_height
>= y
))
1371 event
.m_x
-= child
->m_x
;
1372 event
.m_y
-= child
->m_y
;
1379 event
.SetEventObject( win
);
1381 gs_timeLastClick
= gdk_event
->time
;
1384 wxPrintf( wxT("2) OnButtonPress from ") );
1385 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1386 wxPrintf( win->GetClassInfo()->GetClassName() );
1387 wxPrintf( wxT(".\n") );
1390 if (win
->GetEventHandler()->ProcessEvent( event
))
1392 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1399 //-----------------------------------------------------------------------------
1400 // "button_release_event"
1401 //-----------------------------------------------------------------------------
1403 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1408 wxapp_install_idle_handler();
1410 if (!win
->m_hasVMT
) return FALSE
;
1411 if (g_blockEventsOnDrag
) return FALSE
;
1412 if (g_blockEventsOnScroll
) return FALSE
;
1414 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1417 printf( "OnButtonRelease from " );
1418 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1419 printf( win->GetClassInfo()->GetClassName() );
1423 wxEventType event_type
= wxEVT_NULL
;
1425 switch (gdk_event
->button
)
1427 case 1: event_type
= wxEVT_LEFT_UP
; break;
1428 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1429 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1430 default: return FALSE
;
1433 wxMouseEvent
event( event_type
);
1434 InitMouseEvent( win
, event
, gdk_event
);
1436 AdjustEventButtonState(event
);
1438 // wxListBox actually get mouse events from the item
1440 if (win
->m_isListBox
)
1442 event
.m_x
+= widget
->allocation
.x
;
1443 event
.m_y
+= widget
->allocation
.y
;
1446 // Some control don't have their own X window and thus cannot get
1449 if (!g_captureWindow
)
1451 wxCoord x
= event
.m_x
;
1452 wxCoord y
= event
.m_y
;
1453 if (win
->m_wxwindow
)
1455 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1456 x
+= pizza
->xoffset
;
1457 y
+= pizza
->yoffset
;
1460 wxNode
*node
= win
->GetChildren().First();
1463 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1465 node
= node
->Next();
1466 if (!child
->IsShown())
1469 if (child
->m_isStaticBox
)
1471 // wxStaticBox is transparent in the box itself
1472 int xx1
= child
->m_x
;
1473 int yy1
= child
->m_y
;
1474 int xx2
= child
->m_x
+ child
->m_width
;
1475 int yy2
= child
->m_x
+ child
->m_height
;
1478 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1480 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1482 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1484 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1487 event
.m_x
-= child
->m_x
;
1488 event
.m_y
-= child
->m_y
;
1495 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1496 (child
->m_x
<= x
) &&
1497 (child
->m_y
<= y
) &&
1498 (child
->m_x
+child
->m_width
>= x
) &&
1499 (child
->m_y
+child
->m_height
>= y
))
1502 event
.m_x
-= child
->m_x
;
1503 event
.m_y
-= child
->m_y
;
1510 event
.SetEventObject( win
);
1512 if (win
->GetEventHandler()->ProcessEvent( event
))
1514 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1521 //-----------------------------------------------------------------------------
1522 // "motion_notify_event"
1523 //-----------------------------------------------------------------------------
1525 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
,
1526 GdkEventMotion
*gdk_event
,
1532 wxapp_install_idle_handler();
1534 if (!win
->m_hasVMT
) return FALSE
;
1535 if (g_blockEventsOnDrag
) return FALSE
;
1536 if (g_blockEventsOnScroll
) return FALSE
;
1538 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1540 if (gdk_event
->is_hint
)
1544 GdkModifierType state
;
1545 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1551 printf( "OnMotion from " );
1552 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1553 printf( win->GetClassInfo()->GetClassName() );
1557 wxMouseEvent
event( wxEVT_MOTION
);
1558 InitMouseEvent(win
, event
, gdk_event
);
1560 if ( g_captureWindow
)
1562 // synthetize a mouse enter or leave event if needed
1563 GdkWindow
*winUnderMouse
= gdk_window_at_pointer(NULL
, NULL
);
1564 bool hasMouse
= winUnderMouse
== gdk_event
->window
;
1565 if ( hasMouse
!= g_captureWindowHasMouse
)
1567 // the mouse changed window
1568 g_captureWindowHasMouse
= hasMouse
;
1570 wxMouseEvent
event(g_captureWindowHasMouse
? wxEVT_ENTER_WINDOW
1571 : wxEVT_LEAVE_WINDOW
);
1572 InitMouseEvent(win
, event
, gdk_event
);
1573 event
.SetEventObject(win
);
1574 win
->GetEventHandler()->ProcessEvent(event
);
1579 // Some control don't have their own X window and thus cannot get
1582 wxCoord x
= event
.m_x
;
1583 wxCoord y
= event
.m_y
;
1584 if (win
->m_wxwindow
)
1586 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1587 x
+= pizza
->xoffset
;
1588 y
+= pizza
->yoffset
;
1591 wxNode
*node
= win
->GetChildren().First();
1594 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1596 node
= node
->Next();
1597 if (!child
->IsShown())
1600 if (child
->m_isStaticBox
)
1602 // wxStaticBox is transparent in the box itself
1603 int xx1
= child
->m_x
;
1604 int yy1
= child
->m_y
;
1605 int xx2
= child
->m_x
+ child
->m_width
;
1606 int yy2
= child
->m_x
+ child
->m_height
;
1609 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1611 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1613 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1615 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1618 event
.m_x
-= child
->m_x
;
1619 event
.m_y
-= child
->m_y
;
1626 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1627 (child
->m_x
<= x
) &&
1628 (child
->m_y
<= y
) &&
1629 (child
->m_x
+child
->m_width
>= x
) &&
1630 (child
->m_y
+child
->m_height
>= y
))
1633 event
.m_x
-= child
->m_x
;
1634 event
.m_y
-= child
->m_y
;
1641 event
.SetEventObject( win
);
1643 if (win
->GetEventHandler()->ProcessEvent( event
))
1645 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1652 //-----------------------------------------------------------------------------
1654 //-----------------------------------------------------------------------------
1656 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
,
1657 GdkEvent
*WXUNUSED(event
),
1663 wxapp_install_idle_handler();
1665 if (!win
->m_hasVMT
) return FALSE
;
1666 if (g_blockEventsOnDrag
) return FALSE
;
1668 switch ( g_sendActivateEvent
)
1671 // we've got focus from outside, synthetize wxActivateEvent
1672 g_sendActivateEvent
= 1;
1676 // another our window just lost focus, it was already ours before
1677 // - don't send any wxActivateEvent
1678 g_sendActivateEvent
= -1;
1683 g_focusWindow
= win
;
1686 wxLogDebug( wxT("OnSetFocus from %s\n"), win
->GetName().c_str() );
1689 // notify the parent keeping track of focus for the kbd navigation
1690 // purposes that we got it
1691 wxChildFocusEvent
eventFocus(win
);
1692 (void)win
->GetEventHandler()->ProcessEvent(eventFocus
);
1696 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1700 // caret needs to be informed about focus change
1701 wxCaret
*caret
= win
->GetCaret();
1704 caret
->OnSetFocus();
1706 #endif // wxUSE_CARET
1708 wxWindowGTK
*active
= wxGetTopLevelParent(win
);
1709 if ( active
!= g_activeFrame
)
1711 if ( g_activeFrame
)
1713 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame
);
1714 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
1715 event
.SetEventObject(g_activeFrame
);
1716 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1719 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active
);
1720 g_activeFrame
= active
;
1721 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId());
1722 event
.SetEventObject(g_activeFrame
);
1723 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1725 g_activeFrameLostFocus
= FALSE
;
1728 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1729 event
.SetEventObject( win
);
1731 if (win
->GetEventHandler()->ProcessEvent( event
))
1733 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1741 //-----------------------------------------------------------------------------
1742 // "focus_out_event"
1743 //-----------------------------------------------------------------------------
1745 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEventFocus
*gdk_event
, wxWindowGTK
*win
)
1750 wxapp_install_idle_handler();
1752 if (!win
->m_hasVMT
) return FALSE
;
1753 if (g_blockEventsOnDrag
) return FALSE
;
1756 wxLogDebug( wxT("OnKillFocus from %s"), win
->GetName().c_str() );
1759 if ( !g_activeFrameLostFocus
&& g_activeFrame
)
1761 // VZ: commenting this out because it does happen (although not easy
1762 // to reproduce, I only see it when using wxMiniFrame and not
1763 // always) and makes using Mahogany quite annoying
1765 wxASSERT_MSG( wxGetTopLevelParent(win
) == g_activeFrame
,
1766 wxT("unfocusing window that hasn't gained focus properly") )
1769 g_activeFrameLostFocus
= TRUE
;
1772 // if the focus goes out of our app alltogether, OnIdle() will send
1773 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1774 // g_sendActivateEvent to -1
1775 g_sendActivateEvent
= 0;
1777 wxWindowGTK
*winFocus
= wxFindFocusedChild(win
);
1781 g_focusWindow
= (wxWindowGTK
*)NULL
;
1789 // caret needs to be informed about focus change
1790 wxCaret
*caret
= win
->GetCaret();
1793 caret
->OnKillFocus();
1795 #endif // wxUSE_CARET
1797 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1798 event
.SetEventObject( win
);
1800 if (win
->GetEventHandler()->ProcessEvent( event
))
1802 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1809 //-----------------------------------------------------------------------------
1810 // "enter_notify_event"
1811 //-----------------------------------------------------------------------------
1813 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1818 wxapp_install_idle_handler();
1820 if (!win
->m_hasVMT
) return FALSE
;
1821 if (g_blockEventsOnDrag
) return FALSE
;
1823 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1825 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1826 event
.SetTimestamp( gdk_event
->time
);
1827 event
.SetEventObject( win
);
1831 GdkModifierType state
= (GdkModifierType
)0;
1833 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1835 InitMouseEvent(win
, event
, gdk_event
);
1836 wxPoint pt
= win
->GetClientAreaOrigin();
1837 event
.m_x
= x
+ pt
.x
;
1838 event
.m_y
= y
+ pt
.y
;
1840 if (win
->GetEventHandler()->ProcessEvent( event
))
1842 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1849 //-----------------------------------------------------------------------------
1850 // "leave_notify_event"
1851 //-----------------------------------------------------------------------------
1853 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1858 wxapp_install_idle_handler();
1860 if (!win
->m_hasVMT
) return FALSE
;
1861 if (g_blockEventsOnDrag
) return FALSE
;
1863 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1865 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1866 event
.SetTimestamp( gdk_event
->time
);
1867 event
.SetEventObject( win
);
1871 GdkModifierType state
= (GdkModifierType
)0;
1873 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1875 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1876 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1877 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1878 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1879 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1880 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1881 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1883 wxPoint pt
= win
->GetClientAreaOrigin();
1884 event
.m_x
= x
+ pt
.x
;
1885 event
.m_y
= y
+ pt
.y
;
1887 if (win
->GetEventHandler()->ProcessEvent( event
))
1889 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1896 //-----------------------------------------------------------------------------
1897 // "value_changed" from m_vAdjust
1898 //-----------------------------------------------------------------------------
1900 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
,
1907 wxapp_install_idle_handler();
1909 if (g_blockEventsOnDrag
) return;
1911 if (!win
->m_hasVMT
) return;
1913 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1914 if (fabs(diff
) < 0.2) return;
1916 win
->m_oldVerticalPos
= adjust
->value
;
1918 wxEventType command
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(win
->m_widget
));
1920 int value
= (int)(adjust
->value
+0.5);
1922 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1923 event
.SetEventObject( win
);
1924 win
->GetEventHandler()->ProcessEvent( event
);
1927 //-----------------------------------------------------------------------------
1928 // "value_changed" from m_hAdjust
1929 //-----------------------------------------------------------------------------
1931 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
,
1938 wxapp_install_idle_handler();
1940 if (g_blockEventsOnDrag
) return;
1941 if (!win
->m_hasVMT
) return;
1943 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1944 if (fabs(diff
) < 0.2) return;
1946 wxEventType command
= GtkScrollWinTypeToWx(GET_SCROLL_TYPE(win
->m_widget
));
1948 win
->m_oldHorizontalPos
= adjust
->value
;
1950 int value
= (int)(adjust
->value
+0.5);
1952 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1953 event
.SetEventObject( win
);
1954 win
->GetEventHandler()->ProcessEvent( event
);
1957 //-----------------------------------------------------------------------------
1958 // "button_press_event" from scrollbar
1959 //-----------------------------------------------------------------------------
1961 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1962 GdkEventButton
*gdk_event
,
1968 wxapp_install_idle_handler();
1971 g_blockEventsOnScroll
= TRUE
;
1973 // FIXME: there is no 'slider' field in GTK+ 2.0 any more
1975 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1981 //-----------------------------------------------------------------------------
1982 // "button_release_event" from scrollbar
1983 //-----------------------------------------------------------------------------
1985 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1986 GdkEventButton
*WXUNUSED(gdk_event
),
1991 // don't test here as we can release the mouse while being over
1992 // a different window than the slider
1994 // if (gdk_event->window != widget->slider) return FALSE;
1996 g_blockEventsOnScroll
= FALSE
;
1998 if (win
->m_isScrolling
)
2000 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
2004 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
2005 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
2007 value
= (int)(win
->m_hAdjust
->value
+0.5);
2010 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
2012 value
= (int)(win
->m_vAdjust
->value
+0.5);
2016 wxScrollWinEvent
event( command
, value
, dir
);
2017 event
.SetEventObject( win
);
2018 win
->GetEventHandler()->ProcessEvent( event
);
2021 win
->m_isScrolling
= FALSE
;
2026 // ----------------------------------------------------------------------------
2027 // this wxWindowBase function is implemented here (in platform-specific file)
2028 // because it is static and so couldn't be made virtual
2029 // ----------------------------------------------------------------------------
2031 wxWindow
*wxWindowBase::FindFocus()
2033 // the cast is necessary when we compile in wxUniversal mode
2034 return (wxWindow
*)g_focusWindow
;
2037 //-----------------------------------------------------------------------------
2038 // "realize" from m_widget
2039 //-----------------------------------------------------------------------------
2041 /* We cannot set colours and fonts before the widget has
2042 been realized, so we do this directly after realization. */
2045 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
2050 wxapp_install_idle_handler();
2052 if (win
->m_delayedBackgroundColour
)
2053 win
->SetBackgroundColour( win
->GetBackgroundColour() );
2055 if (win
->m_delayedForegroundColour
)
2056 win
->SetForegroundColour( win
->GetForegroundColour() );
2058 wxWindowCreateEvent
event( win
);
2059 event
.SetEventObject( win
);
2060 win
->GetEventHandler()->ProcessEvent( event
);
2065 //-----------------------------------------------------------------------------
2067 //-----------------------------------------------------------------------------
2070 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
2071 GtkAllocation
*WXUNUSED(alloc
),
2075 wxapp_install_idle_handler();
2077 if (!win
->m_hasScrolling
) return;
2079 int client_width
= 0;
2080 int client_height
= 0;
2081 win
->GetClientSize( &client_width
, &client_height
);
2082 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
2085 win
->m_oldClientWidth
= client_width
;
2086 win
->m_oldClientHeight
= client_height
;
2088 if (!win
->m_nativeSizeEvent
)
2090 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
2091 event
.SetEventObject( win
);
2092 win
->GetEventHandler()->ProcessEvent( event
);
2098 #define WXUNUSED_UNLESS_XIM(param) param
2100 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2103 /* Resize XIM window */
2106 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2107 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
2108 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2111 wxapp_install_idle_handler();
2117 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
2121 gdk_window_get_size (widget
->window
, &width
, &height
);
2122 win
->m_icattr
->preedit_area
.width
= width
;
2123 win
->m_icattr
->preedit_area
.height
= height
;
2124 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2129 //-----------------------------------------------------------------------------
2130 // "realize" from m_wxwindow
2131 //-----------------------------------------------------------------------------
2133 /* Initialize XIM support */
2136 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2137 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2140 wxapp_install_idle_handler();
2143 if (win
->m_ic
) return FALSE
;
2144 if (!widget
) return FALSE
;
2145 if (!gdk_im_ready()) return FALSE
;
2147 win
->m_icattr
= gdk_ic_attr_new();
2148 if (!win
->m_icattr
) return FALSE
;
2152 GdkColormap
*colormap
;
2153 GdkICAttr
*attr
= win
->m_icattr
;
2154 unsigned attrmask
= GDK_IC_ALL_REQ
;
2156 GdkIMStyle supported_style
= (GdkIMStyle
)
2157 (GDK_IM_PREEDIT_NONE
|
2158 GDK_IM_PREEDIT_NOTHING
|
2159 GDK_IM_PREEDIT_POSITION
|
2160 GDK_IM_STATUS_NONE
|
2161 GDK_IM_STATUS_NOTHING
);
2163 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2164 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2166 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2167 attr
->client_window
= widget
->window
;
2169 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2170 gtk_widget_get_default_colormap ())
2172 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2173 attr
->preedit_colormap
= colormap
;
2176 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2177 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2178 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2179 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2181 switch (style
& GDK_IM_PREEDIT_MASK
)
2183 case GDK_IM_PREEDIT_POSITION
:
2184 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2186 g_warning ("over-the-spot style requires fontset");
2190 gdk_window_get_size (widget
->window
, &width
, &height
);
2192 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2193 attr
->spot_location
.x
= 0;
2194 attr
->spot_location
.y
= height
;
2195 attr
->preedit_area
.x
= 0;
2196 attr
->preedit_area
.y
= 0;
2197 attr
->preedit_area
.width
= width
;
2198 attr
->preedit_area
.height
= height
;
2199 attr
->preedit_fontset
= widget
->style
->font
;
2204 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2206 if (win
->m_ic
== NULL
)
2207 g_warning ("Can't create input context.");
2210 mask
= gdk_window_get_events (widget
->window
);
2211 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2212 gdk_window_set_events (widget
->window
, mask
);
2214 if (GTK_WIDGET_HAS_FOCUS(widget
))
2215 gdk_im_begin (win
->m_ic
, widget
->window
);
2222 //-----------------------------------------------------------------------------
2223 // InsertChild for wxWindowGTK.
2224 //-----------------------------------------------------------------------------
2226 /* Callback for wxWindowGTK. This very strange beast has to be used because
2227 * C++ has no virtual methods in a constructor. We have to emulate a
2228 * virtual function here as wxNotebook requires a different way to insert
2229 * a child in it. I had opted for creating a wxNotebookPage window class
2230 * which would have made this superfluous (such in the MDI window system),
2231 * but no-one was listening to me... */
2233 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child
)
2235 /* the window might have been scrolled already, do we
2236 have to adapt the position */
2237 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2238 child
->m_x
+= pizza
->xoffset
;
2239 child
->m_y
+= pizza
->yoffset
;
2241 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2242 GTK_WIDGET(child
->m_widget
),
2249 //-----------------------------------------------------------------------------
2251 //-----------------------------------------------------------------------------
2253 wxWindow
*wxGetActiveWindow()
2255 // the cast is necessary when we compile in wxUniversal mode
2256 return (wxWindow
*)g_focusWindow
;
2259 //-----------------------------------------------------------------------------
2261 //-----------------------------------------------------------------------------
2263 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
2265 #ifdef __WXUNIVERSAL__
2266 IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
)
2268 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2269 #endif // __WXUNIVERSAL__/__WXGTK__
2271 void wxWindowGTK::Init()
2277 m_widget
= (GtkWidget
*) NULL
;
2278 m_wxwindow
= (GtkWidget
*) NULL
;
2279 m_focusWidget
= (GtkWidget
*) NULL
;
2289 m_needParent
= TRUE
;
2290 m_isBeingDeleted
= FALSE
;
2293 m_nativeSizeEvent
= FALSE
;
2295 m_hasScrolling
= FALSE
;
2296 m_isScrolling
= FALSE
;
2298 m_hAdjust
= (GtkAdjustment
*) NULL
;
2299 m_vAdjust
= (GtkAdjustment
*) NULL
;
2300 m_oldHorizontalPos
= 0.0;
2301 m_oldVerticalPos
= 0.0;
2304 m_widgetStyle
= (GtkStyle
*) NULL
;
2306 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2308 m_isStaticBox
= FALSE
;
2309 m_isRadioButton
= FALSE
;
2310 m_isListBox
= FALSE
;
2312 m_acceptsFocus
= FALSE
;
2314 m_clipPaintRegion
= FALSE
;
2316 m_cursor
= *wxSTANDARD_CURSOR
;
2318 m_delayedForegroundColour
= FALSE
;
2319 m_delayedBackgroundColour
= FALSE
;
2322 m_ic
= (GdkIC
*) NULL
;
2323 m_icattr
= (GdkICAttr
*) NULL
;
2327 wxWindowGTK::wxWindowGTK()
2332 wxWindowGTK::wxWindowGTK( wxWindow
*parent
,
2337 const wxString
&name
)
2341 Create( parent
, id
, pos
, size
, style
, name
);
2344 bool wxWindowGTK::Create( wxWindow
*parent
,
2349 const wxString
&name
)
2351 if (!PreCreation( parent
, pos
, size
) ||
2352 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2354 wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
2358 m_insertCallback
= wxInsertChildInWindow
;
2360 // always needed for background clearing
2361 m_delayedBackgroundColour
= TRUE
;
2363 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2364 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2366 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2368 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2369 scroll_class
->scrollbar_spacing
= 0;
2371 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2373 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2374 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2376 m_wxwindow
= gtk_pizza_new();
2378 #ifndef __WXUNIVERSAL__
2379 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2381 if (HasFlag(wxRAISED_BORDER
))
2383 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2385 else if (HasFlag(wxSUNKEN_BORDER
))
2387 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2389 else if (HasFlag(wxSIMPLE_BORDER
))
2391 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2395 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2397 #endif // __WXUNIVERSAL__
2399 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2401 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2402 m_acceptsFocus
= TRUE
;
2404 // I _really_ don't want scrollbars in the beginning
2405 m_vAdjust
->lower
= 0.0;
2406 m_vAdjust
->upper
= 1.0;
2407 m_vAdjust
->value
= 0.0;
2408 m_vAdjust
->step_increment
= 1.0;
2409 m_vAdjust
->page_increment
= 1.0;
2410 m_vAdjust
->page_size
= 5.0;
2411 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2412 m_hAdjust
->lower
= 0.0;
2413 m_hAdjust
->upper
= 1.0;
2414 m_hAdjust
->value
= 0.0;
2415 m_hAdjust
->step_increment
= 1.0;
2416 m_hAdjust
->page_increment
= 1.0;
2417 m_hAdjust
->page_size
= 5.0;
2418 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2420 // these handlers block mouse events to any window during scrolling such as
2421 // motion events and prevent GTK and wxWindows from fighting over where the
2424 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2425 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2427 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2428 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2430 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2431 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2433 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2434 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2436 // these handlers get notified when screen updates are required either when
2437 // scrolling or when the window size (and therefore scrollbar configuration)
2440 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2441 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2442 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2443 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2445 gtk_widget_show( m_wxwindow
);
2448 m_parent
->DoAddChild( this );
2450 m_focusWidget
= m_wxwindow
;
2459 wxWindowGTK::~wxWindowGTK()
2461 if (g_focusWindow
== this)
2462 g_focusWindow
= NULL
;
2464 if (g_activeFrame
== this)
2465 g_activeFrame
= NULL
;
2467 m_isBeingDeleted
= TRUE
;
2476 m_parent
->RemoveChild( this );
2480 gdk_ic_destroy (m_ic
);
2482 gdk_ic_attr_destroy (m_icattr
);
2487 #if DISABLE_STYLE_IF_BROKEN_THEME
2488 // don't delete if it's a pixmap theme style
2489 if (!m_widgetStyle
->engine_data
)
2490 gtk_style_unref( m_widgetStyle
);
2492 m_widgetStyle
= (GtkStyle
*) NULL
;
2497 gtk_widget_destroy( m_wxwindow
);
2498 m_wxwindow
= (GtkWidget
*) NULL
;
2503 gtk_widget_destroy( m_widget
);
2504 m_widget
= (GtkWidget
*) NULL
;
2508 bool wxWindowGTK::PreCreation( wxWindowGTK
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2510 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2512 /* this turns -1 into 20 so that a minimal window is
2513 visible even although -1,-1 has been given as the
2514 size of the window. the same trick is used in other
2515 ports and should make debugging easier */
2516 m_width
= WidthDefault(size
.x
);
2517 m_height
= HeightDefault(size
.y
);
2522 /* some reasonable defaults */
2527 m_x
= (gdk_screen_width () - m_width
) / 2;
2528 if (m_x
< 10) m_x
= 10;
2532 m_y
= (gdk_screen_height () - m_height
) / 2;
2533 if (m_y
< 10) m_y
= 10;
2540 void wxWindowGTK::PostCreation()
2542 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2548 // these get reported to wxWindows -> wxPaintEvent
2550 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2552 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2553 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2556 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2557 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2559 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2561 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2562 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2565 gtk_widget_set_redraw_on_allocate( GTK_WIDGET(m_wxwindow
), HasFlag( wxNO_FULL_REPAINT_ON_RESIZE
) );
2569 // these are called when the "sunken" or "raised" borders are drawn
2570 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2571 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2574 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2575 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2581 if (m_focusWidget
== NULL
)
2582 m_focusWidget
= m_widget
;
2584 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event",
2585 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2587 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event",
2588 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2590 // connect to the various key and mouse handlers
2592 GtkWidget
*connect_widget
= GetConnectWidget();
2594 ConnectWidget( connect_widget
);
2596 /* We cannot set colours, fonts and cursors before the widget has
2597 been realized, so we do this directly after realization */
2598 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2599 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2603 // Catch native resize events
2604 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2605 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2607 // Initialize XIM support
2608 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2609 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2611 // And resize XIM window
2612 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2613 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2616 if (!GTK_IS_COMBO(m_widget
))
2618 // This is needed if we want to add our windows into native
2619 // GTK control, such as the toolbar. With this callback, the
2620 // toolbar gets to know the correct size (the one set by the
2621 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2622 // when moving to GTK 2.0.
2623 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2624 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2630 void wxWindowGTK::ConnectWidget( GtkWidget
*widget
)
2632 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2633 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2635 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2636 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2638 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2639 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2641 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2642 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2644 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2645 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2647 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2648 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2650 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2651 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2654 bool wxWindowGTK::Destroy()
2656 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2660 return wxWindowBase::Destroy();
2663 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
)
2665 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2668 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2670 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2671 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") );
2674 printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
2677 if (m_resizing
) return; /* I don't like recursions */
2680 int currentX
, currentY
;
2681 GetPosition(¤tX
, ¤tY
);
2686 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
2688 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2690 /* don't set the size for children of wxNotebook, just take the values. */
2698 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2699 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2701 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2702 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2703 if (width
!= -1) m_width
= width
;
2704 if (height
!= -1) m_height
= height
;
2708 m_x
= x
+ pizza
->xoffset
;
2709 m_y
= y
+ pizza
->yoffset
;
2714 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2716 if (width
== -1) m_width
= 80;
2719 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2721 if (height
== -1) m_height
= 26;
2724 int minWidth
= GetMinWidth(),
2725 minHeight
= GetMinHeight(),
2726 maxWidth
= GetMaxWidth(),
2727 maxHeight
= GetMaxHeight();
2729 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
2730 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
2731 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
2732 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
2735 int bottom_border
= 0;
2738 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2740 /* the default button has a border around it */
2746 DoMoveWindow( m_x
-border
,
2749 m_height
+border
+bottom_border
);
2754 /* Sometimes the client area changes size without the
2755 whole windows's size changing, but if the whole
2756 windows's size doesn't change, no wxSizeEvent will
2757 normally be sent. Here we add an extra test if
2758 the client test has been changed and this will
2760 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2764 wxPrintf( "OnSize sent from " );
2765 if (GetClassInfo() && GetClassInfo()->GetClassName())
2766 wxPrintf( GetClassInfo()->GetClassName() );
2767 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2770 if (!m_nativeSizeEvent
)
2772 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2773 event
.SetEventObject( this );
2774 GetEventHandler()->ProcessEvent( event
);
2780 void wxWindowGTK::OnInternalIdle()
2782 // Update invalidated regions.
2785 // Synthetize activate events.
2786 if ( g_sendActivateEvent
!= -1 )
2788 bool activate
= g_sendActivateEvent
!= 0;
2791 g_sendActivateEvent
= -1;
2793 wxTheApp
->SetActive(activate
, (wxWindow
*)g_focusWindowLast
);
2796 if ( g_activeFrameLostFocus
)
2798 if ( g_activeFrame
)
2800 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame
);
2801 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
2802 event
.SetEventObject(g_activeFrame
);
2803 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
2804 g_activeFrame
= NULL
;
2806 g_activeFrameLostFocus
= FALSE
;
2809 wxCursor cursor
= m_cursor
;
2810 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2814 /* I now set the cursor anew in every OnInternalIdle call
2815 as setting the cursor in a parent window also effects the
2816 windows above so that checking for the current cursor is
2821 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2823 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2825 if (!g_globalCursor
.Ok())
2826 cursor
= *wxSTANDARD_CURSOR
;
2828 window
= m_widget
->window
;
2829 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2830 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2836 GdkWindow
*window
= m_widget
->window
;
2837 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2838 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2846 void wxWindowGTK::DoGetSize( int *width
, int *height
) const
2848 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2850 if (width
) (*width
) = m_width
;
2851 if (height
) (*height
) = m_height
;
2854 void wxWindowGTK::DoSetClientSize( int width
, int height
)
2856 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2860 SetSize( width
, height
);
2867 #ifndef __WXUNIVERSAL__
2868 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2870 /* when using GTK 1.2 we set the shadow border size to 2 */
2874 if (HasFlag(wxSIMPLE_BORDER
))
2876 /* when using GTK 1.2 we set the simple border size to 1 */
2880 #endif // __WXUNIVERSAL__
2884 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2886 GtkRequisition vscroll_req
;
2887 vscroll_req
.width
= 2;
2888 vscroll_req
.height
= 2;
2889 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2890 (scroll_window
->vscrollbar
, &vscroll_req
);
2892 GtkRequisition hscroll_req
;
2893 hscroll_req
.width
= 2;
2894 hscroll_req
.height
= 2;
2895 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2896 (scroll_window
->hscrollbar
, &hscroll_req
);
2898 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2900 if (scroll_window
->vscrollbar_visible
)
2902 dw
+= vscroll_req
.width
;
2903 dw
+= scroll_class
->scrollbar_spacing
;
2906 if (scroll_window
->hscrollbar_visible
)
2908 dh
+= hscroll_req
.height
;
2909 dh
+= scroll_class
->scrollbar_spacing
;
2913 SetSize( width
+dw
, height
+dh
);
2917 void wxWindowGTK::DoGetClientSize( int *width
, int *height
) const
2919 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2923 if (width
) (*width
) = m_width
;
2924 if (height
) (*height
) = m_height
;
2931 #ifndef __WXUNIVERSAL__
2932 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2934 /* when using GTK 1.2 we set the shadow border size to 2 */
2938 if (HasFlag(wxSIMPLE_BORDER
))
2940 /* when using GTK 1.2 we set the simple border size to 1 */
2944 #endif // __WXUNIVERSAL__
2948 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2950 GtkRequisition vscroll_req
;
2951 vscroll_req
.width
= 2;
2952 vscroll_req
.height
= 2;
2953 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2954 (scroll_window
->vscrollbar
, &vscroll_req
);
2956 GtkRequisition hscroll_req
;
2957 hscroll_req
.width
= 2;
2958 hscroll_req
.height
= 2;
2959 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2960 (scroll_window
->hscrollbar
, &hscroll_req
);
2962 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2964 if (scroll_window
->vscrollbar_visible
)
2966 dw
+= vscroll_req
.width
;
2967 dw
+= scroll_class
->scrollbar_spacing
;
2970 if (scroll_window
->hscrollbar_visible
)
2972 dh
+= hscroll_req
.height
;
2973 dh
+= scroll_class
->scrollbar_spacing
;
2977 if (width
) (*width
) = m_width
- dw
;
2978 if (height
) (*height
) = m_height
- dh
;
2982 printf( "GetClientSize, name %s ", GetName().c_str() );
2983 if (width) printf( " width = %d", (*width) );
2984 if (height) printf( " height = %d", (*height) );
2989 void wxWindowGTK::DoGetPosition( int *x
, int *y
) const
2991 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2995 if (m_parent
&& m_parent
->m_wxwindow
)
2997 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2998 dx
= pizza
->xoffset
;
2999 dy
= pizza
->yoffset
;
3002 if (x
) (*x
) = m_x
- dx
;
3003 if (y
) (*y
) = m_y
- dy
;
3006 void wxWindowGTK::DoClientToScreen( int *x
, int *y
) const
3008 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3010 if (!m_widget
->window
) return;
3012 GdkWindow
*source
= (GdkWindow
*) NULL
;
3014 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3016 source
= m_widget
->window
;
3020 gdk_window_get_origin( source
, &org_x
, &org_y
);
3024 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3026 org_x
+= m_widget
->allocation
.x
;
3027 org_y
+= m_widget
->allocation
.y
;
3035 void wxWindowGTK::DoScreenToClient( int *x
, int *y
) const
3037 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3039 if (!m_widget
->window
) return;
3041 GdkWindow
*source
= (GdkWindow
*) NULL
;
3043 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3045 source
= m_widget
->window
;
3049 gdk_window_get_origin( source
, &org_x
, &org_y
);
3053 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3055 org_x
+= m_widget
->allocation
.x
;
3056 org_y
+= m_widget
->allocation
.y
;
3064 bool wxWindowGTK::Show( bool show
)
3066 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3068 if (!wxWindowBase::Show(show
))
3075 gtk_widget_show( m_widget
);
3077 gtk_widget_hide( m_widget
);
3082 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
)
3084 win
->OnParentEnable(enable
);
3086 // Recurse, so that children have the opportunity to Do The Right Thing
3087 // and reset colours that have been messed up by a parent's (really ancestor's)
3089 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
3091 node
= node
->GetNext() )
3093 wxWindow
*child
= node
->GetData();
3094 if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
)))
3095 wxWindowNotifyEnable(child
, enable
);
3099 bool wxWindowGTK::Enable( bool enable
)
3101 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3103 if (!wxWindowBase::Enable(enable
))
3109 gtk_widget_set_sensitive( m_widget
, enable
);
3111 gtk_widget_set_sensitive( m_wxwindow
, enable
);
3113 wxWindowNotifyEnable(this, enable
);
3118 int wxWindowGTK::GetCharHeight() const
3120 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
3122 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
3124 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3126 return font
->ascent
+ font
->descent
;
3129 int wxWindowGTK::GetCharWidth() const
3131 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
3133 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
3135 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3137 return gdk_string_width( font
, "H" );
3140 void wxWindowGTK::GetTextExtent( const wxString
& string
,
3144 int *externalLeading
,
3145 const wxFont
*theFont
) const
3147 wxFont fontToUse
= m_font
;
3148 if (theFont
) fontToUse
= *theFont
;
3150 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
3152 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
3153 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
3154 if (y
) (*y
) = font
->ascent
+ font
->descent
;
3155 if (descent
) (*descent
) = font
->descent
;
3156 if (externalLeading
) (*externalLeading
) = 0; // ??
3159 void wxWindowGTK::SetFocus()
3161 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3164 wxPrintf( "SetFocus from " );
3165 if (GetClassInfo() && GetClassInfo()->GetClassName())
3166 wxPrintf( GetClassInfo()->GetClassName() );
3172 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3174 gtk_widget_grab_focus (m_wxwindow
);
3179 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
3181 gtk_widget_grab_focus (m_widget
);
3183 else if (GTK_IS_CONTAINER(m_widget
))
3185 SET_CONTAINER_FOCUS( m_widget
, GTK_DIR_TAB_FORWARD
);
3194 bool wxWindowGTK::AcceptsFocus() const
3196 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3199 bool wxWindowGTK::Reparent( wxWindowBase
*newParentBase
)
3201 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3203 wxWindowGTK
*oldParent
= m_parent
,
3204 *newParent
= (wxWindowGTK
*)newParentBase
;
3206 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3208 if ( !wxWindowBase::Reparent(newParent
) )
3211 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3213 /* prevent GTK from deleting the widget arbitrarily */
3214 gtk_widget_ref( m_widget
);
3218 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3221 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3225 /* insert GTK representation */
3226 (*(newParent
->m_insertCallback
))(newParent
, this);
3229 /* reverse: prevent GTK from deleting the widget arbitrarily */
3230 gtk_widget_unref( m_widget
);
3235 void wxWindowGTK::DoAddChild(wxWindowGTK
*child
)
3237 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3239 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3241 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3246 /* insert GTK representation */
3247 (*m_insertCallback
)(this, child
);
3250 void wxWindowGTK::Raise()
3252 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3254 if (!m_widget
->window
) return;
3256 gdk_window_raise( m_widget
->window
);
3259 void wxWindowGTK::Lower()
3261 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3263 if (!m_widget
->window
) return;
3265 gdk_window_lower( m_widget
->window
);
3268 bool wxWindowGTK::SetCursor( const wxCursor
&cursor
)
3270 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3272 if (cursor
== m_cursor
)
3276 wxapp_install_idle_handler();
3278 if (cursor
== wxNullCursor
)
3279 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3281 return wxWindowBase::SetCursor( cursor
);
3284 void wxWindowGTK::WarpPointer( int x
, int y
)
3286 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3288 // We provide this function ourselves as it is
3289 // missing in GDK (top of this file).
3291 GdkWindow
*window
= (GdkWindow
*) NULL
;
3293 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3295 window
= GetConnectWidget()->window
;
3298 gdk_window_warp_pointer( window
, x
, y
);
3301 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect
*rect
)
3303 if (!m_widget
) return;
3304 if (!m_widget
->window
) return;
3307 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3311 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3312 m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
3316 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3317 m_clearRegion
.Clear();
3318 m_clearRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height
);
3326 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3327 m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
3331 GdkRectangle gdk_rect
;
3332 gdk_rect
.x
= rect
->x
;
3333 gdk_rect
.y
= rect
->y
;
3334 gdk_rect
.width
= rect
->width
;
3335 gdk_rect
.height
= rect
->height
;
3336 gtk_widget_draw( m_widget
, &gdk_rect
);
3343 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3344 m_updateRegion
.Clear();
3345 m_updateRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height
);
3349 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3357 GdkRectangle gdk_rect
;
3358 gdk_rect
.x
= rect
->x
;
3359 gdk_rect
.y
= rect
->y
;
3360 gdk_rect
.width
= rect
->width
;
3361 gdk_rect
.height
= rect
->height
;
3362 gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, &gdk_rect
, TRUE
);
3366 gdk_window_invalidate_rect( GTK_PIZZA(m_wxwindow
)->bin_window
, NULL
, TRUE
);
3372 void wxWindowGTK::Update()
3375 if (m_wxwindow
&& GTK_PIZZA(m_wxwindow
)->bin_window
)
3376 gdk_window_process_updates( GTK_PIZZA(m_wxwindow
)->bin_window
, FALSE
);
3379 if (!m_updateRegion
.IsEmpty())
3380 GtkSendPaintEvents();
3383 void wxWindowGTK::GtkSendPaintEvents()
3387 m_clearRegion
.Clear();
3388 m_updateRegion
.Clear();
3392 m_clipPaintRegion
= TRUE
;
3394 // if (!m_clearRegion.IsEmpty()) // always send an erase event
3396 wxWindowDC
dc( (wxWindow
*)this );
3397 dc
.SetClippingRegion( m_clearRegion
);
3399 wxEraseEvent
erase_event( GetId(), &dc
);
3400 erase_event
.SetEventObject( this );
3402 if (!GetEventHandler()->ProcessEvent(erase_event
))
3406 g_eraseGC
= gdk_gc_new( GTK_PIZZA(m_wxwindow
)->bin_window
);
3407 gdk_gc_set_fill( g_eraseGC
, GDK_SOLID
);
3409 gdk_gc_set_foreground( g_eraseGC
, m_backgroundColour
.GetColor() );
3411 wxRegionIterator
upd( m_clearRegion
);
3414 gdk_draw_rectangle( GTK_PIZZA(m_wxwindow
)->bin_window
, g_eraseGC
, 1,
3415 upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
3419 m_clearRegion
.Clear();
3422 wxNcPaintEvent
nc_paint_event( GetId() );
3423 nc_paint_event
.SetEventObject( this );
3424 GetEventHandler()->ProcessEvent( nc_paint_event
);
3426 wxPaintEvent
paint_event( GetId() );
3427 paint_event
.SetEventObject( this );
3428 GetEventHandler()->ProcessEvent( paint_event
);
3430 m_clipPaintRegion
= FALSE
;
3432 #ifndef __WXUNIVERSAL__
3434 // The following code will result in all window-less widgets
3435 // being redrawn because the wxWindows class is allowed to
3436 // paint over the window-less widgets.
3438 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
3440 GList
*children
= pizza
->children
;
3443 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
3444 children
= children
->next
;
3446 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
3447 GTK_WIDGET_DRAWABLE (child
->widget
))
3449 // Get intersection of widget area and update region
3450 wxRegion
region( m_updateRegion
);
3452 GdkEventExpose gdk_event
;
3453 gdk_event
.type
= GDK_EXPOSE
;
3454 gdk_event
.window
= pizza
->bin_window
;
3455 gdk_event
.count
= 0;
3457 wxRegionIterator
upd( m_updateRegion
);
3461 rect
.x
= upd
.GetX();
3462 rect
.y
= upd
.GetY();
3463 rect
.width
= upd
.GetWidth();
3464 rect
.height
= upd
.GetHeight();
3466 if (gtk_widget_intersect (child
->widget
, &rect
, &gdk_event
.area
))
3468 gtk_widget_event (child
->widget
, (GdkEvent
*) &gdk_event
);
3478 m_updateRegion
.Clear();
3481 void wxWindowGTK::Clear()
3483 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3485 if (!m_widget
->window
) return;
3487 if (m_wxwindow
&& m_wxwindow
->window
)
3489 gdk_window_clear( m_wxwindow
->window
);
3494 void wxWindowGTK::DoSetToolTip( wxToolTip
*tip
)
3496 wxWindowBase::DoSetToolTip(tip
);
3499 m_tooltip
->Apply( (wxWindow
*)this );
3502 void wxWindowGTK::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3504 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3506 #endif // wxUSE_TOOLTIPS
3508 bool wxWindowGTK::SetBackgroundColour( const wxColour
&colour
)
3510 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3512 if (!wxWindowBase::SetBackgroundColour(colour
))
3514 // don't leave if the GTK widget has just
3516 if (!m_delayedBackgroundColour
) return FALSE
;
3519 GdkWindow
*window
= (GdkWindow
*) NULL
;
3521 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3523 window
= GetConnectWidget()->window
;
3527 // indicate that a new style has been set
3528 // but it couldn't get applied as the
3529 // widget hasn't been realized yet.
3530 m_delayedBackgroundColour
= TRUE
;
3535 // We need the pixel value e.g. for background clearing.
3536 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3540 (m_wxwindow
->window
) &&
3541 (m_backgroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
)))
3543 /* wxMSW doesn't clear the window here. I don't do that either to
3544 provide compatibility. call Clear() to do the job. */
3546 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3554 bool wxWindowGTK::SetForegroundColour( const wxColour
&colour
)
3556 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3558 if (!wxWindowBase::SetForegroundColour(colour
))
3560 // don't leave if the GTK widget has just
3562 if (!m_delayedForegroundColour
) return FALSE
;
3565 GdkWindow
*window
= (GdkWindow
*) NULL
;
3567 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3569 window
= GetConnectWidget()->window
;
3573 // indicate that a new style has been set
3574 // but it couldn't get applied as the
3575 // widget hasn't been realized yet.
3576 m_delayedForegroundColour
= TRUE
;
3584 GtkStyle
*wxWindowGTK::GetWidgetStyle()
3588 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3590 // FIXME: no more klass in 2.0
3592 remake
->klass
= m_widgetStyle
->klass
;
3595 gtk_style_unref( m_widgetStyle
);
3596 m_widgetStyle
= remake
;
3600 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3603 def
= gtk_widget_get_default_style();
3605 m_widgetStyle
= gtk_style_copy( def
);
3607 // FIXME: no more klass in 2.0
3609 m_widgetStyle
->klass
= def
->klass
;
3613 return m_widgetStyle
;
3616 void wxWindowGTK::SetWidgetStyle()
3618 #if DISABLE_STYLE_IF_BROKEN_THEME
3619 if (m_widget
->style
->engine_data
)
3621 static bool s_warningPrinted
= FALSE
;
3622 if (!s_warningPrinted
)
3624 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3625 s_warningPrinted
= TRUE
;
3627 m_widgetStyle
= m_widget
->style
;
3632 GtkStyle
*style
= GetWidgetStyle();
3634 if (m_font
!= wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT
))
3636 SET_STYLE_FONT(style
, m_font
.GetInternalFont( 1.0 ));
3639 if (m_foregroundColour
.Ok())
3641 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3642 if (m_foregroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT
))
3644 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3645 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3646 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3650 // Try to restore the gtk default style. This is still a little
3651 // oversimplified for what is probably really needed here for controls
3652 // other than buttons, but is better than not being able to (re)set a
3653 // control's foreground colour to *wxBLACK -- RL
3654 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3657 def
= gtk_widget_get_default_style();
3659 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3660 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3661 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3665 if (m_backgroundColour
.Ok())
3667 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3668 if (m_backgroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
))
3670 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3671 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3672 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3673 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3674 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3675 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3676 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3677 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3681 // Try to restore the gtk default style. This is still a little
3682 // oversimplified for what is probably really needed here for controls
3683 // other than buttons, but is better than not being able to (re)set a
3684 // control's background colour to default grey and means resetting a
3685 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3687 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3690 def
= gtk_widget_get_default_style();
3692 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3693 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3694 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3695 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3696 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3697 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3698 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3699 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3704 void wxWindowGTK::ApplyWidgetStyle()
3708 //-----------------------------------------------------------------------------
3709 // Pop-up menu stuff
3710 //-----------------------------------------------------------------------------
3712 #if wxUSE_MENUS_NATIVE
3715 void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3717 *is_waiting
= FALSE
;
3720 static void SetInvokingWindow( wxMenu
*menu
, wxWindowGTK
*win
)
3722 menu
->SetInvokingWindow( win
);
3723 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3726 wxMenuItem
*menuitem
= node
->GetData();
3727 if (menuitem
->IsSubMenu())
3729 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3732 node
= node
->GetNext();
3736 // used to pass the coordinates from wxWindowGTK::DoPopupMenu() to
3737 // wxPopupMenuPositionCallback()
3739 // should be safe even in the MT case as the user can hardly popup 2 menus
3740 // simultaneously, can he?
3741 static gint gs_pop_x
= 0;
3742 static gint gs_pop_y
= 0;
3744 extern "C" void wxPopupMenuPositionCallback( GtkMenu
*menu
,
3747 gboolean
* WXUNUSED(whatever
),
3749 gpointer
WXUNUSED(user_data
) )
3751 // ensure that the menu appears entirely on screen
3753 gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
);
3755 wxSize sizeScreen
= wxGetDisplaySize();
3757 gint xmax
= sizeScreen
.x
- req
.width
,
3758 ymax
= sizeScreen
.y
- req
.height
;
3760 *x
= gs_pop_x
< xmax
? gs_pop_x
: xmax
;
3761 *y
= gs_pop_y
< ymax
? gs_pop_y
: ymax
;
3764 bool wxWindowGTK::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3766 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3768 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3770 SetInvokingWindow( menu
, this );
3776 ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3778 bool is_waiting
= TRUE
;
3780 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
),
3782 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
),
3783 (gpointer
)&is_waiting
);
3786 GTK_MENU(menu
->m_menu
),
3787 (GtkWidget
*) NULL
, // parent menu shell
3788 (GtkWidget
*) NULL
, // parent menu item
3789 wxPopupMenuPositionCallback
, // function to position it
3790 NULL
, // client data
3791 0, // button used to activate it
3792 gs_timeLastClick
// the time of activation
3797 while (gtk_events_pending())
3798 gtk_main_iteration();
3804 #endif // wxUSE_MENUS_NATIVE
3806 #if wxUSE_DRAG_AND_DROP
3808 void wxWindowGTK::SetDropTarget( wxDropTarget
*dropTarget
)
3810 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3812 GtkWidget
*dnd_widget
= GetConnectWidget();
3814 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3816 if (m_dropTarget
) delete m_dropTarget
;
3817 m_dropTarget
= dropTarget
;
3819 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3822 #endif // wxUSE_DRAG_AND_DROP
3824 GtkWidget
* wxWindowGTK::GetConnectWidget()
3826 GtkWidget
*connect_widget
= m_widget
;
3827 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3829 return connect_widget
;
3832 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow
*window
)
3835 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3837 return (window
== m_widget
->window
);
3840 bool wxWindowGTK::SetFont( const wxFont
&font
)
3842 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3844 if (!wxWindowBase::SetFont(font
))
3849 wxColour sysbg
= wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE
);
3850 if ( sysbg
== m_backgroundColour
)
3852 m_backgroundColour
= wxNullColour
;
3854 m_backgroundColour
= sysbg
;
3864 void wxWindowGTK::DoCaptureMouse()
3866 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3868 GdkWindow
*window
= (GdkWindow
*) NULL
;
3870 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3872 window
= GetConnectWidget()->window
;
3874 wxCHECK_RET( window
, _T("CaptureMouse() failed") );
3876 wxCursor
* cursor
= & m_cursor
;
3878 cursor
= wxSTANDARD_CURSOR
;
3880 gdk_pointer_grab( window
, FALSE
,
3882 (GDK_BUTTON_PRESS_MASK
|
3883 GDK_BUTTON_RELEASE_MASK
|
3884 GDK_POINTER_MOTION_HINT_MASK
|
3885 GDK_POINTER_MOTION_MASK
),
3887 cursor
->GetCursor(),
3888 (guint32
)GDK_CURRENT_TIME
);
3889 g_captureWindow
= this;
3890 g_captureWindowHasMouse
= TRUE
;
3893 void wxWindowGTK::DoReleaseMouse()
3895 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3897 wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") );
3899 g_captureWindow
= (wxWindowGTK
*) NULL
;
3901 GdkWindow
*window
= (GdkWindow
*) NULL
;
3903 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3905 window
= GetConnectWidget()->window
;
3910 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3914 wxWindow
*wxWindowBase::GetCapture()
3916 return (wxWindow
*)g_captureWindow
;
3919 bool wxWindowGTK::IsRetained() const
3924 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3925 int range
, bool refresh
)
3927 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3929 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3931 m_hasScrolling
= TRUE
;
3933 if (orient
== wxHORIZONTAL
)
3935 float fpos
= (float)pos
;
3936 float frange
= (float)range
;
3937 float fthumb
= (float)thumbVisible
;
3938 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3939 if (fpos
< 0.0) fpos
= 0.0;
3941 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3942 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3944 SetScrollPos( orient
, pos
, refresh
);
3948 m_oldHorizontalPos
= fpos
;
3950 m_hAdjust
->lower
= 0.0;
3951 m_hAdjust
->upper
= frange
;
3952 m_hAdjust
->value
= fpos
;
3953 m_hAdjust
->step_increment
= 1.0;
3954 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3955 m_hAdjust
->page_size
= fthumb
;
3959 float fpos
= (float)pos
;
3960 float frange
= (float)range
;
3961 float fthumb
= (float)thumbVisible
;
3962 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3963 if (fpos
< 0.0) fpos
= 0.0;
3965 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3966 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3968 SetScrollPos( orient
, pos
, refresh
);
3972 m_oldVerticalPos
= fpos
;
3974 m_vAdjust
->lower
= 0.0;
3975 m_vAdjust
->upper
= frange
;
3976 m_vAdjust
->value
= fpos
;
3977 m_vAdjust
->step_increment
= 1.0;
3978 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3979 m_vAdjust
->page_size
= fthumb
;
3982 if (orient
== wxHORIZONTAL
)
3983 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3985 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3988 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3990 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3992 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3994 if (orient
== wxHORIZONTAL
)
3996 float fpos
= (float)pos
;
3997 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3998 if (fpos
< 0.0) fpos
= 0.0;
3999 m_oldHorizontalPos
= fpos
;
4001 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
4002 m_hAdjust
->value
= fpos
;
4006 float fpos
= (float)pos
;
4007 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
4008 if (fpos
< 0.0) fpos
= 0.0;
4009 m_oldVerticalPos
= fpos
;
4011 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
4012 m_vAdjust
->value
= fpos
;
4015 if (m_wxwindow
->window
)
4017 if (orient
== wxHORIZONTAL
)
4019 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
4020 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
4022 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
4024 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
4025 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
4029 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
4030 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4032 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
4034 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
4035 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4040 int wxWindowGTK::GetScrollThumb( int orient
) const
4042 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4044 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4046 if (orient
== wxHORIZONTAL
)
4047 return (int)(m_hAdjust
->page_size
+0.5);
4049 return (int)(m_vAdjust
->page_size
+0.5);
4052 int wxWindowGTK::GetScrollPos( int orient
) const
4054 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4056 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4058 if (orient
== wxHORIZONTAL
)
4059 return (int)(m_hAdjust
->value
+0.5);
4061 return (int)(m_vAdjust
->value
+0.5);
4064 int wxWindowGTK::GetScrollRange( int orient
) const
4066 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4068 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4070 if (orient
== wxHORIZONTAL
)
4071 return (int)(m_hAdjust
->upper
+0.5);
4073 return (int)(m_vAdjust
->upper
+0.5);
4076 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
4078 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4080 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4082 // No scrolling requested.
4083 if ((dx
== 0) && (dy
== 0)) return;
4086 if (!m_updateRegion
.IsEmpty())
4088 m_updateRegion
.Offset( dx
, dy
);
4092 GetClientSize( &cw
, &ch
);
4093 m_updateRegion
.Intersect( 0, 0, cw
, ch
);
4096 if (!m_clearRegion
.IsEmpty())
4098 m_clearRegion
.Offset( dx
, dy
);
4102 GetClientSize( &cw
, &ch
);
4103 m_clearRegion
.Intersect( 0, 0, cw
, ch
);
4106 m_clipPaintRegion
= TRUE
;
4108 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
4110 m_clipPaintRegion
= FALSE
;
4113 gdk_window_scroll( GTK_PIZZA(m_wxwindow
)->bin_window
, dx
, dy
);
4115 GTK_PIZZA(m_wxwindow
)->xoffset
+= dx
;
4116 GTK_PIZZA(m_wxwindow
)->yoffset
+= dy
;
4123 // Find the wxWindow at the current mouse position, also returning the mouse
4125 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
4127 pt
= wxGetMousePosition();
4128 wxWindow
* found
= wxFindWindowAtPoint(pt
);
4132 // Get the current mouse position.
4133 wxPoint
wxGetMousePosition()
4135 /* This crashes when used within wxHelpContext,
4136 so we have to use the X-specific implementation below.
4138 GdkModifierType *mask;
4139 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
4141 return wxPoint(x, y);
4145 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
4147 return wxPoint(-999, -999);
4149 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
4150 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
4151 Window rootReturn
, childReturn
;
4152 int rootX
, rootY
, winX
, winY
;
4153 unsigned int maskReturn
;
4155 XQueryPointer (display
,
4159 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
4160 return wxPoint(rootX
, rootY
);
4164 // ----------------------------------------------------------------------------
4166 // ----------------------------------------------------------------------------
4168 class wxWinModule
: public wxModule
4175 DECLARE_DYNAMIC_CLASS(wxWinModule
)
4178 IMPLEMENT_DYNAMIC_CLASS(wxWinModule
, wxModule
)
4180 bool wxWinModule::OnInit()
4182 // g_eraseGC = gdk_gc_new( GDK_ROOT_PARENT() );
4183 // gdk_gc_set_fill( g_eraseGC, GDK_SOLID );
4188 void wxWinModule::OnExit()
4191 gdk_gc_unref( g_eraseGC
);