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 // if we detect that the app has got/lost the focus, we set this variable to
220 // either TRUE or FALSE and an activate event will be sent during the next
221 // OnIdle() call and it is reset to -1: this value means that we shouldn't
222 // send any activate events at all
223 static int g_sendActivateEvent
= -1;
225 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
226 the last click here */
227 static guint32 gs_timeLastClick
= 0;
229 extern bool g_mainThreadLocked
;
231 //-----------------------------------------------------------------------------
233 //-----------------------------------------------------------------------------
236 #define DISABLE_STYLE_IF_BROKEN_THEME 1
242 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
244 # define DEBUG_MAIN_THREAD
247 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
248 GdkEvent
*WXUNUSED(event
),
249 const wxChar
*WXUNUSED(name
) )
252 static bool s_done = FALSE;
255 wxLog::AddTraceMask("focus");
258 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
264 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
266 // suppress warnings about gtk_debug_focus_in_callback being unused with
271 tmp
+= wxT(" FROM ");
274 wxChar
*s
= new wxChar
[tmp
.Length()+1];
278 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
279 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
284 #define DEBUG_MAIN_THREAD
287 //-----------------------------------------------------------------------------
288 // missing gdk functions
289 //-----------------------------------------------------------------------------
292 gdk_window_warp_pointer (GdkWindow
*window
,
297 GdkWindowPrivate
*priv
;
301 window
= GDK_ROOT_PARENT();
304 if (!GDK_WINDOW_DESTROYED(window
))
306 XWarpPointer (GDK_WINDOW_XDISPLAY(window
),
307 None
, /* not source window -> move from anywhere */
308 GDK_WINDOW_XID(window
), /* dest window */
309 0, 0, 0, 0, /* not source window -> move from anywhere */
313 priv
= (GdkWindowPrivate
*) window
;
315 if (!priv
->destroyed
)
317 XWarpPointer (priv
->xdisplay
,
318 None
, /* not source window -> move from anywhere */
319 priv
->xwindow
, /* dest window */
320 0, 0, 0, 0, /* not source window -> move from anywhere */
326 //-----------------------------------------------------------------------------
328 //-----------------------------------------------------------------------------
330 extern void wxapp_install_idle_handler();
331 extern bool g_isIdle
;
333 //-----------------------------------------------------------------------------
334 // local code (see below)
335 //-----------------------------------------------------------------------------
337 // returns the child of win which currently has focus or NULL if not found
339 // Note: can't be static, needed by textctrl.cpp.
340 wxWindow
*wxFindFocusedChild(wxWindowGTK
*win
)
342 wxWindow
*winFocus
= wxWindowGTK::FindFocus();
344 return (wxWindow
*)NULL
;
346 if ( winFocus
== win
)
347 return (wxWindow
*)win
;
349 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
351 node
= node
->GetNext() )
353 wxWindow
*child
= wxFindFocusedChild(node
->GetData());
358 return (wxWindow
*)NULL
;
361 static void draw_frame( GtkWidget
*widget
, wxWindowGTK
*win
)
363 // wxUniversal widgets draw the borders and scrollbars themselves
364 #ifndef __WXUNIVERSAL__
371 if (win
->m_hasScrolling
)
373 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
375 GtkRequisition vscroll_req
;
376 vscroll_req
.width
= 2;
377 vscroll_req
.height
= 2;
378 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
379 (scroll_window
->vscrollbar
, &vscroll_req
);
381 GtkRequisition hscroll_req
;
382 hscroll_req
.width
= 2;
383 hscroll_req
.height
= 2;
384 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
385 (scroll_window
->hscrollbar
, &hscroll_req
);
387 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) );
389 if (scroll_window
->vscrollbar_visible
)
391 dw
+= vscroll_req
.width
;
392 dw
+= scroll_class
->scrollbar_spacing
;
395 if (scroll_window
->hscrollbar_visible
)
397 dh
+= hscroll_req
.height
;
398 dh
+= scroll_class
->scrollbar_spacing
;
404 if (GTK_WIDGET_NO_WINDOW (widget
))
406 dx
+= widget
->allocation
.x
;
407 dy
+= widget
->allocation
.y
;
410 if (win
->HasFlag(wxRAISED_BORDER
))
412 gtk_draw_shadow( widget
->style
,
417 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
421 if (win
->HasFlag(wxSUNKEN_BORDER
))
423 gtk_draw_shadow( widget
->style
,
428 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
432 if (win
->HasFlag(wxSIMPLE_BORDER
))
435 gc
= gdk_gc_new( widget
->window
);
436 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
437 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
439 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
443 #endif // __WXUNIVERSAL__
446 //-----------------------------------------------------------------------------
447 // "expose_event" of m_widget
448 //-----------------------------------------------------------------------------
450 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindowGTK
*win
)
452 if (gdk_event
->count
> 0) return FALSE
;
454 draw_frame( widget
, win
);
459 //-----------------------------------------------------------------------------
460 // "draw" of m_widget
461 //-----------------------------------------------------------------------------
463 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindowGTK
*win
)
465 draw_frame( widget
, win
);
468 //-----------------------------------------------------------------------------
469 // key code mapping routines
470 //-----------------------------------------------------------------------------
472 static long map_to_unmodified_wx_keysym( GdkEventKey
*event
)
474 KeySym keysym
= event
->keyval
;
480 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
482 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
488 case GDK_Super_R
: key_code
= WXK_ALT
; break;
489 case GDK_Menu
: key_code
= WXK_MENU
; break;
490 case GDK_Help
: key_code
= WXK_HELP
; break;
491 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
492 case GDK_ISO_Left_Tab
:
493 case GDK_Tab
: key_code
= WXK_TAB
; break;
494 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
495 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
496 case GDK_Return
: key_code
= WXK_RETURN
; break;
497 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
498 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
499 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
500 case GDK_Delete
: key_code
= WXK_DELETE
; break;
501 case GDK_Home
: key_code
= WXK_HOME
; break;
502 case GDK_Left
: key_code
= WXK_LEFT
; break;
503 case GDK_Up
: key_code
= WXK_UP
; break;
504 case GDK_Right
: key_code
= WXK_RIGHT
; break;
505 case GDK_Down
: key_code
= WXK_DOWN
; break;
506 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
507 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
508 case GDK_Next
: key_code
= WXK_NEXT
; break;
509 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
510 case GDK_End
: key_code
= WXK_END
; break;
511 case GDK_Begin
: key_code
= WXK_HOME
; break;
512 case GDK_Select
: key_code
= WXK_SELECT
; break;
513 case GDK_Print
: key_code
= WXK_PRINT
; break;
514 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
515 case GDK_Insert
: key_code
= WXK_INSERT
; break;
516 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
518 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
519 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
520 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
521 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
522 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
523 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
524 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
525 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
526 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
527 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
528 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
529 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
530 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
531 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
532 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
533 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
534 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
535 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
536 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
537 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
538 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
539 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
540 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
541 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
542 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
543 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
544 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
545 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
546 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
547 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
548 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
549 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
550 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
551 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
552 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
553 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
554 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
556 case GDK_F1
: key_code
= WXK_F1
; break;
557 case GDK_F2
: key_code
= WXK_F2
; break;
558 case GDK_F3
: key_code
= WXK_F3
; break;
559 case GDK_F4
: key_code
= WXK_F4
; break;
560 case GDK_F5
: key_code
= WXK_F5
; break;
561 case GDK_F6
: key_code
= WXK_F6
; break;
562 case GDK_F7
: key_code
= WXK_F7
; break;
563 case GDK_F8
: key_code
= WXK_F8
; break;
564 case GDK_F9
: key_code
= WXK_F9
; break;
565 case GDK_F10
: key_code
= WXK_F10
; break;
566 case GDK_F11
: key_code
= WXK_F11
; break;
567 case GDK_F12
: key_code
= WXK_F12
; break;
570 if (event
->length
== 1)
572 key_code
= toupper( (unsigned char)*event
->string
);
574 else if ((keysym
& 0xFF) == keysym
)
576 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
577 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
578 key_code
= (guint
)keysym
;
586 static long map_to_wx_keysym( GdkEventKey
*event
)
588 KeySym keysym
= event
->keyval
;
593 case GDK_Menu
: key_code
= WXK_MENU
; break;
594 case GDK_Help
: key_code
= WXK_HELP
; break;
595 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
596 case GDK_ISO_Left_Tab
:
597 case GDK_Tab
: key_code
= WXK_TAB
; break;
598 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
599 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
600 case GDK_Return
: key_code
= WXK_RETURN
; break;
601 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
602 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
603 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
604 case GDK_Delete
: key_code
= WXK_DELETE
; break;
605 case GDK_Home
: key_code
= WXK_HOME
; break;
606 case GDK_Left
: key_code
= WXK_LEFT
; break;
607 case GDK_Up
: key_code
= WXK_UP
; break;
608 case GDK_Right
: key_code
= WXK_RIGHT
; break;
609 case GDK_Down
: key_code
= WXK_DOWN
; break;
610 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
611 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
612 case GDK_Next
: key_code
= WXK_NEXT
; break;
613 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
614 case GDK_End
: key_code
= WXK_END
; break;
615 case GDK_Begin
: key_code
= WXK_HOME
; break;
616 case GDK_Select
: key_code
= WXK_SELECT
; break;
617 case GDK_Print
: key_code
= WXK_PRINT
; break;
618 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
619 case GDK_Insert
: key_code
= WXK_INSERT
; break;
620 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
622 case GDK_KP_0
: key_code
= '0'; break;
623 case GDK_KP_1
: key_code
= '1'; break;
624 case GDK_KP_2
: key_code
= '2'; break;
625 case GDK_KP_3
: key_code
= '3'; break;
626 case GDK_KP_4
: key_code
= '4'; break;
627 case GDK_KP_5
: key_code
= '5'; break;
628 case GDK_KP_6
: key_code
= '6'; break;
629 case GDK_KP_7
: key_code
= '7'; break;
630 case GDK_KP_8
: key_code
= '8'; break;
631 case GDK_KP_9
: key_code
= '9'; break;
632 case GDK_KP_Space
: key_code
= ' '; break;
633 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
634 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
635 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
636 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
637 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
638 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
639 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
640 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
641 case GDK_KP_Up
: key_code
= WXK_UP
; break;
642 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
643 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
644 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
645 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
646 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
647 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
648 case GDK_KP_End
: key_code
= WXK_END
; break;
649 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
650 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
651 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
652 case GDK_KP_Equal
: key_code
= '='; break;
653 case GDK_KP_Multiply
: key_code
= '*'; break;
654 case GDK_KP_Add
: key_code
= '+'; break;
655 case GDK_KP_Separator
: key_code
= ','; break;
656 case GDK_KP_Subtract
: key_code
= '-'; break;
657 case GDK_KP_Decimal
: key_code
= '.'; break;
658 case GDK_KP_Divide
: key_code
= '/'; break;
660 case GDK_F1
: key_code
= WXK_F1
; break;
661 case GDK_F2
: key_code
= WXK_F2
; break;
662 case GDK_F3
: key_code
= WXK_F3
; break;
663 case GDK_F4
: key_code
= WXK_F4
; break;
664 case GDK_F5
: key_code
= WXK_F5
; break;
665 case GDK_F6
: key_code
= WXK_F6
; break;
666 case GDK_F7
: key_code
= WXK_F7
; break;
667 case GDK_F8
: key_code
= WXK_F8
; break;
668 case GDK_F9
: key_code
= WXK_F9
; break;
669 case GDK_F10
: key_code
= WXK_F10
; break;
670 case GDK_F11
: key_code
= WXK_F11
; break;
671 case GDK_F12
: key_code
= WXK_F12
; break;
674 if (event
->length
== 1)
676 key_code
= (unsigned char)*event
->string
;
678 else if ((keysym
& 0xFF) == keysym
)
680 key_code
= (guint
)keysym
;
688 //-----------------------------------------------------------------------------
689 // "size_request" of m_widget
690 //-----------------------------------------------------------------------------
692 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
695 win
->GetSize( &w
, &h
);
699 requisition
->height
= h
;
700 requisition
->width
= w
;
703 //-----------------------------------------------------------------------------
704 // "expose_event" of m_wxwindow
705 //-----------------------------------------------------------------------------
707 static int gtk_window_expose_callback( GtkWidget
*widget
,
708 GdkEventExpose
*gdk_event
,
714 wxapp_install_idle_handler();
717 if (win->GetName() == wxT("panel"))
719 wxPrintf( wxT("OnExpose from ") );
720 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
721 wxPrintf( win->GetClassInfo()->GetClassName() );
722 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
723 (int)gdk_event->area.y,
724 (int)gdk_event->area.width,
725 (int)gdk_event->area.height );
729 GtkPizza
*pizza
= GTK_PIZZA (widget
);
731 if (win
->GetThemeEnabled())
733 wxWindow
*parent
= win
->GetParent();
734 while (parent
&& !parent
->IsTopLevel())
735 parent
= parent
->GetParent();
739 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
740 GTK_SHADOW_NONE
, &gdk_event
->area
, parent
->m_widget
, "base", 0, 0, -1, -1);
743 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
745 gdk_event
->area
.width
,
746 gdk_event
->area
.height
);
748 if (gdk_event
->count
== 0)
750 win
->m_clipPaintRegion
= TRUE
;
753 dc
.SetClippingRegion(win
->GetUpdateRegion());
754 wxEraseEvent
eevent( win
->GetId(), &dc
);
755 eevent
.SetEventObject( win
);
757 (void)win
->GetEventHandler()->ProcessEvent(eevent
);
759 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
761 wxClientDC
dc( win
);
762 dc
.SetBrush( wxBrush( win
->GetBackgroundColour(), wxSOLID
) );
763 dc
.SetPen( *wxTRANSPARENT_PEN
);
765 wxRegionIterator
upd( win
->GetUpdateRegion() );
768 dc
.DrawRectangle( upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
774 wxNcPaintEvent
eventNc( win
->GetId() );
775 eventNc
.SetEventObject( win
);
776 win
->GetEventHandler()->ProcessEvent( eventNc
);
778 wxPaintEvent
event( win
->GetId() );
779 event
.SetEventObject( win
);
780 win
->GetEventHandler()->ProcessEvent( event
);
782 win
->GetUpdateRegion().Clear();
784 win
->m_clipPaintRegion
= FALSE
;
787 /* The following code will result in all window-less widgets
788 being redrawn if the wxWindows class is given a chance to
789 paint *anything* because it will then be allowed to paint
790 over the window-less widgets */
791 GList
*children
= pizza
->children
;
794 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
795 children
= children
->next
;
797 GdkEventExpose child_event
= *gdk_event
;
799 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
800 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
801 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
803 child_event
.area
.x
= child
->widget
->allocation
.x
;
804 child_event
.area
.y
= child
->widget
->allocation
.y
;
805 child_event
.area
.width
= child
->widget
->allocation
.width
;
806 child_event
.area
.height
= child
->widget
->allocation
.height
;
807 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
814 //-----------------------------------------------------------------------------
815 // "event" of m_wxwindow
816 //-----------------------------------------------------------------------------
818 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
819 expose events. We need them, of course, so we override the main event
820 procedure in GtkWidget by giving our own handler for all system events.
821 There, we look for expose events ourselves whereas all other events are
824 gint
gtk_window_event_event_callback( GtkWidget
*widget
,
825 GdkEventExpose
*event
,
828 if (event
->type
== GDK_EXPOSE
)
830 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
837 //-----------------------------------------------------------------------------
838 // "draw" of m_wxwindow
839 //-----------------------------------------------------------------------------
841 /* This callback is a complete replacement of the gtk_pizza_draw() function,
844 static void gtk_window_draw_callback( GtkWidget
*widget
,
851 wxapp_install_idle_handler();
853 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
854 (win
->GetChildren().GetCount() == 0))
860 if (win->GetName() == wxT("panel"))
862 wxPrintf( wxT("OnDraw from ") );
863 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
864 wxPrintf( win->GetClassInfo()->GetClassName() );
865 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
872 GtkPizza
*pizza
= GTK_PIZZA (widget
);
874 if (win
->GetThemeEnabled())
876 wxWindow
*parent
= win
->GetParent();
877 while (parent
&& !parent
->IsTopLevel())
878 parent
= parent
->GetParent();
882 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
883 GTK_SHADOW_NONE
, rect
, parent
->m_widget
, "base", 0, 0, -1, -1);
887 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
888 (pizza
->clear_on_draw
))
890 gdk_window_clear_area( pizza
->bin_window
,
891 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
894 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
896 win
->m_clipPaintRegion
= TRUE
;
899 dc
.SetClippingRegion(win
->GetUpdateRegion());
900 wxEraseEvent
eevent( win
->GetId(), &dc
);
901 eevent
.SetEventObject( win
);
904 (void)win
->GetEventHandler()->ProcessEvent(eevent
);
906 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
908 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
910 wxClientDC
dc( win
);
911 dc
.SetBrush( wxBrush( win
->GetBackgroundColour(), wxSOLID
) );
912 dc
.SetPen( *wxTRANSPARENT_PEN
);
914 wxRegionIterator
upd( win
->GetUpdateRegion() );
917 dc
.DrawRectangle( upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
924 wxNcPaintEvent
eventNc( win
->GetId() );
925 eventNc
.SetEventObject( win
);
926 win
->GetEventHandler()->ProcessEvent( eventNc
);
928 wxPaintEvent
event( win
->GetId() );
929 event
.SetEventObject( win
);
930 win
->GetEventHandler()->ProcessEvent( event
);
932 win
->GetUpdateRegion().Clear();
934 win
->m_clipPaintRegion
= FALSE
;
937 GList
*children
= pizza
->children
;
940 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
941 children
= children
->next
;
943 GdkRectangle child_area
;
944 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
946 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
951 //-----------------------------------------------------------------------------
952 // "key_press_event" from any window
953 //-----------------------------------------------------------------------------
955 static gint
gtk_window_key_press_callback( GtkWidget
*widget
,
956 GdkEventKey
*gdk_event
,
962 wxapp_install_idle_handler();
964 if (!win
->m_hasVMT
) return FALSE
;
965 if (g_blockEventsOnDrag
) return FALSE
;
970 tmp += (char)gdk_event->keyval;
971 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
972 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
977 GdkModifierType state
;
978 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
982 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
983 /* sending unknown key events doesn't really make sense */
984 if (key_code
== 0) return FALSE
;
986 wxKeyEvent
event( wxEVT_KEY_DOWN
);
987 event
.SetTimestamp( gdk_event
->time
);
988 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
989 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
990 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
991 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
992 event
.m_keyCode
= key_code
;
993 event
.m_scanCode
= gdk_event
->keyval
;
996 event
.SetEventObject( win
);
997 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1002 wxWindowGTK
*ancestor
= win
;
1005 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
1008 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
1009 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
1012 if (ancestor
->IsTopLevel())
1014 ancestor
= ancestor
->GetParent();
1017 #endif // wxUSE_ACCEL
1019 /* wxMSW doesn't send char events with Alt pressed */
1020 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
1021 will only be sent if it is not in an accelerator table. */
1022 key_code
= map_to_wx_keysym( gdk_event
);
1027 wxKeyEvent
event2( wxEVT_CHAR
);
1028 event2
.SetTimestamp( gdk_event
->time
);
1029 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1030 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1031 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1032 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1033 event2
.m_keyCode
= key_code
;
1034 event2
.m_scanCode
= gdk_event
->keyval
;
1037 event2
.SetEventObject( win
);
1038 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
1041 /* win is a control: tab can be propagated up */
1043 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
1044 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
1045 // have this style, yet choose not to process this particular TAB in which
1046 // case TAB must still work as a navigational character
1048 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
1050 (win
->GetParent()) &&
1051 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
1053 wxNavigationKeyEvent new_event
;
1054 new_event
.SetEventObject( win
->GetParent() );
1055 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
1056 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
1057 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1058 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
1059 new_event
.SetCurrentFocus( win
);
1060 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
1063 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
1065 (gdk_event
->keyval
== GDK_Escape
) )
1067 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
1068 new_event
.SetEventObject( win
);
1069 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
1072 #if (GTK_MINOR_VERSION > 0)
1073 /* Pressing F10 will activate the menu bar of the top frame. */
1077 (gdk_event->keyval == GDK_F10) )
1079 wxWindowGTK *ancestor = win;
1082 if (wxIsKindOf(ancestor,wxFrame))
1084 wxFrame *frame = (wxFrame*) ancestor;
1085 wxMenuBar *menubar = frame->GetMenuBar();
1088 wxNode *node = menubar->GetMenus().First();
1091 wxMenu *firstMenu = (wxMenu*) node->Data();
1092 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
1098 ancestor = ancestor->GetParent();
1106 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1113 //-----------------------------------------------------------------------------
1114 // "key_release_event" from any window
1115 //-----------------------------------------------------------------------------
1117 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindowGTK
*win
)
1122 wxapp_install_idle_handler();
1124 if (!win
->m_hasVMT
) return FALSE
;
1125 if (g_blockEventsOnDrag
) return FALSE
;
1128 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
1129 if (gdk_event->state & GDK_SHIFT_MASK)
1130 printf( "ShiftDown.\n" );
1132 printf( "ShiftUp.\n" );
1133 if (gdk_event->state & GDK_CONTROL_MASK)
1134 printf( "ControlDown.\n" );
1136 printf( "ControlUp.\n" );
1140 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
1142 /* sending unknown key events doesn't really make sense */
1143 if (key_code
== 0) return FALSE
;
1147 GdkModifierType state
;
1148 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1150 wxKeyEvent
event( wxEVT_KEY_UP
);
1151 event
.SetTimestamp( gdk_event
->time
);
1152 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1153 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1154 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1155 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1156 event
.m_keyCode
= key_code
;
1157 event
.m_scanCode
= gdk_event
->keyval
;
1160 event
.SetEventObject( win
);
1162 if (win
->GetEventHandler()->ProcessEvent( event
))
1164 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1171 // ----------------------------------------------------------------------------
1172 // mouse event processing helper
1173 // ----------------------------------------------------------------------------
1175 static void AdjustEventButtonState(wxMouseEvent
& event
)
1177 // GDK reports the old state of the button for a button press event, but
1178 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1179 // for a LEFT_DOWN event, not FALSE, so we will invert
1180 // left/right/middleDown for the corresponding click events
1182 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1183 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1184 (event
.GetEventType() == wxEVT_LEFT_UP
))
1186 event
.m_leftDown
= !event
.m_leftDown
;
1190 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1191 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1192 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1194 event
.m_middleDown
= !event
.m_middleDown
;
1198 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1199 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1200 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1202 event
.m_rightDown
= !event
.m_rightDown
;
1207 //-----------------------------------------------------------------------------
1208 // "button_press_event"
1209 //-----------------------------------------------------------------------------
1211 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1216 wxapp_install_idle_handler();
1219 wxPrintf( wxT("1) OnButtonPress from ") );
1220 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1221 wxPrintf( win->GetClassInfo()->GetClassName() );
1222 wxPrintf( wxT(".\n") );
1224 if (!win
->m_hasVMT
) return FALSE
;
1225 if (g_blockEventsOnDrag
) return TRUE
;
1226 if (g_blockEventsOnScroll
) return TRUE
;
1228 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1230 if (win
->m_wxwindow
)
1232 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1234 gtk_widget_grab_focus (win
->m_wxwindow
);
1237 wxPrintf( wxT("GrabFocus from ") );
1238 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1239 wxPrintf( win->GetClassInfo()->GetClassName() );
1240 wxPrintf( wxT(".\n") );
1246 wxEventType event_type
= wxEVT_NULL
;
1248 if (gdk_event
->button
== 1)
1250 switch (gdk_event
->type
)
1252 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1253 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1257 else if (gdk_event
->button
== 2)
1259 switch (gdk_event
->type
)
1261 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1262 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1266 else if (gdk_event
->button
== 3)
1268 switch (gdk_event
->type
)
1270 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1271 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1276 if ( event_type
== wxEVT_NULL
)
1278 // unknown mouse button or click type
1282 wxMouseEvent
event( event_type
);
1283 event
.SetTimestamp( gdk_event
->time
);
1284 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1285 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1286 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1287 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1288 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1289 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1290 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1292 event
.m_x
= (wxCoord
)gdk_event
->x
;
1293 event
.m_y
= (wxCoord
)gdk_event
->y
;
1295 AdjustEventButtonState(event
);
1297 // Some control don't have their own X window and thus cannot get
1300 if (!g_captureWindow
)
1302 wxCoord x
= event
.m_x
;
1303 wxCoord y
= event
.m_y
;
1304 if (win
->m_wxwindow
)
1306 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1307 x
+= pizza
->xoffset
;
1308 y
+= pizza
->yoffset
;
1311 wxNode
*node
= win
->GetChildren().First();
1314 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1316 node
= node
->Next();
1317 if (!child
->IsShown())
1320 if (child
->m_isStaticBox
)
1322 // wxStaticBox is transparent in the box itself
1323 int xx1
= child
->m_x
;
1324 int yy1
= child
->m_y
;
1325 int xx2
= child
->m_x
+ child
->m_width
;
1326 int yy2
= child
->m_x
+ child
->m_height
;
1329 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1331 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1333 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1335 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1338 event
.m_x
-= child
->m_x
;
1339 event
.m_y
-= child
->m_y
;
1346 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1347 (child
->m_x
<= x
) &&
1348 (child
->m_y
<= y
) &&
1349 (child
->m_x
+child
->m_width
>= x
) &&
1350 (child
->m_y
+child
->m_height
>= y
))
1353 event
.m_x
-= child
->m_x
;
1354 event
.m_y
-= child
->m_y
;
1361 event
.SetEventObject( win
);
1363 gs_timeLastClick
= gdk_event
->time
;
1366 wxPrintf( wxT("2) OnButtonPress from ") );
1367 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1368 wxPrintf( win->GetClassInfo()->GetClassName() );
1369 wxPrintf( wxT(".\n") );
1372 if (win
->GetEventHandler()->ProcessEvent( event
))
1374 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1381 //-----------------------------------------------------------------------------
1382 // "button_release_event"
1383 //-----------------------------------------------------------------------------
1385 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1390 wxapp_install_idle_handler();
1392 if (!win
->m_hasVMT
) return FALSE
;
1393 if (g_blockEventsOnDrag
) return FALSE
;
1394 if (g_blockEventsOnScroll
) return FALSE
;
1396 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1399 printf( "OnButtonRelease from " );
1400 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1401 printf( win->GetClassInfo()->GetClassName() );
1405 wxEventType event_type
= wxEVT_NULL
;
1407 switch (gdk_event
->button
)
1409 case 1: event_type
= wxEVT_LEFT_UP
; break;
1410 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1411 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1412 default: return FALSE
;
1415 wxMouseEvent
event( event_type
);
1416 event
.SetTimestamp( gdk_event
->time
);
1417 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1418 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1419 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1420 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1421 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1422 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1423 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1424 event
.m_x
= (wxCoord
)gdk_event
->x
;
1425 event
.m_y
= (wxCoord
)gdk_event
->y
;
1427 AdjustEventButtonState(event
);
1429 // Some control don't have their own X window and thus cannot get
1432 if (!g_captureWindow
)
1434 wxCoord x
= event
.m_x
;
1435 wxCoord y
= event
.m_y
;
1436 if (win
->m_wxwindow
)
1438 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1439 x
+= pizza
->xoffset
;
1440 y
+= pizza
->yoffset
;
1443 wxNode
*node
= win
->GetChildren().First();
1446 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1448 node
= node
->Next();
1449 if (!child
->IsShown())
1452 if (child
->m_isStaticBox
)
1454 // wxStaticBox is transparent in the box itself
1455 int xx1
= child
->m_x
;
1456 int yy1
= child
->m_y
;
1457 int xx2
= child
->m_x
+ child
->m_width
;
1458 int yy2
= child
->m_x
+ child
->m_height
;
1461 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1463 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1465 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1467 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1470 event
.m_x
-= child
->m_x
;
1471 event
.m_y
-= child
->m_y
;
1478 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1479 (child
->m_x
<= x
) &&
1480 (child
->m_y
<= y
) &&
1481 (child
->m_x
+child
->m_width
>= x
) &&
1482 (child
->m_y
+child
->m_height
>= y
))
1485 event
.m_x
-= child
->m_x
;
1486 event
.m_y
-= child
->m_y
;
1493 event
.SetEventObject( win
);
1495 if (win
->GetEventHandler()->ProcessEvent( event
))
1497 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1504 // ============================================================================
1506 // ============================================================================
1508 // init wxMouseEvent with the info from gdk_event
1509 #define InitMouseEvent(event, gdk_event) \
1510 event.SetTimestamp( gdk_event->time ); \
1511 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
1512 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
1513 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
1514 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
1515 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
1516 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
1517 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
1519 event.m_x = (wxCoord)gdk_event->x; \
1520 event.m_y = (wxCoord)gdk_event->y \
1522 //-----------------------------------------------------------------------------
1523 // "motion_notify_event"
1524 //-----------------------------------------------------------------------------
1526 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
,
1527 GdkEventMotion
*gdk_event
,
1533 wxapp_install_idle_handler();
1535 if (!win
->m_hasVMT
) return FALSE
;
1536 if (g_blockEventsOnDrag
) return FALSE
;
1537 if (g_blockEventsOnScroll
) return FALSE
;
1539 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1541 if (gdk_event
->is_hint
)
1545 GdkModifierType state
;
1546 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1552 printf( "OnMotion from " );
1553 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1554 printf( win->GetClassInfo()->GetClassName() );
1558 wxMouseEvent
event( wxEVT_MOTION
);
1559 InitMouseEvent(event
, gdk_event
);
1561 if ( g_captureWindow
)
1563 // synthetize a mouse enter or leave event if needed
1564 GdkWindow
*winUnderMouse
= gdk_window_at_pointer(NULL
, NULL
);
1565 bool hasMouse
= winUnderMouse
== gdk_event
->window
;
1566 if ( hasMouse
!= g_captureWindowHasMouse
)
1568 // the mouse changed window
1569 g_captureWindowHasMouse
= hasMouse
;
1571 wxMouseEvent
event(g_captureWindowHasMouse
? wxEVT_ENTER_WINDOW
1572 : wxEVT_LEAVE_WINDOW
);
1573 InitMouseEvent(event
, gdk_event
);
1574 event
.SetEventObject(win
);
1575 win
->GetEventHandler()->ProcessEvent(event
);
1580 // Some control don't have their own X window and thus cannot get
1583 wxCoord x
= event
.m_x
;
1584 wxCoord y
= event
.m_y
;
1585 if (win
->m_wxwindow
)
1587 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1588 x
+= pizza
->xoffset
;
1589 y
+= pizza
->yoffset
;
1592 wxNode
*node
= win
->GetChildren().First();
1595 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1597 node
= node
->Next();
1598 if (!child
->IsShown())
1601 if (child
->m_isStaticBox
)
1603 // wxStaticBox is transparent in the box itself
1604 int xx1
= child
->m_x
;
1605 int yy1
= child
->m_y
;
1606 int xx2
= child
->m_x
+ child
->m_width
;
1607 int yy2
= child
->m_x
+ child
->m_height
;
1610 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1612 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1614 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1616 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1619 event
.m_x
-= child
->m_x
;
1620 event
.m_y
-= child
->m_y
;
1627 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1628 (child
->m_x
<= x
) &&
1629 (child
->m_y
<= y
) &&
1630 (child
->m_x
+child
->m_width
>= x
) &&
1631 (child
->m_y
+child
->m_height
>= y
))
1634 event
.m_x
-= child
->m_x
;
1635 event
.m_y
-= child
->m_y
;
1642 event
.SetEventObject( win
);
1644 if (win
->GetEventHandler()->ProcessEvent( event
))
1646 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1653 //-----------------------------------------------------------------------------
1655 //-----------------------------------------------------------------------------
1657 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
,
1658 GdkEvent
*WXUNUSED(event
),
1664 wxapp_install_idle_handler();
1666 if (!win
->m_hasVMT
) return FALSE
;
1667 if (g_blockEventsOnDrag
) return FALSE
;
1669 switch ( g_sendActivateEvent
)
1672 // we've got focus from outside, synthtize wxActivateEvent
1673 g_sendActivateEvent
= 1;
1677 // another our window just lost focus, it was already ours before
1678 // - don't send any wxActivateEvent
1679 g_sendActivateEvent
= -1;
1684 g_focusWindow
= win
;
1687 printf( "OnSetFocus from " );
1688 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1689 printf( win->GetClassInfo()->GetClassName() );
1691 printf( WXSTRINGCAST win->GetLabel() );
1695 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1698 panel
->SetLastFocus(win
);
1703 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1707 // caret needs to be informed about focus change
1708 wxCaret
*caret
= win
->GetCaret();
1711 caret
->OnSetFocus();
1713 #endif // wxUSE_CARET
1716 // If it's a wxTextCtrl don't send the event as it will be done
1717 // after the control gets to process it.
1718 wxTextCtrl
*ctrl
= wxDynamicCast(win
, wxTextCtrl
);
1725 if (win
->IsTopLevel())
1727 wxActivateEvent
event( wxEVT_ACTIVATE
, TRUE
, win
->GetId() );
1728 event
.SetEventObject( win
);
1730 // ignore return value
1731 win
->GetEventHandler()->ProcessEvent( event
);
1734 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1735 event
.SetEventObject( win
);
1737 if (win
->GetEventHandler()->ProcessEvent( event
))
1739 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1747 //-----------------------------------------------------------------------------
1748 // "focus_out_event"
1749 //-----------------------------------------------------------------------------
1751 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindowGTK
*win
)
1756 wxapp_install_idle_handler();
1758 if (!win
->m_hasVMT
) return FALSE
;
1759 if (g_blockEventsOnDrag
) return FALSE
;
1761 // if the focus goes out of our app alltogether, OnIdle() will send
1762 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1763 // g_sendActivateEvent to -1
1764 g_sendActivateEvent
= 0;
1766 wxWindowGTK
*winFocus
= wxFindFocusedChild(win
);
1770 g_focusWindow
= (wxWindowGTK
*)NULL
;
1773 printf( "OnKillFocus from " );
1774 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1775 printf( win->GetClassInfo()->GetClassName() );
1785 // caret needs to be informed about focus change
1786 wxCaret
*caret
= win
->GetCaret();
1789 caret
->OnKillFocus();
1791 #endif // wxUSE_CARET
1794 // If it's a wxTextCtrl don't send the event as it will be done
1795 // after the control gets to process it.
1796 wxTextCtrl
*ctrl
= wxDynamicCast(win
, wxTextCtrl
);
1803 if (win
->IsTopLevel())
1805 wxActivateEvent
event( wxEVT_ACTIVATE
, FALSE
, win
->GetId() );
1806 event
.SetEventObject( win
);
1808 // ignore return value
1809 win
->GetEventHandler()->ProcessEvent( event
);
1812 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1813 event
.SetEventObject( win
);
1815 if (win
->GetEventHandler()->ProcessEvent( event
))
1817 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1824 //-----------------------------------------------------------------------------
1825 // "enter_notify_event"
1826 //-----------------------------------------------------------------------------
1828 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1833 wxapp_install_idle_handler();
1835 if (!win
->m_hasVMT
) return FALSE
;
1836 if (g_blockEventsOnDrag
) return FALSE
;
1838 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1840 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1841 #if (GTK_MINOR_VERSION > 0)
1842 event
.SetTimestamp( gdk_event
->time
);
1844 event
.SetEventObject( win
);
1848 GdkModifierType state
= (GdkModifierType
)0;
1850 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1852 InitMouseEvent(event
, gdk_event
);
1857 if (win
->GetEventHandler()->ProcessEvent( event
))
1859 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1866 //-----------------------------------------------------------------------------
1867 // "leave_notify_event"
1868 //-----------------------------------------------------------------------------
1870 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1875 wxapp_install_idle_handler();
1877 if (!win
->m_hasVMT
) return FALSE
;
1878 if (g_blockEventsOnDrag
) return FALSE
;
1880 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1882 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1883 #if (GTK_MINOR_VERSION > 0)
1884 event
.SetTimestamp( gdk_event
->time
);
1886 event
.SetEventObject( win
);
1890 GdkModifierType state
= (GdkModifierType
)0;
1892 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1894 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1895 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1896 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1897 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1898 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1899 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1900 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1905 if (win
->GetEventHandler()->ProcessEvent( event
))
1907 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1914 //-----------------------------------------------------------------------------
1915 // "value_changed" from m_vAdjust
1916 //-----------------------------------------------------------------------------
1918 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1923 wxapp_install_idle_handler();
1925 if (g_blockEventsOnDrag
) return;
1927 if (!win
->m_hasVMT
) return;
1929 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1930 if (fabs(diff
) < 0.2) return;
1932 win
->m_oldVerticalPos
= adjust
->value
;
1934 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1935 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1937 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1938 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1939 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1940 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1941 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1943 int value
= (int)(adjust
->value
+0.5);
1945 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1946 event
.SetEventObject( win
);
1947 win
->GetEventHandler()->ProcessEvent( event
);
1950 //-----------------------------------------------------------------------------
1951 // "value_changed" from m_hAdjust
1952 //-----------------------------------------------------------------------------
1954 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1959 wxapp_install_idle_handler();
1961 if (g_blockEventsOnDrag
) return;
1962 if (!win
->m_hasVMT
) return;
1964 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1965 if (fabs(diff
) < 0.2) return;
1967 win
->m_oldHorizontalPos
= adjust
->value
;
1969 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1970 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1972 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1973 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1974 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1975 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1976 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1978 int value
= (int)(adjust
->value
+0.5);
1980 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1981 event
.SetEventObject( win
);
1982 win
->GetEventHandler()->ProcessEvent( event
);
1985 //-----------------------------------------------------------------------------
1986 // "button_press_event" from scrollbar
1987 //-----------------------------------------------------------------------------
1989 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1990 GdkEventButton
*gdk_event
,
1996 wxapp_install_idle_handler();
1999 g_blockEventsOnScroll
= TRUE
;
2000 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
2005 //-----------------------------------------------------------------------------
2006 // "button_release_event" from scrollbar
2007 //-----------------------------------------------------------------------------
2009 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
2010 GdkEventButton
*WXUNUSED(gdk_event
),
2015 // don't test here as we can release the mouse while being over
2016 // a different window than the slider
2018 // if (gdk_event->window != widget->slider) return FALSE;
2020 g_blockEventsOnScroll
= FALSE
;
2022 if (win
->m_isScrolling
)
2024 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
2028 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
2029 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
2031 value
= (int)(win
->m_hAdjust
->value
+0.5);
2034 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
2036 value
= (int)(win
->m_vAdjust
->value
+0.5);
2040 wxScrollWinEvent
event( command
, value
, dir
);
2041 event
.SetEventObject( win
);
2042 win
->GetEventHandler()->ProcessEvent( event
);
2045 win
->m_isScrolling
= FALSE
;
2050 // ----------------------------------------------------------------------------
2051 // this wxWindowBase function is implemented here (in platform-specific file)
2052 // because it is static and so couldn't be made virtual
2053 // ----------------------------------------------------------------------------
2055 wxWindow
*wxWindowBase::FindFocus()
2057 // the cast is necessary when we compile in wxUniversal mode
2058 return (wxWindow
*)g_focusWindow
;
2061 //-----------------------------------------------------------------------------
2062 // "realize" from m_widget
2063 //-----------------------------------------------------------------------------
2065 /* We cannot set colours and fonts before the widget has
2066 been realized, so we do this directly after realization. */
2069 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
2074 wxapp_install_idle_handler();
2076 if (win
->m_delayedBackgroundColour
)
2077 win
->SetBackgroundColour( win
->GetBackgroundColour() );
2079 if (win
->m_delayedForegroundColour
)
2080 win
->SetForegroundColour( win
->GetForegroundColour() );
2082 wxWindowCreateEvent
event( win
);
2083 event
.SetEventObject( win
);
2084 win
->GetEventHandler()->ProcessEvent( event
);
2089 //-----------------------------------------------------------------------------
2091 //-----------------------------------------------------------------------------
2094 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
2095 GtkAllocation
*WXUNUSED(alloc
),
2099 wxapp_install_idle_handler();
2101 if (!win
->m_hasScrolling
) return;
2103 int client_width
= 0;
2104 int client_height
= 0;
2105 win
->GetClientSize( &client_width
, &client_height
);
2106 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
2109 win
->m_oldClientWidth
= client_width
;
2110 win
->m_oldClientHeight
= client_height
;
2112 if (!win
->m_nativeSizeEvent
)
2114 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
2115 event
.SetEventObject( win
);
2116 win
->GetEventHandler()->ProcessEvent( event
);
2122 #define WXUNUSED_UNLESS_XIM(param) param
2124 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2127 /* Resize XIM window */
2130 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2131 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
2132 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2135 wxapp_install_idle_handler();
2141 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
2145 gdk_window_get_size (widget
->window
, &width
, &height
);
2146 win
->m_icattr
->preedit_area
.width
= width
;
2147 win
->m_icattr
->preedit_area
.height
= height
;
2148 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2153 //-----------------------------------------------------------------------------
2154 // "realize" from m_wxwindow
2155 //-----------------------------------------------------------------------------
2157 /* Initialize XIM support */
2160 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2161 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2164 wxapp_install_idle_handler();
2167 if (win
->m_ic
) return FALSE
;
2168 if (!widget
) return FALSE
;
2169 if (!gdk_im_ready()) return FALSE
;
2171 win
->m_icattr
= gdk_ic_attr_new();
2172 if (!win
->m_icattr
) return FALSE
;
2176 GdkColormap
*colormap
;
2177 GdkICAttr
*attr
= win
->m_icattr
;
2178 unsigned attrmask
= GDK_IC_ALL_REQ
;
2180 GdkIMStyle supported_style
= (GdkIMStyle
)
2181 (GDK_IM_PREEDIT_NONE
|
2182 GDK_IM_PREEDIT_NOTHING
|
2183 GDK_IM_PREEDIT_POSITION
|
2184 GDK_IM_STATUS_NONE
|
2185 GDK_IM_STATUS_NOTHING
);
2187 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2188 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2190 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2191 attr
->client_window
= widget
->window
;
2193 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2194 gtk_widget_get_default_colormap ())
2196 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2197 attr
->preedit_colormap
= colormap
;
2200 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2201 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2202 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2203 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2205 switch (style
& GDK_IM_PREEDIT_MASK
)
2207 case GDK_IM_PREEDIT_POSITION
:
2208 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2210 g_warning ("over-the-spot style requires fontset");
2214 gdk_window_get_size (widget
->window
, &width
, &height
);
2216 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2217 attr
->spot_location
.x
= 0;
2218 attr
->spot_location
.y
= height
;
2219 attr
->preedit_area
.x
= 0;
2220 attr
->preedit_area
.y
= 0;
2221 attr
->preedit_area
.width
= width
;
2222 attr
->preedit_area
.height
= height
;
2223 attr
->preedit_fontset
= widget
->style
->font
;
2228 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2230 if (win
->m_ic
== NULL
)
2231 g_warning ("Can't create input context.");
2234 mask
= gdk_window_get_events (widget
->window
);
2235 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2236 gdk_window_set_events (widget
->window
, mask
);
2238 if (GTK_WIDGET_HAS_FOCUS(widget
))
2239 gdk_im_begin (win
->m_ic
, widget
->window
);
2246 //-----------------------------------------------------------------------------
2247 // InsertChild for wxWindowGTK.
2248 //-----------------------------------------------------------------------------
2250 /* Callback for wxWindowGTK. This very strange beast has to be used because
2251 * C++ has no virtual methods in a constructor. We have to emulate a
2252 * virtual function here as wxNotebook requires a different way to insert
2253 * a child in it. I had opted for creating a wxNotebookPage window class
2254 * which would have made this superfluous (such in the MDI window system),
2255 * but no-one was listening to me... */
2257 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child
)
2259 /* the window might have been scrolled already, do we
2260 have to adapt the position */
2261 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2262 child
->m_x
+= pizza
->xoffset
;
2263 child
->m_y
+= pizza
->yoffset
;
2265 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2266 GTK_WIDGET(child
->m_widget
),
2273 //-----------------------------------------------------------------------------
2275 //-----------------------------------------------------------------------------
2277 wxWindow
*wxGetActiveWindow()
2279 // the cast is necessary when we compile in wxUniversal mode
2280 return (wxWindow
*)g_focusWindow
;
2283 //-----------------------------------------------------------------------------
2285 //-----------------------------------------------------------------------------
2287 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
2289 #ifdef __WXUNIVERSAL__
2290 IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
)
2292 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2293 #endif // __WXUNIVERSAL__/__WXGTK__
2295 void wxWindowGTK::Init()
2301 m_widget
= (GtkWidget
*) NULL
;
2302 m_wxwindow
= (GtkWidget
*) NULL
;
2312 m_needParent
= TRUE
;
2313 m_isBeingDeleted
= FALSE
;
2316 m_nativeSizeEvent
= FALSE
;
2318 m_hasScrolling
= FALSE
;
2319 m_isScrolling
= FALSE
;
2321 m_hAdjust
= (GtkAdjustment
*) NULL
;
2322 m_vAdjust
= (GtkAdjustment
*) NULL
;
2323 m_oldHorizontalPos
= 0.0;
2324 m_oldVerticalPos
= 0.0;
2327 m_widgetStyle
= (GtkStyle
*) NULL
;
2329 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2331 m_isStaticBox
= FALSE
;
2332 m_isRadioButton
= FALSE
;
2334 m_acceptsFocus
= FALSE
;
2336 m_clipPaintRegion
= FALSE
;
2338 m_cursor
= *wxSTANDARD_CURSOR
;
2340 m_delayedForegroundColour
= FALSE
;
2341 m_delayedBackgroundColour
= FALSE
;
2344 m_ic
= (GdkIC
*) NULL
;
2345 m_icattr
= (GdkICAttr
*) NULL
;
2349 wxWindowGTK::wxWindowGTK()
2354 wxWindowGTK::wxWindowGTK( wxWindow
*parent
,
2359 const wxString
&name
)
2363 Create( parent
, id
, pos
, size
, style
, name
);
2366 bool wxWindowGTK::Create( wxWindow
*parent
,
2371 const wxString
&name
)
2373 if (!PreCreation( parent
, pos
, size
) ||
2374 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2376 wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
2380 m_insertCallback
= wxInsertChildInWindow
;
2382 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2383 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2385 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2387 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2388 scroll_class
->scrollbar_spacing
= 0;
2390 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2392 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2393 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2395 m_wxwindow
= gtk_pizza_new();
2397 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2399 #ifndef __WXUNIVERSAL__
2400 #if (GTK_MINOR_VERSION > 0)
2401 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2403 if (HasFlag(wxRAISED_BORDER
))
2405 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2407 else if (HasFlag(wxSUNKEN_BORDER
))
2409 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2411 else if (HasFlag(wxSIMPLE_BORDER
))
2413 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2417 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2419 #else // GTK_MINOR_VERSION == 0
2420 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2422 if (HasFlag(wxRAISED_BORDER
))
2424 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2426 else if (HasFlag(wxSUNKEN_BORDER
))
2428 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2432 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2434 #endif // GTK_MINOR_VERSION
2435 #endif // __WXUNIVERSAL__
2437 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2438 m_acceptsFocus
= TRUE
;
2440 #if (GTK_MINOR_VERSION == 0)
2441 // shut the viewport up
2442 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2443 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2444 #endif // GTK_MINOR_VERSION == 0
2446 // I _really_ don't want scrollbars in the beginning
2447 m_vAdjust
->lower
= 0.0;
2448 m_vAdjust
->upper
= 1.0;
2449 m_vAdjust
->value
= 0.0;
2450 m_vAdjust
->step_increment
= 1.0;
2451 m_vAdjust
->page_increment
= 1.0;
2452 m_vAdjust
->page_size
= 5.0;
2453 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2454 m_hAdjust
->lower
= 0.0;
2455 m_hAdjust
->upper
= 1.0;
2456 m_hAdjust
->value
= 0.0;
2457 m_hAdjust
->step_increment
= 1.0;
2458 m_hAdjust
->page_increment
= 1.0;
2459 m_hAdjust
->page_size
= 5.0;
2460 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2462 // these handlers block mouse events to any window during scrolling such as
2463 // motion events and prevent GTK and wxWindows from fighting over where the
2466 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2467 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2469 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2470 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2472 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2473 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2475 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2476 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2478 // these handlers get notified when screen updates are required either when
2479 // scrolling or when the window size (and therefore scrollbar configuration)
2482 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2483 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2484 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2485 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2487 gtk_widget_show( m_wxwindow
);
2490 m_parent
->DoAddChild( this );
2499 wxWindowGTK::~wxWindowGTK()
2501 if (g_focusWindow
== this)
2502 g_focusWindow
= NULL
;
2504 m_isBeingDeleted
= TRUE
;
2513 m_parent
->RemoveChild( this );
2517 gdk_ic_destroy (m_ic
);
2519 gdk_ic_attr_destroy (m_icattr
);
2524 #if DISABLE_STYLE_IF_BROKEN_THEME
2525 // don't delete if it's a pixmap theme style
2526 if (!m_widgetStyle
->engine_data
)
2527 gtk_style_unref( m_widgetStyle
);
2529 m_widgetStyle
= (GtkStyle
*) NULL
;
2534 gtk_widget_destroy( m_wxwindow
);
2535 m_wxwindow
= (GtkWidget
*) NULL
;
2540 gtk_widget_destroy( m_widget
);
2541 m_widget
= (GtkWidget
*) NULL
;
2545 bool wxWindowGTK::PreCreation( wxWindowGTK
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2547 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2549 /* this turns -1 into 20 so that a minimal window is
2550 visible even although -1,-1 has been given as the
2551 size of the window. the same trick is used in other
2552 ports and should make debugging easier */
2553 m_width
= WidthDefault(size
.x
);
2554 m_height
= HeightDefault(size
.y
);
2559 /* some reasonable defaults */
2564 m_x
= (gdk_screen_width () - m_width
) / 2;
2565 if (m_x
< 10) m_x
= 10;
2569 m_y
= (gdk_screen_height () - m_height
) / 2;
2570 if (m_y
< 10) m_y
= 10;
2577 void wxWindowGTK::PostCreation()
2579 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2585 /* these get reported to wxWindows -> wxPaintEvent */
2587 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2589 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2590 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2592 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2593 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2595 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2597 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2598 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2602 #if (GTK_MINOR_VERSION > 0)
2603 /* these are called when the "sunken" or "raised" borders are drawn */
2604 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2605 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2607 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2608 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2612 if (m_wxwindow
&& m_needParent
)
2614 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2615 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2617 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2618 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2622 // For dialogs and frames, we are interested mainly in
2623 // m_widget's focus.
2625 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2626 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2628 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2629 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2632 GtkWidget
*connect_widget
= GetConnectWidget();
2634 ConnectWidget( connect_widget
);
2636 /* We cannot set colours, fonts and cursors before the widget has
2637 been realized, so we do this directly after realization */
2638 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2639 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2643 // Catch native resize events
2644 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2645 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2647 // Initialize XIM support
2648 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2649 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2651 // And resize XIM window
2652 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2653 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2656 if (!GTK_IS_COMBO(m_widget
))
2658 // This is needed if we want to add our windows into native
2659 // GTK control, such as the toolbar. With this callback, the
2660 // toolbar gets to know the correct size (the one set by the
2661 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2662 // when moving to GTK 2.0.
2663 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2664 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2670 void wxWindowGTK::ConnectWidget( GtkWidget
*widget
)
2672 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2673 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2675 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2676 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2678 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2679 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2681 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2682 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2684 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2685 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2687 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2688 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2690 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2691 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2694 bool wxWindowGTK::Destroy()
2696 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2700 return wxWindowBase::Destroy();
2703 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
)
2705 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2708 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2710 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2711 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") );
2714 printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
2717 if (m_resizing
) return; /* I don't like recursions */
2720 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2722 /* don't set the size for children of wxNotebook, just take the values. */
2730 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2732 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2734 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2735 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2736 if (width
!= -1) m_width
= width
;
2737 if (height
!= -1) m_height
= height
;
2741 m_x
= x
+ pizza
->xoffset
;
2742 m_y
= y
+ pizza
->yoffset
;
2747 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2749 if (width
== -1) m_width
= 80;
2752 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2754 if (height
== -1) m_height
= 26;
2757 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2758 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2759 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2760 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2763 int bottom_border
= 0;
2765 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2767 /* the default button has a border around it */
2772 DoMoveWindow( m_x
-border
,
2775 m_height
+border
+bottom_border
);
2780 /* Sometimes the client area changes size without the
2781 whole windows's size changing, but if the whole
2782 windows's size doesn't change, no wxSizeEvent will
2783 normally be sent. Here we add an extra test if
2784 the client test has been changed and this will
2786 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2790 wxPrintf( "OnSize sent from " );
2791 if (GetClassInfo() && GetClassInfo()->GetClassName())
2792 wxPrintf( GetClassInfo()->GetClassName() );
2793 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2796 if (!m_nativeSizeEvent
)
2798 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2799 event
.SetEventObject( this );
2800 GetEventHandler()->ProcessEvent( event
);
2806 void wxWindowGTK::OnInternalIdle()
2808 if ( g_sendActivateEvent
!= -1 )
2810 bool activate
= g_sendActivateEvent
!= 0;
2813 g_sendActivateEvent
= -1;
2815 wxTheApp
->SetActive(activate
, (wxWindow
*)g_focusWindowLast
);
2817 wxActivateEvent
event(wxEVT_ACTIVATE_APP
, activate
, GetId());
2818 event
.SetEventObject(this);
2820 (void)GetEventHandler()->ProcessEvent(event
);
2823 wxCursor cursor
= m_cursor
;
2824 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2828 /* I now set the cursor anew in every OnInternalIdle call
2829 as setting the cursor in a parent window also effects the
2830 windows above so that checking for the current cursor is
2835 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2837 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2839 if (!g_globalCursor
.Ok())
2840 cursor
= *wxSTANDARD_CURSOR
;
2842 window
= m_widget
->window
;
2843 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2844 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2850 GdkWindow
*window
= m_widget
->window
;
2851 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2852 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2860 void wxWindowGTK::DoGetSize( int *width
, int *height
) const
2862 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2864 if (width
) (*width
) = m_width
;
2865 if (height
) (*height
) = m_height
;
2868 void wxWindowGTK::DoSetClientSize( int width
, int height
)
2870 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2874 SetSize( width
, height
);
2881 #ifndef __WXUNIVERSAL__
2882 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2884 /* when using GTK 1.2 we set the shadow border size to 2 */
2888 if (HasFlag(wxSIMPLE_BORDER
))
2890 /* when using GTK 1.2 we set the simple border size to 1 */
2894 #endif // __WXUNIVERSAL__
2898 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2900 GtkRequisition vscroll_req
;
2901 vscroll_req
.width
= 2;
2902 vscroll_req
.height
= 2;
2903 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2904 (scroll_window
->vscrollbar
, &vscroll_req
);
2906 GtkRequisition hscroll_req
;
2907 hscroll_req
.width
= 2;
2908 hscroll_req
.height
= 2;
2909 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2910 (scroll_window
->hscrollbar
, &hscroll_req
);
2912 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2914 if (scroll_window
->vscrollbar_visible
)
2916 dw
+= vscroll_req
.width
;
2917 dw
+= scroll_class
->scrollbar_spacing
;
2920 if (scroll_window
->hscrollbar_visible
)
2922 dh
+= hscroll_req
.height
;
2923 dh
+= scroll_class
->scrollbar_spacing
;
2927 SetSize( width
+dw
, height
+dh
);
2931 void wxWindowGTK::DoGetClientSize( int *width
, int *height
) const
2933 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2937 if (width
) (*width
) = m_width
;
2938 if (height
) (*height
) = m_height
;
2945 #ifndef __WXUNIVERSAL__
2946 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2948 /* when using GTK 1.2 we set the shadow border size to 2 */
2952 if (HasFlag(wxSIMPLE_BORDER
))
2954 /* when using GTK 1.2 we set the simple border size to 1 */
2958 #endif // __WXUNIVERSAL__
2962 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2964 GtkRequisition vscroll_req
;
2965 vscroll_req
.width
= 2;
2966 vscroll_req
.height
= 2;
2967 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2968 (scroll_window
->vscrollbar
, &vscroll_req
);
2970 GtkRequisition hscroll_req
;
2971 hscroll_req
.width
= 2;
2972 hscroll_req
.height
= 2;
2973 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2974 (scroll_window
->hscrollbar
, &hscroll_req
);
2976 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2978 if (scroll_window
->vscrollbar_visible
)
2980 dw
+= vscroll_req
.width
;
2981 dw
+= scroll_class
->scrollbar_spacing
;
2984 if (scroll_window
->hscrollbar_visible
)
2986 dh
+= hscroll_req
.height
;
2987 dh
+= scroll_class
->scrollbar_spacing
;
2991 if (width
) (*width
) = m_width
- dw
;
2992 if (height
) (*height
) = m_height
- dh
;
2996 printf( "GetClientSize, name %s ", GetName().c_str() );
2997 if (width) printf( " width = %d", (*width) );
2998 if (height) printf( " height = %d", (*height) );
3003 void wxWindowGTK::DoGetPosition( int *x
, int *y
) const
3005 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3009 if (m_parent
&& m_parent
->m_wxwindow
)
3011 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
3012 dx
= pizza
->xoffset
;
3013 dy
= pizza
->yoffset
;
3016 if (x
) (*x
) = m_x
- dx
;
3017 if (y
) (*y
) = m_y
- dy
;
3020 void wxWindowGTK::DoClientToScreen( int *x
, int *y
) const
3022 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3024 if (!m_widget
->window
) return;
3026 GdkWindow
*source
= (GdkWindow
*) NULL
;
3028 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3030 source
= m_widget
->window
;
3034 gdk_window_get_origin( source
, &org_x
, &org_y
);
3038 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3040 org_x
+= m_widget
->allocation
.x
;
3041 org_y
+= m_widget
->allocation
.y
;
3049 void wxWindowGTK::DoScreenToClient( int *x
, int *y
) const
3051 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3053 if (!m_widget
->window
) return;
3055 GdkWindow
*source
= (GdkWindow
*) NULL
;
3057 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3059 source
= m_widget
->window
;
3063 gdk_window_get_origin( source
, &org_x
, &org_y
);
3067 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3069 org_x
+= m_widget
->allocation
.x
;
3070 org_y
+= m_widget
->allocation
.y
;
3078 bool wxWindowGTK::Show( bool show
)
3080 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3082 if (!wxWindowBase::Show(show
))
3089 gtk_widget_show( m_widget
);
3091 gtk_widget_hide( m_widget
);
3096 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
)
3098 win
->OnParentEnable(enable
);
3100 // Recurse, so that children have the opportunity to Do The Right Thing
3101 // and reset colours that have been messed up by a parent's (really ancestor's)
3103 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
3105 node
= node
->GetNext() )
3107 wxWindow
*child
= node
->GetData();
3108 if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
)))
3109 wxWindowNotifyEnable(child
, enable
);
3113 bool wxWindowGTK::Enable( bool enable
)
3115 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3117 if (!wxWindowBase::Enable(enable
))
3123 gtk_widget_set_sensitive( m_widget
, enable
);
3125 gtk_widget_set_sensitive( m_wxwindow
, enable
);
3127 wxWindowNotifyEnable(this, enable
);
3132 int wxWindowGTK::GetCharHeight() const
3134 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
3136 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
3138 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3140 return font
->ascent
+ font
->descent
;
3143 int wxWindowGTK::GetCharWidth() const
3145 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
3147 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
3149 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3151 return gdk_string_width( font
, "H" );
3154 void wxWindowGTK::GetTextExtent( const wxString
& string
,
3158 int *externalLeading
,
3159 const wxFont
*theFont
) const
3161 wxFont fontToUse
= m_font
;
3162 if (theFont
) fontToUse
= *theFont
;
3164 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
3166 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
3167 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
3168 if (y
) (*y
) = font
->ascent
+ font
->descent
;
3169 if (descent
) (*descent
) = font
->descent
;
3170 if (externalLeading
) (*externalLeading
) = 0; // ??
3173 void wxWindowGTK::SetFocus()
3175 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3179 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3180 gtk_widget_grab_focus (m_wxwindow
);
3186 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
3188 gtk_widget_grab_focus (m_widget
);
3190 else if (GTK_IS_CONTAINER(m_widget
))
3192 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
3201 bool wxWindowGTK::AcceptsFocus() const
3203 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3206 bool wxWindowGTK::Reparent( wxWindowBase
*newParentBase
)
3208 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3210 wxWindowGTK
*oldParent
= m_parent
,
3211 *newParent
= (wxWindowGTK
*)newParentBase
;
3213 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3215 if ( !wxWindowBase::Reparent(newParent
) )
3218 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3220 /* prevent GTK from deleting the widget arbitrarily */
3221 gtk_widget_ref( m_widget
);
3225 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3228 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3232 /* insert GTK representation */
3233 (*(newParent
->m_insertCallback
))(newParent
, this);
3236 /* reverse: prevent GTK from deleting the widget arbitrarily */
3237 gtk_widget_unref( m_widget
);
3242 void wxWindowGTK::DoAddChild(wxWindowGTK
*child
)
3244 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3246 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3248 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3253 /* insert GTK representation */
3254 (*m_insertCallback
)(this, child
);
3257 void wxWindowGTK::Raise()
3259 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3261 if (!m_widget
->window
) return;
3263 gdk_window_raise( m_widget
->window
);
3266 void wxWindowGTK::Lower()
3268 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3270 if (!m_widget
->window
) return;
3272 gdk_window_lower( m_widget
->window
);
3275 bool wxWindowGTK::SetCursor( const wxCursor
&cursor
)
3277 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3279 if (cursor
== m_cursor
)
3283 wxapp_install_idle_handler();
3285 if (cursor
== wxNullCursor
)
3286 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3288 return wxWindowBase::SetCursor( cursor
);
3291 void wxWindowGTK::WarpPointer( int x
, int y
)
3293 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3295 /* we provide this function ourselves as it is
3296 missing in GDK (top of this file) */
3298 GdkWindow
*window
= (GdkWindow
*) NULL
;
3300 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3302 window
= GetConnectWidget()->window
;
3305 gdk_window_warp_pointer( window
, x
, y
);
3308 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect
*rect
)
3310 if (!m_widget
) return;
3311 if (!m_widget
->window
) return;
3313 // temporarily hide the caret to avoid nasty interactions between caret
3314 // drawing and the window contents redraw
3315 #if 0 // def wxUSE_CARET -- doesn't seem to help :-(
3316 wxCaretSuspend
cs((wxWindow
*)this);
3317 #endif // wxUSE_CARET
3319 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3323 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3325 rect
->width
, rect
->height
);
3329 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3333 /* there is no GTK equivalent of "draw only, don't clear" so we
3334 invent our own in the GtkPizza widget */
3342 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3343 gboolean old_clear = pizza->clear_on_draw;
3344 gtk_pizza_set_clear( pizza, FALSE );
3345 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3346 gtk_pizza_set_clear( pizza, old_clear );
3348 GdkEventExpose gdk_event
;
3349 gdk_event
.type
= GDK_EXPOSE
;
3350 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3351 gdk_event
.count
= 0;
3352 gdk_event
.area
.x
= 0;
3353 gdk_event
.area
.y
= 0;
3354 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3355 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3356 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, (wxWindow
*)this );
3360 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3369 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3370 gboolean old_clear = pizza->clear_on_draw;
3371 gtk_pizza_set_clear( pizza, FALSE );
3373 GdkRectangle gdk_rect;
3374 gdk_rect.x = rect->x;
3375 gdk_rect.y = rect->y;
3376 gdk_rect.width = rect->width;
3377 gdk_rect.height = rect->height;
3378 gtk_widget_draw( m_wxwindow, &gdk_rect );
3379 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3381 gtk_pizza_set_clear( pizza, old_clear );
3383 GdkEventExpose gdk_event
;
3384 gdk_event
.type
= GDK_EXPOSE
;
3385 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3386 gdk_event
.count
= 0;
3387 gdk_event
.area
.x
= rect
->x
;
3388 gdk_event
.area
.y
= rect
->y
;
3389 gdk_event
.area
.width
= rect
->width
;
3390 gdk_event
.area
.height
= rect
->height
;
3391 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, (wxWindow
*)this );
3395 GdkRectangle gdk_rect
;
3396 gdk_rect
.x
= rect
->x
;
3397 gdk_rect
.y
= rect
->y
;
3398 gdk_rect
.width
= rect
->width
;
3399 gdk_rect
.height
= rect
->height
;
3400 gtk_widget_draw( m_widget
, &gdk_rect
);
3405 void wxWindowGTK::Clear()
3407 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3409 if (!m_widget
->window
) return;
3411 if (m_wxwindow
&& m_wxwindow
->window
)
3413 // gdk_window_clear( m_wxwindow->window );
3418 void wxWindowGTK::DoSetToolTip( wxToolTip
*tip
)
3420 wxWindowBase::DoSetToolTip(tip
);
3423 m_tooltip
->Apply( (wxWindow
*)this );
3426 void wxWindowGTK::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3428 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3430 #endif // wxUSE_TOOLTIPS
3432 bool wxWindowGTK::SetBackgroundColour( const wxColour
&colour
)
3434 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3436 if (!wxWindowBase::SetBackgroundColour(colour
))
3438 // don't leave if the GTK widget has just
3440 if (!m_delayedBackgroundColour
) return FALSE
;
3443 GdkWindow
*window
= (GdkWindow
*) NULL
;
3445 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3447 window
= GetConnectWidget()->window
;
3451 // indicate that a new style has been set
3452 // but it couldn't get applied as the
3453 // widget hasn't been realized yet.
3454 m_delayedBackgroundColour
= TRUE
;
3458 (m_wxwindow
->window
) &&
3459 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3461 /* wxMSW doesn't clear the window here. I don't do that either to
3462 provide compatibility. call Clear() to do the job. */
3464 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3465 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3473 bool wxWindowGTK::SetForegroundColour( const wxColour
&colour
)
3475 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3477 if (!wxWindowBase::SetForegroundColour(colour
))
3479 // don't leave if the GTK widget has just
3481 if (!m_delayedForegroundColour
) return FALSE
;
3484 GdkWindow
*window
= (GdkWindow
*) NULL
;
3486 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3488 window
= GetConnectWidget()->window
;
3492 // indicate that a new style has been set
3493 // but it couldn't get applied as the
3494 // widget hasn't been realized yet.
3495 m_delayedForegroundColour
= TRUE
;
3503 GtkStyle
*wxWindowGTK::GetWidgetStyle()
3507 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3509 /* FIXME: is this necessary? */
3510 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3512 remake
->klass
= m_widgetStyle
->klass
;
3515 gtk_style_unref( m_widgetStyle
);
3516 m_widgetStyle
= remake
;
3520 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3523 def
= gtk_widget_get_default_style();
3525 m_widgetStyle
= gtk_style_copy( def
);
3527 /* FIXME: is this necessary? */
3528 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3530 m_widgetStyle
->klass
= def
->klass
;
3534 return m_widgetStyle
;
3537 void wxWindowGTK::SetWidgetStyle()
3539 #if DISABLE_STYLE_IF_BROKEN_THEM
3540 if (m_widget
->style
->engine_data
)
3542 static bool s_warningPrinted
= FALSE
;
3543 if (!s_warningPrinted
)
3545 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3546 s_warningPrinted
= TRUE
;
3548 m_widgetStyle
= m_widget
->style
;
3553 GtkStyle
*style
= GetWidgetStyle();
3555 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3557 gdk_font_unref( style
->font
);
3558 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3561 if (m_foregroundColour
.Ok())
3563 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3564 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3566 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3567 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3568 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3572 // Try to restore the gtk default style. This is still a little
3573 // oversimplified for what is probably really needed here for controls
3574 // other than buttons, but is better than not being able to (re)set a
3575 // control's foreground colour to *wxBLACK -- RL
3576 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3579 def
= gtk_widget_get_default_style();
3581 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3582 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3583 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3587 if (m_backgroundColour
.Ok())
3589 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3590 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3592 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3593 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3594 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3595 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3596 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3597 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3598 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3599 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3603 // Try to restore the gtk default style. This is still a little
3604 // oversimplified for what is probably really needed here for controls
3605 // other than buttons, but is better than not being able to (re)set a
3606 // control's background colour to default grey and means resetting a
3607 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3609 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3612 def
= gtk_widget_get_default_style();
3614 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3615 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3616 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3617 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3618 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3619 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3620 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3621 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3626 void wxWindowGTK::ApplyWidgetStyle()
3630 //-----------------------------------------------------------------------------
3631 // Pop-up menu stuff
3632 //-----------------------------------------------------------------------------
3634 #if wxUSE_MENUS_NATIVE
3636 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3638 *is_waiting
= FALSE
;
3641 static void SetInvokingWindow( wxMenu
*menu
, wxWindowGTK
*win
)
3643 menu
->SetInvokingWindow( win
);
3644 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3647 wxMenuItem
*menuitem
= node
->GetData();
3648 if (menuitem
->IsSubMenu())
3650 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3653 node
= node
->GetNext();
3657 static gint gs_pop_x
= 0;
3658 static gint gs_pop_y
= 0;
3660 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3664 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3669 bool wxWindowGTK::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3671 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3673 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3675 SetInvokingWindow( menu
, this );
3682 bool is_waiting
= TRUE
;
3684 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3685 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3688 GTK_MENU(menu
->m_menu
),
3689 (GtkWidget
*) NULL
, // parent menu shell
3690 (GtkWidget
*) NULL
, // parent menu item
3691 (GtkMenuPositionFunc
) pop_pos_callback
,
3692 (gpointer
) this, // client data
3693 0, // button used to activate it
3694 gs_timeLastClick
// the time of activation
3699 while (gtk_events_pending())
3700 gtk_main_iteration();
3706 #endif // wxUSE_MENUS_NATIVE
3708 #if wxUSE_DRAG_AND_DROP
3710 void wxWindowGTK::SetDropTarget( wxDropTarget
*dropTarget
)
3712 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3714 GtkWidget
*dnd_widget
= GetConnectWidget();
3716 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3718 if (m_dropTarget
) delete m_dropTarget
;
3719 m_dropTarget
= dropTarget
;
3721 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3724 #endif // wxUSE_DRAG_AND_DROP
3726 GtkWidget
* wxWindowGTK::GetConnectWidget()
3728 GtkWidget
*connect_widget
= m_widget
;
3729 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3731 return connect_widget
;
3734 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow
*window
)
3737 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3739 return (window
== m_widget
->window
);
3742 bool wxWindowGTK::SetFont( const wxFont
&font
)
3744 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3746 if (!wxWindowBase::SetFont(font
))
3751 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3752 if ( sysbg
== m_backgroundColour
)
3754 m_backgroundColour
= wxNullColour
;
3756 m_backgroundColour
= sysbg
;
3766 void wxWindowGTK::CaptureMouse()
3768 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3770 GdkWindow
*window
= (GdkWindow
*) NULL
;
3772 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3774 window
= GetConnectWidget()->window
;
3776 wxCHECK_RET( window
, _T("CaptureMouse() failed") );
3778 wxCursor
* cursor
= & m_cursor
;
3780 cursor
= wxSTANDARD_CURSOR
;
3782 gdk_pointer_grab( window
, FALSE
,
3784 (GDK_BUTTON_PRESS_MASK
|
3785 GDK_BUTTON_RELEASE_MASK
|
3786 GDK_POINTER_MOTION_HINT_MASK
|
3787 GDK_POINTER_MOTION_MASK
),
3789 cursor
->GetCursor(),
3790 (guint32
)GDK_CURRENT_TIME
);
3791 g_captureWindow
= this;
3792 g_captureWindowHasMouse
= TRUE
;
3795 void wxWindowGTK::ReleaseMouse()
3797 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3799 wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") );
3801 GdkWindow
*window
= (GdkWindow
*) NULL
;
3803 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3805 window
= GetConnectWidget()->window
;
3810 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3811 g_captureWindow
= (wxWindowGTK
*) NULL
;
3815 wxWindow
*wxWindowBase::GetCapture()
3817 return (wxWindow
*)g_captureWindow
;
3820 bool wxWindowGTK::IsRetained() const
3825 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3826 int range
, bool refresh
)
3828 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3830 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3832 m_hasScrolling
= TRUE
;
3834 if (orient
== wxHORIZONTAL
)
3836 float fpos
= (float)pos
;
3837 float frange
= (float)range
;
3838 float fthumb
= (float)thumbVisible
;
3839 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3840 if (fpos
< 0.0) fpos
= 0.0;
3842 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3843 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3845 SetScrollPos( orient
, pos
, refresh
);
3849 m_oldHorizontalPos
= fpos
;
3851 m_hAdjust
->lower
= 0.0;
3852 m_hAdjust
->upper
= frange
;
3853 m_hAdjust
->value
= fpos
;
3854 m_hAdjust
->step_increment
= 1.0;
3855 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3856 m_hAdjust
->page_size
= fthumb
;
3860 float fpos
= (float)pos
;
3861 float frange
= (float)range
;
3862 float fthumb
= (float)thumbVisible
;
3863 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3864 if (fpos
< 0.0) fpos
= 0.0;
3866 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3867 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3869 SetScrollPos( orient
, pos
, refresh
);
3873 m_oldVerticalPos
= fpos
;
3875 m_vAdjust
->lower
= 0.0;
3876 m_vAdjust
->upper
= frange
;
3877 m_vAdjust
->value
= fpos
;
3878 m_vAdjust
->step_increment
= 1.0;
3879 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3880 m_vAdjust
->page_size
= fthumb
;
3883 if (orient
== wxHORIZONTAL
)
3884 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3886 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3889 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3891 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3893 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3895 if (orient
== wxHORIZONTAL
)
3897 float fpos
= (float)pos
;
3898 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3899 if (fpos
< 0.0) fpos
= 0.0;
3900 m_oldHorizontalPos
= fpos
;
3902 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3903 m_hAdjust
->value
= fpos
;
3907 float fpos
= (float)pos
;
3908 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3909 if (fpos
< 0.0) fpos
= 0.0;
3910 m_oldVerticalPos
= fpos
;
3912 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3913 m_vAdjust
->value
= fpos
;
3916 if (m_wxwindow
->window
)
3918 if (orient
== wxHORIZONTAL
)
3920 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3921 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3923 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3925 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3926 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3930 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3931 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3933 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3935 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3936 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3941 int wxWindowGTK::GetScrollThumb( int orient
) const
3943 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3945 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3947 if (orient
== wxHORIZONTAL
)
3948 return (int)(m_hAdjust
->page_size
+0.5);
3950 return (int)(m_vAdjust
->page_size
+0.5);
3953 int wxWindowGTK::GetScrollPos( int orient
) const
3955 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3957 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3959 if (orient
== wxHORIZONTAL
)
3960 return (int)(m_hAdjust
->value
+0.5);
3962 return (int)(m_vAdjust
->value
+0.5);
3965 int wxWindowGTK::GetScrollRange( int orient
) const
3967 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3969 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3971 if (orient
== wxHORIZONTAL
)
3972 return (int)(m_hAdjust
->upper
+0.5);
3974 return (int)(m_vAdjust
->upper
+0.5);
3977 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3979 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3981 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3983 if ((dx
== 0) && (dy
== 0)) return;
3985 m_clipPaintRegion
= TRUE
;
3986 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3987 m_clipPaintRegion
= FALSE
;
3990 if (m_children.GetCount() > 0)
3992 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3996 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3998 pizza->xoffset -= dx;
3999 pizza->yoffset -= dy;
4001 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
4002 gdk_gc_set_exposures( m_scrollGC, TRUE );
4006 GetClientSize( &cw, &ch );
4007 int w = cw - abs(dx);
4008 int h = ch - abs(dy);
4010 if ((h < 0) || (w < 0))
4018 if (dx < 0) s_x = -dx;
4019 if (dy < 0) s_y = -dy;
4022 if (dx > 0) d_x = dx;
4023 if (dy > 0) d_y = dy;
4025 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
4026 pizza->bin_window, s_x, s_y, w, h );
4029 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
4030 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
4031 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
4032 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
4034 Refresh( TRUE, &rect );
4037 gdk_gc_unref( m_scrollGC );
4042 // Find the wxWindow at the current mouse position, also returning the mouse
4044 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
4046 pt
= wxGetMousePosition();
4047 wxWindow
* found
= wxFindWindowAtPoint(pt
);
4051 // Get the current mouse position.
4052 wxPoint
wxGetMousePosition()
4054 /* This crashes when used within wxHelpContext,
4055 so we have to use the X-specific implementation below.
4057 GdkModifierType *mask;
4058 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
4060 return wxPoint(x, y);
4064 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
4066 return wxPoint(-999, -999);
4068 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
4069 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
4070 Window rootReturn
, childReturn
;
4071 int rootX
, rootY
, winX
, winY
;
4072 unsigned int maskReturn
;
4074 XQueryPointer (display
,
4078 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
4079 return wxPoint(rootX
, rootY
);