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"
29 #if wxUSE_DRAG_AND_DROP
34 #include "wx/tooltip.h"
42 #include "wx/textctrl.h"
46 #include "wx/statusbr.h"
48 #include "wx/settings.h"
52 #include "wx/thread.h"
59 #include <gdk/gdkprivate.h>
60 #include <gdk/gdkkeysyms.h>
64 #include <gtk/gtkprivate.h>
66 #include "wx/gtk/win_gtk.h"
68 //-----------------------------------------------------------------------------
69 // documentation on internals
70 //-----------------------------------------------------------------------------
73 I have been asked several times about writing some documentation about
74 the GTK port of wxWindows, especially its internal structures. Obviously,
75 you cannot understand wxGTK without knowing a little about the GTK, but
76 some more information about what the wxWindow, which is the base class
77 for all other window classes, does seems required as well.
81 What does wxWindow do? It contains the common interface for the following
82 jobs of its descendants:
84 1) Define the rudimentary behaviour common to all window classes, such as
85 resizing, intercepting user input (so as to make it possible to use these
86 events for special purposes in a derived class), window names etc.
88 2) Provide the possibility to contain and manage children, if the derived
89 class is allowed to contain children, which holds true for those window
90 classes which do not display a native GTK widget. To name them, these
91 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
92 work classes are a special case and are handled a bit differently from
93 the rest. The same holds true for the wxNotebook class.
95 3) Provide the possibility to draw into a client area of a window. This,
96 too, only holds true for classes that do not display a native GTK widget
99 4) Provide the entire mechanism for scrolling widgets. This actual inter-
100 face for this is usually in wxScrolledWindow, but the GTK implementation
103 5) A multitude of helper or extra methods for special purposes, such as
104 Drag'n'Drop, managing validators etc.
106 6) Display a border (sunken, raised, simple or none).
108 Normally one might expect, that one wxWindows window would always correspond
109 to one GTK widget. Under GTK, there is no such allround widget that has all
110 the functionality. Moreover, the GTK defines a client area as a different
111 widget from the actual widget you are handling. Last but not least some
112 special classes (e.g. wxFrame) handle different categories of widgets and
113 still have the possibility to draw something in the client area.
114 It was therefore required to write a special purpose GTK widget, that would
115 represent a client area in the sense of wxWindows capable to do the jobs
116 2), 3) and 4). I have written this class and it resides in win_gtk.c of
119 All windows must have a widget, with which they interact with other under-
120 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
121 thw wxWindow class has a member variable called m_widget which holds a
122 pointer to this widget. When the window class represents a GTK native widget,
123 this is (in most cases) the only GTK widget the class manages. E.g. the
124 wxStatitText class handles only a GtkLabel widget a pointer to which you
125 can find in m_widget (defined in wxWindow)
127 When the class has a client area for drawing into and for containing children
128 it has to handle the client area widget (of the type GtkPizza, defined in
129 win_gtk.c), but there could be any number of widgets, handled by a class
130 The common rule for all windows is only, that the widget that interacts with
131 the rest of GTK must be referenced in m_widget and all other widgets must be
132 children of this widget on the GTK level. The top-most widget, which also
133 represents the client area, must be in the m_wxwindow field and must be of
136 As I said, the window classes that display a GTK native widget only have
137 one widget, so in the case of e.g. the wxButton class m_widget holds a
138 pointer to a GtkButton widget. But windows with client areas (for drawing
139 and children) have a m_widget field that is a pointer to a GtkScrolled-
140 Window and a m_wxwindow field that is pointer to a GtkPizza and this
141 one is (in the GTK sense) a child of the GtkScrolledWindow.
143 If the m_wxwindow field is set, then all input to this widget is inter-
144 cepted and sent to the wxWindows class. If not, all input to the widget
145 that gets pointed to by m_widget gets intercepted and sent to the class.
149 The design of scrolling in wxWindows is markedly different from that offered
150 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
151 clicking on a scrollbar belonging to scrolled window will inevitably move
152 the window. In wxWindows, the scrollbar will only emit an event, send this
153 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
154 which actually moves the window and its subchildren. Note that GtkPizza
155 memorizes how much it has been scrolled but that wxWindows forgets this
156 so that the two coordinates systems have to be kept in synch. This is done
157 in various places using the pizza->xoffset and pizza->yoffset values.
161 Singularily the most broken code in GTK is the code that is supposes to
162 inform subwindows (child windows) about new positions. Very often, duplicate
163 events are sent without changes in size or position, equally often no
164 events are sent at all (All this is due to a bug in the GtkContainer code
165 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
166 GTK's own system and it simply waits for size events for toplevel windows
167 and then iterates down the respective size events to all window. This has
168 the disadvantage, that windows might get size events before the GTK widget
169 actually has the reported size. This doesn't normally pose any problem, but
170 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
171 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
172 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
173 window that is used for OpenGl output really has that size (as reported by
178 If someone at some point of time feels the immense desire to have a look at,
179 change or attempt to optimse the Refresh() logic, this person will need an
180 intimate understanding of what a "draw" and what an "expose" events are and
181 what there are used for, in particular when used in connection with GTK's
182 own windowless widgets. Beware.
186 Cursors, too, have been a constant source of pleasure. The main difficulty
187 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
188 for the parent. To prevent this from doing too much harm, I use idle time
189 to set the cursor over and over again, starting from the toplevel windows
190 and ending with the youngest generation (speaking of parent and child windows).
191 Also don't forget that cursors (like much else) are connected to GdkWindows,
192 not GtkWidgets and that the "window" field of a GtkWidget might very well
193 point to the GdkWindow of the parent widget (-> "window less widget") and
194 that the two obviously have very different meanings.
198 //-----------------------------------------------------------------------------
200 //-----------------------------------------------------------------------------
202 extern wxList wxPendingDelete
;
203 extern bool g_blockEventsOnDrag
;
204 extern bool g_blockEventsOnScroll
;
205 extern wxCursor g_globalCursor
;
207 // mouse capture state: the window which has it and if the mouse is currently
209 static wxWindowGTK
*g_captureWindow
= (wxWindowGTK
*) NULL
;
210 static bool g_captureWindowHasMouse
= FALSE
;
212 /* extern */ wxWindowGTK
*g_focusWindow
= (wxWindowGTK
*) NULL
;
214 // the last window which had the focus - this is normally never NULL (except
215 // if we never had focus at all) as even when g_focusWindow is NULL it still
216 // keeps its previous value
217 static wxWindowGTK
*g_focusWindowLast
= (wxWindowGTK
*)NULL
;
219 // the frame that is currently active (i.e. its child has focus). It is
220 // used to generate wxActivateEvents
221 static wxWindowGTK
*g_activeFrame
= (wxWindowGTK
*)NULL
;
222 static bool g_activeFrameLostFocus
= FALSE
;
224 // if we detect that the app has got/lost the focus, we set this variable to
225 // either TRUE or FALSE and an activate event will be sent during the next
226 // OnIdle() call and it is reset to -1: this value means that we shouldn't
227 // send any activate events at all
228 static int g_sendActivateEvent
= -1;
230 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
231 the last click here */
232 static guint32 gs_timeLastClick
= 0;
234 extern bool g_mainThreadLocked
;
236 //-----------------------------------------------------------------------------
238 //-----------------------------------------------------------------------------
241 #define DISABLE_STYLE_IF_BROKEN_THEME 1
247 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
249 # define DEBUG_MAIN_THREAD
252 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
253 GdkEvent
*WXUNUSED(event
),
254 const wxChar
*WXUNUSED(name
) )
257 static bool s_done = FALSE;
260 wxLog::AddTraceMask("focus");
263 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
269 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
271 // suppress warnings about gtk_debug_focus_in_callback being unused with
276 tmp
+= wxT(" FROM ");
279 wxChar
*s
= new wxChar
[tmp
.Length()+1];
283 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
284 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
289 #define DEBUG_MAIN_THREAD
292 //-----------------------------------------------------------------------------
293 // missing gdk functions
294 //-----------------------------------------------------------------------------
297 gdk_window_warp_pointer (GdkWindow
*window
,
302 GdkWindowPrivate
*priv
;
306 window
= GDK_ROOT_PARENT();
309 if (!GDK_WINDOW_DESTROYED(window
))
311 XWarpPointer (GDK_WINDOW_XDISPLAY(window
),
312 None
, /* not source window -> move from anywhere */
313 GDK_WINDOW_XID(window
), /* dest window */
314 0, 0, 0, 0, /* not source window -> move from anywhere */
318 priv
= (GdkWindowPrivate
*) window
;
320 if (!priv
->destroyed
)
322 XWarpPointer (priv
->xdisplay
,
323 None
, /* not source window -> move from anywhere */
324 priv
->xwindow
, /* dest window */
325 0, 0, 0, 0, /* not source window -> move from anywhere */
331 //-----------------------------------------------------------------------------
333 //-----------------------------------------------------------------------------
335 extern void wxapp_install_idle_handler();
336 extern bool g_isIdle
;
338 //-----------------------------------------------------------------------------
339 // local code (see below)
340 //-----------------------------------------------------------------------------
342 // returns the child of win which currently has focus or NULL if not found
344 // Note: can't be static, needed by textctrl.cpp.
345 wxWindow
*wxFindFocusedChild(wxWindowGTK
*win
)
347 wxWindow
*winFocus
= wxWindowGTK::FindFocus();
349 return (wxWindow
*)NULL
;
351 if ( winFocus
== win
)
352 return (wxWindow
*)win
;
354 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
356 node
= node
->GetNext() )
358 wxWindow
*child
= wxFindFocusedChild(node
->GetData());
363 return (wxWindow
*)NULL
;
366 // Returns toplevel grandparent of given window:
367 static wxWindowGTK
* wxGetTopLevelParent(wxWindowGTK
*win
)
369 wxWindowGTK
*p
= win
;
370 while (p
&& !p
->IsTopLevel())
376 static void draw_frame( GtkWidget
*widget
, wxWindowGTK
*win
)
378 // wxUniversal widgets draw the borders and scrollbars themselves
379 #ifndef __WXUNIVERSAL__
386 if (win
->m_hasScrolling
)
388 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
390 GtkRequisition vscroll_req
;
391 vscroll_req
.width
= 2;
392 vscroll_req
.height
= 2;
393 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
394 (scroll_window
->vscrollbar
, &vscroll_req
);
396 GtkRequisition hscroll_req
;
397 hscroll_req
.width
= 2;
398 hscroll_req
.height
= 2;
399 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
400 (scroll_window
->hscrollbar
, &hscroll_req
);
402 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) );
404 if (scroll_window
->vscrollbar_visible
)
406 dw
+= vscroll_req
.width
;
407 dw
+= scroll_class
->scrollbar_spacing
;
410 if (scroll_window
->hscrollbar_visible
)
412 dh
+= hscroll_req
.height
;
413 dh
+= scroll_class
->scrollbar_spacing
;
419 if (GTK_WIDGET_NO_WINDOW (widget
))
421 dx
+= widget
->allocation
.x
;
422 dy
+= widget
->allocation
.y
;
425 if (win
->HasFlag(wxRAISED_BORDER
))
427 gtk_draw_shadow( widget
->style
,
432 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
436 if (win
->HasFlag(wxSUNKEN_BORDER
))
438 gtk_draw_shadow( widget
->style
,
443 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
447 if (win
->HasFlag(wxSIMPLE_BORDER
))
450 gc
= gdk_gc_new( widget
->window
);
451 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
452 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
454 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
458 #endif // __WXUNIVERSAL__
461 //-----------------------------------------------------------------------------
462 // "expose_event" of m_widget
463 //-----------------------------------------------------------------------------
465 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindowGTK
*win
)
467 if (gdk_event
->count
> 0) return FALSE
;
469 draw_frame( widget
, win
);
474 //-----------------------------------------------------------------------------
475 // "draw" of m_widget
476 //-----------------------------------------------------------------------------
478 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindowGTK
*win
)
480 draw_frame( widget
, win
);
483 //-----------------------------------------------------------------------------
484 // key code mapping routines
485 //-----------------------------------------------------------------------------
487 static long map_to_unmodified_wx_keysym( GdkEventKey
*event
)
489 // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string
490 // but only event->keyval which is quite useless to us, so remember
491 // the last character from GDK_KEY_PRESS and resue it as last resort
493 // NB: should be MT-neutral as always called from main thread only
498 } s_lastKeyPress
= { 0, 0 };
500 KeySym keysym
= event
->keyval
;
506 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
508 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
514 case GDK_Super_R
: key_code
= WXK_ALT
; break;
515 case GDK_Menu
: key_code
= WXK_MENU
; break;
516 case GDK_Help
: key_code
= WXK_HELP
; break;
517 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
518 case GDK_ISO_Left_Tab
:
519 case GDK_Tab
: key_code
= WXK_TAB
; break;
520 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
521 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
522 case GDK_Return
: key_code
= WXK_RETURN
; break;
523 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
524 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
525 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
526 case GDK_Delete
: key_code
= WXK_DELETE
; break;
527 case GDK_Home
: key_code
= WXK_HOME
; break;
528 case GDK_Left
: key_code
= WXK_LEFT
; break;
529 case GDK_Up
: key_code
= WXK_UP
; break;
530 case GDK_Right
: key_code
= WXK_RIGHT
; break;
531 case GDK_Down
: key_code
= WXK_DOWN
; break;
532 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
533 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
534 case GDK_Next
: key_code
= WXK_NEXT
; break;
535 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
536 case GDK_End
: key_code
= WXK_END
; break;
537 case GDK_Begin
: key_code
= WXK_HOME
; break;
538 case GDK_Select
: key_code
= WXK_SELECT
; break;
539 case GDK_Print
: key_code
= WXK_PRINT
; break;
540 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
541 case GDK_Insert
: key_code
= WXK_INSERT
; break;
542 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
544 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
545 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
546 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
547 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
548 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
549 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
550 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
551 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
552 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
553 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
554 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
555 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
556 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
557 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
558 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
559 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
560 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
561 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
562 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
563 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
564 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
565 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
566 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
567 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
568 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
569 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
570 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
571 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
572 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
573 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
574 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
575 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
576 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
577 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
578 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
579 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
580 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
582 case GDK_F1
: key_code
= WXK_F1
; break;
583 case GDK_F2
: key_code
= WXK_F2
; break;
584 case GDK_F3
: key_code
= WXK_F3
; break;
585 case GDK_F4
: key_code
= WXK_F4
; break;
586 case GDK_F5
: key_code
= WXK_F5
; break;
587 case GDK_F6
: key_code
= WXK_F6
; break;
588 case GDK_F7
: key_code
= WXK_F7
; break;
589 case GDK_F8
: key_code
= WXK_F8
; break;
590 case GDK_F9
: key_code
= WXK_F9
; break;
591 case GDK_F10
: key_code
= WXK_F10
; break;
592 case GDK_F11
: key_code
= WXK_F11
; break;
593 case GDK_F12
: key_code
= WXK_F12
; break;
596 // do we have the translation?
597 if ( event
->length
== 1 )
599 keysym
= (KeySym
)event
->string
[0];
601 else if ( (keysym
& 0xFF) != keysym
)
603 // non ASCII key, what to do?
605 if ( event
->type
== GDK_KEY_RELEASE
)
607 // reuse the one from the last keypress if any
608 if ( keysym
== s_lastKeyPress
.keysym
)
610 key_code
= s_lastKeyPress
.keycode
;
617 // ignore this one, we don't know it
620 //else: ASCII key, ok
622 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
623 key_code
= upper
? upper
: keysym
;
625 if ( event
->type
== GDK_KEY_PRESS
)
627 // remember it to be reused below later
628 s_lastKeyPress
.keysym
= keysym
;
629 s_lastKeyPress
.keycode
= key_code
;
637 static long map_to_wx_keysym( GdkEventKey
*event
)
639 KeySym keysym
= event
->keyval
;
644 case GDK_Menu
: key_code
= WXK_MENU
; break;
645 case GDK_Help
: key_code
= WXK_HELP
; break;
646 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
647 case GDK_ISO_Left_Tab
:
648 case GDK_Tab
: key_code
= WXK_TAB
; break;
649 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
650 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
651 case GDK_Return
: key_code
= WXK_RETURN
; break;
652 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
653 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
654 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
655 case GDK_Delete
: key_code
= WXK_DELETE
; break;
656 case GDK_Home
: key_code
= WXK_HOME
; break;
657 case GDK_Left
: key_code
= WXK_LEFT
; break;
658 case GDK_Up
: key_code
= WXK_UP
; break;
659 case GDK_Right
: key_code
= WXK_RIGHT
; break;
660 case GDK_Down
: key_code
= WXK_DOWN
; break;
661 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
662 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
663 case GDK_Next
: key_code
= WXK_NEXT
; break;
664 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
665 case GDK_End
: key_code
= WXK_END
; break;
666 case GDK_Begin
: key_code
= WXK_HOME
; break;
667 case GDK_Select
: key_code
= WXK_SELECT
; break;
668 case GDK_Print
: key_code
= WXK_PRINT
; break;
669 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
670 case GDK_Insert
: key_code
= WXK_INSERT
; break;
671 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
673 case GDK_KP_0
: key_code
= '0'; break;
674 case GDK_KP_1
: key_code
= '1'; break;
675 case GDK_KP_2
: key_code
= '2'; break;
676 case GDK_KP_3
: key_code
= '3'; break;
677 case GDK_KP_4
: key_code
= '4'; break;
678 case GDK_KP_5
: key_code
= '5'; break;
679 case GDK_KP_6
: key_code
= '6'; break;
680 case GDK_KP_7
: key_code
= '7'; break;
681 case GDK_KP_8
: key_code
= '8'; break;
682 case GDK_KP_9
: key_code
= '9'; break;
683 case GDK_KP_Space
: key_code
= ' '; break;
684 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
685 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
686 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
687 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
688 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
689 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
690 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
691 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
692 case GDK_KP_Up
: key_code
= WXK_UP
; break;
693 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
694 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
695 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
696 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
697 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
698 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
699 case GDK_KP_End
: key_code
= WXK_END
; break;
700 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
701 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
702 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
703 case GDK_KP_Equal
: key_code
= '='; break;
704 case GDK_KP_Multiply
: key_code
= '*'; break;
705 case GDK_KP_Add
: key_code
= '+'; break;
706 case GDK_KP_Separator
: key_code
= ','; break;
707 case GDK_KP_Subtract
: key_code
= '-'; break;
708 case GDK_KP_Decimal
: key_code
= '.'; break;
709 case GDK_KP_Divide
: key_code
= '/'; break;
711 case GDK_F1
: key_code
= WXK_F1
; break;
712 case GDK_F2
: key_code
= WXK_F2
; break;
713 case GDK_F3
: key_code
= WXK_F3
; break;
714 case GDK_F4
: key_code
= WXK_F4
; break;
715 case GDK_F5
: key_code
= WXK_F5
; break;
716 case GDK_F6
: key_code
= WXK_F6
; break;
717 case GDK_F7
: key_code
= WXK_F7
; break;
718 case GDK_F8
: key_code
= WXK_F8
; break;
719 case GDK_F9
: key_code
= WXK_F9
; break;
720 case GDK_F10
: key_code
= WXK_F10
; break;
721 case GDK_F11
: key_code
= WXK_F11
; break;
722 case GDK_F12
: key_code
= WXK_F12
; break;
724 if (event
->length
== 1)
726 key_code
= (unsigned char)*event
->string
;
728 else if ((keysym
& 0xFF) == keysym
)
730 key_code
= (guint
)keysym
;
737 //-----------------------------------------------------------------------------
738 // "size_request" of m_widget
739 //-----------------------------------------------------------------------------
741 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
744 win
->GetSize( &w
, &h
);
748 requisition
->height
= h
;
749 requisition
->width
= w
;
752 //-----------------------------------------------------------------------------
753 // "expose_event" of m_wxwindow
754 //-----------------------------------------------------------------------------
756 static int gtk_window_expose_callback( GtkWidget
*widget
,
757 GdkEventExpose
*gdk_event
,
763 wxapp_install_idle_handler();
766 if (win->GetName() == wxT("panel"))
768 wxPrintf( wxT("OnExpose from ") );
769 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
770 wxPrintf( win->GetClassInfo()->GetClassName() );
771 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
772 (int)gdk_event->area.y,
773 (int)gdk_event->area.width,
774 (int)gdk_event->area.height );
778 GtkPizza
*pizza
= GTK_PIZZA (widget
);
780 if (win
->GetThemeEnabled())
782 wxWindow
*parent
= win
->GetParent();
783 while (parent
&& !parent
->IsTopLevel())
784 parent
= parent
->GetParent();
788 gtk_paint_flat_box (parent
->m_widget
->style
,
798 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
800 gdk_event
->area
.width
,
801 gdk_event
->area
.height
);
803 // Actual redrawing takes place in idle time.
808 //-----------------------------------------------------------------------------
809 // "event" of m_wxwindow
810 //-----------------------------------------------------------------------------
812 // GTK thinks it is clever and filters out a certain amount of "unneeded"
813 // expose events. We need them, of course, so we override the main event
814 // procedure in GtkWidget by giving our own handler for all system events.
815 // There, we look for expose events ourselves whereas all other events are
818 gint
gtk_window_event_event_callback( GtkWidget
*widget
,
819 GdkEventExpose
*event
,
822 if (event
->type
== GDK_EXPOSE
)
824 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
831 //-----------------------------------------------------------------------------
832 // "draw" of m_wxwindow
833 //-----------------------------------------------------------------------------
835 // This callback is a complete replacement of the gtk_pizza_draw() function,
838 static void gtk_window_draw_callback( GtkWidget
*widget
,
845 wxapp_install_idle_handler();
847 // The wxNO_FULL_REPAINT_ON_RESIZE flag only works if
848 // there are no child windows.
849 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
850 (win
->GetChildren().GetCount() == 0))
856 if (win->GetName() == wxT("panel"))
858 wxPrintf( wxT("OnDraw from ") );
859 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
860 wxPrintf( win->GetClassInfo()->GetClassName() );
861 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
868 GtkPizza
*pizza
= GTK_PIZZA (widget
);
870 if (win
->GetThemeEnabled())
872 wxWindow
*parent
= win
->GetParent();
873 while (parent
&& !parent
->IsTopLevel())
874 parent
= parent
->GetParent();
878 gtk_paint_flat_box (parent
->m_widget
->style
,
889 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
890 (pizza
->clear_on_draw
))
892 gdk_window_clear_area( pizza
->bin_window
,
893 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
896 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
898 // Actual redrawing takes place in idle time.
900 #ifndef __WXUNIVERSAL__
901 // Redraw child widgets
902 GList
*children
= pizza
->children
;
905 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
906 children
= children
->next
;
908 GdkRectangle child_area
;
909 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
911 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
917 //-----------------------------------------------------------------------------
918 // "key_press_event" from any window
919 //-----------------------------------------------------------------------------
921 // turn on to see the key event codes on the console
922 #undef DEBUG_KEY_EVENTS
924 static gint
gtk_window_key_press_callback( GtkWidget
*widget
,
925 GdkEventKey
*gdk_event
,
931 wxapp_install_idle_handler();
933 if (!win
->m_hasVMT
) return FALSE
;
934 if (g_blockEventsOnDrag
) return FALSE
;
939 GdkModifierType state
;
940 if (gdk_event
->window
)
941 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
945 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
947 #ifdef DEBUG_KEY_EVENTS
948 wxPrintf(_T("Key press event: %d => %ld\n"), gdk_event
->keyval
, key_code
);
949 #endif // DEBUG_KEY_EVENTS
951 /* sending unknown key events doesn't really make sense */
955 wxKeyEvent
event( wxEVT_KEY_DOWN
);
956 event
.SetTimestamp( gdk_event
->time
);
957 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
958 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
959 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
960 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
961 event
.m_keyCode
= key_code
;
962 event
.m_scanCode
= gdk_event
->keyval
;
965 event
.SetEventObject( win
);
966 ret
= win
->GetEventHandler()->ProcessEvent( event
);
971 wxWindowGTK
*ancestor
= win
;
974 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
977 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
978 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
981 if (ancestor
->IsTopLevel())
983 ancestor
= ancestor
->GetParent();
986 #endif // wxUSE_ACCEL
988 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
989 will only be sent if it is not in an accelerator table. */
992 key_code
= map_to_wx_keysym( gdk_event
);
996 #ifdef DEBUG_KEY_EVENTS
997 wxPrintf(_T("Char event: %ld\n"), key_code
);
998 #endif // DEBUG_KEY_EVENTS
1000 // reuse the ame event object, just change its type and use the
1001 // translated keycode instead of the raw one
1002 event
.SetEventType(wxEVT_CHAR
);
1003 event
.m_keyCode
= key_code
;
1005 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1009 /* win is a control: tab can be propagated up */
1011 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
1012 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
1013 // have this style, yet choose not to process this particular TAB in which
1014 // case TAB must still work as a navigational character
1016 !win
->HasFlag(wxTE_PROCESS_TAB
) &&
1018 win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
1020 wxNavigationKeyEvent new_event
;
1021 new_event
.SetEventObject( win
->GetParent() );
1022 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
1023 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
1024 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1025 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
1026 new_event
.SetCurrentFocus( win
);
1027 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
1030 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
1032 (gdk_event
->keyval
== GDK_Escape
) )
1034 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
1035 new_event
.SetEventObject( win
);
1036 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
1040 #if 0 // (GTK_MINOR_VERSION > 0)
1041 /* Pressing F10 will activate the menu bar of the top frame. */
1043 (gdk_event
->keyval
== GDK_F10
) )
1045 wxWindowGTK
*ancestor
= win
;
1048 if (wxIsKindOf(ancestor
,wxFrame
))
1050 wxFrame
*frame
= (wxFrame
*) ancestor
;
1051 wxMenuBar
*menubar
= frame
->GetMenuBar();
1054 wxNode
*node
= menubar
->GetMenus().First();
1057 wxMenu
*firstMenu
= (wxMenu
*) node
->Data();
1058 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu
->m_owner
) );
1064 ancestor
= ancestor
->GetParent();
1071 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1078 //-----------------------------------------------------------------------------
1079 // "key_release_event" from any window
1080 //-----------------------------------------------------------------------------
1082 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindowGTK
*win
)
1087 wxapp_install_idle_handler();
1089 if (!win
->m_hasVMT
) return FALSE
;
1090 if (g_blockEventsOnDrag
) return FALSE
;
1092 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
1094 #ifdef DEBUG_KEY_EVENTS
1095 wxPrintf(_T("Key release event: %d => %ld\n"), gdk_event
->keyval
, key_code
);
1096 #endif // DEBUG_KEY_EVENTS
1098 /* sending unknown key events doesn't really make sense */
1099 if (key_code
== 0) return FALSE
;
1103 GdkModifierType state
;
1104 if (gdk_event
->window
)
1105 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1107 wxKeyEvent
event( wxEVT_KEY_UP
);
1108 event
.SetTimestamp( gdk_event
->time
);
1109 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1110 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1111 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1112 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1113 event
.m_keyCode
= key_code
;
1114 event
.m_scanCode
= gdk_event
->keyval
;
1117 event
.SetEventObject( win
);
1119 if (win
->GetEventHandler()->ProcessEvent( event
))
1121 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1128 // ============================================================================
1130 // ============================================================================
1132 // init wxMouseEvent with the info from gdk_event
1133 #define InitMouseEvent(win, event, gdk_event) \
1135 event.SetTimestamp( gdk_event->time ); \
1136 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
1137 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
1138 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
1139 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
1140 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
1141 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
1142 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
1144 wxPoint pt = win->GetClientAreaOrigin(); \
1145 event.m_x = (wxCoord)gdk_event->x - pt.x; \
1146 event.m_y = (wxCoord)gdk_event->y - pt.y; \
1149 // ----------------------------------------------------------------------------
1150 // mouse event processing helper
1151 // ----------------------------------------------------------------------------
1153 static void AdjustEventButtonState(wxMouseEvent
& event
)
1155 // GDK reports the old state of the button for a button press event, but
1156 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1157 // for a LEFT_DOWN event, not FALSE, so we will invert
1158 // left/right/middleDown for the corresponding click events
1160 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1161 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1162 (event
.GetEventType() == wxEVT_LEFT_UP
))
1164 event
.m_leftDown
= !event
.m_leftDown
;
1168 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1169 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1170 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1172 event
.m_middleDown
= !event
.m_middleDown
;
1176 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1177 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1178 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1180 event
.m_rightDown
= !event
.m_rightDown
;
1185 //-----------------------------------------------------------------------------
1186 // "button_press_event"
1187 //-----------------------------------------------------------------------------
1189 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1194 wxapp_install_idle_handler();
1197 wxPrintf( wxT("1) OnButtonPress from ") );
1198 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1199 wxPrintf( win->GetClassInfo()->GetClassName() );
1200 wxPrintf( wxT(".\n") );
1202 if (!win
->m_hasVMT
) return FALSE
;
1203 if (g_blockEventsOnDrag
) return TRUE
;
1204 if (g_blockEventsOnScroll
) return TRUE
;
1206 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1208 if (win
->m_wxwindow
)
1210 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1212 gtk_widget_grab_focus (win
->m_wxwindow
);
1215 wxPrintf( wxT("GrabFocus from ") );
1216 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1217 wxPrintf( win->GetClassInfo()->GetClassName() );
1218 wxPrintf( wxT(".\n") );
1224 wxEventType event_type
= wxEVT_NULL
;
1226 if (gdk_event
->button
== 1)
1228 switch (gdk_event
->type
)
1230 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1231 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1235 else if (gdk_event
->button
== 2)
1237 switch (gdk_event
->type
)
1239 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1240 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1244 else if (gdk_event
->button
== 3)
1246 switch (gdk_event
->type
)
1248 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1249 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1254 if ( event_type
== wxEVT_NULL
)
1256 // unknown mouse button or click type
1260 wxMouseEvent
event( event_type
);
1261 InitMouseEvent( win
, event
, gdk_event
);
1263 AdjustEventButtonState(event
);
1265 // wxListBox actually get mouse events from the item
1267 if (win
->m_isListBox
)
1269 event
.m_x
+= widget
->allocation
.x
;
1270 event
.m_y
+= widget
->allocation
.y
;
1273 // Some control don't have their own X window and thus cannot get
1276 if (!g_captureWindow
)
1278 wxCoord x
= event
.m_x
;
1279 wxCoord y
= event
.m_y
;
1280 if (win
->m_wxwindow
)
1282 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1283 x
+= pizza
->xoffset
;
1284 y
+= pizza
->yoffset
;
1287 wxNode
*node
= win
->GetChildren().First();
1290 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1292 node
= node
->Next();
1293 if (!child
->IsShown())
1296 if (child
->m_isStaticBox
)
1298 // wxStaticBox is transparent in the box itself
1299 int xx1
= child
->m_x
;
1300 int yy1
= child
->m_y
;
1301 int xx2
= child
->m_x
+ child
->m_width
;
1302 int yy2
= child
->m_x
+ child
->m_height
;
1305 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1307 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1309 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1311 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1314 event
.m_x
-= child
->m_x
;
1315 event
.m_y
-= child
->m_y
;
1322 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1323 (child
->m_x
<= x
) &&
1324 (child
->m_y
<= y
) &&
1325 (child
->m_x
+child
->m_width
>= x
) &&
1326 (child
->m_y
+child
->m_height
>= y
))
1329 event
.m_x
-= child
->m_x
;
1330 event
.m_y
-= child
->m_y
;
1337 event
.SetEventObject( win
);
1339 gs_timeLastClick
= gdk_event
->time
;
1342 wxPrintf( wxT("2) OnButtonPress from ") );
1343 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1344 wxPrintf( win->GetClassInfo()->GetClassName() );
1345 wxPrintf( wxT(".\n") );
1348 if (win
->GetEventHandler()->ProcessEvent( event
))
1350 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1357 //-----------------------------------------------------------------------------
1358 // "button_release_event"
1359 //-----------------------------------------------------------------------------
1361 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1366 wxapp_install_idle_handler();
1368 if (!win
->m_hasVMT
) return FALSE
;
1369 if (g_blockEventsOnDrag
) return FALSE
;
1370 if (g_blockEventsOnScroll
) return FALSE
;
1372 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1375 printf( "OnButtonRelease from " );
1376 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1377 printf( win->GetClassInfo()->GetClassName() );
1381 wxEventType event_type
= wxEVT_NULL
;
1383 switch (gdk_event
->button
)
1385 case 1: event_type
= wxEVT_LEFT_UP
; break;
1386 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1387 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1388 default: return FALSE
;
1391 wxMouseEvent
event( event_type
);
1392 InitMouseEvent( win
, event
, gdk_event
);
1394 AdjustEventButtonState(event
);
1396 // wxListBox actually get mouse events from the item
1398 if (win
->m_isListBox
)
1400 event
.m_x
+= widget
->allocation
.x
;
1401 event
.m_y
+= widget
->allocation
.y
;
1404 // Some control don't have their own X window and thus cannot get
1407 if (!g_captureWindow
)
1409 wxCoord x
= event
.m_x
;
1410 wxCoord y
= event
.m_y
;
1411 if (win
->m_wxwindow
)
1413 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1414 x
+= pizza
->xoffset
;
1415 y
+= pizza
->yoffset
;
1418 wxNode
*node
= win
->GetChildren().First();
1421 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1423 node
= node
->Next();
1424 if (!child
->IsShown())
1427 if (child
->m_isStaticBox
)
1429 // wxStaticBox is transparent in the box itself
1430 int xx1
= child
->m_x
;
1431 int yy1
= child
->m_y
;
1432 int xx2
= child
->m_x
+ child
->m_width
;
1433 int yy2
= child
->m_x
+ child
->m_height
;
1436 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1438 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1440 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1442 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1445 event
.m_x
-= child
->m_x
;
1446 event
.m_y
-= child
->m_y
;
1453 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1454 (child
->m_x
<= x
) &&
1455 (child
->m_y
<= y
) &&
1456 (child
->m_x
+child
->m_width
>= x
) &&
1457 (child
->m_y
+child
->m_height
>= y
))
1460 event
.m_x
-= child
->m_x
;
1461 event
.m_y
-= child
->m_y
;
1468 event
.SetEventObject( win
);
1470 if (win
->GetEventHandler()->ProcessEvent( event
))
1472 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1479 //-----------------------------------------------------------------------------
1480 // "motion_notify_event"
1481 //-----------------------------------------------------------------------------
1483 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
,
1484 GdkEventMotion
*gdk_event
,
1490 wxapp_install_idle_handler();
1492 if (!win
->m_hasVMT
) return FALSE
;
1493 if (g_blockEventsOnDrag
) return FALSE
;
1494 if (g_blockEventsOnScroll
) return FALSE
;
1496 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1498 if (gdk_event
->is_hint
)
1502 GdkModifierType state
;
1503 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1509 printf( "OnMotion from " );
1510 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1511 printf( win->GetClassInfo()->GetClassName() );
1515 wxMouseEvent
event( wxEVT_MOTION
);
1516 InitMouseEvent(win
, event
, gdk_event
);
1518 if ( g_captureWindow
)
1520 // synthetize a mouse enter or leave event if needed
1521 GdkWindow
*winUnderMouse
= gdk_window_at_pointer(NULL
, NULL
);
1522 bool hasMouse
= winUnderMouse
== gdk_event
->window
;
1523 if ( hasMouse
!= g_captureWindowHasMouse
)
1525 // the mouse changed window
1526 g_captureWindowHasMouse
= hasMouse
;
1528 wxMouseEvent
event(g_captureWindowHasMouse
? wxEVT_ENTER_WINDOW
1529 : wxEVT_LEAVE_WINDOW
);
1530 InitMouseEvent(win
, event
, gdk_event
);
1531 event
.SetEventObject(win
);
1532 win
->GetEventHandler()->ProcessEvent(event
);
1537 // Some control don't have their own X window and thus cannot get
1540 wxCoord x
= event
.m_x
;
1541 wxCoord y
= event
.m_y
;
1542 if (win
->m_wxwindow
)
1544 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1545 x
+= pizza
->xoffset
;
1546 y
+= pizza
->yoffset
;
1549 wxNode
*node
= win
->GetChildren().First();
1552 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1554 node
= node
->Next();
1555 if (!child
->IsShown())
1558 if (child
->m_isStaticBox
)
1560 // wxStaticBox is transparent in the box itself
1561 int xx1
= child
->m_x
;
1562 int yy1
= child
->m_y
;
1563 int xx2
= child
->m_x
+ child
->m_width
;
1564 int yy2
= child
->m_x
+ child
->m_height
;
1567 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1569 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1571 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1573 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1576 event
.m_x
-= child
->m_x
;
1577 event
.m_y
-= child
->m_y
;
1584 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1585 (child
->m_x
<= x
) &&
1586 (child
->m_y
<= y
) &&
1587 (child
->m_x
+child
->m_width
>= x
) &&
1588 (child
->m_y
+child
->m_height
>= y
))
1591 event
.m_x
-= child
->m_x
;
1592 event
.m_y
-= child
->m_y
;
1599 event
.SetEventObject( win
);
1601 if (win
->GetEventHandler()->ProcessEvent( event
))
1603 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1610 //-----------------------------------------------------------------------------
1612 //-----------------------------------------------------------------------------
1614 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
,
1615 GdkEvent
*WXUNUSED(event
),
1621 wxapp_install_idle_handler();
1623 if (!win
->m_hasVMT
) return FALSE
;
1624 if (g_blockEventsOnDrag
) return FALSE
;
1626 switch ( g_sendActivateEvent
)
1629 // we've got focus from outside, synthetize wxActivateEvent
1630 g_sendActivateEvent
= 1;
1634 // another our window just lost focus, it was already ours before
1635 // - don't send any wxActivateEvent
1636 g_sendActivateEvent
= -1;
1641 g_focusWindow
= win
;
1644 wxPrintf( "OnSetFocus from " );
1645 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
1646 wxPrintf( win
->GetClassInfo()->GetClassName() );
1650 // notify the parent keeping track of focus for the kbd navigation
1651 // purposes that we got it
1652 wxChildFocusEvent
eventFocus(win
);
1653 (void)win
->GetEventHandler()->ProcessEvent(eventFocus
);
1657 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1661 // caret needs to be informed about focus change
1662 wxCaret
*caret
= win
->GetCaret();
1665 caret
->OnSetFocus();
1667 #endif // wxUSE_CARET
1669 wxWindowGTK
*active
= wxGetTopLevelParent(win
);
1670 if ( active
!= g_activeFrame
)
1672 if ( g_activeFrame
)
1674 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame
);
1675 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
1676 event
.SetEventObject(g_activeFrame
);
1677 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1680 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active
);
1681 g_activeFrame
= active
;
1682 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId());
1683 event
.SetEventObject(g_activeFrame
);
1684 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1686 g_activeFrameLostFocus
= FALSE
;
1689 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1690 event
.SetEventObject( win
);
1692 if (win
->GetEventHandler()->ProcessEvent( event
))
1694 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1702 //-----------------------------------------------------------------------------
1703 // "focus_out_event"
1704 //-----------------------------------------------------------------------------
1706 static GtkWidget
*gs_widgetLastFocus
= NULL
;
1708 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindowGTK
*win
)
1713 wxapp_install_idle_handler();
1715 if (!win
->m_hasVMT
) return FALSE
;
1716 if (g_blockEventsOnDrag
) return FALSE
;
1718 // VZ: this is really weird but GTK+ seems to call us from inside
1719 // gtk_widget_grab_focus(), i.e. it first sends "focus_out" signal to
1720 // this widget and then "focus_in". This is totally unexpected and
1721 // completely breaks wxUniv code so ignore this dummy event (we can't
1722 // be losing focus if we're about to acquire it!)
1723 if ( widget
== gs_widgetLastFocus
)
1725 gs_widgetLastFocus
= NULL
;
1730 if ( !g_activeFrameLostFocus
&& g_activeFrame
)
1732 // VZ: commenting this out because it does happen (although not easy
1733 // to reproduce, I only see it when using wxMiniFrame and not
1734 // always) and makes using Mahogany quite annoying
1736 wxASSERT_MSG( wxGetTopLevelParent(win
) == g_activeFrame
,
1737 wxT("unfocusing window that hasn't gained focus properly") )
1740 g_activeFrameLostFocus
= TRUE
;
1743 // if the focus goes out of our app alltogether, OnIdle() will send
1744 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1745 // g_sendActivateEvent to -1
1746 g_sendActivateEvent
= 0;
1748 wxWindowGTK
*winFocus
= wxFindFocusedChild(win
);
1752 g_focusWindow
= (wxWindowGTK
*)NULL
;
1755 wxPrintf( "OnKillFocus from " );
1756 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
1757 wxPrintf( win
->GetClassInfo()->GetClassName() );
1767 // caret needs to be informed about focus change
1768 wxCaret
*caret
= win
->GetCaret();
1771 caret
->OnKillFocus();
1773 #endif // wxUSE_CARET
1775 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1776 event
.SetEventObject( win
);
1778 if (win
->GetEventHandler()->ProcessEvent( event
))
1780 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1787 //-----------------------------------------------------------------------------
1788 // "enter_notify_event"
1789 //-----------------------------------------------------------------------------
1791 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1796 wxapp_install_idle_handler();
1798 if (!win
->m_hasVMT
) return FALSE
;
1799 if (g_blockEventsOnDrag
) return FALSE
;
1801 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1803 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1804 event
.SetTimestamp( gdk_event
->time
);
1805 event
.SetEventObject( win
);
1809 GdkModifierType state
= (GdkModifierType
)0;
1811 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1813 InitMouseEvent(win
, event
, gdk_event
);
1814 wxPoint pt
= win
->GetClientAreaOrigin();
1815 event
.m_x
= x
+ pt
.x
;
1816 event
.m_y
= y
+ pt
.y
;
1818 if (win
->GetEventHandler()->ProcessEvent( event
))
1820 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1827 //-----------------------------------------------------------------------------
1828 // "leave_notify_event"
1829 //-----------------------------------------------------------------------------
1831 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1836 wxapp_install_idle_handler();
1838 if (!win
->m_hasVMT
) return FALSE
;
1839 if (g_blockEventsOnDrag
) return FALSE
;
1841 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1843 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1844 event
.SetTimestamp( gdk_event
->time
);
1845 event
.SetEventObject( win
);
1849 GdkModifierType state
= (GdkModifierType
)0;
1851 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1853 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1854 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1855 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1856 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1857 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1858 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1859 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1861 wxPoint pt
= win
->GetClientAreaOrigin();
1862 event
.m_x
= x
+ pt
.x
;
1863 event
.m_y
= y
+ pt
.y
;
1865 if (win
->GetEventHandler()->ProcessEvent( event
))
1867 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1874 //-----------------------------------------------------------------------------
1875 // "value_changed" from m_vAdjust
1876 //-----------------------------------------------------------------------------
1878 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1883 wxapp_install_idle_handler();
1885 if (g_blockEventsOnDrag
) return;
1887 if (!win
->m_hasVMT
) return;
1889 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1890 if (fabs(diff
) < 0.2) return;
1892 win
->m_oldVerticalPos
= adjust
->value
;
1894 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1895 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1897 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1898 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1899 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1900 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1901 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1903 int value
= (int)(adjust
->value
+0.5);
1905 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1906 event
.SetEventObject( win
);
1907 win
->GetEventHandler()->ProcessEvent( event
);
1910 //-----------------------------------------------------------------------------
1911 // "value_changed" from m_hAdjust
1912 //-----------------------------------------------------------------------------
1914 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1919 wxapp_install_idle_handler();
1921 if (g_blockEventsOnDrag
) return;
1922 if (!win
->m_hasVMT
) return;
1924 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1925 if (fabs(diff
) < 0.2) return;
1927 win
->m_oldHorizontalPos
= adjust
->value
;
1929 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1930 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1932 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1933 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1934 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1935 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1936 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1938 int value
= (int)(adjust
->value
+0.5);
1940 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1941 event
.SetEventObject( win
);
1942 win
->GetEventHandler()->ProcessEvent( event
);
1945 //-----------------------------------------------------------------------------
1946 // "button_press_event" from scrollbar
1947 //-----------------------------------------------------------------------------
1949 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1950 GdkEventButton
*gdk_event
,
1956 wxapp_install_idle_handler();
1959 g_blockEventsOnScroll
= TRUE
;
1960 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1965 //-----------------------------------------------------------------------------
1966 // "button_release_event" from scrollbar
1967 //-----------------------------------------------------------------------------
1969 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1970 GdkEventButton
*WXUNUSED(gdk_event
),
1975 // don't test here as we can release the mouse while being over
1976 // a different window than the slider
1978 // if (gdk_event->window != widget->slider) return FALSE;
1980 g_blockEventsOnScroll
= FALSE
;
1982 if (win
->m_isScrolling
)
1984 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
1988 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1989 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1991 value
= (int)(win
->m_hAdjust
->value
+0.5);
1994 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1996 value
= (int)(win
->m_vAdjust
->value
+0.5);
2000 wxScrollWinEvent
event( command
, value
, dir
);
2001 event
.SetEventObject( win
);
2002 win
->GetEventHandler()->ProcessEvent( event
);
2005 win
->m_isScrolling
= FALSE
;
2010 // ----------------------------------------------------------------------------
2011 // this wxWindowBase function is implemented here (in platform-specific file)
2012 // because it is static and so couldn't be made virtual
2013 // ----------------------------------------------------------------------------
2015 wxWindow
*wxWindowBase::FindFocus()
2017 // the cast is necessary when we compile in wxUniversal mode
2018 return (wxWindow
*)g_focusWindow
;
2021 //-----------------------------------------------------------------------------
2022 // "realize" from m_widget
2023 //-----------------------------------------------------------------------------
2025 /* We cannot set colours and fonts before the widget has
2026 been realized, so we do this directly after realization. */
2029 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
2034 wxapp_install_idle_handler();
2036 if (win
->m_delayedBackgroundColour
)
2037 win
->SetBackgroundColour( win
->GetBackgroundColour() );
2039 if (win
->m_delayedForegroundColour
)
2040 win
->SetForegroundColour( win
->GetForegroundColour() );
2042 wxWindowCreateEvent
event( win
);
2043 event
.SetEventObject( win
);
2044 win
->GetEventHandler()->ProcessEvent( event
);
2049 //-----------------------------------------------------------------------------
2051 //-----------------------------------------------------------------------------
2054 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
2055 GtkAllocation
*WXUNUSED(alloc
),
2059 wxapp_install_idle_handler();
2061 if (!win
->m_hasScrolling
) return;
2063 int client_width
= 0;
2064 int client_height
= 0;
2065 win
->GetClientSize( &client_width
, &client_height
);
2066 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
2069 win
->m_oldClientWidth
= client_width
;
2070 win
->m_oldClientHeight
= client_height
;
2072 if (!win
->m_nativeSizeEvent
)
2074 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
2075 event
.SetEventObject( win
);
2076 win
->GetEventHandler()->ProcessEvent( event
);
2082 #define WXUNUSED_UNLESS_XIM(param) param
2084 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2087 /* Resize XIM window */
2090 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2091 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
2092 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2095 wxapp_install_idle_handler();
2101 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
2105 gdk_window_get_size (widget
->window
, &width
, &height
);
2106 win
->m_icattr
->preedit_area
.width
= width
;
2107 win
->m_icattr
->preedit_area
.height
= height
;
2108 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2113 //-----------------------------------------------------------------------------
2114 // "realize" from m_wxwindow
2115 //-----------------------------------------------------------------------------
2117 /* Initialize XIM support */
2120 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2121 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2124 wxapp_install_idle_handler();
2127 if (win
->m_ic
) return FALSE
;
2128 if (!widget
) return FALSE
;
2129 if (!gdk_im_ready()) return FALSE
;
2131 win
->m_icattr
= gdk_ic_attr_new();
2132 if (!win
->m_icattr
) return FALSE
;
2136 GdkColormap
*colormap
;
2137 GdkICAttr
*attr
= win
->m_icattr
;
2138 unsigned attrmask
= GDK_IC_ALL_REQ
;
2140 GdkIMStyle supported_style
= (GdkIMStyle
)
2141 (GDK_IM_PREEDIT_NONE
|
2142 GDK_IM_PREEDIT_NOTHING
|
2143 GDK_IM_PREEDIT_POSITION
|
2144 GDK_IM_STATUS_NONE
|
2145 GDK_IM_STATUS_NOTHING
);
2147 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2148 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2150 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2151 attr
->client_window
= widget
->window
;
2153 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2154 gtk_widget_get_default_colormap ())
2156 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2157 attr
->preedit_colormap
= colormap
;
2160 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2161 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2162 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2163 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2165 switch (style
& GDK_IM_PREEDIT_MASK
)
2167 case GDK_IM_PREEDIT_POSITION
:
2168 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2170 g_warning ("over-the-spot style requires fontset");
2174 gdk_window_get_size (widget
->window
, &width
, &height
);
2176 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2177 attr
->spot_location
.x
= 0;
2178 attr
->spot_location
.y
= height
;
2179 attr
->preedit_area
.x
= 0;
2180 attr
->preedit_area
.y
= 0;
2181 attr
->preedit_area
.width
= width
;
2182 attr
->preedit_area
.height
= height
;
2183 attr
->preedit_fontset
= widget
->style
->font
;
2188 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2190 if (win
->m_ic
== NULL
)
2191 g_warning ("Can't create input context.");
2194 mask
= gdk_window_get_events (widget
->window
);
2195 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2196 gdk_window_set_events (widget
->window
, mask
);
2198 if (GTK_WIDGET_HAS_FOCUS(widget
))
2199 gdk_im_begin (win
->m_ic
, widget
->window
);
2206 //-----------------------------------------------------------------------------
2207 // InsertChild for wxWindowGTK.
2208 //-----------------------------------------------------------------------------
2210 /* Callback for wxWindowGTK. This very strange beast has to be used because
2211 * C++ has no virtual methods in a constructor. We have to emulate a
2212 * virtual function here as wxNotebook requires a different way to insert
2213 * a child in it. I had opted for creating a wxNotebookPage window class
2214 * which would have made this superfluous (such in the MDI window system),
2215 * but no-one was listening to me... */
2217 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child
)
2219 /* the window might have been scrolled already, do we
2220 have to adapt the position */
2221 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2222 child
->m_x
+= pizza
->xoffset
;
2223 child
->m_y
+= pizza
->yoffset
;
2225 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2226 GTK_WIDGET(child
->m_widget
),
2233 //-----------------------------------------------------------------------------
2235 //-----------------------------------------------------------------------------
2237 wxWindow
*wxGetActiveWindow()
2239 // the cast is necessary when we compile in wxUniversal mode
2240 return (wxWindow
*)g_focusWindow
;
2243 //-----------------------------------------------------------------------------
2245 //-----------------------------------------------------------------------------
2247 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
2249 #ifdef __WXUNIVERSAL__
2250 IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
)
2252 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2253 #endif // __WXUNIVERSAL__/__WXGTK__
2255 void wxWindowGTK::Init()
2261 m_widget
= (GtkWidget
*) NULL
;
2262 m_wxwindow
= (GtkWidget
*) NULL
;
2263 m_focusWidget
= (GtkWidget
*) NULL
;
2273 m_needParent
= TRUE
;
2274 m_isBeingDeleted
= FALSE
;
2277 m_nativeSizeEvent
= FALSE
;
2279 m_hasScrolling
= FALSE
;
2280 m_isScrolling
= FALSE
;
2282 m_hAdjust
= (GtkAdjustment
*) NULL
;
2283 m_vAdjust
= (GtkAdjustment
*) NULL
;
2284 m_oldHorizontalPos
= 0.0;
2285 m_oldVerticalPos
= 0.0;
2288 m_widgetStyle
= (GtkStyle
*) NULL
;
2290 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2292 m_isStaticBox
= FALSE
;
2293 m_isRadioButton
= FALSE
;
2294 m_isListBox
= FALSE
;
2296 m_acceptsFocus
= FALSE
;
2298 m_clipPaintRegion
= FALSE
;
2300 m_cursor
= *wxSTANDARD_CURSOR
;
2302 m_delayedForegroundColour
= FALSE
;
2303 m_delayedBackgroundColour
= FALSE
;
2306 m_ic
= (GdkIC
*) NULL
;
2307 m_icattr
= (GdkICAttr
*) NULL
;
2311 wxWindowGTK::wxWindowGTK()
2316 wxWindowGTK::wxWindowGTK( wxWindow
*parent
,
2321 const wxString
&name
)
2325 Create( parent
, id
, pos
, size
, style
, name
);
2328 bool wxWindowGTK::Create( wxWindow
*parent
,
2333 const wxString
&name
)
2335 if (!PreCreation( parent
, pos
, size
) ||
2336 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2338 wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
2342 m_insertCallback
= wxInsertChildInWindow
;
2344 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2345 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2347 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2349 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2350 scroll_class
->scrollbar_spacing
= 0;
2352 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2354 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2355 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2357 m_wxwindow
= gtk_pizza_new();
2359 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2361 #ifndef __WXUNIVERSAL__
2362 #if (GTK_MINOR_VERSION > 0)
2363 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2365 if (HasFlag(wxRAISED_BORDER
))
2367 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2369 else if (HasFlag(wxSUNKEN_BORDER
))
2371 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2373 else if (HasFlag(wxSIMPLE_BORDER
))
2375 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2379 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2381 #else // GTK_MINOR_VERSION == 0
2382 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2384 if (HasFlag(wxRAISED_BORDER
))
2386 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2388 else if (HasFlag(wxSUNKEN_BORDER
))
2390 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2394 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2396 #endif // GTK_MINOR_VERSION
2397 #endif // __WXUNIVERSAL__
2399 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2400 m_acceptsFocus
= TRUE
;
2402 #if (GTK_MINOR_VERSION == 0)
2403 // shut the viewport up
2404 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2405 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2406 #endif // GTK_MINOR_VERSION == 0
2408 // I _really_ don't want scrollbars in the beginning
2409 m_vAdjust
->lower
= 0.0;
2410 m_vAdjust
->upper
= 1.0;
2411 m_vAdjust
->value
= 0.0;
2412 m_vAdjust
->step_increment
= 1.0;
2413 m_vAdjust
->page_increment
= 1.0;
2414 m_vAdjust
->page_size
= 5.0;
2415 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2416 m_hAdjust
->lower
= 0.0;
2417 m_hAdjust
->upper
= 1.0;
2418 m_hAdjust
->value
= 0.0;
2419 m_hAdjust
->step_increment
= 1.0;
2420 m_hAdjust
->page_increment
= 1.0;
2421 m_hAdjust
->page_size
= 5.0;
2422 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2424 // these handlers block mouse events to any window during scrolling such as
2425 // motion events and prevent GTK and wxWindows from fighting over where the
2428 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2429 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2431 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2432 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2434 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2435 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2437 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2438 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2440 // these handlers get notified when screen updates are required either when
2441 // scrolling or when the window size (and therefore scrollbar configuration)
2444 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2445 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2446 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2447 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2449 gtk_widget_show( m_wxwindow
);
2452 m_parent
->DoAddChild( this );
2454 m_focusWidget
= m_wxwindow
;
2463 wxWindowGTK::~wxWindowGTK()
2465 if (g_focusWindow
== this)
2466 g_focusWindow
= NULL
;
2468 if (g_activeFrame
== this)
2469 g_activeFrame
= NULL
;
2471 m_isBeingDeleted
= TRUE
;
2480 m_parent
->RemoveChild( this );
2484 gdk_ic_destroy (m_ic
);
2486 gdk_ic_attr_destroy (m_icattr
);
2491 #if DISABLE_STYLE_IF_BROKEN_THEME
2492 // don't delete if it's a pixmap theme style
2493 if (!m_widgetStyle
->engine_data
)
2494 gtk_style_unref( m_widgetStyle
);
2496 m_widgetStyle
= (GtkStyle
*) NULL
;
2501 gtk_widget_destroy( m_wxwindow
);
2502 m_wxwindow
= (GtkWidget
*) NULL
;
2507 gtk_widget_destroy( m_widget
);
2508 m_widget
= (GtkWidget
*) NULL
;
2512 bool wxWindowGTK::PreCreation( wxWindowGTK
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2514 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2516 /* this turns -1 into 20 so that a minimal window is
2517 visible even although -1,-1 has been given as the
2518 size of the window. the same trick is used in other
2519 ports and should make debugging easier */
2520 m_width
= WidthDefault(size
.x
);
2521 m_height
= HeightDefault(size
.y
);
2526 /* some reasonable defaults */
2531 m_x
= (gdk_screen_width () - m_width
) / 2;
2532 if (m_x
< 10) m_x
= 10;
2536 m_y
= (gdk_screen_height () - m_height
) / 2;
2537 if (m_y
< 10) m_y
= 10;
2544 void wxWindowGTK::PostCreation()
2546 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2552 // these get reported to wxWindows -> wxPaintEvent
2554 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2556 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2557 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2559 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2560 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2562 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2564 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2565 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
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 );
2573 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2574 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2579 if (m_focusWidget
== NULL
)
2580 m_focusWidget
= m_widget
;
2583 if (GetClassInfo() && GetClassInfo()->GetClassName())
2584 wxPrintf( GetClassInfo()->GetClassName() );
2588 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event",
2589 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2591 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event",
2592 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2594 // connect to the various key and mouse handlers
2596 GtkWidget
*connect_widget
= GetConnectWidget();
2598 ConnectWidget( connect_widget
);
2600 /* We cannot set colours, fonts and cursors before the widget has
2601 been realized, so we do this directly after realization */
2602 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2603 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2607 // Catch native resize events
2608 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2609 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2611 // Initialize XIM support
2612 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2613 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2615 // And resize XIM window
2616 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2617 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2620 if (!GTK_IS_COMBO(m_widget
))
2622 // This is needed if we want to add our windows into native
2623 // GTK control, such as the toolbar. With this callback, the
2624 // toolbar gets to know the correct size (the one set by the
2625 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2626 // when moving to GTK 2.0.
2627 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2628 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2634 void wxWindowGTK::ConnectWidget( GtkWidget
*widget
)
2636 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2637 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2639 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2640 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2642 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2643 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2645 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2646 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2648 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2649 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2651 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2652 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2654 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2655 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2658 bool wxWindowGTK::Destroy()
2660 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2664 return wxWindowBase::Destroy();
2667 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
)
2669 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2672 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2674 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2675 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") );
2678 printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
2681 if (m_resizing
) return; /* I don't like recursions */
2684 int currentX
, currentY
;
2685 GetPosition(¤tX
, ¤tY
);
2690 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
2692 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2694 /* don't set the size for children of wxNotebook, just take the values. */
2702 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2704 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2706 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2707 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2708 if (width
!= -1) m_width
= width
;
2709 if (height
!= -1) m_height
= height
;
2713 m_x
= x
+ pizza
->xoffset
;
2714 m_y
= y
+ pizza
->yoffset
;
2719 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2721 if (width
== -1) m_width
= 80;
2724 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2726 if (height
== -1) m_height
= 26;
2729 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2730 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2731 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2732 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2735 int bottom_border
= 0;
2737 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2739 /* the default button has a border around it */
2744 DoMoveWindow( m_x
-border
,
2747 m_height
+border
+bottom_border
);
2752 /* Sometimes the client area changes size without the
2753 whole windows's size changing, but if the whole
2754 windows's size doesn't change, no wxSizeEvent will
2755 normally be sent. Here we add an extra test if
2756 the client test has been changed and this will
2758 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2762 wxPrintf( "OnSize sent from " );
2763 if (GetClassInfo() && GetClassInfo()->GetClassName())
2764 wxPrintf( GetClassInfo()->GetClassName() );
2765 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2768 if (!m_nativeSizeEvent
)
2770 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2771 event
.SetEventObject( this );
2772 GetEventHandler()->ProcessEvent( event
);
2778 void wxWindowGTK::OnInternalIdle()
2780 // Update invalidated regions.
2783 // Synthetize activate events.
2784 if ( g_sendActivateEvent
!= -1 )
2786 bool activate
= g_sendActivateEvent
!= 0;
2789 g_sendActivateEvent
= -1;
2791 wxTheApp
->SetActive(activate
, (wxWindow
*)g_focusWindowLast
);
2794 if ( g_activeFrameLostFocus
)
2796 if ( g_activeFrame
)
2798 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame
);
2799 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
2800 event
.SetEventObject(g_activeFrame
);
2801 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
2802 g_activeFrame
= NULL
;
2804 g_activeFrameLostFocus
= FALSE
;
2807 wxCursor cursor
= m_cursor
;
2808 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2812 /* I now set the cursor anew in every OnInternalIdle call
2813 as setting the cursor in a parent window also effects the
2814 windows above so that checking for the current cursor is
2819 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2821 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2823 if (!g_globalCursor
.Ok())
2824 cursor
= *wxSTANDARD_CURSOR
;
2826 window
= m_widget
->window
;
2827 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2828 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2834 GdkWindow
*window
= m_widget
->window
;
2835 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2836 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2844 void wxWindowGTK::DoGetSize( int *width
, int *height
) const
2846 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2848 if (width
) (*width
) = m_width
;
2849 if (height
) (*height
) = m_height
;
2852 void wxWindowGTK::DoSetClientSize( int width
, int height
)
2854 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2858 SetSize( width
, height
);
2865 #ifndef __WXUNIVERSAL__
2866 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2868 /* when using GTK 1.2 we set the shadow border size to 2 */
2872 if (HasFlag(wxSIMPLE_BORDER
))
2874 /* when using GTK 1.2 we set the simple border size to 1 */
2878 #endif // __WXUNIVERSAL__
2882 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2884 GtkRequisition vscroll_req
;
2885 vscroll_req
.width
= 2;
2886 vscroll_req
.height
= 2;
2887 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2888 (scroll_window
->vscrollbar
, &vscroll_req
);
2890 GtkRequisition hscroll_req
;
2891 hscroll_req
.width
= 2;
2892 hscroll_req
.height
= 2;
2893 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2894 (scroll_window
->hscrollbar
, &hscroll_req
);
2896 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2898 if (scroll_window
->vscrollbar_visible
)
2900 dw
+= vscroll_req
.width
;
2901 dw
+= scroll_class
->scrollbar_spacing
;
2904 if (scroll_window
->hscrollbar_visible
)
2906 dh
+= hscroll_req
.height
;
2907 dh
+= scroll_class
->scrollbar_spacing
;
2911 SetSize( width
+dw
, height
+dh
);
2915 void wxWindowGTK::DoGetClientSize( int *width
, int *height
) const
2917 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2921 if (width
) (*width
) = m_width
;
2922 if (height
) (*height
) = m_height
;
2929 #ifndef __WXUNIVERSAL__
2930 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2932 /* when using GTK 1.2 we set the shadow border size to 2 */
2936 if (HasFlag(wxSIMPLE_BORDER
))
2938 /* when using GTK 1.2 we set the simple border size to 1 */
2942 #endif // __WXUNIVERSAL__
2946 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2948 GtkRequisition vscroll_req
;
2949 vscroll_req
.width
= 2;
2950 vscroll_req
.height
= 2;
2951 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2952 (scroll_window
->vscrollbar
, &vscroll_req
);
2954 GtkRequisition hscroll_req
;
2955 hscroll_req
.width
= 2;
2956 hscroll_req
.height
= 2;
2957 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2958 (scroll_window
->hscrollbar
, &hscroll_req
);
2960 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2962 if (scroll_window
->vscrollbar_visible
)
2964 dw
+= vscroll_req
.width
;
2965 dw
+= scroll_class
->scrollbar_spacing
;
2968 if (scroll_window
->hscrollbar_visible
)
2970 dh
+= hscroll_req
.height
;
2971 dh
+= scroll_class
->scrollbar_spacing
;
2975 if (width
) (*width
) = m_width
- dw
;
2976 if (height
) (*height
) = m_height
- dh
;
2980 printf( "GetClientSize, name %s ", GetName().c_str() );
2981 if (width) printf( " width = %d", (*width) );
2982 if (height) printf( " height = %d", (*height) );
2987 void wxWindowGTK::DoGetPosition( int *x
, int *y
) const
2989 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2993 if (m_parent
&& m_parent
->m_wxwindow
)
2995 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2996 dx
= pizza
->xoffset
;
2997 dy
= pizza
->yoffset
;
3000 if (x
) (*x
) = m_x
- dx
;
3001 if (y
) (*y
) = m_y
- dy
;
3004 void wxWindowGTK::DoClientToScreen( int *x
, int *y
) const
3006 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3008 if (!m_widget
->window
) return;
3010 GdkWindow
*source
= (GdkWindow
*) NULL
;
3012 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3014 source
= m_widget
->window
;
3018 gdk_window_get_origin( source
, &org_x
, &org_y
);
3022 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3024 org_x
+= m_widget
->allocation
.x
;
3025 org_y
+= m_widget
->allocation
.y
;
3033 void wxWindowGTK::DoScreenToClient( int *x
, int *y
) const
3035 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3037 if (!m_widget
->window
) return;
3039 GdkWindow
*source
= (GdkWindow
*) NULL
;
3041 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3043 source
= m_widget
->window
;
3047 gdk_window_get_origin( source
, &org_x
, &org_y
);
3051 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3053 org_x
+= m_widget
->allocation
.x
;
3054 org_y
+= m_widget
->allocation
.y
;
3062 bool wxWindowGTK::Show( bool show
)
3064 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3066 if (!wxWindowBase::Show(show
))
3073 gtk_widget_show( m_widget
);
3075 gtk_widget_hide( m_widget
);
3080 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
)
3082 win
->OnParentEnable(enable
);
3084 // Recurse, so that children have the opportunity to Do The Right Thing
3085 // and reset colours that have been messed up by a parent's (really ancestor's)
3087 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
3089 node
= node
->GetNext() )
3091 wxWindow
*child
= node
->GetData();
3092 if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
)))
3093 wxWindowNotifyEnable(child
, enable
);
3097 bool wxWindowGTK::Enable( bool enable
)
3099 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3101 if (!wxWindowBase::Enable(enable
))
3107 gtk_widget_set_sensitive( m_widget
, enable
);
3109 gtk_widget_set_sensitive( m_wxwindow
, enable
);
3111 wxWindowNotifyEnable(this, enable
);
3116 int wxWindowGTK::GetCharHeight() const
3118 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
3120 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
3122 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3124 return font
->ascent
+ font
->descent
;
3127 int wxWindowGTK::GetCharWidth() const
3129 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
3131 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
3133 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3135 return gdk_string_width( font
, "H" );
3138 void wxWindowGTK::GetTextExtent( const wxString
& string
,
3142 int *externalLeading
,
3143 const wxFont
*theFont
) const
3145 wxFont fontToUse
= m_font
;
3146 if (theFont
) fontToUse
= *theFont
;
3148 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
3150 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
3151 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
3152 if (y
) (*y
) = font
->ascent
+ font
->descent
;
3153 if (descent
) (*descent
) = font
->descent
;
3154 if (externalLeading
) (*externalLeading
) = 0; // ??
3157 void wxWindowGTK::SetFocus()
3159 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3162 wxPrintf( "SetFocus from " );
3163 if (GetClassInfo() && GetClassInfo()->GetClassName())
3164 wxPrintf( GetClassInfo()->GetClassName() );
3170 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3172 // see comment in gtk_window_focus_out_callback()
3173 gs_widgetLastFocus
= 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 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
3194 wxPrintf( "SetFocus finished in " );
3195 if (GetClassInfo() && GetClassInfo()->GetClassName())
3196 wxPrintf( GetClassInfo()->GetClassName() );
3202 bool wxWindowGTK::AcceptsFocus() const
3204 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3207 bool wxWindowGTK::Reparent( wxWindowBase
*newParentBase
)
3209 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3211 wxWindowGTK
*oldParent
= m_parent
,
3212 *newParent
= (wxWindowGTK
*)newParentBase
;
3214 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3216 if ( !wxWindowBase::Reparent(newParent
) )
3219 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3221 /* prevent GTK from deleting the widget arbitrarily */
3222 gtk_widget_ref( m_widget
);
3226 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3229 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3233 /* insert GTK representation */
3234 (*(newParent
->m_insertCallback
))(newParent
, this);
3237 /* reverse: prevent GTK from deleting the widget arbitrarily */
3238 gtk_widget_unref( m_widget
);
3243 void wxWindowGTK::DoAddChild(wxWindowGTK
*child
)
3245 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3247 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3249 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3254 /* insert GTK representation */
3255 (*m_insertCallback
)(this, child
);
3258 void wxWindowGTK::Raise()
3260 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3262 if (!m_widget
->window
) return;
3264 gdk_window_raise( m_widget
->window
);
3267 void wxWindowGTK::Lower()
3269 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3271 if (!m_widget
->window
) return;
3273 gdk_window_lower( m_widget
->window
);
3276 bool wxWindowGTK::SetCursor( const wxCursor
&cursor
)
3278 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3280 if (cursor
== m_cursor
)
3284 wxapp_install_idle_handler();
3286 if (cursor
== wxNullCursor
)
3287 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3289 return wxWindowBase::SetCursor( cursor
);
3292 void wxWindowGTK::WarpPointer( int x
, int y
)
3294 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3296 // We provide this function ourselves as it is
3297 // missing in GDK (top of this file).
3299 GdkWindow
*window
= (GdkWindow
*) NULL
;
3301 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3303 window
= GetConnectWidget()->window
;
3306 gdk_window_warp_pointer( window
, x
, y
);
3309 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect
*rect
)
3311 if (!m_widget
) return;
3312 if (!m_widget
->window
) return;
3314 // temporarily hide the caret to avoid nasty interactions between caret
3315 // drawing and the window contents redraw
3316 #if 0 // def wxUSE_CARET -- doesn't seem to help :-(
3317 wxCaretSuspend
cs((wxWindow
*)this);
3318 #endif // wxUSE_CARET
3320 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3324 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3325 m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
3329 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3330 m_clearRegion
.Clear();
3331 m_clearRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height
);
3339 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3340 m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
3344 GdkRectangle gdk_rect
;
3345 gdk_rect
.x
= rect
->x
;
3346 gdk_rect
.y
= rect
->y
;
3347 gdk_rect
.width
= rect
->width
;
3348 gdk_rect
.height
= rect
->height
;
3349 gtk_widget_draw( m_widget
, &gdk_rect
);
3356 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3357 m_updateRegion
.Clear();
3358 m_updateRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height
);
3362 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3367 void wxWindowGTK::Update()
3369 if (!m_updateRegion
.IsEmpty())
3371 GtkSendPaintEvents();
3375 void wxWindowGTK::GtkSendPaintEvents()
3379 m_clearRegion
.Clear();
3380 m_updateRegion
.Clear();
3384 m_clipPaintRegion
= TRUE
;
3386 if (!m_clearRegion
.IsEmpty())
3388 wxWindowDC
dc( (wxWindow
*)this );
3389 dc
.SetClippingRegion( m_clearRegion
);
3391 wxEraseEvent
erase_event( GetId(), &dc
);
3392 erase_event
.SetEventObject( this );
3394 if (!GetEventHandler()->ProcessEvent(erase_event
))
3396 wxRegionIterator
upd( m_clearRegion
);
3399 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3400 upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
3404 m_clearRegion
.Clear();
3407 wxNcPaintEvent
nc_paint_event( GetId() );
3408 nc_paint_event
.SetEventObject( this );
3409 GetEventHandler()->ProcessEvent( nc_paint_event
);
3411 wxPaintEvent
paint_event( GetId() );
3412 paint_event
.SetEventObject( this );
3413 GetEventHandler()->ProcessEvent( paint_event
);
3415 m_clipPaintRegion
= FALSE
;
3417 #ifndef __WXUNIVERSAL__
3418 // The following code will result in all window-less widgets
3419 // being redrawn because the wxWindows class is allowed to
3420 // paint over the window-less widgets.
3422 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
3424 GList
*children
= pizza
->children
;
3427 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
3428 children
= children
->next
;
3430 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
3431 GTK_WIDGET_DRAWABLE (child
->widget
))
3433 // Get intersection of widget area and update region
3434 wxRegion
region( m_updateRegion
);
3436 GdkEventExpose gdk_event
;
3437 gdk_event
.type
= GDK_EXPOSE
;
3438 gdk_event
.window
= pizza
->bin_window
;
3439 gdk_event
.count
= 0;
3441 wxRegionIterator
upd( m_updateRegion
);
3445 rect
.x
= upd
.GetX();
3446 rect
.y
= upd
.GetY();
3447 rect
.width
= upd
.GetWidth();
3448 rect
.height
= upd
.GetHeight();
3450 if (gtk_widget_intersect (child
->widget
, &rect
, &gdk_event
.area
))
3452 gtk_widget_event (child
->widget
, (GdkEvent
*) &gdk_event
);
3461 m_updateRegion
.Clear();
3464 void wxWindowGTK::Clear()
3466 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3468 if (!m_widget
->window
) return;
3470 if (m_wxwindow
&& m_wxwindow
->window
)
3472 // gdk_window_clear( m_wxwindow->window );
3477 void wxWindowGTK::DoSetToolTip( wxToolTip
*tip
)
3479 wxWindowBase::DoSetToolTip(tip
);
3482 m_tooltip
->Apply( (wxWindow
*)this );
3485 void wxWindowGTK::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3487 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3489 #endif // wxUSE_TOOLTIPS
3491 bool wxWindowGTK::SetBackgroundColour( const wxColour
&colour
)
3493 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3495 if (!wxWindowBase::SetBackgroundColour(colour
))
3497 // don't leave if the GTK widget has just
3499 if (!m_delayedBackgroundColour
) return FALSE
;
3502 GdkWindow
*window
= (GdkWindow
*) NULL
;
3504 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3506 window
= GetConnectWidget()->window
;
3510 // indicate that a new style has been set
3511 // but it couldn't get applied as the
3512 // widget hasn't been realized yet.
3513 m_delayedBackgroundColour
= TRUE
;
3517 (m_wxwindow
->window
) &&
3518 (m_backgroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
)))
3520 /* wxMSW doesn't clear the window here. I don't do that either to
3521 provide compatibility. call Clear() to do the job. */
3523 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3524 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3532 bool wxWindowGTK::SetForegroundColour( const wxColour
&colour
)
3534 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3536 if (!wxWindowBase::SetForegroundColour(colour
))
3538 // don't leave if the GTK widget has just
3540 if (!m_delayedForegroundColour
) return FALSE
;
3543 GdkWindow
*window
= (GdkWindow
*) NULL
;
3545 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3547 window
= GetConnectWidget()->window
;
3551 // indicate that a new style has been set
3552 // but it couldn't get applied as the
3553 // widget hasn't been realized yet.
3554 m_delayedForegroundColour
= TRUE
;
3562 GtkStyle
*wxWindowGTK::GetWidgetStyle()
3566 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3568 /* FIXME: is this necessary? */
3569 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3571 remake
->klass
= m_widgetStyle
->klass
;
3574 gtk_style_unref( m_widgetStyle
);
3575 m_widgetStyle
= remake
;
3579 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3582 def
= gtk_widget_get_default_style();
3584 m_widgetStyle
= gtk_style_copy( def
);
3586 /* FIXME: is this necessary? */
3587 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3589 m_widgetStyle
->klass
= def
->klass
;
3593 return m_widgetStyle
;
3596 void wxWindowGTK::SetWidgetStyle()
3598 #if DISABLE_STYLE_IF_BROKEN_THEME
3599 if (m_widget
->style
->engine_data
)
3601 static bool s_warningPrinted
= FALSE
;
3602 if (!s_warningPrinted
)
3604 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3605 s_warningPrinted
= TRUE
;
3607 m_widgetStyle
= m_widget
->style
;
3612 GtkStyle
*style
= GetWidgetStyle();
3614 if (m_font
!= wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT
))
3616 gdk_font_unref( style
->font
);
3617 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3620 if (m_foregroundColour
.Ok())
3622 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3623 if (m_foregroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT
))
3625 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3626 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3627 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3631 // Try to restore the gtk default style. This is still a little
3632 // oversimplified for what is probably really needed here for controls
3633 // other than buttons, but is better than not being able to (re)set a
3634 // control's foreground colour to *wxBLACK -- RL
3635 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3638 def
= gtk_widget_get_default_style();
3640 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3641 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3642 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3646 if (m_backgroundColour
.Ok())
3648 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3649 if (m_backgroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
))
3651 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3652 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3653 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3654 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3655 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3656 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3657 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3658 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3662 // Try to restore the gtk default style. This is still a little
3663 // oversimplified for what is probably really needed here for controls
3664 // other than buttons, but is better than not being able to (re)set a
3665 // control's background colour to default grey and means resetting a
3666 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3668 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3671 def
= gtk_widget_get_default_style();
3673 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3674 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3675 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3676 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3677 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3678 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3679 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3680 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3685 void wxWindowGTK::ApplyWidgetStyle()
3689 //-----------------------------------------------------------------------------
3690 // Pop-up menu stuff
3691 //-----------------------------------------------------------------------------
3693 #if wxUSE_MENUS_NATIVE
3696 void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3698 *is_waiting
= FALSE
;
3701 static void SetInvokingWindow( wxMenu
*menu
, wxWindowGTK
*win
)
3703 menu
->SetInvokingWindow( win
);
3704 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3707 wxMenuItem
*menuitem
= node
->GetData();
3708 if (menuitem
->IsSubMenu())
3710 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3713 node
= node
->GetNext();
3717 // used to pass the coordinates from wxWindowGTK::DoPopupMenu() to
3718 // wxPopupMenuPositionCallback()
3720 // should be safe even in the MT case as the user can hardly popup 2 menus
3721 // simultaneously, can he?
3722 static gint gs_pop_x
= 0;
3723 static gint gs_pop_y
= 0;
3725 extern "C" void wxPopupMenuPositionCallback( GtkMenu
*menu
,
3727 gpointer
WXUNUSED(user_data
) )
3729 // ensure that the menu appears entirely on screen
3731 gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
);
3733 wxSize sizeScreen
= wxGetDisplaySize();
3735 gint xmax
= sizeScreen
.x
- req
.width
,
3736 ymax
= sizeScreen
.y
- req
.height
;
3738 *x
= gs_pop_x
< xmax
? gs_pop_x
: xmax
;
3739 *y
= gs_pop_y
< ymax
? gs_pop_y
: ymax
;
3742 bool wxWindowGTK::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3744 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3746 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3748 SetInvokingWindow( menu
, this );
3754 ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3756 bool is_waiting
= TRUE
;
3758 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
),
3760 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
),
3761 (gpointer
)&is_waiting
);
3764 GTK_MENU(menu
->m_menu
),
3765 (GtkWidget
*) NULL
, // parent menu shell
3766 (GtkWidget
*) NULL
, // parent menu item
3767 wxPopupMenuPositionCallback
, // function to position it
3768 NULL
, // client data
3769 0, // button used to activate it
3770 gs_timeLastClick
// the time of activation
3775 while (gtk_events_pending())
3776 gtk_main_iteration();
3782 #endif // wxUSE_MENUS_NATIVE
3784 #if wxUSE_DRAG_AND_DROP
3786 void wxWindowGTK::SetDropTarget( wxDropTarget
*dropTarget
)
3788 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3790 GtkWidget
*dnd_widget
= GetConnectWidget();
3792 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3794 if (m_dropTarget
) delete m_dropTarget
;
3795 m_dropTarget
= dropTarget
;
3797 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3800 #endif // wxUSE_DRAG_AND_DROP
3802 GtkWidget
* wxWindowGTK::GetConnectWidget()
3804 GtkWidget
*connect_widget
= m_widget
;
3805 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3807 return connect_widget
;
3810 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow
*window
)
3813 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3815 return (window
== m_widget
->window
);
3818 bool wxWindowGTK::SetFont( const wxFont
&font
)
3820 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3822 if (!wxWindowBase::SetFont(font
))
3827 wxColour sysbg
= wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE
);
3828 if ( sysbg
== m_backgroundColour
)
3830 m_backgroundColour
= wxNullColour
;
3832 m_backgroundColour
= sysbg
;
3842 void wxWindowGTK::DoCaptureMouse()
3844 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3846 GdkWindow
*window
= (GdkWindow
*) NULL
;
3848 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3850 window
= GetConnectWidget()->window
;
3852 wxCHECK_RET( window
, _T("CaptureMouse() failed") );
3854 wxCursor
* cursor
= & m_cursor
;
3856 cursor
= wxSTANDARD_CURSOR
;
3858 gdk_pointer_grab( window
, FALSE
,
3860 (GDK_BUTTON_PRESS_MASK
|
3861 GDK_BUTTON_RELEASE_MASK
|
3862 GDK_POINTER_MOTION_HINT_MASK
|
3863 GDK_POINTER_MOTION_MASK
),
3865 cursor
->GetCursor(),
3866 (guint32
)GDK_CURRENT_TIME
);
3867 g_captureWindow
= this;
3868 g_captureWindowHasMouse
= TRUE
;
3871 void wxWindowGTK::DoReleaseMouse()
3873 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3875 wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") );
3877 g_captureWindow
= (wxWindowGTK
*) NULL
;
3879 GdkWindow
*window
= (GdkWindow
*) NULL
;
3881 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3883 window
= GetConnectWidget()->window
;
3888 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3892 wxWindow
*wxWindowBase::GetCapture()
3894 return (wxWindow
*)g_captureWindow
;
3897 bool wxWindowGTK::IsRetained() const
3902 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3903 int range
, bool refresh
)
3905 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3907 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3909 m_hasScrolling
= TRUE
;
3911 if (orient
== wxHORIZONTAL
)
3913 float fpos
= (float)pos
;
3914 float frange
= (float)range
;
3915 float fthumb
= (float)thumbVisible
;
3916 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3917 if (fpos
< 0.0) fpos
= 0.0;
3919 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3920 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3922 SetScrollPos( orient
, pos
, refresh
);
3926 m_oldHorizontalPos
= fpos
;
3928 m_hAdjust
->lower
= 0.0;
3929 m_hAdjust
->upper
= frange
;
3930 m_hAdjust
->value
= fpos
;
3931 m_hAdjust
->step_increment
= 1.0;
3932 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3933 m_hAdjust
->page_size
= fthumb
;
3937 float fpos
= (float)pos
;
3938 float frange
= (float)range
;
3939 float fthumb
= (float)thumbVisible
;
3940 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3941 if (fpos
< 0.0) fpos
= 0.0;
3943 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3944 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3946 SetScrollPos( orient
, pos
, refresh
);
3950 m_oldVerticalPos
= fpos
;
3952 m_vAdjust
->lower
= 0.0;
3953 m_vAdjust
->upper
= frange
;
3954 m_vAdjust
->value
= fpos
;
3955 m_vAdjust
->step_increment
= 1.0;
3956 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3957 m_vAdjust
->page_size
= fthumb
;
3960 if (orient
== wxHORIZONTAL
)
3961 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3963 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3966 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3968 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3970 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3972 if (orient
== wxHORIZONTAL
)
3974 float fpos
= (float)pos
;
3975 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3976 if (fpos
< 0.0) fpos
= 0.0;
3977 m_oldHorizontalPos
= fpos
;
3979 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3980 m_hAdjust
->value
= fpos
;
3984 float fpos
= (float)pos
;
3985 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3986 if (fpos
< 0.0) fpos
= 0.0;
3987 m_oldVerticalPos
= fpos
;
3989 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3990 m_vAdjust
->value
= fpos
;
3993 if (m_wxwindow
->window
)
3995 if (orient
== wxHORIZONTAL
)
3997 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3998 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
4000 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
4002 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
4003 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
4007 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
4008 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4010 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
4012 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
4013 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4018 int wxWindowGTK::GetScrollThumb( int orient
) const
4020 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4022 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4024 if (orient
== wxHORIZONTAL
)
4025 return (int)(m_hAdjust
->page_size
+0.5);
4027 return (int)(m_vAdjust
->page_size
+0.5);
4030 int wxWindowGTK::GetScrollPos( int orient
) const
4032 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4034 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4036 if (orient
== wxHORIZONTAL
)
4037 return (int)(m_hAdjust
->value
+0.5);
4039 return (int)(m_vAdjust
->value
+0.5);
4042 int wxWindowGTK::GetScrollRange( int orient
) const
4044 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4046 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4048 if (orient
== wxHORIZONTAL
)
4049 return (int)(m_hAdjust
->upper
+0.5);
4051 return (int)(m_vAdjust
->upper
+0.5);
4054 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
4056 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4058 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4060 // No scrolling requested.
4061 if ((dx
== 0) && (dy
== 0)) return;
4063 if (!m_updateRegion
.IsEmpty())
4065 m_updateRegion
.Offset( dx
, dy
);
4069 GetClientSize( &cw
, &ch
);
4070 m_updateRegion
.Intersect( 0, 0, cw
, ch
);
4073 if (!m_clearRegion
.IsEmpty())
4075 m_clearRegion
.Offset( dx
, dy
);
4079 GetClientSize( &cw
, &ch
);
4080 m_clearRegion
.Intersect( 0, 0, cw
, ch
);
4085 m_clipPaintRegion
= TRUE
;
4087 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
4089 m_clipPaintRegion
= FALSE
;
4093 if (m_children
.GetCount() > 0)
4095 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
4099 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
4101 pizza
->xoffset
-= dx
;
4102 pizza
->yoffset
-= dy
;
4104 GdkGC
*m_scrollGC
= gdk_gc_new( pizza
->bin_window
);
4105 gdk_gc_set_exposures( m_scrollGC
, TRUE
);
4109 GetClientSize( &cw
, &ch
);
4110 int w
= cw
- abs(dx
);
4111 int h
= ch
- abs(dy
);
4113 if ((h
< 0) || (w
< 0))
4121 if (dx
< 0) s_x
= -dx
;
4122 if (dy
< 0) s_y
= -dy
;
4125 if (dx
> 0) d_x
= dx
;
4126 if (dy
> 0) d_y
= dy
;
4128 gdk_window_copy_area( pizza
->bin_window
, m_scrollGC
, d_x
, d_y
,
4129 pizza
->bin_window
, s_x
, s_y
, w
, h
);
4132 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
4133 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
4134 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
4135 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
4137 Refresh( TRUE
, &rect
);
4140 gdk_gc_unref( m_scrollGC
);
4145 // Find the wxWindow at the current mouse position, also returning the mouse
4147 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
4149 pt
= wxGetMousePosition();
4150 wxWindow
* found
= wxFindWindowAtPoint(pt
);
4154 // Get the current mouse position.
4155 wxPoint
wxGetMousePosition()
4157 /* This crashes when used within wxHelpContext,
4158 so we have to use the X-specific implementation below.
4160 GdkModifierType *mask;
4161 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
4163 return wxPoint(x, y);
4167 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
4169 return wxPoint(-999, -999);
4171 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
4172 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
4173 Window rootReturn
, childReturn
;
4174 int rootX
, rootY
, winX
, winY
;
4175 unsigned int maskReturn
;
4177 XQueryPointer (display
,
4181 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
4182 return wxPoint(rootX
, rootY
);