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 if (gdk_event
->count
== 0)
805 win
->m_clipPaintRegion
= TRUE
;
808 dc
.SetClippingRegion(win
->GetUpdateRegion());
809 wxEraseEvent
eevent( win
->GetId(), &dc
);
810 eevent
.SetEventObject( win
);
812 (void)win
->GetEventHandler()->ProcessEvent(eevent
);
814 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
816 wxClientDC
dc( win
);
817 dc
.SetBrush( wxBrush( win
->GetBackgroundColour(), wxSOLID
) );
818 dc
.SetPen( *wxTRANSPARENT_PEN
);
820 wxRegionIterator
upd( win
->GetUpdateRegion() );
823 dc
.DrawRectangle( upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
829 wxNcPaintEvent
eventNc( win
->GetId() );
830 eventNc
.SetEventObject( win
);
831 win
->GetEventHandler()->ProcessEvent( eventNc
);
833 wxPaintEvent
event( win
->GetId() );
834 event
.SetEventObject( win
);
835 win
->GetEventHandler()->ProcessEvent( event
);
837 win
->GetUpdateRegion().Clear();
839 win
->m_clipPaintRegion
= FALSE
;
842 /* The following code will result in all window-less widgets
843 being redrawn if the wxWindows class is given a chance to
844 paint *anything* because it will then be allowed to paint
845 over the window-less widgets */
846 GList
*children
= pizza
->children
;
849 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
850 children
= children
->next
;
852 GdkEventExpose child_event
= *gdk_event
;
854 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
855 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
856 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
858 child_event
.area
.x
= child
->widget
->allocation
.x
;
859 child_event
.area
.y
= child
->widget
->allocation
.y
;
860 child_event
.area
.width
= child
->widget
->allocation
.width
;
861 child_event
.area
.height
= child
->widget
->allocation
.height
;
862 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
869 //-----------------------------------------------------------------------------
870 // "event" of m_wxwindow
871 //-----------------------------------------------------------------------------
873 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
874 expose events. We need them, of course, so we override the main event
875 procedure in GtkWidget by giving our own handler for all system events.
876 There, we look for expose events ourselves whereas all other events are
879 gint
gtk_window_event_event_callback( GtkWidget
*widget
,
880 GdkEventExpose
*event
,
883 if (event
->type
== GDK_EXPOSE
)
885 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
892 //-----------------------------------------------------------------------------
893 // "draw" of m_wxwindow
894 //-----------------------------------------------------------------------------
896 /* This callback is a complete replacement of the gtk_pizza_draw() function,
899 static void gtk_window_draw_callback( GtkWidget
*widget
,
906 wxapp_install_idle_handler();
908 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
909 (win
->GetChildren().GetCount() == 0))
915 if (win->GetName() == wxT("panel"))
917 wxPrintf( wxT("OnDraw from ") );
918 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
919 wxPrintf( win->GetClassInfo()->GetClassName() );
920 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
927 GtkPizza
*pizza
= GTK_PIZZA (widget
);
929 if (win
->GetThemeEnabled())
931 wxWindow
*parent
= win
->GetParent();
932 while (parent
&& !parent
->IsTopLevel())
933 parent
= parent
->GetParent();
937 gtk_paint_flat_box (parent
->m_widget
->style
,
948 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
949 (pizza
->clear_on_draw
))
951 gdk_window_clear_area( pizza
->bin_window
,
952 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
955 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
957 win
->m_clipPaintRegion
= TRUE
;
960 dc
.SetClippingRegion(win
->GetUpdateRegion());
961 wxEraseEvent
eevent( win
->GetId(), &dc
);
962 eevent
.SetEventObject( win
);
965 (void)win
->GetEventHandler()->ProcessEvent(eevent
);
967 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
969 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
971 wxClientDC
dc( win
);
972 dc
.SetBrush( wxBrush( win
->GetBackgroundColour(), wxSOLID
) );
973 dc
.SetPen( *wxTRANSPARENT_PEN
);
975 wxRegionIterator
upd( win
->GetUpdateRegion() );
978 dc
.DrawRectangle( upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
985 wxNcPaintEvent
eventNc( win
->GetId() );
986 eventNc
.SetEventObject( win
);
987 win
->GetEventHandler()->ProcessEvent( eventNc
);
989 wxPaintEvent
event( win
->GetId() );
990 event
.SetEventObject( win
);
991 win
->GetEventHandler()->ProcessEvent( event
);
993 win
->GetUpdateRegion().Clear();
995 win
->m_clipPaintRegion
= FALSE
;
998 GList
*children
= pizza
->children
;
1001 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
1002 children
= children
->next
;
1004 GdkRectangle child_area
;
1005 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
1007 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
1012 //-----------------------------------------------------------------------------
1013 // "key_press_event" from any window
1014 //-----------------------------------------------------------------------------
1016 // turn on to see the key event codes on the console
1017 #undef DEBUG_KEY_EVENTS
1019 static gint
gtk_window_key_press_callback( GtkWidget
*widget
,
1020 GdkEventKey
*gdk_event
,
1026 wxapp_install_idle_handler();
1028 if (!win
->m_hasVMT
) return FALSE
;
1029 if (g_blockEventsOnDrag
) return FALSE
;
1034 GdkModifierType state
;
1035 if (gdk_event
->window
)
1036 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1040 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
1042 #ifdef DEBUG_KEY_EVENTS
1043 wxPrintf(_T("Key press event: %d => %ld\n"), gdk_event
->keyval
, key_code
);
1044 #endif // DEBUG_KEY_EVENTS
1046 /* sending unknown key events doesn't really make sense */
1050 wxKeyEvent
event( wxEVT_KEY_DOWN
);
1051 event
.SetTimestamp( gdk_event
->time
);
1052 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1053 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1054 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1055 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1056 event
.m_keyCode
= key_code
;
1057 event
.m_scanCode
= gdk_event
->keyval
;
1060 event
.SetEventObject( win
);
1061 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1066 wxWindowGTK
*ancestor
= win
;
1069 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
1072 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
1073 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
1076 if (ancestor
->IsTopLevel())
1078 ancestor
= ancestor
->GetParent();
1081 #endif // wxUSE_ACCEL
1083 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
1084 will only be sent if it is not in an accelerator table. */
1087 key_code
= map_to_wx_keysym( gdk_event
);
1091 #ifdef DEBUG_KEY_EVENTS
1092 wxPrintf(_T("Char event: %ld\n"), key_code
);
1093 #endif // DEBUG_KEY_EVENTS
1095 // reuse the ame event object, just change its type and use the
1096 // translated keycode instead of the raw one
1097 event
.SetEventType(wxEVT_CHAR
);
1098 event
.m_keyCode
= key_code
;
1100 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1104 /* win is a control: tab can be propagated up */
1106 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
1107 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
1108 // have this style, yet choose not to process this particular TAB in which
1109 // case TAB must still work as a navigational character
1111 !win
->HasFlag(wxTE_PROCESS_TAB
) &&
1113 win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
1115 wxNavigationKeyEvent new_event
;
1116 new_event
.SetEventObject( win
->GetParent() );
1117 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
1118 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
1119 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1120 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
1121 new_event
.SetCurrentFocus( win
);
1122 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
1125 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
1127 (gdk_event
->keyval
== GDK_Escape
) )
1129 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
1130 new_event
.SetEventObject( win
);
1131 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
1135 #if 0 // (GTK_MINOR_VERSION > 0)
1136 /* Pressing F10 will activate the menu bar of the top frame. */
1138 (gdk_event
->keyval
== GDK_F10
) )
1140 wxWindowGTK
*ancestor
= win
;
1143 if (wxIsKindOf(ancestor
,wxFrame
))
1145 wxFrame
*frame
= (wxFrame
*) ancestor
;
1146 wxMenuBar
*menubar
= frame
->GetMenuBar();
1149 wxNode
*node
= menubar
->GetMenus().First();
1152 wxMenu
*firstMenu
= (wxMenu
*) node
->Data();
1153 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu
->m_owner
) );
1159 ancestor
= ancestor
->GetParent();
1166 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1173 //-----------------------------------------------------------------------------
1174 // "key_release_event" from any window
1175 //-----------------------------------------------------------------------------
1177 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindowGTK
*win
)
1182 wxapp_install_idle_handler();
1184 if (!win
->m_hasVMT
) return FALSE
;
1185 if (g_blockEventsOnDrag
) return FALSE
;
1187 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
1189 #ifdef DEBUG_KEY_EVENTS
1190 wxPrintf(_T("Key release event: %d => %ld\n"), gdk_event
->keyval
, key_code
);
1191 #endif // DEBUG_KEY_EVENTS
1193 /* sending unknown key events doesn't really make sense */
1194 if (key_code
== 0) return FALSE
;
1198 GdkModifierType state
;
1199 if (gdk_event
->window
)
1200 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1202 wxKeyEvent
event( wxEVT_KEY_UP
);
1203 event
.SetTimestamp( gdk_event
->time
);
1204 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1205 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1206 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1207 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1208 event
.m_keyCode
= key_code
;
1209 event
.m_scanCode
= gdk_event
->keyval
;
1212 event
.SetEventObject( win
);
1214 if (win
->GetEventHandler()->ProcessEvent( event
))
1216 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1223 // ============================================================================
1225 // ============================================================================
1227 // init wxMouseEvent with the info from gdk_event
1228 #define InitMouseEvent(win, event, gdk_event) \
1230 event.SetTimestamp( gdk_event->time ); \
1231 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
1232 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
1233 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
1234 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
1235 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
1236 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
1237 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
1239 wxPoint pt = win->GetClientAreaOrigin(); \
1240 event.m_x = (wxCoord)gdk_event->x - pt.x; \
1241 event.m_y = (wxCoord)gdk_event->y - pt.y; \
1244 // ----------------------------------------------------------------------------
1245 // mouse event processing helper
1246 // ----------------------------------------------------------------------------
1248 static void AdjustEventButtonState(wxMouseEvent
& event
)
1250 // GDK reports the old state of the button for a button press event, but
1251 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1252 // for a LEFT_DOWN event, not FALSE, so we will invert
1253 // left/right/middleDown for the corresponding click events
1255 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1256 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1257 (event
.GetEventType() == wxEVT_LEFT_UP
))
1259 event
.m_leftDown
= !event
.m_leftDown
;
1263 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1264 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1265 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1267 event
.m_middleDown
= !event
.m_middleDown
;
1271 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1272 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1273 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1275 event
.m_rightDown
= !event
.m_rightDown
;
1280 //-----------------------------------------------------------------------------
1281 // "button_press_event"
1282 //-----------------------------------------------------------------------------
1284 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1289 wxapp_install_idle_handler();
1292 wxPrintf( wxT("1) OnButtonPress from ") );
1293 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1294 wxPrintf( win->GetClassInfo()->GetClassName() );
1295 wxPrintf( wxT(".\n") );
1297 if (!win
->m_hasVMT
) return FALSE
;
1298 if (g_blockEventsOnDrag
) return TRUE
;
1299 if (g_blockEventsOnScroll
) return TRUE
;
1301 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1303 if (win
->m_wxwindow
)
1305 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1307 gtk_widget_grab_focus (win
->m_wxwindow
);
1310 wxPrintf( wxT("GrabFocus from ") );
1311 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1312 wxPrintf( win->GetClassInfo()->GetClassName() );
1313 wxPrintf( wxT(".\n") );
1319 wxEventType event_type
= wxEVT_NULL
;
1321 if (gdk_event
->button
== 1)
1323 switch (gdk_event
->type
)
1325 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1326 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1330 else if (gdk_event
->button
== 2)
1332 switch (gdk_event
->type
)
1334 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1335 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1339 else if (gdk_event
->button
== 3)
1341 switch (gdk_event
->type
)
1343 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1344 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1349 if ( event_type
== wxEVT_NULL
)
1351 // unknown mouse button or click type
1355 wxMouseEvent
event( event_type
);
1356 InitMouseEvent( win
, event
, gdk_event
);
1358 AdjustEventButtonState(event
);
1360 // wxListBox actually get mouse events from the item
1362 if (win
->m_isListBox
)
1364 event
.m_x
+= widget
->allocation
.x
;
1365 event
.m_y
+= widget
->allocation
.y
;
1368 // Some control don't have their own X window and thus cannot get
1371 if (!g_captureWindow
)
1373 wxCoord x
= event
.m_x
;
1374 wxCoord y
= event
.m_y
;
1375 if (win
->m_wxwindow
)
1377 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1378 x
+= pizza
->xoffset
;
1379 y
+= pizza
->yoffset
;
1382 wxNode
*node
= win
->GetChildren().First();
1385 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1387 node
= node
->Next();
1388 if (!child
->IsShown())
1391 if (child
->m_isStaticBox
)
1393 // wxStaticBox is transparent in the box itself
1394 int xx1
= child
->m_x
;
1395 int yy1
= child
->m_y
;
1396 int xx2
= child
->m_x
+ child
->m_width
;
1397 int yy2
= child
->m_x
+ child
->m_height
;
1400 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1402 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1404 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1406 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1409 event
.m_x
-= child
->m_x
;
1410 event
.m_y
-= child
->m_y
;
1417 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1418 (child
->m_x
<= x
) &&
1419 (child
->m_y
<= y
) &&
1420 (child
->m_x
+child
->m_width
>= x
) &&
1421 (child
->m_y
+child
->m_height
>= y
))
1424 event
.m_x
-= child
->m_x
;
1425 event
.m_y
-= child
->m_y
;
1432 event
.SetEventObject( win
);
1434 gs_timeLastClick
= gdk_event
->time
;
1437 wxPrintf( wxT("2) OnButtonPress from ") );
1438 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1439 wxPrintf( win->GetClassInfo()->GetClassName() );
1440 wxPrintf( wxT(".\n") );
1443 if (win
->GetEventHandler()->ProcessEvent( event
))
1445 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1452 //-----------------------------------------------------------------------------
1453 // "button_release_event"
1454 //-----------------------------------------------------------------------------
1456 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1461 wxapp_install_idle_handler();
1463 if (!win
->m_hasVMT
) return FALSE
;
1464 if (g_blockEventsOnDrag
) return FALSE
;
1465 if (g_blockEventsOnScroll
) return FALSE
;
1467 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1470 printf( "OnButtonRelease from " );
1471 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1472 printf( win->GetClassInfo()->GetClassName() );
1476 wxEventType event_type
= wxEVT_NULL
;
1478 switch (gdk_event
->button
)
1480 case 1: event_type
= wxEVT_LEFT_UP
; break;
1481 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1482 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1483 default: return FALSE
;
1486 wxMouseEvent
event( event_type
);
1487 InitMouseEvent( win
, event
, gdk_event
);
1489 AdjustEventButtonState(event
);
1491 // wxListBox actually get mouse events from the item
1493 if (win
->m_isListBox
)
1495 event
.m_x
+= widget
->allocation
.x
;
1496 event
.m_y
+= widget
->allocation
.y
;
1499 // Some control don't have their own X window and thus cannot get
1502 if (!g_captureWindow
)
1504 wxCoord x
= event
.m_x
;
1505 wxCoord y
= event
.m_y
;
1506 if (win
->m_wxwindow
)
1508 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1509 x
+= pizza
->xoffset
;
1510 y
+= pizza
->yoffset
;
1513 wxNode
*node
= win
->GetChildren().First();
1516 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1518 node
= node
->Next();
1519 if (!child
->IsShown())
1522 if (child
->m_isStaticBox
)
1524 // wxStaticBox is transparent in the box itself
1525 int xx1
= child
->m_x
;
1526 int yy1
= child
->m_y
;
1527 int xx2
= child
->m_x
+ child
->m_width
;
1528 int yy2
= child
->m_x
+ child
->m_height
;
1531 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1533 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1535 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1537 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1540 event
.m_x
-= child
->m_x
;
1541 event
.m_y
-= child
->m_y
;
1548 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1549 (child
->m_x
<= x
) &&
1550 (child
->m_y
<= y
) &&
1551 (child
->m_x
+child
->m_width
>= x
) &&
1552 (child
->m_y
+child
->m_height
>= y
))
1555 event
.m_x
-= child
->m_x
;
1556 event
.m_y
-= child
->m_y
;
1563 event
.SetEventObject( win
);
1565 if (win
->GetEventHandler()->ProcessEvent( event
))
1567 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1574 //-----------------------------------------------------------------------------
1575 // "motion_notify_event"
1576 //-----------------------------------------------------------------------------
1578 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
,
1579 GdkEventMotion
*gdk_event
,
1585 wxapp_install_idle_handler();
1587 if (!win
->m_hasVMT
) return FALSE
;
1588 if (g_blockEventsOnDrag
) return FALSE
;
1589 if (g_blockEventsOnScroll
) return FALSE
;
1591 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1593 if (gdk_event
->is_hint
)
1597 GdkModifierType state
;
1598 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1604 printf( "OnMotion from " );
1605 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1606 printf( win->GetClassInfo()->GetClassName() );
1610 wxMouseEvent
event( wxEVT_MOTION
);
1611 InitMouseEvent(win
, event
, gdk_event
);
1613 if ( g_captureWindow
)
1615 // synthetize a mouse enter or leave event if needed
1616 GdkWindow
*winUnderMouse
= gdk_window_at_pointer(NULL
, NULL
);
1617 bool hasMouse
= winUnderMouse
== gdk_event
->window
;
1618 if ( hasMouse
!= g_captureWindowHasMouse
)
1620 // the mouse changed window
1621 g_captureWindowHasMouse
= hasMouse
;
1623 wxMouseEvent
event(g_captureWindowHasMouse
? wxEVT_ENTER_WINDOW
1624 : wxEVT_LEAVE_WINDOW
);
1625 InitMouseEvent(win
, event
, gdk_event
);
1626 event
.SetEventObject(win
);
1627 win
->GetEventHandler()->ProcessEvent(event
);
1632 // Some control don't have their own X window and thus cannot get
1635 wxCoord x
= event
.m_x
;
1636 wxCoord y
= event
.m_y
;
1637 if (win
->m_wxwindow
)
1639 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1640 x
+= pizza
->xoffset
;
1641 y
+= pizza
->yoffset
;
1644 wxNode
*node
= win
->GetChildren().First();
1647 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1649 node
= node
->Next();
1650 if (!child
->IsShown())
1653 if (child
->m_isStaticBox
)
1655 // wxStaticBox is transparent in the box itself
1656 int xx1
= child
->m_x
;
1657 int yy1
= child
->m_y
;
1658 int xx2
= child
->m_x
+ child
->m_width
;
1659 int yy2
= child
->m_x
+ child
->m_height
;
1662 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1664 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1666 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1668 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1671 event
.m_x
-= child
->m_x
;
1672 event
.m_y
-= child
->m_y
;
1679 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1680 (child
->m_x
<= x
) &&
1681 (child
->m_y
<= y
) &&
1682 (child
->m_x
+child
->m_width
>= x
) &&
1683 (child
->m_y
+child
->m_height
>= y
))
1686 event
.m_x
-= child
->m_x
;
1687 event
.m_y
-= child
->m_y
;
1694 event
.SetEventObject( win
);
1696 if (win
->GetEventHandler()->ProcessEvent( event
))
1698 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1705 //-----------------------------------------------------------------------------
1707 //-----------------------------------------------------------------------------
1709 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
,
1710 GdkEvent
*WXUNUSED(event
),
1716 wxapp_install_idle_handler();
1718 if (!win
->m_hasVMT
) return FALSE
;
1719 if (g_blockEventsOnDrag
) return FALSE
;
1721 switch ( g_sendActivateEvent
)
1724 // we've got focus from outside, synthetize wxActivateEvent
1725 g_sendActivateEvent
= 1;
1729 // another our window just lost focus, it was already ours before
1730 // - don't send any wxActivateEvent
1731 g_sendActivateEvent
= -1;
1736 g_focusWindow
= win
;
1739 wxPrintf( "OnSetFocus from " );
1740 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
1741 wxPrintf( win
->GetClassInfo()->GetClassName() );
1745 // notify the parent keeping track of focus for the kbd navigation
1746 // purposes that we got it
1747 wxChildFocusEvent
eventFocus(win
);
1748 (void)win
->GetEventHandler()->ProcessEvent(eventFocus
);
1752 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1756 // caret needs to be informed about focus change
1757 wxCaret
*caret
= win
->GetCaret();
1760 caret
->OnSetFocus();
1762 #endif // wxUSE_CARET
1764 wxWindowGTK
*active
= wxGetTopLevelParent(win
);
1765 if ( active
!= g_activeFrame
)
1767 if ( g_activeFrame
)
1769 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame
);
1770 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
1771 event
.SetEventObject(g_activeFrame
);
1772 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1775 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active
);
1776 g_activeFrame
= active
;
1777 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId());
1778 event
.SetEventObject(g_activeFrame
);
1779 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1781 g_activeFrameLostFocus
= FALSE
;
1784 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1785 event
.SetEventObject( win
);
1787 if (win
->GetEventHandler()->ProcessEvent( event
))
1789 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1797 //-----------------------------------------------------------------------------
1798 // "focus_out_event"
1799 //-----------------------------------------------------------------------------
1801 static GtkWidget
*gs_widgetLastFocus
= NULL
;
1803 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindowGTK
*win
)
1808 wxapp_install_idle_handler();
1810 if (!win
->m_hasVMT
) return FALSE
;
1811 if (g_blockEventsOnDrag
) return FALSE
;
1813 // VZ: this is really weird but GTK+ seems to call us from inside
1814 // gtk_widget_grab_focus(), i.e. it first sends "focus_out" signal to
1815 // this widget and then "focus_in". This is totally unexpected and
1816 // completely breaks wxUniv code so ignore this dummy event (we can't
1817 // be losing focus if we're about to acquire it!)
1818 if ( widget
== gs_widgetLastFocus
)
1820 gs_widgetLastFocus
= NULL
;
1825 if ( !g_activeFrameLostFocus
&& g_activeFrame
)
1827 // VZ: commenting this out because it does happen (although not easy
1828 // to reproduce, I only see it when using wxMiniFrame and not
1829 // always) and makes using Mahogany quite annoying
1831 wxASSERT_MSG( wxGetTopLevelParent(win
) == g_activeFrame
,
1832 wxT("unfocusing window that hasn't gained focus properly") )
1835 g_activeFrameLostFocus
= TRUE
;
1838 // if the focus goes out of our app alltogether, OnIdle() will send
1839 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1840 // g_sendActivateEvent to -1
1841 g_sendActivateEvent
= 0;
1843 wxWindowGTK
*winFocus
= wxFindFocusedChild(win
);
1847 g_focusWindow
= (wxWindowGTK
*)NULL
;
1850 wxPrintf( "OnKillFocus from " );
1851 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
1852 wxPrintf( win
->GetClassInfo()->GetClassName() );
1862 // caret needs to be informed about focus change
1863 wxCaret
*caret
= win
->GetCaret();
1866 caret
->OnKillFocus();
1868 #endif // wxUSE_CARET
1870 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1871 event
.SetEventObject( win
);
1873 if (win
->GetEventHandler()->ProcessEvent( event
))
1875 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1882 //-----------------------------------------------------------------------------
1883 // "enter_notify_event"
1884 //-----------------------------------------------------------------------------
1886 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1891 wxapp_install_idle_handler();
1893 if (!win
->m_hasVMT
) return FALSE
;
1894 if (g_blockEventsOnDrag
) return FALSE
;
1896 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1898 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1899 event
.SetTimestamp( gdk_event
->time
);
1900 event
.SetEventObject( win
);
1904 GdkModifierType state
= (GdkModifierType
)0;
1906 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1908 InitMouseEvent(win
, event
, gdk_event
);
1909 wxPoint pt
= win
->GetClientAreaOrigin();
1910 event
.m_x
= x
+ pt
.x
;
1911 event
.m_y
= y
+ pt
.y
;
1913 if (win
->GetEventHandler()->ProcessEvent( event
))
1915 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1922 //-----------------------------------------------------------------------------
1923 // "leave_notify_event"
1924 //-----------------------------------------------------------------------------
1926 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1931 wxapp_install_idle_handler();
1933 if (!win
->m_hasVMT
) return FALSE
;
1934 if (g_blockEventsOnDrag
) return FALSE
;
1936 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1938 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1939 event
.SetTimestamp( gdk_event
->time
);
1940 event
.SetEventObject( win
);
1944 GdkModifierType state
= (GdkModifierType
)0;
1946 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1948 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1949 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1950 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1951 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1952 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1953 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1954 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1956 wxPoint pt
= win
->GetClientAreaOrigin();
1957 event
.m_x
= x
+ pt
.x
;
1958 event
.m_y
= y
+ pt
.y
;
1960 if (win
->GetEventHandler()->ProcessEvent( event
))
1962 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1969 //-----------------------------------------------------------------------------
1970 // "value_changed" from m_vAdjust
1971 //-----------------------------------------------------------------------------
1973 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1978 wxapp_install_idle_handler();
1980 if (g_blockEventsOnDrag
) return;
1982 if (!win
->m_hasVMT
) return;
1984 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1985 if (fabs(diff
) < 0.2) return;
1987 win
->m_oldVerticalPos
= adjust
->value
;
1989 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1990 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1992 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1993 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1994 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1995 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1996 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1998 int value
= (int)(adjust
->value
+0.5);
2000 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
2001 event
.SetEventObject( win
);
2002 win
->GetEventHandler()->ProcessEvent( event
);
2005 //-----------------------------------------------------------------------------
2006 // "value_changed" from m_hAdjust
2007 //-----------------------------------------------------------------------------
2009 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
2014 wxapp_install_idle_handler();
2016 if (g_blockEventsOnDrag
) return;
2017 if (!win
->m_hasVMT
) return;
2019 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
2020 if (fabs(diff
) < 0.2) return;
2022 win
->m_oldHorizontalPos
= adjust
->value
;
2024 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
2025 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
2027 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
2028 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
2029 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
2030 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
2031 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
2033 int value
= (int)(adjust
->value
+0.5);
2035 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
2036 event
.SetEventObject( win
);
2037 win
->GetEventHandler()->ProcessEvent( event
);
2040 //-----------------------------------------------------------------------------
2041 // "button_press_event" from scrollbar
2042 //-----------------------------------------------------------------------------
2044 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
2045 GdkEventButton
*gdk_event
,
2051 wxapp_install_idle_handler();
2054 g_blockEventsOnScroll
= TRUE
;
2055 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
2060 //-----------------------------------------------------------------------------
2061 // "button_release_event" from scrollbar
2062 //-----------------------------------------------------------------------------
2064 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
2065 GdkEventButton
*WXUNUSED(gdk_event
),
2070 // don't test here as we can release the mouse while being over
2071 // a different window than the slider
2073 // if (gdk_event->window != widget->slider) return FALSE;
2075 g_blockEventsOnScroll
= FALSE
;
2077 if (win
->m_isScrolling
)
2079 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
2083 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
2084 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
2086 value
= (int)(win
->m_hAdjust
->value
+0.5);
2089 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
2091 value
= (int)(win
->m_vAdjust
->value
+0.5);
2095 wxScrollWinEvent
event( command
, value
, dir
);
2096 event
.SetEventObject( win
);
2097 win
->GetEventHandler()->ProcessEvent( event
);
2100 win
->m_isScrolling
= FALSE
;
2105 // ----------------------------------------------------------------------------
2106 // this wxWindowBase function is implemented here (in platform-specific file)
2107 // because it is static and so couldn't be made virtual
2108 // ----------------------------------------------------------------------------
2110 wxWindow
*wxWindowBase::FindFocus()
2112 // the cast is necessary when we compile in wxUniversal mode
2113 return (wxWindow
*)g_focusWindow
;
2116 //-----------------------------------------------------------------------------
2117 // "realize" from m_widget
2118 //-----------------------------------------------------------------------------
2120 /* We cannot set colours and fonts before the widget has
2121 been realized, so we do this directly after realization. */
2124 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
2129 wxapp_install_idle_handler();
2131 if (win
->m_delayedBackgroundColour
)
2132 win
->SetBackgroundColour( win
->GetBackgroundColour() );
2134 if (win
->m_delayedForegroundColour
)
2135 win
->SetForegroundColour( win
->GetForegroundColour() );
2137 wxWindowCreateEvent
event( win
);
2138 event
.SetEventObject( win
);
2139 win
->GetEventHandler()->ProcessEvent( event
);
2144 //-----------------------------------------------------------------------------
2146 //-----------------------------------------------------------------------------
2149 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
2150 GtkAllocation
*WXUNUSED(alloc
),
2154 wxapp_install_idle_handler();
2156 if (!win
->m_hasScrolling
) return;
2158 int client_width
= 0;
2159 int client_height
= 0;
2160 win
->GetClientSize( &client_width
, &client_height
);
2161 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
2164 win
->m_oldClientWidth
= client_width
;
2165 win
->m_oldClientHeight
= client_height
;
2167 if (!win
->m_nativeSizeEvent
)
2169 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
2170 event
.SetEventObject( win
);
2171 win
->GetEventHandler()->ProcessEvent( event
);
2177 #define WXUNUSED_UNLESS_XIM(param) param
2179 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2182 /* Resize XIM window */
2185 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2186 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
2187 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2190 wxapp_install_idle_handler();
2196 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
2200 gdk_window_get_size (widget
->window
, &width
, &height
);
2201 win
->m_icattr
->preedit_area
.width
= width
;
2202 win
->m_icattr
->preedit_area
.height
= height
;
2203 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2208 //-----------------------------------------------------------------------------
2209 // "realize" from m_wxwindow
2210 //-----------------------------------------------------------------------------
2212 /* Initialize XIM support */
2215 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2216 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2219 wxapp_install_idle_handler();
2222 if (win
->m_ic
) return FALSE
;
2223 if (!widget
) return FALSE
;
2224 if (!gdk_im_ready()) return FALSE
;
2226 win
->m_icattr
= gdk_ic_attr_new();
2227 if (!win
->m_icattr
) return FALSE
;
2231 GdkColormap
*colormap
;
2232 GdkICAttr
*attr
= win
->m_icattr
;
2233 unsigned attrmask
= GDK_IC_ALL_REQ
;
2235 GdkIMStyle supported_style
= (GdkIMStyle
)
2236 (GDK_IM_PREEDIT_NONE
|
2237 GDK_IM_PREEDIT_NOTHING
|
2238 GDK_IM_PREEDIT_POSITION
|
2239 GDK_IM_STATUS_NONE
|
2240 GDK_IM_STATUS_NOTHING
);
2242 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2243 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2245 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2246 attr
->client_window
= widget
->window
;
2248 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2249 gtk_widget_get_default_colormap ())
2251 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2252 attr
->preedit_colormap
= colormap
;
2255 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2256 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2257 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2258 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2260 switch (style
& GDK_IM_PREEDIT_MASK
)
2262 case GDK_IM_PREEDIT_POSITION
:
2263 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2265 g_warning ("over-the-spot style requires fontset");
2269 gdk_window_get_size (widget
->window
, &width
, &height
);
2271 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2272 attr
->spot_location
.x
= 0;
2273 attr
->spot_location
.y
= height
;
2274 attr
->preedit_area
.x
= 0;
2275 attr
->preedit_area
.y
= 0;
2276 attr
->preedit_area
.width
= width
;
2277 attr
->preedit_area
.height
= height
;
2278 attr
->preedit_fontset
= widget
->style
->font
;
2283 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2285 if (win
->m_ic
== NULL
)
2286 g_warning ("Can't create input context.");
2289 mask
= gdk_window_get_events (widget
->window
);
2290 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2291 gdk_window_set_events (widget
->window
, mask
);
2293 if (GTK_WIDGET_HAS_FOCUS(widget
))
2294 gdk_im_begin (win
->m_ic
, widget
->window
);
2301 //-----------------------------------------------------------------------------
2302 // InsertChild for wxWindowGTK.
2303 //-----------------------------------------------------------------------------
2305 /* Callback for wxWindowGTK. This very strange beast has to be used because
2306 * C++ has no virtual methods in a constructor. We have to emulate a
2307 * virtual function here as wxNotebook requires a different way to insert
2308 * a child in it. I had opted for creating a wxNotebookPage window class
2309 * which would have made this superfluous (such in the MDI window system),
2310 * but no-one was listening to me... */
2312 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child
)
2314 /* the window might have been scrolled already, do we
2315 have to adapt the position */
2316 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2317 child
->m_x
+= pizza
->xoffset
;
2318 child
->m_y
+= pizza
->yoffset
;
2320 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2321 GTK_WIDGET(child
->m_widget
),
2328 //-----------------------------------------------------------------------------
2330 //-----------------------------------------------------------------------------
2332 wxWindow
*wxGetActiveWindow()
2334 // the cast is necessary when we compile in wxUniversal mode
2335 return (wxWindow
*)g_focusWindow
;
2338 //-----------------------------------------------------------------------------
2340 //-----------------------------------------------------------------------------
2342 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
2344 #ifdef __WXUNIVERSAL__
2345 IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
)
2347 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2348 #endif // __WXUNIVERSAL__/__WXGTK__
2350 void wxWindowGTK::Init()
2356 m_widget
= (GtkWidget
*) NULL
;
2357 m_wxwindow
= (GtkWidget
*) NULL
;
2358 m_focusWidget
= (GtkWidget
*) NULL
;
2368 m_needParent
= TRUE
;
2369 m_isBeingDeleted
= FALSE
;
2372 m_nativeSizeEvent
= FALSE
;
2374 m_hasScrolling
= FALSE
;
2375 m_isScrolling
= FALSE
;
2377 m_hAdjust
= (GtkAdjustment
*) NULL
;
2378 m_vAdjust
= (GtkAdjustment
*) NULL
;
2379 m_oldHorizontalPos
= 0.0;
2380 m_oldVerticalPos
= 0.0;
2383 m_widgetStyle
= (GtkStyle
*) NULL
;
2385 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2387 m_isStaticBox
= FALSE
;
2388 m_isRadioButton
= FALSE
;
2389 m_isListBox
= FALSE
;
2391 m_acceptsFocus
= FALSE
;
2393 m_clipPaintRegion
= FALSE
;
2395 m_cursor
= *wxSTANDARD_CURSOR
;
2397 m_delayedForegroundColour
= FALSE
;
2398 m_delayedBackgroundColour
= FALSE
;
2401 m_ic
= (GdkIC
*) NULL
;
2402 m_icattr
= (GdkICAttr
*) NULL
;
2406 wxWindowGTK::wxWindowGTK()
2411 wxWindowGTK::wxWindowGTK( wxWindow
*parent
,
2416 const wxString
&name
)
2420 Create( parent
, id
, pos
, size
, style
, name
);
2423 bool wxWindowGTK::Create( wxWindow
*parent
,
2428 const wxString
&name
)
2430 if (!PreCreation( parent
, pos
, size
) ||
2431 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2433 wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
2437 m_insertCallback
= wxInsertChildInWindow
;
2439 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2440 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2442 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2444 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2445 scroll_class
->scrollbar_spacing
= 0;
2447 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2449 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2450 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2452 m_wxwindow
= gtk_pizza_new();
2454 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2456 #ifndef __WXUNIVERSAL__
2457 #if (GTK_MINOR_VERSION > 0)
2458 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2460 if (HasFlag(wxRAISED_BORDER
))
2462 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2464 else if (HasFlag(wxSUNKEN_BORDER
))
2466 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2468 else if (HasFlag(wxSIMPLE_BORDER
))
2470 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2474 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2476 #else // GTK_MINOR_VERSION == 0
2477 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2479 if (HasFlag(wxRAISED_BORDER
))
2481 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2483 else if (HasFlag(wxSUNKEN_BORDER
))
2485 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2489 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2491 #endif // GTK_MINOR_VERSION
2492 #endif // __WXUNIVERSAL__
2494 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2495 m_acceptsFocus
= TRUE
;
2497 #if (GTK_MINOR_VERSION == 0)
2498 // shut the viewport up
2499 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2500 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2501 #endif // GTK_MINOR_VERSION == 0
2503 // I _really_ don't want scrollbars in the beginning
2504 m_vAdjust
->lower
= 0.0;
2505 m_vAdjust
->upper
= 1.0;
2506 m_vAdjust
->value
= 0.0;
2507 m_vAdjust
->step_increment
= 1.0;
2508 m_vAdjust
->page_increment
= 1.0;
2509 m_vAdjust
->page_size
= 5.0;
2510 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2511 m_hAdjust
->lower
= 0.0;
2512 m_hAdjust
->upper
= 1.0;
2513 m_hAdjust
->value
= 0.0;
2514 m_hAdjust
->step_increment
= 1.0;
2515 m_hAdjust
->page_increment
= 1.0;
2516 m_hAdjust
->page_size
= 5.0;
2517 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2519 // these handlers block mouse events to any window during scrolling such as
2520 // motion events and prevent GTK and wxWindows from fighting over where the
2523 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2524 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2526 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2527 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2529 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2530 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2532 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2533 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2535 // these handlers get notified when screen updates are required either when
2536 // scrolling or when the window size (and therefore scrollbar configuration)
2539 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2540 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2541 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2542 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2544 gtk_widget_show( m_wxwindow
);
2547 m_parent
->DoAddChild( this );
2549 m_focusWidget
= m_wxwindow
;
2558 wxWindowGTK::~wxWindowGTK()
2560 if (g_focusWindow
== this)
2561 g_focusWindow
= NULL
;
2563 if (g_activeFrame
== this)
2564 g_activeFrame
= NULL
;
2566 m_isBeingDeleted
= TRUE
;
2575 m_parent
->RemoveChild( this );
2579 gdk_ic_destroy (m_ic
);
2581 gdk_ic_attr_destroy (m_icattr
);
2586 #if DISABLE_STYLE_IF_BROKEN_THEME
2587 // don't delete if it's a pixmap theme style
2588 if (!m_widgetStyle
->engine_data
)
2589 gtk_style_unref( m_widgetStyle
);
2591 m_widgetStyle
= (GtkStyle
*) NULL
;
2596 gtk_widget_destroy( m_wxwindow
);
2597 m_wxwindow
= (GtkWidget
*) NULL
;
2602 gtk_widget_destroy( m_widget
);
2603 m_widget
= (GtkWidget
*) NULL
;
2607 bool wxWindowGTK::PreCreation( wxWindowGTK
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2609 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2611 /* this turns -1 into 20 so that a minimal window is
2612 visible even although -1,-1 has been given as the
2613 size of the window. the same trick is used in other
2614 ports and should make debugging easier */
2615 m_width
= WidthDefault(size
.x
);
2616 m_height
= HeightDefault(size
.y
);
2621 /* some reasonable defaults */
2626 m_x
= (gdk_screen_width () - m_width
) / 2;
2627 if (m_x
< 10) m_x
= 10;
2631 m_y
= (gdk_screen_height () - m_height
) / 2;
2632 if (m_y
< 10) m_y
= 10;
2639 void wxWindowGTK::PostCreation()
2641 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2647 // these get reported to wxWindows -> wxPaintEvent
2649 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2651 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2652 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2654 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2655 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2657 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2659 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2660 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2664 // these are called when the "sunken" or "raised" borders are drawn */
2665 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2666 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2668 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2669 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2674 if (m_focusWidget
== NULL
)
2675 m_focusWidget
= m_widget
;
2678 if (GetClassInfo() && GetClassInfo()->GetClassName())
2679 wxPrintf( GetClassInfo()->GetClassName() );
2683 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event",
2684 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2686 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event",
2687 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2689 // connect to the various key and mouse handlers
2691 GtkWidget
*connect_widget
= GetConnectWidget();
2693 ConnectWidget( connect_widget
);
2695 /* We cannot set colours, fonts and cursors before the widget has
2696 been realized, so we do this directly after realization */
2697 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2698 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2702 // Catch native resize events
2703 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2704 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2706 // Initialize XIM support
2707 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2708 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2710 // And resize XIM window
2711 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2712 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2715 if (!GTK_IS_COMBO(m_widget
))
2717 // This is needed if we want to add our windows into native
2718 // GTK control, such as the toolbar. With this callback, the
2719 // toolbar gets to know the correct size (the one set by the
2720 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2721 // when moving to GTK 2.0.
2722 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2723 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2729 void wxWindowGTK::ConnectWidget( GtkWidget
*widget
)
2731 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2732 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2734 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2735 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2737 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2738 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2740 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2741 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2743 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2744 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2746 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2747 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2749 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2750 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2753 bool wxWindowGTK::Destroy()
2755 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2759 return wxWindowBase::Destroy();
2762 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
)
2764 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2767 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2769 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2770 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") );
2773 printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
2776 if (m_resizing
) return; /* I don't like recursions */
2779 int currentX
, currentY
;
2780 GetPosition(¤tX
, ¤tY
);
2785 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
2787 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2789 /* don't set the size for children of wxNotebook, just take the values. */
2797 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2799 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2801 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2802 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2803 if (width
!= -1) m_width
= width
;
2804 if (height
!= -1) m_height
= height
;
2808 m_x
= x
+ pizza
->xoffset
;
2809 m_y
= y
+ pizza
->yoffset
;
2814 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2816 if (width
== -1) m_width
= 80;
2819 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2821 if (height
== -1) m_height
= 26;
2824 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2825 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2826 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2827 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2830 int bottom_border
= 0;
2832 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2834 /* the default button has a border around it */
2839 DoMoveWindow( m_x
-border
,
2842 m_height
+border
+bottom_border
);
2847 /* Sometimes the client area changes size without the
2848 whole windows's size changing, but if the whole
2849 windows's size doesn't change, no wxSizeEvent will
2850 normally be sent. Here we add an extra test if
2851 the client test has been changed and this will
2853 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2857 wxPrintf( "OnSize sent from " );
2858 if (GetClassInfo() && GetClassInfo()->GetClassName())
2859 wxPrintf( GetClassInfo()->GetClassName() );
2860 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2863 if (!m_nativeSizeEvent
)
2865 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2866 event
.SetEventObject( this );
2867 GetEventHandler()->ProcessEvent( event
);
2873 void wxWindowGTK::OnInternalIdle()
2875 if ( g_sendActivateEvent
!= -1 )
2877 bool activate
= g_sendActivateEvent
!= 0;
2880 g_sendActivateEvent
= -1;
2882 wxTheApp
->SetActive(activate
, (wxWindow
*)g_focusWindowLast
);
2885 if ( g_activeFrameLostFocus
)
2887 if ( g_activeFrame
)
2889 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame
);
2890 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
2891 event
.SetEventObject(g_activeFrame
);
2892 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
2893 g_activeFrame
= NULL
;
2895 g_activeFrameLostFocus
= FALSE
;
2898 wxCursor cursor
= m_cursor
;
2899 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2903 /* I now set the cursor anew in every OnInternalIdle call
2904 as setting the cursor in a parent window also effects the
2905 windows above so that checking for the current cursor is
2910 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2912 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2914 if (!g_globalCursor
.Ok())
2915 cursor
= *wxSTANDARD_CURSOR
;
2917 window
= m_widget
->window
;
2918 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2919 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2925 GdkWindow
*window
= m_widget
->window
;
2926 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2927 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2935 void wxWindowGTK::DoGetSize( int *width
, int *height
) const
2937 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2939 if (width
) (*width
) = m_width
;
2940 if (height
) (*height
) = m_height
;
2943 void wxWindowGTK::DoSetClientSize( int width
, int height
)
2945 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2949 SetSize( width
, height
);
2956 #ifndef __WXUNIVERSAL__
2957 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2959 /* when using GTK 1.2 we set the shadow border size to 2 */
2963 if (HasFlag(wxSIMPLE_BORDER
))
2965 /* when using GTK 1.2 we set the simple border size to 1 */
2969 #endif // __WXUNIVERSAL__
2973 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2975 GtkRequisition vscroll_req
;
2976 vscroll_req
.width
= 2;
2977 vscroll_req
.height
= 2;
2978 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2979 (scroll_window
->vscrollbar
, &vscroll_req
);
2981 GtkRequisition hscroll_req
;
2982 hscroll_req
.width
= 2;
2983 hscroll_req
.height
= 2;
2984 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2985 (scroll_window
->hscrollbar
, &hscroll_req
);
2987 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2989 if (scroll_window
->vscrollbar_visible
)
2991 dw
+= vscroll_req
.width
;
2992 dw
+= scroll_class
->scrollbar_spacing
;
2995 if (scroll_window
->hscrollbar_visible
)
2997 dh
+= hscroll_req
.height
;
2998 dh
+= scroll_class
->scrollbar_spacing
;
3002 SetSize( width
+dw
, height
+dh
);
3006 void wxWindowGTK::DoGetClientSize( int *width
, int *height
) const
3008 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3012 if (width
) (*width
) = m_width
;
3013 if (height
) (*height
) = m_height
;
3020 #ifndef __WXUNIVERSAL__
3021 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
3023 /* when using GTK 1.2 we set the shadow border size to 2 */
3027 if (HasFlag(wxSIMPLE_BORDER
))
3029 /* when using GTK 1.2 we set the simple border size to 1 */
3033 #endif // __WXUNIVERSAL__
3037 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
3039 GtkRequisition vscroll_req
;
3040 vscroll_req
.width
= 2;
3041 vscroll_req
.height
= 2;
3042 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
3043 (scroll_window
->vscrollbar
, &vscroll_req
);
3045 GtkRequisition hscroll_req
;
3046 hscroll_req
.width
= 2;
3047 hscroll_req
.height
= 2;
3048 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
3049 (scroll_window
->hscrollbar
, &hscroll_req
);
3051 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
3053 if (scroll_window
->vscrollbar_visible
)
3055 dw
+= vscroll_req
.width
;
3056 dw
+= scroll_class
->scrollbar_spacing
;
3059 if (scroll_window
->hscrollbar_visible
)
3061 dh
+= hscroll_req
.height
;
3062 dh
+= scroll_class
->scrollbar_spacing
;
3066 if (width
) (*width
) = m_width
- dw
;
3067 if (height
) (*height
) = m_height
- dh
;
3071 printf( "GetClientSize, name %s ", GetName().c_str() );
3072 if (width) printf( " width = %d", (*width) );
3073 if (height) printf( " height = %d", (*height) );
3078 void wxWindowGTK::DoGetPosition( int *x
, int *y
) const
3080 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3084 if (m_parent
&& m_parent
->m_wxwindow
)
3086 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
3087 dx
= pizza
->xoffset
;
3088 dy
= pizza
->yoffset
;
3091 if (x
) (*x
) = m_x
- dx
;
3092 if (y
) (*y
) = m_y
- dy
;
3095 void wxWindowGTK::DoClientToScreen( int *x
, int *y
) const
3097 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3099 if (!m_widget
->window
) return;
3101 GdkWindow
*source
= (GdkWindow
*) NULL
;
3103 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3105 source
= m_widget
->window
;
3109 gdk_window_get_origin( source
, &org_x
, &org_y
);
3113 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3115 org_x
+= m_widget
->allocation
.x
;
3116 org_y
+= m_widget
->allocation
.y
;
3124 void wxWindowGTK::DoScreenToClient( int *x
, int *y
) const
3126 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3128 if (!m_widget
->window
) return;
3130 GdkWindow
*source
= (GdkWindow
*) NULL
;
3132 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3134 source
= m_widget
->window
;
3138 gdk_window_get_origin( source
, &org_x
, &org_y
);
3142 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3144 org_x
+= m_widget
->allocation
.x
;
3145 org_y
+= m_widget
->allocation
.y
;
3153 bool wxWindowGTK::Show( bool show
)
3155 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3157 if (!wxWindowBase::Show(show
))
3164 gtk_widget_show( m_widget
);
3166 gtk_widget_hide( m_widget
);
3171 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
)
3173 win
->OnParentEnable(enable
);
3175 // Recurse, so that children have the opportunity to Do The Right Thing
3176 // and reset colours that have been messed up by a parent's (really ancestor's)
3178 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
3180 node
= node
->GetNext() )
3182 wxWindow
*child
= node
->GetData();
3183 if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
)))
3184 wxWindowNotifyEnable(child
, enable
);
3188 bool wxWindowGTK::Enable( bool enable
)
3190 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3192 if (!wxWindowBase::Enable(enable
))
3198 gtk_widget_set_sensitive( m_widget
, enable
);
3200 gtk_widget_set_sensitive( m_wxwindow
, enable
);
3202 wxWindowNotifyEnable(this, enable
);
3207 int wxWindowGTK::GetCharHeight() const
3209 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
3211 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
3213 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3215 return font
->ascent
+ font
->descent
;
3218 int wxWindowGTK::GetCharWidth() const
3220 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
3222 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
3224 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3226 return gdk_string_width( font
, "H" );
3229 void wxWindowGTK::GetTextExtent( const wxString
& string
,
3233 int *externalLeading
,
3234 const wxFont
*theFont
) const
3236 wxFont fontToUse
= m_font
;
3237 if (theFont
) fontToUse
= *theFont
;
3239 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
3241 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
3242 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
3243 if (y
) (*y
) = font
->ascent
+ font
->descent
;
3244 if (descent
) (*descent
) = font
->descent
;
3245 if (externalLeading
) (*externalLeading
) = 0; // ??
3248 void wxWindowGTK::SetFocus()
3250 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3253 wxPrintf( "SetFocus from " );
3254 if (GetClassInfo() && GetClassInfo()->GetClassName())
3255 wxPrintf( GetClassInfo()->GetClassName() );
3261 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3263 // see comment in gtk_window_focus_out_callback()
3264 gs_widgetLastFocus
= m_wxwindow
;
3265 gtk_widget_grab_focus (m_wxwindow
);
3270 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
3272 gtk_widget_grab_focus (m_widget
);
3274 else if (GTK_IS_CONTAINER(m_widget
))
3276 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
3285 wxPrintf( "SetFocus finished in " );
3286 if (GetClassInfo() && GetClassInfo()->GetClassName())
3287 wxPrintf( GetClassInfo()->GetClassName() );
3293 bool wxWindowGTK::AcceptsFocus() const
3295 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3298 bool wxWindowGTK::Reparent( wxWindowBase
*newParentBase
)
3300 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3302 wxWindowGTK
*oldParent
= m_parent
,
3303 *newParent
= (wxWindowGTK
*)newParentBase
;
3305 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3307 if ( !wxWindowBase::Reparent(newParent
) )
3310 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3312 /* prevent GTK from deleting the widget arbitrarily */
3313 gtk_widget_ref( m_widget
);
3317 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3320 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3324 /* insert GTK representation */
3325 (*(newParent
->m_insertCallback
))(newParent
, this);
3328 /* reverse: prevent GTK from deleting the widget arbitrarily */
3329 gtk_widget_unref( m_widget
);
3334 void wxWindowGTK::DoAddChild(wxWindowGTK
*child
)
3336 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3338 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3340 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3345 /* insert GTK representation */
3346 (*m_insertCallback
)(this, child
);
3349 void wxWindowGTK::Raise()
3351 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3353 if (!m_widget
->window
) return;
3355 gdk_window_raise( m_widget
->window
);
3358 void wxWindowGTK::Lower()
3360 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3362 if (!m_widget
->window
) return;
3364 gdk_window_lower( m_widget
->window
);
3367 bool wxWindowGTK::SetCursor( const wxCursor
&cursor
)
3369 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3371 if (cursor
== m_cursor
)
3375 wxapp_install_idle_handler();
3377 if (cursor
== wxNullCursor
)
3378 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3380 return wxWindowBase::SetCursor( cursor
);
3383 void wxWindowGTK::WarpPointer( int x
, int y
)
3385 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3387 /* we provide this function ourselves as it is
3388 missing in GDK (top of this file) */
3390 GdkWindow
*window
= (GdkWindow
*) NULL
;
3392 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3394 window
= GetConnectWidget()->window
;
3397 gdk_window_warp_pointer( window
, x
, y
);
3400 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect
*rect
)
3402 if (!m_widget
) return;
3403 if (!m_widget
->window
) return;
3405 // temporarily hide the caret to avoid nasty interactions between caret
3406 // drawing and the window contents redraw
3407 #if 0 // def wxUSE_CARET -- doesn't seem to help :-(
3408 wxCaretSuspend
cs((wxWindow
*)this);
3409 #endif // wxUSE_CARET
3411 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3415 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3417 rect
->width
, rect
->height
);
3421 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3425 /* there is no GTK equivalent of "draw only, don't clear" so we
3426 invent our own in the GtkPizza widget */
3434 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3435 gboolean old_clear = pizza->clear_on_draw;
3436 gtk_pizza_set_clear( pizza, FALSE );
3437 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3438 gtk_pizza_set_clear( pizza, old_clear );
3440 GdkEventExpose gdk_event
;
3441 gdk_event
.type
= GDK_EXPOSE
;
3442 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3443 gdk_event
.count
= 0;
3444 gdk_event
.area
.x
= 0;
3445 gdk_event
.area
.y
= 0;
3446 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3447 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3448 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, (wxWindow
*)this );
3452 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3461 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3462 gboolean old_clear = pizza->clear_on_draw;
3463 gtk_pizza_set_clear( pizza, FALSE );
3465 GdkRectangle gdk_rect;
3466 gdk_rect.x = rect->x;
3467 gdk_rect.y = rect->y;
3468 gdk_rect.width = rect->width;
3469 gdk_rect.height = rect->height;
3470 gtk_widget_draw( m_wxwindow, &gdk_rect );
3471 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3473 gtk_pizza_set_clear( pizza, old_clear );
3475 GdkEventExpose gdk_event
;
3476 gdk_event
.type
= GDK_EXPOSE
;
3477 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3478 gdk_event
.count
= 0;
3479 gdk_event
.area
.x
= rect
->x
;
3480 gdk_event
.area
.y
= rect
->y
;
3481 gdk_event
.area
.width
= rect
->width
;
3482 gdk_event
.area
.height
= rect
->height
;
3483 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, (wxWindow
*)this );
3487 GdkRectangle gdk_rect
;
3488 gdk_rect
.x
= rect
->x
;
3489 gdk_rect
.y
= rect
->y
;
3490 gdk_rect
.width
= rect
->width
;
3491 gdk_rect
.height
= rect
->height
;
3492 gtk_widget_draw( m_widget
, &gdk_rect
);
3497 void wxWindowGTK::Clear()
3499 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3501 if (!m_widget
->window
) return;
3503 if (m_wxwindow
&& m_wxwindow
->window
)
3505 // gdk_window_clear( m_wxwindow->window );
3510 void wxWindowGTK::DoSetToolTip( wxToolTip
*tip
)
3512 wxWindowBase::DoSetToolTip(tip
);
3515 m_tooltip
->Apply( (wxWindow
*)this );
3518 void wxWindowGTK::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3520 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3522 #endif // wxUSE_TOOLTIPS
3524 bool wxWindowGTK::SetBackgroundColour( const wxColour
&colour
)
3526 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3528 if (!wxWindowBase::SetBackgroundColour(colour
))
3530 // don't leave if the GTK widget has just
3532 if (!m_delayedBackgroundColour
) return FALSE
;
3535 GdkWindow
*window
= (GdkWindow
*) NULL
;
3537 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3539 window
= GetConnectWidget()->window
;
3543 // indicate that a new style has been set
3544 // but it couldn't get applied as the
3545 // widget hasn't been realized yet.
3546 m_delayedBackgroundColour
= TRUE
;
3550 (m_wxwindow
->window
) &&
3551 (m_backgroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
)))
3553 /* wxMSW doesn't clear the window here. I don't do that either to
3554 provide compatibility. call Clear() to do the job. */
3556 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3557 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3565 bool wxWindowGTK::SetForegroundColour( const wxColour
&colour
)
3567 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3569 if (!wxWindowBase::SetForegroundColour(colour
))
3571 // don't leave if the GTK widget has just
3573 if (!m_delayedForegroundColour
) return FALSE
;
3576 GdkWindow
*window
= (GdkWindow
*) NULL
;
3578 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3580 window
= GetConnectWidget()->window
;
3584 // indicate that a new style has been set
3585 // but it couldn't get applied as the
3586 // widget hasn't been realized yet.
3587 m_delayedForegroundColour
= TRUE
;
3595 GtkStyle
*wxWindowGTK::GetWidgetStyle()
3599 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3601 /* FIXME: is this necessary? */
3602 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3604 remake
->klass
= m_widgetStyle
->klass
;
3607 gtk_style_unref( m_widgetStyle
);
3608 m_widgetStyle
= remake
;
3612 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3615 def
= gtk_widget_get_default_style();
3617 m_widgetStyle
= gtk_style_copy( def
);
3619 /* FIXME: is this necessary? */
3620 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3622 m_widgetStyle
->klass
= def
->klass
;
3626 return m_widgetStyle
;
3629 void wxWindowGTK::SetWidgetStyle()
3631 #if DISABLE_STYLE_IF_BROKEN_THEM
3632 if (m_widget
->style
->engine_data
)
3634 static bool s_warningPrinted
= FALSE
;
3635 if (!s_warningPrinted
)
3637 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3638 s_warningPrinted
= TRUE
;
3640 m_widgetStyle
= m_widget
->style
;
3645 GtkStyle
*style
= GetWidgetStyle();
3647 if (m_font
!= wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT
))
3649 gdk_font_unref( style
->font
);
3650 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3653 if (m_foregroundColour
.Ok())
3655 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3656 if (m_foregroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT
))
3658 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3659 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3660 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3664 // Try to restore the gtk default style. This is still a little
3665 // oversimplified for what is probably really needed here for controls
3666 // other than buttons, but is better than not being able to (re)set a
3667 // control's foreground colour to *wxBLACK -- RL
3668 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3671 def
= gtk_widget_get_default_style();
3673 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3674 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3675 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3679 if (m_backgroundColour
.Ok())
3681 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3682 if (m_backgroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
))
3684 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3685 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3686 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3687 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3688 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3689 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3690 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3691 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3695 // Try to restore the gtk default style. This is still a little
3696 // oversimplified for what is probably really needed here for controls
3697 // other than buttons, but is better than not being able to (re)set a
3698 // control's background colour to default grey and means resetting a
3699 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3701 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3704 def
= gtk_widget_get_default_style();
3706 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3707 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3708 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3709 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3710 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3711 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3712 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3713 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3718 void wxWindowGTK::ApplyWidgetStyle()
3722 //-----------------------------------------------------------------------------
3723 // Pop-up menu stuff
3724 //-----------------------------------------------------------------------------
3726 #if wxUSE_MENUS_NATIVE
3729 void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3731 *is_waiting
= FALSE
;
3734 static void SetInvokingWindow( wxMenu
*menu
, wxWindowGTK
*win
)
3736 menu
->SetInvokingWindow( win
);
3737 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3740 wxMenuItem
*menuitem
= node
->GetData();
3741 if (menuitem
->IsSubMenu())
3743 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3746 node
= node
->GetNext();
3750 // used to pass the coordinates from wxWindowGTK::DoPopupMenu() to
3751 // wxPopupMenuPositionCallback()
3753 // should be safe even in the MT case as the user can hardly popup 2 menus
3754 // simultaneously, can he?
3755 static gint gs_pop_x
= 0;
3756 static gint gs_pop_y
= 0;
3758 static void wxPopupMenuPositionCallback( GtkMenu
*menu
,
3760 gpointer
WXUNUSED(user_data
) )
3762 // ensure that the menu appears entirely on screen
3764 gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
);
3766 wxSize sizeScreen
= wxGetDisplaySize();
3768 gint xmax
= sizeScreen
.x
- req
.width
,
3769 ymax
= sizeScreen
.y
- req
.height
;
3771 *x
= gs_pop_x
< xmax
? gs_pop_x
: xmax
;
3772 *y
= gs_pop_y
< ymax
? gs_pop_y
: ymax
;
3775 bool wxWindowGTK::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3777 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3779 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3781 SetInvokingWindow( menu
, this );
3787 ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3789 bool is_waiting
= TRUE
;
3791 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
),
3793 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
),
3794 (gpointer
)&is_waiting
);
3797 GTK_MENU(menu
->m_menu
),
3798 (GtkWidget
*) NULL
, // parent menu shell
3799 (GtkWidget
*) NULL
, // parent menu item
3800 wxPopupMenuPositionCallback
, // function to position it
3801 NULL
, // client data
3802 0, // button used to activate it
3803 gs_timeLastClick
// the time of activation
3808 while (gtk_events_pending())
3809 gtk_main_iteration();
3815 #endif // wxUSE_MENUS_NATIVE
3817 #if wxUSE_DRAG_AND_DROP
3819 void wxWindowGTK::SetDropTarget( wxDropTarget
*dropTarget
)
3821 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3823 GtkWidget
*dnd_widget
= GetConnectWidget();
3825 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3827 if (m_dropTarget
) delete m_dropTarget
;
3828 m_dropTarget
= dropTarget
;
3830 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3833 #endif // wxUSE_DRAG_AND_DROP
3835 GtkWidget
* wxWindowGTK::GetConnectWidget()
3837 GtkWidget
*connect_widget
= m_widget
;
3838 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3840 return connect_widget
;
3843 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow
*window
)
3846 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3848 return (window
== m_widget
->window
);
3851 bool wxWindowGTK::SetFont( const wxFont
&font
)
3853 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3855 if (!wxWindowBase::SetFont(font
))
3860 wxColour sysbg
= wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE
);
3861 if ( sysbg
== m_backgroundColour
)
3863 m_backgroundColour
= wxNullColour
;
3865 m_backgroundColour
= sysbg
;
3875 void wxWindowGTK::CaptureMouse()
3877 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3879 GdkWindow
*window
= (GdkWindow
*) NULL
;
3881 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3883 window
= GetConnectWidget()->window
;
3885 wxCHECK_RET( window
, _T("CaptureMouse() failed") );
3887 wxCursor
* cursor
= & m_cursor
;
3889 cursor
= wxSTANDARD_CURSOR
;
3891 gdk_pointer_grab( window
, FALSE
,
3893 (GDK_BUTTON_PRESS_MASK
|
3894 GDK_BUTTON_RELEASE_MASK
|
3895 GDK_POINTER_MOTION_HINT_MASK
|
3896 GDK_POINTER_MOTION_MASK
),
3898 cursor
->GetCursor(),
3899 (guint32
)GDK_CURRENT_TIME
);
3900 g_captureWindow
= this;
3901 g_captureWindowHasMouse
= TRUE
;
3904 void wxWindowGTK::ReleaseMouse()
3906 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3908 wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") );
3910 GdkWindow
*window
= (GdkWindow
*) NULL
;
3912 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3914 window
= GetConnectWidget()->window
;
3919 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3920 g_captureWindow
= (wxWindowGTK
*) NULL
;
3924 wxWindow
*wxWindowBase::GetCapture()
3926 return (wxWindow
*)g_captureWindow
;
3929 bool wxWindowGTK::IsRetained() const
3934 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3935 int range
, bool refresh
)
3937 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3939 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3941 m_hasScrolling
= TRUE
;
3943 if (orient
== wxHORIZONTAL
)
3945 float fpos
= (float)pos
;
3946 float frange
= (float)range
;
3947 float fthumb
= (float)thumbVisible
;
3948 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3949 if (fpos
< 0.0) fpos
= 0.0;
3951 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3952 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3954 SetScrollPos( orient
, pos
, refresh
);
3958 m_oldHorizontalPos
= fpos
;
3960 m_hAdjust
->lower
= 0.0;
3961 m_hAdjust
->upper
= frange
;
3962 m_hAdjust
->value
= fpos
;
3963 m_hAdjust
->step_increment
= 1.0;
3964 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3965 m_hAdjust
->page_size
= fthumb
;
3969 float fpos
= (float)pos
;
3970 float frange
= (float)range
;
3971 float fthumb
= (float)thumbVisible
;
3972 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3973 if (fpos
< 0.0) fpos
= 0.0;
3975 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3976 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3978 SetScrollPos( orient
, pos
, refresh
);
3982 m_oldVerticalPos
= fpos
;
3984 m_vAdjust
->lower
= 0.0;
3985 m_vAdjust
->upper
= frange
;
3986 m_vAdjust
->value
= fpos
;
3987 m_vAdjust
->step_increment
= 1.0;
3988 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3989 m_vAdjust
->page_size
= fthumb
;
3992 if (orient
== wxHORIZONTAL
)
3993 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3995 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3998 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
4000 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4002 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4004 if (orient
== wxHORIZONTAL
)
4006 float fpos
= (float)pos
;
4007 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
4008 if (fpos
< 0.0) fpos
= 0.0;
4009 m_oldHorizontalPos
= fpos
;
4011 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
4012 m_hAdjust
->value
= fpos
;
4016 float fpos
= (float)pos
;
4017 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
4018 if (fpos
< 0.0) fpos
= 0.0;
4019 m_oldVerticalPos
= fpos
;
4021 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
4022 m_vAdjust
->value
= fpos
;
4025 if (m_wxwindow
->window
)
4027 if (orient
== wxHORIZONTAL
)
4029 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
4030 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
4032 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
4034 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
4035 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
4039 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
4040 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4042 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
4044 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
4045 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4050 int wxWindowGTK::GetScrollThumb( int orient
) const
4052 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4054 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4056 if (orient
== wxHORIZONTAL
)
4057 return (int)(m_hAdjust
->page_size
+0.5);
4059 return (int)(m_vAdjust
->page_size
+0.5);
4062 int wxWindowGTK::GetScrollPos( int orient
) const
4064 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4066 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4068 if (orient
== wxHORIZONTAL
)
4069 return (int)(m_hAdjust
->value
+0.5);
4071 return (int)(m_vAdjust
->value
+0.5);
4074 int wxWindowGTK::GetScrollRange( int orient
) const
4076 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4078 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4080 if (orient
== wxHORIZONTAL
)
4081 return (int)(m_hAdjust
->upper
+0.5);
4083 return (int)(m_vAdjust
->upper
+0.5);
4086 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
4088 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4090 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4092 if ((dx
== 0) && (dy
== 0)) return;
4094 m_clipPaintRegion
= TRUE
;
4095 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
4096 m_clipPaintRegion
= FALSE
;
4099 if (m_children.GetCount() > 0)
4101 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
4105 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
4107 pizza->xoffset -= dx;
4108 pizza->yoffset -= dy;
4110 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
4111 gdk_gc_set_exposures( m_scrollGC, TRUE );
4115 GetClientSize( &cw, &ch );
4116 int w = cw - abs(dx);
4117 int h = ch - abs(dy);
4119 if ((h < 0) || (w < 0))
4127 if (dx < 0) s_x = -dx;
4128 if (dy < 0) s_y = -dy;
4131 if (dx > 0) d_x = dx;
4132 if (dy > 0) d_y = dy;
4134 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
4135 pizza->bin_window, s_x, s_y, w, h );
4138 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
4139 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
4140 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
4141 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
4143 Refresh( TRUE, &rect );
4146 gdk_gc_unref( m_scrollGC );
4151 // Find the wxWindow at the current mouse position, also returning the mouse
4153 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
4155 pt
= wxGetMousePosition();
4156 wxWindow
* found
= wxFindWindowAtPoint(pt
);
4160 // Get the current mouse position.
4161 wxPoint
wxGetMousePosition()
4163 /* This crashes when used within wxHelpContext,
4164 so we have to use the X-specific implementation below.
4166 GdkModifierType *mask;
4167 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
4169 return wxPoint(x, y);
4173 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
4175 return wxPoint(-999, -999);
4177 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
4178 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
4179 Window rootReturn
, childReturn
;
4180 int rootX
, rootY
, winX
, winY
;
4181 unsigned int maskReturn
;
4183 XQueryPointer (display
,
4187 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
4188 return wxPoint(rootX
, rootY
);