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
, pizza
->bin_window
, GTK_STATE_NORMAL
,
789 GTK_SHADOW_NONE
, &gdk_event
->area
, parent
->m_widget
, "base", 0, 0, -1, -1);
792 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
794 gdk_event
->area
.width
,
795 gdk_event
->area
.height
);
797 if (gdk_event
->count
== 0)
799 win
->m_clipPaintRegion
= TRUE
;
802 dc
.SetClippingRegion(win
->GetUpdateRegion());
803 wxEraseEvent
eevent( win
->GetId(), &dc
);
804 eevent
.SetEventObject( win
);
806 (void)win
->GetEventHandler()->ProcessEvent(eevent
);
808 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
810 wxClientDC
dc( win
);
811 dc
.SetBrush( wxBrush( win
->GetBackgroundColour(), wxSOLID
) );
812 dc
.SetPen( *wxTRANSPARENT_PEN
);
814 wxRegionIterator
upd( win
->GetUpdateRegion() );
817 dc
.DrawRectangle( upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
823 wxNcPaintEvent
eventNc( win
->GetId() );
824 eventNc
.SetEventObject( win
);
825 win
->GetEventHandler()->ProcessEvent( eventNc
);
827 wxPaintEvent
event( win
->GetId() );
828 event
.SetEventObject( win
);
829 win
->GetEventHandler()->ProcessEvent( event
);
831 win
->GetUpdateRegion().Clear();
833 win
->m_clipPaintRegion
= FALSE
;
836 /* The following code will result in all window-less widgets
837 being redrawn if the wxWindows class is given a chance to
838 paint *anything* because it will then be allowed to paint
839 over the window-less widgets */
840 GList
*children
= pizza
->children
;
843 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
844 children
= children
->next
;
846 GdkEventExpose child_event
= *gdk_event
;
848 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
849 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
850 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
852 child_event
.area
.x
= child
->widget
->allocation
.x
;
853 child_event
.area
.y
= child
->widget
->allocation
.y
;
854 child_event
.area
.width
= child
->widget
->allocation
.width
;
855 child_event
.area
.height
= child
->widget
->allocation
.height
;
856 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
863 //-----------------------------------------------------------------------------
864 // "event" of m_wxwindow
865 //-----------------------------------------------------------------------------
867 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
868 expose events. We need them, of course, so we override the main event
869 procedure in GtkWidget by giving our own handler for all system events.
870 There, we look for expose events ourselves whereas all other events are
873 gint
gtk_window_event_event_callback( GtkWidget
*widget
,
874 GdkEventExpose
*event
,
877 if (event
->type
== GDK_EXPOSE
)
879 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
886 //-----------------------------------------------------------------------------
887 // "draw" of m_wxwindow
888 //-----------------------------------------------------------------------------
890 /* This callback is a complete replacement of the gtk_pizza_draw() function,
893 static void gtk_window_draw_callback( GtkWidget
*widget
,
900 wxapp_install_idle_handler();
902 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
903 (win
->GetChildren().GetCount() == 0))
909 if (win->GetName() == wxT("panel"))
911 wxPrintf( wxT("OnDraw from ") );
912 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
913 wxPrintf( win->GetClassInfo()->GetClassName() );
914 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
921 GtkPizza
*pizza
= GTK_PIZZA (widget
);
923 if (win
->GetThemeEnabled())
925 wxWindow
*parent
= win
->GetParent();
926 while (parent
&& !parent
->IsTopLevel())
927 parent
= parent
->GetParent();
931 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
932 GTK_SHADOW_NONE
, rect
, parent
->m_widget
, "base", 0, 0, -1, -1);
936 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
937 (pizza
->clear_on_draw
))
939 gdk_window_clear_area( pizza
->bin_window
,
940 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
943 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
945 win
->m_clipPaintRegion
= TRUE
;
948 dc
.SetClippingRegion(win
->GetUpdateRegion());
949 wxEraseEvent
eevent( win
->GetId(), &dc
);
950 eevent
.SetEventObject( win
);
953 (void)win
->GetEventHandler()->ProcessEvent(eevent
);
955 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
957 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
959 wxClientDC
dc( win
);
960 dc
.SetBrush( wxBrush( win
->GetBackgroundColour(), wxSOLID
) );
961 dc
.SetPen( *wxTRANSPARENT_PEN
);
963 wxRegionIterator
upd( win
->GetUpdateRegion() );
966 dc
.DrawRectangle( upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
973 wxNcPaintEvent
eventNc( win
->GetId() );
974 eventNc
.SetEventObject( win
);
975 win
->GetEventHandler()->ProcessEvent( eventNc
);
977 wxPaintEvent
event( win
->GetId() );
978 event
.SetEventObject( win
);
979 win
->GetEventHandler()->ProcessEvent( event
);
981 win
->GetUpdateRegion().Clear();
983 win
->m_clipPaintRegion
= FALSE
;
986 GList
*children
= pizza
->children
;
989 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
990 children
= children
->next
;
992 GdkRectangle child_area
;
993 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
995 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
1000 //-----------------------------------------------------------------------------
1001 // "key_press_event" from any window
1002 //-----------------------------------------------------------------------------
1004 // turn on to see the key event codes on the console
1005 #undef DEBUG_KEY_EVENTS
1007 static gint
gtk_window_key_press_callback( GtkWidget
*widget
,
1008 GdkEventKey
*gdk_event
,
1014 wxapp_install_idle_handler();
1016 if (!win
->m_hasVMT
) return FALSE
;
1017 if (g_blockEventsOnDrag
) return FALSE
;
1022 GdkModifierType state
;
1023 if (gdk_event
->window
)
1024 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1028 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
1030 #ifdef DEBUG_KEY_EVENTS
1031 wxPrintf(_T("Key press event: %d => %ld\n"), gdk_event
->keyval
, key_code
);
1032 #endif // DEBUG_KEY_EVENTS
1034 /* sending unknown key events doesn't really make sense */
1038 wxKeyEvent
event( wxEVT_KEY_DOWN
);
1039 event
.SetTimestamp( gdk_event
->time
);
1040 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1041 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1042 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1043 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1044 event
.m_keyCode
= key_code
;
1045 event
.m_scanCode
= gdk_event
->keyval
;
1048 event
.SetEventObject( win
);
1049 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1054 wxWindowGTK
*ancestor
= win
;
1057 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
1060 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
1061 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
1064 if (ancestor
->IsTopLevel())
1066 ancestor
= ancestor
->GetParent();
1069 #endif // wxUSE_ACCEL
1071 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
1072 will only be sent if it is not in an accelerator table. */
1075 key_code
= map_to_wx_keysym( gdk_event
);
1079 #ifdef DEBUG_KEY_EVENTS
1080 wxPrintf(_T("Char event: %ld\n"), key_code
);
1081 #endif // DEBUG_KEY_EVENTS
1083 // reuse the ame event object, just change its type and use the
1084 // translated keycode instead of the raw one
1085 event
.SetEventType(wxEVT_CHAR
);
1086 event
.m_keyCode
= key_code
;
1088 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1092 /* win is a control: tab can be propagated up */
1094 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
1095 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
1096 // have this style, yet choose not to process this particular TAB in which
1097 // case TAB must still work as a navigational character
1099 !win
->HasFlag(wxTE_PROCESS_TAB
) &&
1101 win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
1103 wxNavigationKeyEvent new_event
;
1104 new_event
.SetEventObject( win
->GetParent() );
1105 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
1106 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
1107 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1108 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
1109 new_event
.SetCurrentFocus( win
);
1110 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
1113 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
1115 (gdk_event
->keyval
== GDK_Escape
) )
1117 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
1118 new_event
.SetEventObject( win
);
1119 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
1123 #if 0 // (GTK_MINOR_VERSION > 0)
1124 /* Pressing F10 will activate the menu bar of the top frame. */
1126 (gdk_event
->keyval
== GDK_F10
) )
1128 wxWindowGTK
*ancestor
= win
;
1131 if (wxIsKindOf(ancestor
,wxFrame
))
1133 wxFrame
*frame
= (wxFrame
*) ancestor
;
1134 wxMenuBar
*menubar
= frame
->GetMenuBar();
1137 wxNode
*node
= menubar
->GetMenus().First();
1140 wxMenu
*firstMenu
= (wxMenu
*) node
->Data();
1141 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu
->m_owner
) );
1147 ancestor
= ancestor
->GetParent();
1154 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1161 //-----------------------------------------------------------------------------
1162 // "key_release_event" from any window
1163 //-----------------------------------------------------------------------------
1165 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindowGTK
*win
)
1170 wxapp_install_idle_handler();
1172 if (!win
->m_hasVMT
) return FALSE
;
1173 if (g_blockEventsOnDrag
) return FALSE
;
1175 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
1177 #ifdef DEBUG_KEY_EVENTS
1178 wxPrintf(_T("Key release event: %d => %ld\n"), gdk_event
->keyval
, key_code
);
1179 #endif // DEBUG_KEY_EVENTS
1181 /* sending unknown key events doesn't really make sense */
1182 if (key_code
== 0) return FALSE
;
1186 GdkModifierType state
;
1187 if (gdk_event
->window
)
1188 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1190 wxKeyEvent
event( wxEVT_KEY_UP
);
1191 event
.SetTimestamp( gdk_event
->time
);
1192 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1193 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1194 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1195 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1196 event
.m_keyCode
= key_code
;
1197 event
.m_scanCode
= gdk_event
->keyval
;
1200 event
.SetEventObject( win
);
1202 if (win
->GetEventHandler()->ProcessEvent( event
))
1204 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1211 // ----------------------------------------------------------------------------
1212 // mouse event processing helper
1213 // ----------------------------------------------------------------------------
1215 static void AdjustEventButtonState(wxMouseEvent
& event
)
1217 // GDK reports the old state of the button for a button press event, but
1218 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1219 // for a LEFT_DOWN event, not FALSE, so we will invert
1220 // left/right/middleDown for the corresponding click events
1222 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1223 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1224 (event
.GetEventType() == wxEVT_LEFT_UP
))
1226 event
.m_leftDown
= !event
.m_leftDown
;
1230 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1231 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1232 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1234 event
.m_middleDown
= !event
.m_middleDown
;
1238 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1239 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1240 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1242 event
.m_rightDown
= !event
.m_rightDown
;
1247 //-----------------------------------------------------------------------------
1248 // "button_press_event"
1249 //-----------------------------------------------------------------------------
1251 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1256 wxapp_install_idle_handler();
1259 wxPrintf( wxT("1) OnButtonPress from ") );
1260 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1261 wxPrintf( win->GetClassInfo()->GetClassName() );
1262 wxPrintf( wxT(".\n") );
1264 if (!win
->m_hasVMT
) return FALSE
;
1265 if (g_blockEventsOnDrag
) return TRUE
;
1266 if (g_blockEventsOnScroll
) return TRUE
;
1268 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1270 if (win
->m_wxwindow
)
1272 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1274 gtk_widget_grab_focus (win
->m_wxwindow
);
1277 wxPrintf( wxT("GrabFocus from ") );
1278 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1279 wxPrintf( win->GetClassInfo()->GetClassName() );
1280 wxPrintf( wxT(".\n") );
1286 wxEventType event_type
= wxEVT_NULL
;
1288 if (gdk_event
->button
== 1)
1290 switch (gdk_event
->type
)
1292 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1293 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1297 else if (gdk_event
->button
== 2)
1299 switch (gdk_event
->type
)
1301 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1302 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1306 else if (gdk_event
->button
== 3)
1308 switch (gdk_event
->type
)
1310 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1311 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1316 if ( event_type
== wxEVT_NULL
)
1318 // unknown mouse button or click type
1322 wxMouseEvent
event( event_type
);
1323 event
.SetTimestamp( gdk_event
->time
);
1324 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1325 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1326 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1327 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1328 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1329 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1330 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1332 event
.m_x
= (wxCoord
)gdk_event
->x
;
1333 event
.m_y
= (wxCoord
)gdk_event
->y
;
1335 AdjustEventButtonState(event
);
1337 // wxListBox actually get mouse events from the item
1339 if (win
->m_isListBox
)
1341 event
.m_x
+= widget
->allocation
.x
;
1342 event
.m_y
+= widget
->allocation
.y
;
1345 // Some control don't have their own X window and thus cannot get
1348 if (!g_captureWindow
)
1350 wxCoord x
= event
.m_x
;
1351 wxCoord y
= event
.m_y
;
1352 if (win
->m_wxwindow
)
1354 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1355 x
+= pizza
->xoffset
;
1356 y
+= pizza
->yoffset
;
1359 wxNode
*node
= win
->GetChildren().First();
1362 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1364 node
= node
->Next();
1365 if (!child
->IsShown())
1368 if (child
->m_isStaticBox
)
1370 // wxStaticBox is transparent in the box itself
1371 int xx1
= child
->m_x
;
1372 int yy1
= child
->m_y
;
1373 int xx2
= child
->m_x
+ child
->m_width
;
1374 int yy2
= child
->m_x
+ child
->m_height
;
1377 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1379 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1381 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1383 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1386 event
.m_x
-= child
->m_x
;
1387 event
.m_y
-= child
->m_y
;
1394 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1395 (child
->m_x
<= x
) &&
1396 (child
->m_y
<= y
) &&
1397 (child
->m_x
+child
->m_width
>= x
) &&
1398 (child
->m_y
+child
->m_height
>= y
))
1401 event
.m_x
-= child
->m_x
;
1402 event
.m_y
-= child
->m_y
;
1409 event
.SetEventObject( win
);
1411 gs_timeLastClick
= gdk_event
->time
;
1414 wxPrintf( wxT("2) OnButtonPress from ") );
1415 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1416 wxPrintf( win->GetClassInfo()->GetClassName() );
1417 wxPrintf( wxT(".\n") );
1420 if (win
->GetEventHandler()->ProcessEvent( event
))
1422 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1429 //-----------------------------------------------------------------------------
1430 // "button_release_event"
1431 //-----------------------------------------------------------------------------
1433 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1438 wxapp_install_idle_handler();
1440 if (!win
->m_hasVMT
) return FALSE
;
1441 if (g_blockEventsOnDrag
) return FALSE
;
1442 if (g_blockEventsOnScroll
) return FALSE
;
1444 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1447 printf( "OnButtonRelease from " );
1448 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1449 printf( win->GetClassInfo()->GetClassName() );
1453 wxEventType event_type
= wxEVT_NULL
;
1455 switch (gdk_event
->button
)
1457 case 1: event_type
= wxEVT_LEFT_UP
; break;
1458 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1459 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1460 default: return FALSE
;
1463 wxMouseEvent
event( event_type
);
1464 event
.SetTimestamp( gdk_event
->time
);
1465 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1466 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1467 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1468 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1469 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1470 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1471 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1472 event
.m_x
= (wxCoord
)gdk_event
->x
;
1473 event
.m_y
= (wxCoord
)gdk_event
->y
;
1475 AdjustEventButtonState(event
);
1477 // wxListBox actually get mouse events from the item
1479 if (win
->m_isListBox
)
1481 event
.m_x
+= widget
->allocation
.x
;
1482 event
.m_y
+= widget
->allocation
.y
;
1485 // Some control don't have their own X window and thus cannot get
1488 if (!g_captureWindow
)
1490 wxCoord x
= event
.m_x
;
1491 wxCoord y
= event
.m_y
;
1492 if (win
->m_wxwindow
)
1494 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1495 x
+= pizza
->xoffset
;
1496 y
+= pizza
->yoffset
;
1499 wxNode
*node
= win
->GetChildren().First();
1502 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1504 node
= node
->Next();
1505 if (!child
->IsShown())
1508 if (child
->m_isStaticBox
)
1510 // wxStaticBox is transparent in the box itself
1511 int xx1
= child
->m_x
;
1512 int yy1
= child
->m_y
;
1513 int xx2
= child
->m_x
+ child
->m_width
;
1514 int yy2
= child
->m_x
+ child
->m_height
;
1517 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1519 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1521 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1523 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1526 event
.m_x
-= child
->m_x
;
1527 event
.m_y
-= child
->m_y
;
1534 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1535 (child
->m_x
<= x
) &&
1536 (child
->m_y
<= y
) &&
1537 (child
->m_x
+child
->m_width
>= x
) &&
1538 (child
->m_y
+child
->m_height
>= y
))
1541 event
.m_x
-= child
->m_x
;
1542 event
.m_y
-= child
->m_y
;
1549 event
.SetEventObject( win
);
1551 if (win
->GetEventHandler()->ProcessEvent( event
))
1553 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1560 // ============================================================================
1562 // ============================================================================
1564 // init wxMouseEvent with the info from gdk_event
1565 #define InitMouseEvent(event, gdk_event) \
1566 event.SetTimestamp( gdk_event->time ); \
1567 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
1568 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
1569 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
1570 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
1571 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
1572 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
1573 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
1575 event.m_x = (wxCoord)gdk_event->x; \
1576 event.m_y = (wxCoord)gdk_event->y \
1578 //-----------------------------------------------------------------------------
1579 // "motion_notify_event"
1580 //-----------------------------------------------------------------------------
1582 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
,
1583 GdkEventMotion
*gdk_event
,
1589 wxapp_install_idle_handler();
1591 if (!win
->m_hasVMT
) return FALSE
;
1592 if (g_blockEventsOnDrag
) return FALSE
;
1593 if (g_blockEventsOnScroll
) return FALSE
;
1595 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1597 if (gdk_event
->is_hint
)
1601 GdkModifierType state
;
1602 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1608 printf( "OnMotion from " );
1609 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1610 printf( win->GetClassInfo()->GetClassName() );
1614 wxMouseEvent
event( wxEVT_MOTION
);
1615 InitMouseEvent(event
, gdk_event
);
1617 if ( g_captureWindow
)
1619 // synthetize a mouse enter or leave event if needed
1620 GdkWindow
*winUnderMouse
= gdk_window_at_pointer(NULL
, NULL
);
1621 bool hasMouse
= winUnderMouse
== gdk_event
->window
;
1622 if ( hasMouse
!= g_captureWindowHasMouse
)
1624 // the mouse changed window
1625 g_captureWindowHasMouse
= hasMouse
;
1627 wxMouseEvent
event(g_captureWindowHasMouse
? wxEVT_ENTER_WINDOW
1628 : wxEVT_LEAVE_WINDOW
);
1629 InitMouseEvent(event
, gdk_event
);
1630 event
.SetEventObject(win
);
1631 win
->GetEventHandler()->ProcessEvent(event
);
1636 // Some control don't have their own X window and thus cannot get
1639 wxCoord x
= event
.m_x
;
1640 wxCoord y
= event
.m_y
;
1641 if (win
->m_wxwindow
)
1643 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1644 x
+= pizza
->xoffset
;
1645 y
+= pizza
->yoffset
;
1648 wxNode
*node
= win
->GetChildren().First();
1651 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1653 node
= node
->Next();
1654 if (!child
->IsShown())
1657 if (child
->m_isStaticBox
)
1659 // wxStaticBox is transparent in the box itself
1660 int xx1
= child
->m_x
;
1661 int yy1
= child
->m_y
;
1662 int xx2
= child
->m_x
+ child
->m_width
;
1663 int yy2
= child
->m_x
+ child
->m_height
;
1666 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1668 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1670 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1672 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1675 event
.m_x
-= child
->m_x
;
1676 event
.m_y
-= child
->m_y
;
1683 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1684 (child
->m_x
<= x
) &&
1685 (child
->m_y
<= y
) &&
1686 (child
->m_x
+child
->m_width
>= x
) &&
1687 (child
->m_y
+child
->m_height
>= y
))
1690 event
.m_x
-= child
->m_x
;
1691 event
.m_y
-= child
->m_y
;
1698 event
.SetEventObject( win
);
1700 if (win
->GetEventHandler()->ProcessEvent( event
))
1702 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1709 //-----------------------------------------------------------------------------
1711 //-----------------------------------------------------------------------------
1713 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
,
1714 GdkEvent
*WXUNUSED(event
),
1720 wxapp_install_idle_handler();
1722 if (!win
->m_hasVMT
) return FALSE
;
1723 if (g_blockEventsOnDrag
) return FALSE
;
1725 switch ( g_sendActivateEvent
)
1728 // we've got focus from outside, synthetize wxActivateEvent
1729 g_sendActivateEvent
= 1;
1733 // another our window just lost focus, it was already ours before
1734 // - don't send any wxActivateEvent
1735 g_sendActivateEvent
= -1;
1740 g_focusWindow
= win
;
1743 wxPrintf( "OnSetFocus from " );
1744 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
1745 wxPrintf( win
->GetClassInfo()->GetClassName() );
1749 // notify the parent keeping track of focus for the kbd navigation
1750 // purposes that we got it
1751 wxChildFocusEvent
eventFocus(win
);
1752 (void)win
->GetEventHandler()->ProcessEvent(eventFocus
);
1756 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1760 // caret needs to be informed about focus change
1761 wxCaret
*caret
= win
->GetCaret();
1764 caret
->OnSetFocus();
1766 #endif // wxUSE_CARET
1768 wxWindowGTK
*active
= wxGetTopLevelParent(win
);
1769 if ( active
!= g_activeFrame
)
1771 if ( g_activeFrame
)
1773 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame
);
1774 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
1775 event
.SetEventObject(g_activeFrame
);
1776 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1779 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active
);
1780 g_activeFrame
= active
;
1781 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId());
1782 event
.SetEventObject(g_activeFrame
);
1783 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1785 g_activeFrameLostFocus
= FALSE
;
1788 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1789 event
.SetEventObject( win
);
1791 if (win
->GetEventHandler()->ProcessEvent( event
))
1793 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1801 //-----------------------------------------------------------------------------
1802 // "focus_out_event"
1803 //-----------------------------------------------------------------------------
1805 static GtkWidget
*gs_widgetLastFocus
= NULL
;
1807 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindowGTK
*win
)
1812 wxapp_install_idle_handler();
1814 if (!win
->m_hasVMT
) return FALSE
;
1815 if (g_blockEventsOnDrag
) return FALSE
;
1817 // VZ: this is really weird but GTK+ seems to call us from inside
1818 // gtk_widget_grab_focus(), i.e. it first sends "focus_out" signal to
1819 // this widget and then "focus_in". This is totally unexpected and
1820 // completely breaks wxUniv code so ignore this dummy event (we can't
1821 // be losing focus if we're about to acquire it!)
1822 if ( widget
== gs_widgetLastFocus
)
1824 gs_widgetLastFocus
= NULL
;
1829 if ( !g_activeFrameLostFocus
&& g_activeFrame
)
1831 // VZ: commenting this out because it does happen (although not easy
1832 // to reproduce, I only see it when using wxMiniFrame and not
1833 // always) and makes using Mahogany quite annoying
1835 wxASSERT_MSG( wxGetTopLevelParent(win
) == g_activeFrame
,
1836 wxT("unfocusing window that hasn't gained focus properly") )
1839 g_activeFrameLostFocus
= TRUE
;
1842 // if the focus goes out of our app alltogether, OnIdle() will send
1843 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1844 // g_sendActivateEvent to -1
1845 g_sendActivateEvent
= 0;
1847 wxWindowGTK
*winFocus
= wxFindFocusedChild(win
);
1851 g_focusWindow
= (wxWindowGTK
*)NULL
;
1854 wxPrintf( "OnKillFocus from " );
1855 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
1856 wxPrintf( win
->GetClassInfo()->GetClassName() );
1866 // caret needs to be informed about focus change
1867 wxCaret
*caret
= win
->GetCaret();
1870 caret
->OnKillFocus();
1872 #endif // wxUSE_CARET
1874 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1875 event
.SetEventObject( win
);
1877 if (win
->GetEventHandler()->ProcessEvent( event
))
1879 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1886 //-----------------------------------------------------------------------------
1887 // "enter_notify_event"
1888 //-----------------------------------------------------------------------------
1890 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1895 wxapp_install_idle_handler();
1897 if (!win
->m_hasVMT
) return FALSE
;
1898 if (g_blockEventsOnDrag
) return FALSE
;
1900 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1902 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1903 event
.SetTimestamp( gdk_event
->time
);
1904 event
.SetEventObject( win
);
1908 GdkModifierType state
= (GdkModifierType
)0;
1910 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1912 InitMouseEvent(event
, gdk_event
);
1917 if (win
->GetEventHandler()->ProcessEvent( event
))
1919 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1926 //-----------------------------------------------------------------------------
1927 // "leave_notify_event"
1928 //-----------------------------------------------------------------------------
1930 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1935 wxapp_install_idle_handler();
1937 if (!win
->m_hasVMT
) return FALSE
;
1938 if (g_blockEventsOnDrag
) return FALSE
;
1940 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1942 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1943 event
.SetTimestamp( gdk_event
->time
);
1944 event
.SetEventObject( win
);
1948 GdkModifierType state
= (GdkModifierType
)0;
1950 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1952 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1953 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1954 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1955 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1956 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1957 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1958 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1963 if (win
->GetEventHandler()->ProcessEvent( event
))
1965 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1972 //-----------------------------------------------------------------------------
1973 // "value_changed" from m_vAdjust
1974 //-----------------------------------------------------------------------------
1976 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1981 wxapp_install_idle_handler();
1983 if (g_blockEventsOnDrag
) return;
1985 if (!win
->m_hasVMT
) return;
1987 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1988 if (fabs(diff
) < 0.2) return;
1990 win
->m_oldVerticalPos
= adjust
->value
;
1992 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1993 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1995 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1996 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1997 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1998 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1999 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
2001 int value
= (int)(adjust
->value
+0.5);
2003 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
2004 event
.SetEventObject( win
);
2005 win
->GetEventHandler()->ProcessEvent( event
);
2008 //-----------------------------------------------------------------------------
2009 // "value_changed" from m_hAdjust
2010 //-----------------------------------------------------------------------------
2012 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
2017 wxapp_install_idle_handler();
2019 if (g_blockEventsOnDrag
) return;
2020 if (!win
->m_hasVMT
) return;
2022 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
2023 if (fabs(diff
) < 0.2) return;
2025 win
->m_oldHorizontalPos
= adjust
->value
;
2027 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
2028 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
2030 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
2031 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
2032 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
2033 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
2034 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
2036 int value
= (int)(adjust
->value
+0.5);
2038 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
2039 event
.SetEventObject( win
);
2040 win
->GetEventHandler()->ProcessEvent( event
);
2043 //-----------------------------------------------------------------------------
2044 // "button_press_event" from scrollbar
2045 //-----------------------------------------------------------------------------
2047 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
2048 GdkEventButton
*gdk_event
,
2054 wxapp_install_idle_handler();
2057 g_blockEventsOnScroll
= TRUE
;
2058 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
2063 //-----------------------------------------------------------------------------
2064 // "button_release_event" from scrollbar
2065 //-----------------------------------------------------------------------------
2067 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
2068 GdkEventButton
*WXUNUSED(gdk_event
),
2073 // don't test here as we can release the mouse while being over
2074 // a different window than the slider
2076 // if (gdk_event->window != widget->slider) return FALSE;
2078 g_blockEventsOnScroll
= FALSE
;
2080 if (win
->m_isScrolling
)
2082 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
2086 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
2087 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
2089 value
= (int)(win
->m_hAdjust
->value
+0.5);
2092 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
2094 value
= (int)(win
->m_vAdjust
->value
+0.5);
2098 wxScrollWinEvent
event( command
, value
, dir
);
2099 event
.SetEventObject( win
);
2100 win
->GetEventHandler()->ProcessEvent( event
);
2103 win
->m_isScrolling
= FALSE
;
2108 // ----------------------------------------------------------------------------
2109 // this wxWindowBase function is implemented here (in platform-specific file)
2110 // because it is static and so couldn't be made virtual
2111 // ----------------------------------------------------------------------------
2113 wxWindow
*wxWindowBase::FindFocus()
2115 // the cast is necessary when we compile in wxUniversal mode
2116 return (wxWindow
*)g_focusWindow
;
2119 //-----------------------------------------------------------------------------
2120 // "realize" from m_widget
2121 //-----------------------------------------------------------------------------
2123 /* We cannot set colours and fonts before the widget has
2124 been realized, so we do this directly after realization. */
2127 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
2132 wxapp_install_idle_handler();
2134 if (win
->m_delayedBackgroundColour
)
2135 win
->SetBackgroundColour( win
->GetBackgroundColour() );
2137 if (win
->m_delayedForegroundColour
)
2138 win
->SetForegroundColour( win
->GetForegroundColour() );
2140 wxWindowCreateEvent
event( win
);
2141 event
.SetEventObject( win
);
2142 win
->GetEventHandler()->ProcessEvent( event
);
2147 //-----------------------------------------------------------------------------
2149 //-----------------------------------------------------------------------------
2152 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
2153 GtkAllocation
*WXUNUSED(alloc
),
2157 wxapp_install_idle_handler();
2159 if (!win
->m_hasScrolling
) return;
2161 int client_width
= 0;
2162 int client_height
= 0;
2163 win
->GetClientSize( &client_width
, &client_height
);
2164 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
2167 win
->m_oldClientWidth
= client_width
;
2168 win
->m_oldClientHeight
= client_height
;
2170 if (!win
->m_nativeSizeEvent
)
2172 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
2173 event
.SetEventObject( win
);
2174 win
->GetEventHandler()->ProcessEvent( event
);
2180 #define WXUNUSED_UNLESS_XIM(param) param
2182 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2185 /* Resize XIM window */
2188 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2189 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
2190 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2193 wxapp_install_idle_handler();
2199 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
2203 gdk_window_get_size (widget
->window
, &width
, &height
);
2204 win
->m_icattr
->preedit_area
.width
= width
;
2205 win
->m_icattr
->preedit_area
.height
= height
;
2206 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2211 //-----------------------------------------------------------------------------
2212 // "realize" from m_wxwindow
2213 //-----------------------------------------------------------------------------
2215 /* Initialize XIM support */
2218 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2219 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2222 wxapp_install_idle_handler();
2225 if (win
->m_ic
) return FALSE
;
2226 if (!widget
) return FALSE
;
2227 if (!gdk_im_ready()) return FALSE
;
2229 win
->m_icattr
= gdk_ic_attr_new();
2230 if (!win
->m_icattr
) return FALSE
;
2234 GdkColormap
*colormap
;
2235 GdkICAttr
*attr
= win
->m_icattr
;
2236 unsigned attrmask
= GDK_IC_ALL_REQ
;
2238 GdkIMStyle supported_style
= (GdkIMStyle
)
2239 (GDK_IM_PREEDIT_NONE
|
2240 GDK_IM_PREEDIT_NOTHING
|
2241 GDK_IM_PREEDIT_POSITION
|
2242 GDK_IM_STATUS_NONE
|
2243 GDK_IM_STATUS_NOTHING
);
2245 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2246 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2248 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2249 attr
->client_window
= widget
->window
;
2251 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2252 gtk_widget_get_default_colormap ())
2254 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2255 attr
->preedit_colormap
= colormap
;
2258 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2259 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2260 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2261 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2263 switch (style
& GDK_IM_PREEDIT_MASK
)
2265 case GDK_IM_PREEDIT_POSITION
:
2266 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2268 g_warning ("over-the-spot style requires fontset");
2272 gdk_window_get_size (widget
->window
, &width
, &height
);
2274 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2275 attr
->spot_location
.x
= 0;
2276 attr
->spot_location
.y
= height
;
2277 attr
->preedit_area
.x
= 0;
2278 attr
->preedit_area
.y
= 0;
2279 attr
->preedit_area
.width
= width
;
2280 attr
->preedit_area
.height
= height
;
2281 attr
->preedit_fontset
= widget
->style
->font
;
2286 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2288 if (win
->m_ic
== NULL
)
2289 g_warning ("Can't create input context.");
2292 mask
= gdk_window_get_events (widget
->window
);
2293 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2294 gdk_window_set_events (widget
->window
, mask
);
2296 if (GTK_WIDGET_HAS_FOCUS(widget
))
2297 gdk_im_begin (win
->m_ic
, widget
->window
);
2304 //-----------------------------------------------------------------------------
2305 // InsertChild for wxWindowGTK.
2306 //-----------------------------------------------------------------------------
2308 /* Callback for wxWindowGTK. This very strange beast has to be used because
2309 * C++ has no virtual methods in a constructor. We have to emulate a
2310 * virtual function here as wxNotebook requires a different way to insert
2311 * a child in it. I had opted for creating a wxNotebookPage window class
2312 * which would have made this superfluous (such in the MDI window system),
2313 * but no-one was listening to me... */
2315 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child
)
2317 /* the window might have been scrolled already, do we
2318 have to adapt the position */
2319 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2320 child
->m_x
+= pizza
->xoffset
;
2321 child
->m_y
+= pizza
->yoffset
;
2323 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2324 GTK_WIDGET(child
->m_widget
),
2331 //-----------------------------------------------------------------------------
2333 //-----------------------------------------------------------------------------
2335 wxWindow
*wxGetActiveWindow()
2337 // the cast is necessary when we compile in wxUniversal mode
2338 return (wxWindow
*)g_focusWindow
;
2341 //-----------------------------------------------------------------------------
2343 //-----------------------------------------------------------------------------
2345 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
2347 #ifdef __WXUNIVERSAL__
2348 IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
)
2350 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2351 #endif // __WXUNIVERSAL__/__WXGTK__
2353 void wxWindowGTK::Init()
2359 m_widget
= (GtkWidget
*) NULL
;
2360 m_wxwindow
= (GtkWidget
*) NULL
;
2361 m_focusWidget
= (GtkWidget
*) NULL
;
2371 m_needParent
= TRUE
;
2372 m_isBeingDeleted
= FALSE
;
2375 m_nativeSizeEvent
= FALSE
;
2377 m_hasScrolling
= FALSE
;
2378 m_isScrolling
= FALSE
;
2380 m_hAdjust
= (GtkAdjustment
*) NULL
;
2381 m_vAdjust
= (GtkAdjustment
*) NULL
;
2382 m_oldHorizontalPos
= 0.0;
2383 m_oldVerticalPos
= 0.0;
2386 m_widgetStyle
= (GtkStyle
*) NULL
;
2388 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2390 m_isStaticBox
= FALSE
;
2391 m_isRadioButton
= FALSE
;
2392 m_isListBox
= FALSE
;
2394 m_acceptsFocus
= FALSE
;
2396 m_clipPaintRegion
= FALSE
;
2398 m_cursor
= *wxSTANDARD_CURSOR
;
2400 m_delayedForegroundColour
= FALSE
;
2401 m_delayedBackgroundColour
= FALSE
;
2404 m_ic
= (GdkIC
*) NULL
;
2405 m_icattr
= (GdkICAttr
*) NULL
;
2409 wxWindowGTK::wxWindowGTK()
2414 wxWindowGTK::wxWindowGTK( wxWindow
*parent
,
2419 const wxString
&name
)
2423 Create( parent
, id
, pos
, size
, style
, name
);
2426 bool wxWindowGTK::Create( wxWindow
*parent
,
2431 const wxString
&name
)
2433 if (!PreCreation( parent
, pos
, size
) ||
2434 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2436 wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
2440 m_insertCallback
= wxInsertChildInWindow
;
2442 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2443 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2445 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2447 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2448 scroll_class
->scrollbar_spacing
= 0;
2450 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2452 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2453 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2455 m_wxwindow
= gtk_pizza_new();
2457 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2459 #ifndef __WXUNIVERSAL__
2460 #if (GTK_MINOR_VERSION > 0)
2461 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2463 if (HasFlag(wxRAISED_BORDER
))
2465 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2467 else if (HasFlag(wxSUNKEN_BORDER
))
2469 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2471 else if (HasFlag(wxSIMPLE_BORDER
))
2473 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2477 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2479 #else // GTK_MINOR_VERSION == 0
2480 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2482 if (HasFlag(wxRAISED_BORDER
))
2484 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2486 else if (HasFlag(wxSUNKEN_BORDER
))
2488 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2492 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2494 #endif // GTK_MINOR_VERSION
2495 #endif // __WXUNIVERSAL__
2497 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2498 m_acceptsFocus
= TRUE
;
2500 #if (GTK_MINOR_VERSION == 0)
2501 // shut the viewport up
2502 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2503 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2504 #endif // GTK_MINOR_VERSION == 0
2506 // I _really_ don't want scrollbars in the beginning
2507 m_vAdjust
->lower
= 0.0;
2508 m_vAdjust
->upper
= 1.0;
2509 m_vAdjust
->value
= 0.0;
2510 m_vAdjust
->step_increment
= 1.0;
2511 m_vAdjust
->page_increment
= 1.0;
2512 m_vAdjust
->page_size
= 5.0;
2513 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2514 m_hAdjust
->lower
= 0.0;
2515 m_hAdjust
->upper
= 1.0;
2516 m_hAdjust
->value
= 0.0;
2517 m_hAdjust
->step_increment
= 1.0;
2518 m_hAdjust
->page_increment
= 1.0;
2519 m_hAdjust
->page_size
= 5.0;
2520 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2522 // these handlers block mouse events to any window during scrolling such as
2523 // motion events and prevent GTK and wxWindows from fighting over where the
2526 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2527 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2529 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2530 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2532 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2533 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2535 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2536 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2538 // these handlers get notified when screen updates are required either when
2539 // scrolling or when the window size (and therefore scrollbar configuration)
2542 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2543 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2544 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2545 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2547 gtk_widget_show( m_wxwindow
);
2550 m_parent
->DoAddChild( this );
2552 m_focusWidget
= m_wxwindow
;
2561 wxWindowGTK::~wxWindowGTK()
2563 if (g_focusWindow
== this)
2564 g_focusWindow
= NULL
;
2566 if (g_activeFrame
== this)
2567 g_activeFrame
= NULL
;
2569 m_isBeingDeleted
= TRUE
;
2578 m_parent
->RemoveChild( this );
2582 gdk_ic_destroy (m_ic
);
2584 gdk_ic_attr_destroy (m_icattr
);
2589 #if DISABLE_STYLE_IF_BROKEN_THEME
2590 // don't delete if it's a pixmap theme style
2591 if (!m_widgetStyle
->engine_data
)
2592 gtk_style_unref( m_widgetStyle
);
2594 m_widgetStyle
= (GtkStyle
*) NULL
;
2599 gtk_widget_destroy( m_wxwindow
);
2600 m_wxwindow
= (GtkWidget
*) NULL
;
2605 gtk_widget_destroy( m_widget
);
2606 m_widget
= (GtkWidget
*) NULL
;
2610 bool wxWindowGTK::PreCreation( wxWindowGTK
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2612 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2614 /* this turns -1 into 20 so that a minimal window is
2615 visible even although -1,-1 has been given as the
2616 size of the window. the same trick is used in other
2617 ports and should make debugging easier */
2618 m_width
= WidthDefault(size
.x
);
2619 m_height
= HeightDefault(size
.y
);
2624 /* some reasonable defaults */
2629 m_x
= (gdk_screen_width () - m_width
) / 2;
2630 if (m_x
< 10) m_x
= 10;
2634 m_y
= (gdk_screen_height () - m_height
) / 2;
2635 if (m_y
< 10) m_y
= 10;
2642 void wxWindowGTK::PostCreation()
2644 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2650 // these get reported to wxWindows -> wxPaintEvent
2652 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2654 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2655 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2657 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2658 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2660 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2662 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2663 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2667 // these are called when the "sunken" or "raised" borders are drawn */
2668 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2669 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2671 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2672 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2677 if (m_focusWidget
== NULL
)
2678 m_focusWidget
= m_widget
;
2681 if (GetClassInfo() && GetClassInfo()->GetClassName())
2682 wxPrintf( GetClassInfo()->GetClassName() );
2686 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event",
2687 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2689 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event",
2690 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2692 // connect to the various key and mouse handlers
2694 GtkWidget
*connect_widget
= GetConnectWidget();
2696 ConnectWidget( connect_widget
);
2698 /* We cannot set colours, fonts and cursors before the widget has
2699 been realized, so we do this directly after realization */
2700 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2701 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2705 // Catch native resize events
2706 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2707 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2709 // Initialize XIM support
2710 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2711 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2713 // And resize XIM window
2714 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2715 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2718 if (!GTK_IS_COMBO(m_widget
))
2720 // This is needed if we want to add our windows into native
2721 // GTK control, such as the toolbar. With this callback, the
2722 // toolbar gets to know the correct size (the one set by the
2723 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2724 // when moving to GTK 2.0.
2725 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2726 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2732 void wxWindowGTK::ConnectWidget( GtkWidget
*widget
)
2734 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2735 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2737 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2738 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2740 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2741 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2743 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2744 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2746 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2747 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2749 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2750 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2752 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2753 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2756 bool wxWindowGTK::Destroy()
2758 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2762 return wxWindowBase::Destroy();
2765 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
)
2767 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2770 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2772 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2773 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") );
2776 printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
2779 if (m_resizing
) return; /* I don't like recursions */
2782 int currentX
, currentY
;
2783 GetPosition(¤tX
, ¤tY
);
2788 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
2790 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2792 /* don't set the size for children of wxNotebook, just take the values. */
2800 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2802 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2804 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2805 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2806 if (width
!= -1) m_width
= width
;
2807 if (height
!= -1) m_height
= height
;
2811 m_x
= x
+ pizza
->xoffset
;
2812 m_y
= y
+ pizza
->yoffset
;
2817 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2819 if (width
== -1) m_width
= 80;
2822 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2824 if (height
== -1) m_height
= 26;
2827 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2828 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2829 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2830 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2833 int bottom_border
= 0;
2835 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2837 /* the default button has a border around it */
2842 DoMoveWindow( m_x
-border
,
2845 m_height
+border
+bottom_border
);
2850 /* Sometimes the client area changes size without the
2851 whole windows's size changing, but if the whole
2852 windows's size doesn't change, no wxSizeEvent will
2853 normally be sent. Here we add an extra test if
2854 the client test has been changed and this will
2856 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2860 wxPrintf( "OnSize sent from " );
2861 if (GetClassInfo() && GetClassInfo()->GetClassName())
2862 wxPrintf( GetClassInfo()->GetClassName() );
2863 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2866 if (!m_nativeSizeEvent
)
2868 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2869 event
.SetEventObject( this );
2870 GetEventHandler()->ProcessEvent( event
);
2876 void wxWindowGTK::OnInternalIdle()
2878 if ( g_sendActivateEvent
!= -1 )
2880 bool activate
= g_sendActivateEvent
!= 0;
2883 g_sendActivateEvent
= -1;
2885 wxTheApp
->SetActive(activate
, (wxWindow
*)g_focusWindowLast
);
2888 if ( g_activeFrameLostFocus
)
2890 if ( g_activeFrame
)
2892 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame
);
2893 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
2894 event
.SetEventObject(g_activeFrame
);
2895 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
2896 g_activeFrame
= NULL
;
2898 g_activeFrameLostFocus
= FALSE
;
2901 wxCursor cursor
= m_cursor
;
2902 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2906 /* I now set the cursor anew in every OnInternalIdle call
2907 as setting the cursor in a parent window also effects the
2908 windows above so that checking for the current cursor is
2913 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2915 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2917 if (!g_globalCursor
.Ok())
2918 cursor
= *wxSTANDARD_CURSOR
;
2920 window
= m_widget
->window
;
2921 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2922 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2928 GdkWindow
*window
= m_widget
->window
;
2929 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2930 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2938 void wxWindowGTK::DoGetSize( int *width
, int *height
) const
2940 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2942 if (width
) (*width
) = m_width
;
2943 if (height
) (*height
) = m_height
;
2946 void wxWindowGTK::DoSetClientSize( int width
, int height
)
2948 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2952 SetSize( width
, height
);
2959 #ifndef __WXUNIVERSAL__
2960 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2962 /* when using GTK 1.2 we set the shadow border size to 2 */
2966 if (HasFlag(wxSIMPLE_BORDER
))
2968 /* when using GTK 1.2 we set the simple border size to 1 */
2972 #endif // __WXUNIVERSAL__
2976 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2978 GtkRequisition vscroll_req
;
2979 vscroll_req
.width
= 2;
2980 vscroll_req
.height
= 2;
2981 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2982 (scroll_window
->vscrollbar
, &vscroll_req
);
2984 GtkRequisition hscroll_req
;
2985 hscroll_req
.width
= 2;
2986 hscroll_req
.height
= 2;
2987 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2988 (scroll_window
->hscrollbar
, &hscroll_req
);
2990 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2992 if (scroll_window
->vscrollbar_visible
)
2994 dw
+= vscroll_req
.width
;
2995 dw
+= scroll_class
->scrollbar_spacing
;
2998 if (scroll_window
->hscrollbar_visible
)
3000 dh
+= hscroll_req
.height
;
3001 dh
+= scroll_class
->scrollbar_spacing
;
3005 SetSize( width
+dw
, height
+dh
);
3009 void wxWindowGTK::DoGetClientSize( int *width
, int *height
) const
3011 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3015 if (width
) (*width
) = m_width
;
3016 if (height
) (*height
) = m_height
;
3023 #ifndef __WXUNIVERSAL__
3024 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
3026 /* when using GTK 1.2 we set the shadow border size to 2 */
3030 if (HasFlag(wxSIMPLE_BORDER
))
3032 /* when using GTK 1.2 we set the simple border size to 1 */
3036 #endif // __WXUNIVERSAL__
3040 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
3042 GtkRequisition vscroll_req
;
3043 vscroll_req
.width
= 2;
3044 vscroll_req
.height
= 2;
3045 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
3046 (scroll_window
->vscrollbar
, &vscroll_req
);
3048 GtkRequisition hscroll_req
;
3049 hscroll_req
.width
= 2;
3050 hscroll_req
.height
= 2;
3051 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
3052 (scroll_window
->hscrollbar
, &hscroll_req
);
3054 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
3056 if (scroll_window
->vscrollbar_visible
)
3058 dw
+= vscroll_req
.width
;
3059 dw
+= scroll_class
->scrollbar_spacing
;
3062 if (scroll_window
->hscrollbar_visible
)
3064 dh
+= hscroll_req
.height
;
3065 dh
+= scroll_class
->scrollbar_spacing
;
3069 if (width
) (*width
) = m_width
- dw
;
3070 if (height
) (*height
) = m_height
- dh
;
3074 printf( "GetClientSize, name %s ", GetName().c_str() );
3075 if (width) printf( " width = %d", (*width) );
3076 if (height) printf( " height = %d", (*height) );
3081 void wxWindowGTK::DoGetPosition( int *x
, int *y
) const
3083 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3087 if (m_parent
&& m_parent
->m_wxwindow
)
3089 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
3090 dx
= pizza
->xoffset
;
3091 dy
= pizza
->yoffset
;
3094 if (x
) (*x
) = m_x
- dx
;
3095 if (y
) (*y
) = m_y
- dy
;
3098 void wxWindowGTK::DoClientToScreen( int *x
, int *y
) const
3100 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3102 if (!m_widget
->window
) return;
3104 GdkWindow
*source
= (GdkWindow
*) NULL
;
3106 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3108 source
= m_widget
->window
;
3112 gdk_window_get_origin( source
, &org_x
, &org_y
);
3116 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3118 org_x
+= m_widget
->allocation
.x
;
3119 org_y
+= m_widget
->allocation
.y
;
3127 void wxWindowGTK::DoScreenToClient( int *x
, int *y
) const
3129 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3131 if (!m_widget
->window
) return;
3133 GdkWindow
*source
= (GdkWindow
*) NULL
;
3135 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3137 source
= m_widget
->window
;
3141 gdk_window_get_origin( source
, &org_x
, &org_y
);
3145 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3147 org_x
+= m_widget
->allocation
.x
;
3148 org_y
+= m_widget
->allocation
.y
;
3156 bool wxWindowGTK::Show( bool show
)
3158 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3160 if (!wxWindowBase::Show(show
))
3167 gtk_widget_show( m_widget
);
3169 gtk_widget_hide( m_widget
);
3174 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
)
3176 win
->OnParentEnable(enable
);
3178 // Recurse, so that children have the opportunity to Do The Right Thing
3179 // and reset colours that have been messed up by a parent's (really ancestor's)
3181 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
3183 node
= node
->GetNext() )
3185 wxWindow
*child
= node
->GetData();
3186 if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
)))
3187 wxWindowNotifyEnable(child
, enable
);
3191 bool wxWindowGTK::Enable( bool enable
)
3193 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3195 if (!wxWindowBase::Enable(enable
))
3201 gtk_widget_set_sensitive( m_widget
, enable
);
3203 gtk_widget_set_sensitive( m_wxwindow
, enable
);
3205 wxWindowNotifyEnable(this, enable
);
3210 int wxWindowGTK::GetCharHeight() const
3212 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
3214 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
3216 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3218 return font
->ascent
+ font
->descent
;
3221 int wxWindowGTK::GetCharWidth() const
3223 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
3225 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
3227 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3229 return gdk_string_width( font
, "H" );
3232 void wxWindowGTK::GetTextExtent( const wxString
& string
,
3236 int *externalLeading
,
3237 const wxFont
*theFont
) const
3239 wxFont fontToUse
= m_font
;
3240 if (theFont
) fontToUse
= *theFont
;
3242 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
3244 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
3245 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
3246 if (y
) (*y
) = font
->ascent
+ font
->descent
;
3247 if (descent
) (*descent
) = font
->descent
;
3248 if (externalLeading
) (*externalLeading
) = 0; // ??
3251 void wxWindowGTK::SetFocus()
3253 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3257 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3259 // see comment in gtk_window_focus_out_callback()
3260 gs_widgetLastFocus
= m_wxwindow
;
3261 gtk_widget_grab_focus (m_wxwindow
);
3266 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
3268 gtk_widget_grab_focus (m_widget
);
3270 else if (GTK_IS_CONTAINER(m_widget
))
3272 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
3281 bool wxWindowGTK::AcceptsFocus() const
3283 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3286 bool wxWindowGTK::Reparent( wxWindowBase
*newParentBase
)
3288 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3290 wxWindowGTK
*oldParent
= m_parent
,
3291 *newParent
= (wxWindowGTK
*)newParentBase
;
3293 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3295 if ( !wxWindowBase::Reparent(newParent
) )
3298 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3300 /* prevent GTK from deleting the widget arbitrarily */
3301 gtk_widget_ref( m_widget
);
3305 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3308 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3312 /* insert GTK representation */
3313 (*(newParent
->m_insertCallback
))(newParent
, this);
3316 /* reverse: prevent GTK from deleting the widget arbitrarily */
3317 gtk_widget_unref( m_widget
);
3322 void wxWindowGTK::DoAddChild(wxWindowGTK
*child
)
3324 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3326 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3328 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3333 /* insert GTK representation */
3334 (*m_insertCallback
)(this, child
);
3337 void wxWindowGTK::Raise()
3339 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3341 if (!m_widget
->window
) return;
3343 gdk_window_raise( m_widget
->window
);
3346 void wxWindowGTK::Lower()
3348 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3350 if (!m_widget
->window
) return;
3352 gdk_window_lower( m_widget
->window
);
3355 bool wxWindowGTK::SetCursor( const wxCursor
&cursor
)
3357 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3359 if (cursor
== m_cursor
)
3363 wxapp_install_idle_handler();
3365 if (cursor
== wxNullCursor
)
3366 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3368 return wxWindowBase::SetCursor( cursor
);
3371 void wxWindowGTK::WarpPointer( int x
, int y
)
3373 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3375 /* we provide this function ourselves as it is
3376 missing in GDK (top of this file) */
3378 GdkWindow
*window
= (GdkWindow
*) NULL
;
3380 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3382 window
= GetConnectWidget()->window
;
3385 gdk_window_warp_pointer( window
, x
, y
);
3388 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect
*rect
)
3390 if (!m_widget
) return;
3391 if (!m_widget
->window
) return;
3393 // temporarily hide the caret to avoid nasty interactions between caret
3394 // drawing and the window contents redraw
3395 #if 0 // def wxUSE_CARET -- doesn't seem to help :-(
3396 wxCaretSuspend
cs((wxWindow
*)this);
3397 #endif // wxUSE_CARET
3399 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3403 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3405 rect
->width
, rect
->height
);
3409 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3413 /* there is no GTK equivalent of "draw only, don't clear" so we
3414 invent our own in the GtkPizza widget */
3422 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3423 gboolean old_clear = pizza->clear_on_draw;
3424 gtk_pizza_set_clear( pizza, FALSE );
3425 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3426 gtk_pizza_set_clear( pizza, old_clear );
3428 GdkEventExpose gdk_event
;
3429 gdk_event
.type
= GDK_EXPOSE
;
3430 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3431 gdk_event
.count
= 0;
3432 gdk_event
.area
.x
= 0;
3433 gdk_event
.area
.y
= 0;
3434 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3435 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3436 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, (wxWindow
*)this );
3440 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3449 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3450 gboolean old_clear = pizza->clear_on_draw;
3451 gtk_pizza_set_clear( pizza, FALSE );
3453 GdkRectangle gdk_rect;
3454 gdk_rect.x = rect->x;
3455 gdk_rect.y = rect->y;
3456 gdk_rect.width = rect->width;
3457 gdk_rect.height = rect->height;
3458 gtk_widget_draw( m_wxwindow, &gdk_rect );
3459 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3461 gtk_pizza_set_clear( pizza, old_clear );
3463 GdkEventExpose gdk_event
;
3464 gdk_event
.type
= GDK_EXPOSE
;
3465 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3466 gdk_event
.count
= 0;
3467 gdk_event
.area
.x
= rect
->x
;
3468 gdk_event
.area
.y
= rect
->y
;
3469 gdk_event
.area
.width
= rect
->width
;
3470 gdk_event
.area
.height
= rect
->height
;
3471 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, (wxWindow
*)this );
3475 GdkRectangle gdk_rect
;
3476 gdk_rect
.x
= rect
->x
;
3477 gdk_rect
.y
= rect
->y
;
3478 gdk_rect
.width
= rect
->width
;
3479 gdk_rect
.height
= rect
->height
;
3480 gtk_widget_draw( m_widget
, &gdk_rect
);
3485 void wxWindowGTK::Clear()
3487 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3489 if (!m_widget
->window
) return;
3491 if (m_wxwindow
&& m_wxwindow
->window
)
3493 // gdk_window_clear( m_wxwindow->window );
3498 void wxWindowGTK::DoSetToolTip( wxToolTip
*tip
)
3500 wxWindowBase::DoSetToolTip(tip
);
3503 m_tooltip
->Apply( (wxWindow
*)this );
3506 void wxWindowGTK::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3508 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3510 #endif // wxUSE_TOOLTIPS
3512 bool wxWindowGTK::SetBackgroundColour( const wxColour
&colour
)
3514 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3516 if (!wxWindowBase::SetBackgroundColour(colour
))
3518 // don't leave if the GTK widget has just
3520 if (!m_delayedBackgroundColour
) return FALSE
;
3523 GdkWindow
*window
= (GdkWindow
*) NULL
;
3525 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3527 window
= GetConnectWidget()->window
;
3531 // indicate that a new style has been set
3532 // but it couldn't get applied as the
3533 // widget hasn't been realized yet.
3534 m_delayedBackgroundColour
= TRUE
;
3538 (m_wxwindow
->window
) &&
3539 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3541 /* wxMSW doesn't clear the window here. I don't do that either to
3542 provide compatibility. call Clear() to do the job. */
3544 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3545 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3553 bool wxWindowGTK::SetForegroundColour( const wxColour
&colour
)
3555 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3557 if (!wxWindowBase::SetForegroundColour(colour
))
3559 // don't leave if the GTK widget has just
3561 if (!m_delayedForegroundColour
) return FALSE
;
3564 GdkWindow
*window
= (GdkWindow
*) NULL
;
3566 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3568 window
= GetConnectWidget()->window
;
3572 // indicate that a new style has been set
3573 // but it couldn't get applied as the
3574 // widget hasn't been realized yet.
3575 m_delayedForegroundColour
= TRUE
;
3583 GtkStyle
*wxWindowGTK::GetWidgetStyle()
3587 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3589 /* FIXME: is this necessary? */
3590 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3592 remake
->klass
= m_widgetStyle
->klass
;
3595 gtk_style_unref( m_widgetStyle
);
3596 m_widgetStyle
= remake
;
3600 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3603 def
= gtk_widget_get_default_style();
3605 m_widgetStyle
= gtk_style_copy( def
);
3607 /* FIXME: is this necessary? */
3608 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3610 m_widgetStyle
->klass
= def
->klass
;
3614 return m_widgetStyle
;
3617 void wxWindowGTK::SetWidgetStyle()
3619 #if DISABLE_STYLE_IF_BROKEN_THEM
3620 if (m_widget
->style
->engine_data
)
3622 static bool s_warningPrinted
= FALSE
;
3623 if (!s_warningPrinted
)
3625 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3626 s_warningPrinted
= TRUE
;
3628 m_widgetStyle
= m_widget
->style
;
3633 GtkStyle
*style
= GetWidgetStyle();
3635 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3637 gdk_font_unref( style
->font
);
3638 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3641 if (m_foregroundColour
.Ok())
3643 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3644 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3646 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3647 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3648 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3652 // Try to restore the gtk default style. This is still a little
3653 // oversimplified for what is probably really needed here for controls
3654 // other than buttons, but is better than not being able to (re)set a
3655 // control's foreground colour to *wxBLACK -- RL
3656 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3659 def
= gtk_widget_get_default_style();
3661 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3662 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3663 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3667 if (m_backgroundColour
.Ok())
3669 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3670 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3672 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3673 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3674 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3675 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3676 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3677 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3678 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3679 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3683 // Try to restore the gtk default style. This is still a little
3684 // oversimplified for what is probably really needed here for controls
3685 // other than buttons, but is better than not being able to (re)set a
3686 // control's background colour to default grey and means resetting a
3687 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3689 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3692 def
= gtk_widget_get_default_style();
3694 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3695 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3696 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3697 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3698 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3699 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3700 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3701 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3706 void wxWindowGTK::ApplyWidgetStyle()
3710 //-----------------------------------------------------------------------------
3711 // Pop-up menu stuff
3712 //-----------------------------------------------------------------------------
3714 #if wxUSE_MENUS_NATIVE
3716 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3718 *is_waiting
= FALSE
;
3721 static void SetInvokingWindow( wxMenu
*menu
, wxWindowGTK
*win
)
3723 menu
->SetInvokingWindow( win
);
3724 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3727 wxMenuItem
*menuitem
= node
->GetData();
3728 if (menuitem
->IsSubMenu())
3730 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3733 node
= node
->GetNext();
3737 // used to pass the coordinates from wxWindowGTK::DoPopupMenu() to
3738 // wxPopupMenuPositionCallback()
3740 // should be safe even in the MT case as the user can hardly popup 2 menus
3741 // simultaneously, can he?
3742 static gint gs_pop_x
= 0;
3743 static gint gs_pop_y
= 0;
3745 static void wxPopupMenuPositionCallback( GtkMenu
*menu
,
3747 gpointer
WXUNUSED(user_data
) )
3749 // ensure that the menu appears entirely on screen
3751 gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
);
3753 wxSize sizeScreen
= wxGetDisplaySize();
3755 gint xmax
= sizeScreen
.x
- req
.width
,
3756 ymax
= sizeScreen
.y
- req
.height
;
3758 *x
= gs_pop_x
< xmax
? gs_pop_x
: xmax
;
3759 *y
= gs_pop_y
< ymax
? gs_pop_y
: ymax
;
3762 bool wxWindowGTK::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3764 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3766 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3768 SetInvokingWindow( menu
, this );
3774 ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3776 bool is_waiting
= TRUE
;
3778 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3779 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3782 GTK_MENU(menu
->m_menu
),
3783 (GtkWidget
*) NULL
, // parent menu shell
3784 (GtkWidget
*) NULL
, // parent menu item
3785 wxPopupMenuPositionCallback
, // function to position it
3786 NULL
, // client data
3787 0, // button used to activate it
3788 gs_timeLastClick
// the time of activation
3793 while (gtk_events_pending())
3794 gtk_main_iteration();
3800 #endif // wxUSE_MENUS_NATIVE
3802 #if wxUSE_DRAG_AND_DROP
3804 void wxWindowGTK::SetDropTarget( wxDropTarget
*dropTarget
)
3806 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3808 GtkWidget
*dnd_widget
= GetConnectWidget();
3810 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3812 if (m_dropTarget
) delete m_dropTarget
;
3813 m_dropTarget
= dropTarget
;
3815 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3818 #endif // wxUSE_DRAG_AND_DROP
3820 GtkWidget
* wxWindowGTK::GetConnectWidget()
3822 GtkWidget
*connect_widget
= m_widget
;
3823 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3825 return connect_widget
;
3828 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow
*window
)
3831 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3833 return (window
== m_widget
->window
);
3836 bool wxWindowGTK::SetFont( const wxFont
&font
)
3838 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3840 if (!wxWindowBase::SetFont(font
))
3845 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3846 if ( sysbg
== m_backgroundColour
)
3848 m_backgroundColour
= wxNullColour
;
3850 m_backgroundColour
= sysbg
;
3860 void wxWindowGTK::CaptureMouse()
3862 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3864 GdkWindow
*window
= (GdkWindow
*) NULL
;
3866 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3868 window
= GetConnectWidget()->window
;
3870 wxCHECK_RET( window
, _T("CaptureMouse() failed") );
3872 wxCursor
* cursor
= & m_cursor
;
3874 cursor
= wxSTANDARD_CURSOR
;
3876 gdk_pointer_grab( window
, FALSE
,
3878 (GDK_BUTTON_PRESS_MASK
|
3879 GDK_BUTTON_RELEASE_MASK
|
3880 GDK_POINTER_MOTION_HINT_MASK
|
3881 GDK_POINTER_MOTION_MASK
),
3883 cursor
->GetCursor(),
3884 (guint32
)GDK_CURRENT_TIME
);
3885 g_captureWindow
= this;
3886 g_captureWindowHasMouse
= TRUE
;
3889 void wxWindowGTK::ReleaseMouse()
3891 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3893 wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") );
3895 GdkWindow
*window
= (GdkWindow
*) NULL
;
3897 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3899 window
= GetConnectWidget()->window
;
3904 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3905 g_captureWindow
= (wxWindowGTK
*) NULL
;
3909 wxWindow
*wxWindowBase::GetCapture()
3911 return (wxWindow
*)g_captureWindow
;
3914 bool wxWindowGTK::IsRetained() const
3919 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3920 int range
, bool refresh
)
3922 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3924 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3926 m_hasScrolling
= TRUE
;
3928 if (orient
== wxHORIZONTAL
)
3930 float fpos
= (float)pos
;
3931 float frange
= (float)range
;
3932 float fthumb
= (float)thumbVisible
;
3933 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3934 if (fpos
< 0.0) fpos
= 0.0;
3936 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3937 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3939 SetScrollPos( orient
, pos
, refresh
);
3943 m_oldHorizontalPos
= fpos
;
3945 m_hAdjust
->lower
= 0.0;
3946 m_hAdjust
->upper
= frange
;
3947 m_hAdjust
->value
= fpos
;
3948 m_hAdjust
->step_increment
= 1.0;
3949 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3950 m_hAdjust
->page_size
= fthumb
;
3954 float fpos
= (float)pos
;
3955 float frange
= (float)range
;
3956 float fthumb
= (float)thumbVisible
;
3957 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3958 if (fpos
< 0.0) fpos
= 0.0;
3960 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3961 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3963 SetScrollPos( orient
, pos
, refresh
);
3967 m_oldVerticalPos
= fpos
;
3969 m_vAdjust
->lower
= 0.0;
3970 m_vAdjust
->upper
= frange
;
3971 m_vAdjust
->value
= fpos
;
3972 m_vAdjust
->step_increment
= 1.0;
3973 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3974 m_vAdjust
->page_size
= fthumb
;
3977 if (orient
== wxHORIZONTAL
)
3978 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3980 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3983 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3985 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3987 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3989 if (orient
== wxHORIZONTAL
)
3991 float fpos
= (float)pos
;
3992 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3993 if (fpos
< 0.0) fpos
= 0.0;
3994 m_oldHorizontalPos
= fpos
;
3996 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3997 m_hAdjust
->value
= fpos
;
4001 float fpos
= (float)pos
;
4002 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
4003 if (fpos
< 0.0) fpos
= 0.0;
4004 m_oldVerticalPos
= fpos
;
4006 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
4007 m_vAdjust
->value
= fpos
;
4010 if (m_wxwindow
->window
)
4012 if (orient
== wxHORIZONTAL
)
4014 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
4015 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
4017 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
4019 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
4020 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
4024 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
4025 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4027 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
4029 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
4030 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4035 int wxWindowGTK::GetScrollThumb( int orient
) const
4037 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4039 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4041 if (orient
== wxHORIZONTAL
)
4042 return (int)(m_hAdjust
->page_size
+0.5);
4044 return (int)(m_vAdjust
->page_size
+0.5);
4047 int wxWindowGTK::GetScrollPos( int orient
) const
4049 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4051 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4053 if (orient
== wxHORIZONTAL
)
4054 return (int)(m_hAdjust
->value
+0.5);
4056 return (int)(m_vAdjust
->value
+0.5);
4059 int wxWindowGTK::GetScrollRange( int orient
) const
4061 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4063 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4065 if (orient
== wxHORIZONTAL
)
4066 return (int)(m_hAdjust
->upper
+0.5);
4068 return (int)(m_vAdjust
->upper
+0.5);
4071 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
4073 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4075 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4077 if ((dx
== 0) && (dy
== 0)) return;
4079 m_clipPaintRegion
= TRUE
;
4080 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
4081 m_clipPaintRegion
= FALSE
;
4084 if (m_children.GetCount() > 0)
4086 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
4090 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
4092 pizza->xoffset -= dx;
4093 pizza->yoffset -= dy;
4095 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
4096 gdk_gc_set_exposures( m_scrollGC, TRUE );
4100 GetClientSize( &cw, &ch );
4101 int w = cw - abs(dx);
4102 int h = ch - abs(dy);
4104 if ((h < 0) || (w < 0))
4112 if (dx < 0) s_x = -dx;
4113 if (dy < 0) s_y = -dy;
4116 if (dx > 0) d_x = dx;
4117 if (dy > 0) d_y = dy;
4119 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
4120 pizza->bin_window, s_x, s_y, w, h );
4123 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
4124 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
4125 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
4126 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
4128 Refresh( TRUE, &rect );
4131 gdk_gc_unref( m_scrollGC );
4136 // Find the wxWindow at the current mouse position, also returning the mouse
4138 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
4140 pt
= wxGetMousePosition();
4141 wxWindow
* found
= wxFindWindowAtPoint(pt
);
4145 // Get the current mouse position.
4146 wxPoint
wxGetMousePosition()
4148 /* This crashes when used within wxHelpContext,
4149 so we have to use the X-specific implementation below.
4151 GdkModifierType *mask;
4152 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
4154 return wxPoint(x, y);
4158 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
4160 return wxPoint(-999, -999);
4162 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
4163 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
4164 Window rootReturn
, childReturn
;
4165 int rootX
, rootY
, winX
, winY
;
4166 unsigned int maskReturn
;
4168 XQueryPointer (display
,
4172 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
4173 return wxPoint(rootX
, rootY
);