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
;
211 static wxWindowList g_capturedWindows
;
213 /* extern */ wxWindowGTK
*g_focusWindow
= (wxWindowGTK
*) NULL
;
215 // the last window which had the focus - this is normally never NULL (except
216 // if we never had focus at all) as even when g_focusWindow is NULL it still
217 // keeps its previous value
218 static wxWindowGTK
*g_focusWindowLast
= (wxWindowGTK
*)NULL
;
220 // if we detect that the app has got/lost the focus, we set this variable to
221 // either TRUE or FALSE and an activate event will be sent during the next
222 // OnIdle() call and it is reset to -1: this value means that we shouldn't
223 // send any activate events at all
224 static int g_sendActivateEvent
= -1;
226 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
227 the last click here */
228 static guint32 gs_timeLastClick
= 0;
230 extern bool g_mainThreadLocked
;
232 //-----------------------------------------------------------------------------
234 //-----------------------------------------------------------------------------
237 #define DISABLE_STYLE_IF_BROKEN_THEME 1
243 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
245 # define DEBUG_MAIN_THREAD
248 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
249 GdkEvent
*WXUNUSED(event
),
250 const wxChar
*WXUNUSED(name
) )
253 static bool s_done = FALSE;
256 wxLog::AddTraceMask("focus");
259 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
265 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
267 // suppress warnings about gtk_debug_focus_in_callback being unused with
272 tmp
+= wxT(" FROM ");
275 wxChar
*s
= new wxChar
[tmp
.Length()+1];
279 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
280 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
285 #define DEBUG_MAIN_THREAD
288 //-----------------------------------------------------------------------------
289 // missing gdk functions
290 //-----------------------------------------------------------------------------
293 gdk_window_warp_pointer (GdkWindow
*window
,
298 GdkWindowPrivate
*priv
;
302 window
= GDK_ROOT_PARENT();
305 if (!GDK_WINDOW_DESTROYED(window
))
307 XWarpPointer (GDK_WINDOW_XDISPLAY(window
),
308 None
, /* not source window -> move from anywhere */
309 GDK_WINDOW_XID(window
), /* dest window */
310 0, 0, 0, 0, /* not source window -> move from anywhere */
314 priv
= (GdkWindowPrivate
*) window
;
316 if (!priv
->destroyed
)
318 XWarpPointer (priv
->xdisplay
,
319 None
, /* not source window -> move from anywhere */
320 priv
->xwindow
, /* dest window */
321 0, 0, 0, 0, /* not source window -> move from anywhere */
327 //-----------------------------------------------------------------------------
329 //-----------------------------------------------------------------------------
331 extern void wxapp_install_idle_handler();
332 extern bool g_isIdle
;
334 //-----------------------------------------------------------------------------
335 // local code (see below)
336 //-----------------------------------------------------------------------------
338 // returns the child of win which currently has focus or NULL if not found
340 // Note: can't be static, needed by textctrl.cpp.
341 wxWindow
*wxFindFocusedChild(wxWindowGTK
*win
)
343 wxWindow
*winFocus
= wxWindowGTK::FindFocus();
345 return (wxWindow
*)NULL
;
347 if ( winFocus
== win
)
348 return (wxWindow
*)win
;
350 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
352 node
= node
->GetNext() )
354 wxWindow
*child
= wxFindFocusedChild(node
->GetData());
359 return (wxWindow
*)NULL
;
362 static void draw_frame( GtkWidget
*widget
, wxWindowGTK
*win
)
364 // wxUniversal widgets draw the borders and scrollbars themselves
365 #ifndef __WXUNIVERSAL__
372 if (win
->m_hasScrolling
)
374 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
376 GtkRequisition vscroll_req
;
377 vscroll_req
.width
= 2;
378 vscroll_req
.height
= 2;
379 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
380 (scroll_window
->vscrollbar
, &vscroll_req
);
382 GtkRequisition hscroll_req
;
383 hscroll_req
.width
= 2;
384 hscroll_req
.height
= 2;
385 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
386 (scroll_window
->hscrollbar
, &hscroll_req
);
388 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) );
390 if (scroll_window
->vscrollbar_visible
)
392 dw
+= vscroll_req
.width
;
393 dw
+= scroll_class
->scrollbar_spacing
;
396 if (scroll_window
->hscrollbar_visible
)
398 dh
+= hscroll_req
.height
;
399 dh
+= scroll_class
->scrollbar_spacing
;
405 if (GTK_WIDGET_NO_WINDOW (widget
))
407 dx
+= widget
->allocation
.x
;
408 dy
+= widget
->allocation
.y
;
411 if (win
->HasFlag(wxRAISED_BORDER
))
413 gtk_draw_shadow( widget
->style
,
418 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
422 if (win
->HasFlag(wxSUNKEN_BORDER
))
424 gtk_draw_shadow( widget
->style
,
429 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
433 if (win
->HasFlag(wxSIMPLE_BORDER
))
436 gc
= gdk_gc_new( widget
->window
);
437 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
438 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
440 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
444 #endif // __WXUNIVERSAL__
447 //-----------------------------------------------------------------------------
448 // "expose_event" of m_widget
449 //-----------------------------------------------------------------------------
451 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindowGTK
*win
)
453 if (gdk_event
->count
> 0) return FALSE
;
455 draw_frame( widget
, win
);
460 //-----------------------------------------------------------------------------
461 // "draw" of m_widget
462 //-----------------------------------------------------------------------------
464 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindowGTK
*win
)
466 draw_frame( widget
, win
);
469 //-----------------------------------------------------------------------------
470 // key code mapping routines
471 //-----------------------------------------------------------------------------
473 static long map_to_unmodified_wx_keysym( GdkEventKey
*event
)
475 KeySym keysym
= event
->keyval
;
481 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
483 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
489 case GDK_Super_R
: key_code
= WXK_ALT
; break;
490 case GDK_Menu
: key_code
= WXK_MENU
; break;
491 case GDK_Help
: key_code
= WXK_HELP
; break;
492 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
493 case GDK_ISO_Left_Tab
:
494 case GDK_Tab
: key_code
= WXK_TAB
; break;
495 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
496 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
497 case GDK_Return
: key_code
= WXK_RETURN
; break;
498 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
499 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
500 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
501 case GDK_Delete
: key_code
= WXK_DELETE
; break;
502 case GDK_Home
: key_code
= WXK_HOME
; break;
503 case GDK_Left
: key_code
= WXK_LEFT
; break;
504 case GDK_Up
: key_code
= WXK_UP
; break;
505 case GDK_Right
: key_code
= WXK_RIGHT
; break;
506 case GDK_Down
: key_code
= WXK_DOWN
; break;
507 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
508 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
509 case GDK_Next
: key_code
= WXK_NEXT
; break;
510 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
511 case GDK_End
: key_code
= WXK_END
; break;
512 case GDK_Begin
: key_code
= WXK_HOME
; break;
513 case GDK_Select
: key_code
= WXK_SELECT
; break;
514 case GDK_Print
: key_code
= WXK_PRINT
; break;
515 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
516 case GDK_Insert
: key_code
= WXK_INSERT
; break;
517 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
519 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
520 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
521 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
522 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
523 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
524 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
525 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
526 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
527 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
528 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
529 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
530 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
531 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
532 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
533 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
534 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
535 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
536 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
537 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
538 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
539 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
540 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
541 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
542 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
543 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
544 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
545 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
546 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
547 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
548 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
549 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
550 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
551 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
552 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
553 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
554 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
555 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
557 case GDK_F1
: key_code
= WXK_F1
; break;
558 case GDK_F2
: key_code
= WXK_F2
; break;
559 case GDK_F3
: key_code
= WXK_F3
; break;
560 case GDK_F4
: key_code
= WXK_F4
; break;
561 case GDK_F5
: key_code
= WXK_F5
; break;
562 case GDK_F6
: key_code
= WXK_F6
; break;
563 case GDK_F7
: key_code
= WXK_F7
; break;
564 case GDK_F8
: key_code
= WXK_F8
; break;
565 case GDK_F9
: key_code
= WXK_F9
; break;
566 case GDK_F10
: key_code
= WXK_F10
; break;
567 case GDK_F11
: key_code
= WXK_F11
; break;
568 case GDK_F12
: key_code
= WXK_F12
; break;
571 if (event
->length
== 1)
573 key_code
= toupper( (unsigned char)*event
->string
);
575 else if ((keysym
& 0xFF) == keysym
)
577 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
578 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
579 key_code
= (guint
)keysym
;
587 static long map_to_wx_keysym( GdkEventKey
*event
)
589 KeySym keysym
= event
->keyval
;
594 case GDK_Menu
: key_code
= WXK_MENU
; break;
595 case GDK_Help
: key_code
= WXK_HELP
; break;
596 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
597 case GDK_ISO_Left_Tab
:
598 case GDK_Tab
: key_code
= WXK_TAB
; break;
599 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
600 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
601 case GDK_Return
: key_code
= WXK_RETURN
; break;
602 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
603 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
604 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
605 case GDK_Delete
: key_code
= WXK_DELETE
; break;
606 case GDK_Home
: key_code
= WXK_HOME
; break;
607 case GDK_Left
: key_code
= WXK_LEFT
; break;
608 case GDK_Up
: key_code
= WXK_UP
; break;
609 case GDK_Right
: key_code
= WXK_RIGHT
; break;
610 case GDK_Down
: key_code
= WXK_DOWN
; break;
611 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
612 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
613 case GDK_Next
: key_code
= WXK_NEXT
; break;
614 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
615 case GDK_End
: key_code
= WXK_END
; break;
616 case GDK_Begin
: key_code
= WXK_HOME
; break;
617 case GDK_Select
: key_code
= WXK_SELECT
; break;
618 case GDK_Print
: key_code
= WXK_PRINT
; break;
619 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
620 case GDK_Insert
: key_code
= WXK_INSERT
; break;
621 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
623 case GDK_KP_0
: key_code
= '0'; break;
624 case GDK_KP_1
: key_code
= '1'; break;
625 case GDK_KP_2
: key_code
= '2'; break;
626 case GDK_KP_3
: key_code
= '3'; break;
627 case GDK_KP_4
: key_code
= '4'; break;
628 case GDK_KP_5
: key_code
= '5'; break;
629 case GDK_KP_6
: key_code
= '6'; break;
630 case GDK_KP_7
: key_code
= '7'; break;
631 case GDK_KP_8
: key_code
= '8'; break;
632 case GDK_KP_9
: key_code
= '9'; break;
633 case GDK_KP_Space
: key_code
= ' '; break;
634 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
635 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
636 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
637 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
638 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
639 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
640 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
641 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
642 case GDK_KP_Up
: key_code
= WXK_UP
; break;
643 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
644 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
645 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
646 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
647 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
648 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
649 case GDK_KP_End
: key_code
= WXK_END
; break;
650 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
651 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
652 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
653 case GDK_KP_Equal
: key_code
= '='; break;
654 case GDK_KP_Multiply
: key_code
= '*'; break;
655 case GDK_KP_Add
: key_code
= '+'; break;
656 case GDK_KP_Separator
: key_code
= ','; break;
657 case GDK_KP_Subtract
: key_code
= '-'; break;
658 case GDK_KP_Decimal
: key_code
= '.'; break;
659 case GDK_KP_Divide
: key_code
= '/'; break;
661 case GDK_F1
: key_code
= WXK_F1
; break;
662 case GDK_F2
: key_code
= WXK_F2
; break;
663 case GDK_F3
: key_code
= WXK_F3
; break;
664 case GDK_F4
: key_code
= WXK_F4
; break;
665 case GDK_F5
: key_code
= WXK_F5
; break;
666 case GDK_F6
: key_code
= WXK_F6
; break;
667 case GDK_F7
: key_code
= WXK_F7
; break;
668 case GDK_F8
: key_code
= WXK_F8
; break;
669 case GDK_F9
: key_code
= WXK_F9
; break;
670 case GDK_F10
: key_code
= WXK_F10
; break;
671 case GDK_F11
: key_code
= WXK_F11
; break;
672 case GDK_F12
: key_code
= WXK_F12
; break;
675 if (event
->length
== 1)
677 key_code
= (unsigned char)*event
->string
;
679 else if ((keysym
& 0xFF) == keysym
)
681 key_code
= (guint
)keysym
;
689 //-----------------------------------------------------------------------------
690 // "size_request" of m_widget
691 //-----------------------------------------------------------------------------
693 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
696 win
->GetSize( &w
, &h
);
700 requisition
->height
= h
;
701 requisition
->width
= w
;
704 //-----------------------------------------------------------------------------
705 // "expose_event" of m_wxwindow
706 //-----------------------------------------------------------------------------
708 static int gtk_window_expose_callback( GtkWidget
*widget
,
709 GdkEventExpose
*gdk_event
,
715 wxapp_install_idle_handler();
718 if (win->GetName() == wxT("panel"))
720 wxPrintf( wxT("OnExpose from ") );
721 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
722 wxPrintf( win->GetClassInfo()->GetClassName() );
723 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
724 (int)gdk_event->area.y,
725 (int)gdk_event->area.width,
726 (int)gdk_event->area.height );
730 GtkPizza
*pizza
= GTK_PIZZA (widget
);
732 if (win
->GetThemeEnabled())
734 wxWindow
*parent
= win
->GetParent();
735 while (parent
&& !parent
->IsTopLevel())
736 parent
= parent
->GetParent();
740 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
741 GTK_SHADOW_NONE
, &gdk_event
->area
, parent
->m_widget
, "base", 0, 0, -1, -1);
744 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
746 gdk_event
->area
.width
,
747 gdk_event
->area
.height
);
749 if (gdk_event
->count
== 0)
751 win
->m_clipPaintRegion
= TRUE
;
754 dc
.SetClippingRegion(win
->GetUpdateRegion());
755 wxEraseEvent
eevent( win
->GetId(), &dc
);
756 eevent
.SetEventObject( win
);
758 (void)win
->GetEventHandler()->ProcessEvent(eevent
);
760 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
762 wxClientDC
dc( win
);
763 dc
.SetBrush( wxBrush( win
->GetBackgroundColour(), wxSOLID
) );
764 dc
.SetPen( *wxTRANSPARENT_PEN
);
766 wxRegionIterator
upd( win
->GetUpdateRegion() );
769 dc
.DrawRectangle( upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
775 wxNcPaintEvent
eventNc( win
->GetId() );
776 eventNc
.SetEventObject( win
);
777 win
->GetEventHandler()->ProcessEvent( eventNc
);
779 wxPaintEvent
event( win
->GetId() );
780 event
.SetEventObject( win
);
781 win
->GetEventHandler()->ProcessEvent( event
);
783 win
->GetUpdateRegion().Clear();
785 win
->m_clipPaintRegion
= FALSE
;
788 /* The following code will result in all window-less widgets
789 being redrawn if the wxWindows class is given a chance to
790 paint *anything* because it will then be allowed to paint
791 over the window-less widgets */
792 GList
*children
= pizza
->children
;
795 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
796 children
= children
->next
;
798 GdkEventExpose child_event
= *gdk_event
;
800 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
801 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
802 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
804 child_event
.area
.x
= child
->widget
->allocation
.x
;
805 child_event
.area
.y
= child
->widget
->allocation
.y
;
806 child_event
.area
.width
= child
->widget
->allocation
.width
;
807 child_event
.area
.height
= child
->widget
->allocation
.height
;
808 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
815 //-----------------------------------------------------------------------------
816 // "event" of m_wxwindow
817 //-----------------------------------------------------------------------------
819 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
820 expose events. We need them, of course, so we override the main event
821 procedure in GtkWidget by giving our own handler for all system events.
822 There, we look for expose events ourselves whereas all other events are
825 gint
gtk_window_event_event_callback( GtkWidget
*widget
,
826 GdkEventExpose
*event
,
829 if (event
->type
== GDK_EXPOSE
)
831 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
838 //-----------------------------------------------------------------------------
839 // "draw" of m_wxwindow
840 //-----------------------------------------------------------------------------
842 /* This callback is a complete replacement of the gtk_pizza_draw() function,
845 static void gtk_window_draw_callback( GtkWidget
*widget
,
852 wxapp_install_idle_handler();
854 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
855 (win
->GetChildren().GetCount() == 0))
861 if (win->GetName() == wxT("panel"))
863 wxPrintf( wxT("OnDraw from ") );
864 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
865 wxPrintf( win->GetClassInfo()->GetClassName() );
866 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
873 GtkPizza
*pizza
= GTK_PIZZA (widget
);
875 if (win
->GetThemeEnabled())
877 wxWindow
*parent
= win
->GetParent();
878 while (parent
&& !parent
->IsTopLevel())
879 parent
= parent
->GetParent();
883 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
884 GTK_SHADOW_NONE
, rect
, parent
->m_widget
, "base", 0, 0, -1, -1);
888 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
889 (pizza
->clear_on_draw
))
891 gdk_window_clear_area( pizza
->bin_window
,
892 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
895 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
897 win
->m_clipPaintRegion
= TRUE
;
900 dc
.SetClippingRegion(win
->GetUpdateRegion());
901 wxEraseEvent
eevent( win
->GetId(), &dc
);
902 eevent
.SetEventObject( win
);
905 (void)win
->GetEventHandler()->ProcessEvent(eevent
);
907 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
909 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
911 wxClientDC
dc( win
);
912 dc
.SetBrush( wxBrush( win
->GetBackgroundColour(), wxSOLID
) );
913 dc
.SetPen( *wxTRANSPARENT_PEN
);
915 wxRegionIterator
upd( win
->GetUpdateRegion() );
918 dc
.DrawRectangle( upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
925 wxNcPaintEvent
eventNc( win
->GetId() );
926 eventNc
.SetEventObject( win
);
927 win
->GetEventHandler()->ProcessEvent( eventNc
);
929 wxPaintEvent
event( win
->GetId() );
930 event
.SetEventObject( win
);
931 win
->GetEventHandler()->ProcessEvent( event
);
933 win
->GetUpdateRegion().Clear();
935 win
->m_clipPaintRegion
= FALSE
;
938 GList
*children
= pizza
->children
;
941 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
942 children
= children
->next
;
944 GdkRectangle child_area
;
945 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
947 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
952 //-----------------------------------------------------------------------------
953 // "key_press_event" from any window
954 //-----------------------------------------------------------------------------
956 static gint
gtk_window_key_press_callback( GtkWidget
*widget
,
957 GdkEventKey
*gdk_event
,
963 wxapp_install_idle_handler();
965 if (!win
->m_hasVMT
) return FALSE
;
966 if (g_blockEventsOnDrag
) return FALSE
;
971 tmp += (char)gdk_event->keyval;
972 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
973 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
978 GdkModifierType state
;
979 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
983 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
984 /* sending unknown key events doesn't really make sense */
985 if (key_code
== 0) return FALSE
;
987 wxKeyEvent
event( wxEVT_KEY_DOWN
);
988 event
.SetTimestamp( gdk_event
->time
);
989 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
990 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
991 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
992 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
993 event
.m_keyCode
= key_code
;
994 event
.m_scanCode
= gdk_event
->keyval
;
997 event
.SetEventObject( win
);
998 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1003 wxWindowGTK
*ancestor
= win
;
1006 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
1009 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
1010 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
1013 if (ancestor
->IsTopLevel())
1015 ancestor
= ancestor
->GetParent();
1018 #endif // wxUSE_ACCEL
1020 /* wxMSW doesn't send char events with Alt pressed */
1021 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
1022 will only be sent if it is not in an accelerator table. */
1023 key_code
= map_to_wx_keysym( gdk_event
);
1028 wxKeyEvent
event2( wxEVT_CHAR
);
1029 event2
.SetTimestamp( gdk_event
->time
);
1030 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1031 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1032 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1033 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1034 event2
.m_keyCode
= key_code
;
1035 event2
.m_scanCode
= gdk_event
->keyval
;
1038 event2
.SetEventObject( win
);
1039 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
1042 /* win is a control: tab can be propagated up */
1044 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
1045 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
1046 // have this style, yet choose not to process this particular TAB in which
1047 // case TAB must still work as a navigational character
1049 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
1051 (win
->GetParent()) &&
1052 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
1054 wxNavigationKeyEvent new_event
;
1055 new_event
.SetEventObject( win
->GetParent() );
1056 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
1057 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
1058 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1059 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
1060 new_event
.SetCurrentFocus( win
);
1061 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
1064 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
1066 (gdk_event
->keyval
== GDK_Escape
) )
1068 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
1069 new_event
.SetEventObject( win
);
1070 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
1073 #if (GTK_MINOR_VERSION > 0)
1074 /* Pressing F10 will activate the menu bar of the top frame. */
1078 (gdk_event->keyval == GDK_F10) )
1080 wxWindowGTK *ancestor = win;
1083 if (wxIsKindOf(ancestor,wxFrame))
1085 wxFrame *frame = (wxFrame*) ancestor;
1086 wxMenuBar *menubar = frame->GetMenuBar();
1089 wxNode *node = menubar->GetMenus().First();
1092 wxMenu *firstMenu = (wxMenu*) node->Data();
1093 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
1099 ancestor = ancestor->GetParent();
1107 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1114 //-----------------------------------------------------------------------------
1115 // "key_release_event" from any window
1116 //-----------------------------------------------------------------------------
1118 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindowGTK
*win
)
1123 wxapp_install_idle_handler();
1125 if (!win
->m_hasVMT
) return FALSE
;
1126 if (g_blockEventsOnDrag
) return FALSE
;
1129 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
1130 if (gdk_event->state & GDK_SHIFT_MASK)
1131 printf( "ShiftDown.\n" );
1133 printf( "ShiftUp.\n" );
1134 if (gdk_event->state & GDK_CONTROL_MASK)
1135 printf( "ControlDown.\n" );
1137 printf( "ControlUp.\n" );
1141 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
1143 /* sending unknown key events doesn't really make sense */
1144 if (key_code
== 0) return FALSE
;
1148 GdkModifierType state
;
1149 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1151 wxKeyEvent
event( wxEVT_KEY_UP
);
1152 event
.SetTimestamp( gdk_event
->time
);
1153 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1154 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1155 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1156 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1157 event
.m_keyCode
= key_code
;
1158 event
.m_scanCode
= gdk_event
->keyval
;
1161 event
.SetEventObject( win
);
1163 if (win
->GetEventHandler()->ProcessEvent( event
))
1165 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1172 // ----------------------------------------------------------------------------
1173 // mouse event processing helper
1174 // ----------------------------------------------------------------------------
1176 static void AdjustEventButtonState(wxMouseEvent
& event
)
1178 // GDK reports the old state of the button for a button press event, but
1179 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1180 // for a LEFT_DOWN event, not FALSE, so we will invert
1181 // left/right/middleDown for the corresponding click events
1183 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1184 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1185 (event
.GetEventType() == wxEVT_LEFT_UP
))
1187 event
.m_leftDown
= !event
.m_leftDown
;
1191 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1192 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1193 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1195 event
.m_middleDown
= !event
.m_middleDown
;
1199 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1200 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1201 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1203 event
.m_rightDown
= !event
.m_rightDown
;
1208 //-----------------------------------------------------------------------------
1209 // "button_press_event"
1210 //-----------------------------------------------------------------------------
1212 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1217 wxapp_install_idle_handler();
1220 wxPrintf( wxT("1) OnButtonPress from ") );
1221 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1222 wxPrintf( win->GetClassInfo()->GetClassName() );
1223 wxPrintf( wxT(".\n") );
1225 if (!win
->m_hasVMT
) return FALSE
;
1226 if (g_blockEventsOnDrag
) return TRUE
;
1227 if (g_blockEventsOnScroll
) return TRUE
;
1229 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1231 if (win
->m_wxwindow
)
1233 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1235 gtk_widget_grab_focus (win
->m_wxwindow
);
1238 wxPrintf( wxT("GrabFocus from ") );
1239 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1240 wxPrintf( win->GetClassInfo()->GetClassName() );
1241 wxPrintf( wxT(".\n") );
1247 wxEventType event_type
= wxEVT_NULL
;
1249 if (gdk_event
->button
== 1)
1251 switch (gdk_event
->type
)
1253 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1254 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1258 else if (gdk_event
->button
== 2)
1260 switch (gdk_event
->type
)
1262 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1263 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1267 else if (gdk_event
->button
== 3)
1269 switch (gdk_event
->type
)
1271 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1272 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1277 if ( event_type
== wxEVT_NULL
)
1279 // unknown mouse button or click type
1283 wxMouseEvent
event( event_type
);
1284 event
.SetTimestamp( gdk_event
->time
);
1285 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1286 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1287 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1288 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1289 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1290 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1291 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1293 event
.m_x
= (wxCoord
)gdk_event
->x
;
1294 event
.m_y
= (wxCoord
)gdk_event
->y
;
1296 AdjustEventButtonState(event
);
1298 // Some control don't have their own X window and thus cannot get
1301 if (!g_captureWindow
)
1303 wxCoord x
= event
.m_x
;
1304 wxCoord y
= event
.m_y
;
1305 if (win
->m_wxwindow
)
1307 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1308 x
+= pizza
->xoffset
;
1309 y
+= pizza
->yoffset
;
1312 wxNode
*node
= win
->GetChildren().First();
1315 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1317 node
= node
->Next();
1318 if (!child
->IsShown())
1321 if (child
->m_isStaticBox
)
1323 // wxStaticBox is transparent in the box itself
1324 int xx1
= child
->m_x
;
1325 int yy1
= child
->m_y
;
1326 int xx2
= child
->m_x
+ child
->m_width
;
1327 int yy2
= child
->m_x
+ child
->m_height
;
1330 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1332 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1334 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1336 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1339 event
.m_x
-= child
->m_x
;
1340 event
.m_y
-= child
->m_y
;
1347 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1348 (child
->m_x
<= x
) &&
1349 (child
->m_y
<= y
) &&
1350 (child
->m_x
+child
->m_width
>= x
) &&
1351 (child
->m_y
+child
->m_height
>= y
))
1354 event
.m_x
-= child
->m_x
;
1355 event
.m_y
-= child
->m_y
;
1362 event
.SetEventObject( win
);
1364 gs_timeLastClick
= gdk_event
->time
;
1367 wxPrintf( wxT("2) OnButtonPress from ") );
1368 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1369 wxPrintf( win->GetClassInfo()->GetClassName() );
1370 wxPrintf( wxT(".\n") );
1373 if (win
->GetEventHandler()->ProcessEvent( event
))
1375 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1382 //-----------------------------------------------------------------------------
1383 // "button_release_event"
1384 //-----------------------------------------------------------------------------
1386 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1391 wxapp_install_idle_handler();
1393 if (!win
->m_hasVMT
) return FALSE
;
1394 if (g_blockEventsOnDrag
) return FALSE
;
1395 if (g_blockEventsOnScroll
) return FALSE
;
1397 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1400 printf( "OnButtonRelease from " );
1401 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1402 printf( win->GetClassInfo()->GetClassName() );
1406 wxEventType event_type
= wxEVT_NULL
;
1408 switch (gdk_event
->button
)
1410 case 1: event_type
= wxEVT_LEFT_UP
; break;
1411 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1412 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1413 default: return FALSE
;
1416 wxMouseEvent
event( event_type
);
1417 event
.SetTimestamp( gdk_event
->time
);
1418 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1419 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1420 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1421 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1422 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1423 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1424 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1425 event
.m_x
= (wxCoord
)gdk_event
->x
;
1426 event
.m_y
= (wxCoord
)gdk_event
->y
;
1428 AdjustEventButtonState(event
);
1430 // Some control don't have their own X window and thus cannot get
1433 if (!g_captureWindow
)
1435 wxCoord x
= event
.m_x
;
1436 wxCoord y
= event
.m_y
;
1437 if (win
->m_wxwindow
)
1439 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1440 x
+= pizza
->xoffset
;
1441 y
+= pizza
->yoffset
;
1444 wxNode
*node
= win
->GetChildren().First();
1447 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1449 node
= node
->Next();
1450 if (!child
->IsShown())
1453 if (child
->m_isStaticBox
)
1455 // wxStaticBox is transparent in the box itself
1456 int xx1
= child
->m_x
;
1457 int yy1
= child
->m_y
;
1458 int xx2
= child
->m_x
+ child
->m_width
;
1459 int yy2
= child
->m_x
+ child
->m_height
;
1462 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1464 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1466 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1468 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1471 event
.m_x
-= child
->m_x
;
1472 event
.m_y
-= child
->m_y
;
1479 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1480 (child
->m_x
<= x
) &&
1481 (child
->m_y
<= y
) &&
1482 (child
->m_x
+child
->m_width
>= x
) &&
1483 (child
->m_y
+child
->m_height
>= y
))
1486 event
.m_x
-= child
->m_x
;
1487 event
.m_y
-= child
->m_y
;
1494 event
.SetEventObject( win
);
1496 if (win
->GetEventHandler()->ProcessEvent( event
))
1498 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1505 // ============================================================================
1507 // ============================================================================
1509 // init wxMouseEvent with the info from gdk_event
1510 #define InitMouseEvent(event, gdk_event) \
1511 event.SetTimestamp( gdk_event->time ); \
1512 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
1513 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
1514 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
1515 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
1516 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
1517 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
1518 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
1520 event.m_x = (wxCoord)gdk_event->x; \
1521 event.m_y = (wxCoord)gdk_event->y \
1523 //-----------------------------------------------------------------------------
1524 // "motion_notify_event"
1525 //-----------------------------------------------------------------------------
1527 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
,
1528 GdkEventMotion
*gdk_event
,
1534 wxapp_install_idle_handler();
1536 if (!win
->m_hasVMT
) return FALSE
;
1537 if (g_blockEventsOnDrag
) return FALSE
;
1538 if (g_blockEventsOnScroll
) return FALSE
;
1540 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1542 if (gdk_event
->is_hint
)
1546 GdkModifierType state
;
1547 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1553 printf( "OnMotion from " );
1554 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1555 printf( win->GetClassInfo()->GetClassName() );
1559 wxMouseEvent
event( wxEVT_MOTION
);
1560 InitMouseEvent(event
, gdk_event
);
1562 if ( g_captureWindow
)
1564 // synthetize a mouse enter or leave event if needed
1565 GdkWindow
*winUnderMouse
= gdk_window_at_pointer(NULL
, NULL
);
1566 bool hasMouse
= winUnderMouse
== gdk_event
->window
;
1567 if ( hasMouse
!= g_captureWindowHasMouse
)
1569 // the mouse changed window
1570 g_captureWindowHasMouse
= hasMouse
;
1572 wxMouseEvent
event(g_captureWindowHasMouse
? wxEVT_ENTER_WINDOW
1573 : wxEVT_LEAVE_WINDOW
);
1574 InitMouseEvent(event
, gdk_event
);
1575 event
.SetEventObject(win
);
1576 win
->GetEventHandler()->ProcessEvent(event
);
1581 // Some control don't have their own X window and thus cannot get
1584 wxCoord x
= event
.m_x
;
1585 wxCoord y
= event
.m_y
;
1586 if (win
->m_wxwindow
)
1588 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1589 x
+= pizza
->xoffset
;
1590 y
+= pizza
->yoffset
;
1593 wxNode
*node
= win
->GetChildren().First();
1596 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1598 node
= node
->Next();
1599 if (!child
->IsShown())
1602 if (child
->m_isStaticBox
)
1604 // wxStaticBox is transparent in the box itself
1605 int xx1
= child
->m_x
;
1606 int yy1
= child
->m_y
;
1607 int xx2
= child
->m_x
+ child
->m_width
;
1608 int yy2
= child
->m_x
+ child
->m_height
;
1611 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1613 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1615 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1617 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1620 event
.m_x
-= child
->m_x
;
1621 event
.m_y
-= child
->m_y
;
1628 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1629 (child
->m_x
<= x
) &&
1630 (child
->m_y
<= y
) &&
1631 (child
->m_x
+child
->m_width
>= x
) &&
1632 (child
->m_y
+child
->m_height
>= y
))
1635 event
.m_x
-= child
->m_x
;
1636 event
.m_y
-= child
->m_y
;
1643 event
.SetEventObject( win
);
1645 if (win
->GetEventHandler()->ProcessEvent( event
))
1647 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1654 //-----------------------------------------------------------------------------
1656 //-----------------------------------------------------------------------------
1658 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
,
1659 GdkEvent
*WXUNUSED(event
),
1665 wxapp_install_idle_handler();
1667 if (!win
->m_hasVMT
) return FALSE
;
1668 if (g_blockEventsOnDrag
) return FALSE
;
1670 switch ( g_sendActivateEvent
)
1673 // we've got focus from outside, synthetize wxActivateEvent
1674 g_sendActivateEvent
= 1;
1678 // another our window just lost focus, it was already ours before
1679 // - don't send any wxActivateEvent
1680 g_sendActivateEvent
= -1;
1685 g_focusWindow
= win
;
1688 wxPrintf( "OnSetFocus from " );
1689 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
1690 wxPrintf( win
->GetClassInfo()->GetClassName() );
1694 // notify the parent keeping track of focus for the kbd navigation
1695 // purposes that we got it
1696 wxChildFocusEvent
eventFocus(win
);
1697 (void)win
->GetEventHandler()->ProcessEvent(eventFocus
);
1701 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1705 // caret needs to be informed about focus change
1706 wxCaret
*caret
= win
->GetCaret();
1709 caret
->OnSetFocus();
1711 #endif // wxUSE_CARET
1713 if (win
->IsTopLevel())
1715 wxActivateEvent
event( wxEVT_ACTIVATE
, TRUE
, win
->GetId() );
1716 event
.SetEventObject( win
);
1718 // ignore return value
1719 win
->GetEventHandler()->ProcessEvent( event
);
1722 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1723 event
.SetEventObject( win
);
1725 if (win
->GetEventHandler()->ProcessEvent( event
))
1727 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1735 //-----------------------------------------------------------------------------
1736 // "focus_out_event"
1737 //-----------------------------------------------------------------------------
1739 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindowGTK
*win
)
1744 wxapp_install_idle_handler();
1746 if (!win
->m_hasVMT
) return FALSE
;
1747 if (g_blockEventsOnDrag
) return FALSE
;
1749 // if the focus goes out of our app alltogether, OnIdle() will send
1750 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1751 // g_sendActivateEvent to -1
1752 g_sendActivateEvent
= 0;
1754 wxWindowGTK
*winFocus
= wxFindFocusedChild(win
);
1758 g_focusWindow
= (wxWindowGTK
*)NULL
;
1761 wxPrintf( "OnKillFocus from " );
1762 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
1763 wxPrintf( win
->GetClassInfo()->GetClassName() );
1773 // caret needs to be informed about focus change
1774 wxCaret
*caret
= win
->GetCaret();
1777 caret
->OnKillFocus();
1779 #endif // wxUSE_CARET
1781 if (win
->IsTopLevel())
1783 wxActivateEvent
event( wxEVT_ACTIVATE
, FALSE
, win
->GetId() );
1784 event
.SetEventObject( win
);
1786 // ignore return value
1787 win
->GetEventHandler()->ProcessEvent( event
);
1790 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1791 event
.SetEventObject( win
);
1793 if (win
->GetEventHandler()->ProcessEvent( event
))
1795 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1802 //-----------------------------------------------------------------------------
1803 // "enter_notify_event"
1804 //-----------------------------------------------------------------------------
1806 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1811 wxapp_install_idle_handler();
1813 if (!win
->m_hasVMT
) return FALSE
;
1814 if (g_blockEventsOnDrag
) return FALSE
;
1816 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1818 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1819 event
.SetTimestamp( gdk_event
->time
);
1820 event
.SetEventObject( win
);
1824 GdkModifierType state
= (GdkModifierType
)0;
1826 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1828 InitMouseEvent(event
, gdk_event
);
1833 if (win
->GetEventHandler()->ProcessEvent( event
))
1835 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1842 //-----------------------------------------------------------------------------
1843 // "leave_notify_event"
1844 //-----------------------------------------------------------------------------
1846 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1851 wxapp_install_idle_handler();
1853 if (!win
->m_hasVMT
) return FALSE
;
1854 if (g_blockEventsOnDrag
) return FALSE
;
1856 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1858 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1859 event
.SetTimestamp( gdk_event
->time
);
1860 event
.SetEventObject( win
);
1864 GdkModifierType state
= (GdkModifierType
)0;
1866 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1868 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1869 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1870 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1871 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1872 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1873 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1874 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1879 if (win
->GetEventHandler()->ProcessEvent( event
))
1881 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1888 //-----------------------------------------------------------------------------
1889 // "value_changed" from m_vAdjust
1890 //-----------------------------------------------------------------------------
1892 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1897 wxapp_install_idle_handler();
1899 if (g_blockEventsOnDrag
) return;
1901 if (!win
->m_hasVMT
) return;
1903 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1904 if (fabs(diff
) < 0.2) return;
1906 win
->m_oldVerticalPos
= adjust
->value
;
1908 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1909 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1911 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1912 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1913 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1914 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1915 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1917 int value
= (int)(adjust
->value
+0.5);
1919 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1920 event
.SetEventObject( win
);
1921 win
->GetEventHandler()->ProcessEvent( event
);
1924 //-----------------------------------------------------------------------------
1925 // "value_changed" from m_hAdjust
1926 //-----------------------------------------------------------------------------
1928 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1933 wxapp_install_idle_handler();
1935 if (g_blockEventsOnDrag
) return;
1936 if (!win
->m_hasVMT
) return;
1938 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1939 if (fabs(diff
) < 0.2) return;
1941 win
->m_oldHorizontalPos
= adjust
->value
;
1943 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1944 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1946 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1947 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1948 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1949 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1950 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1952 int value
= (int)(adjust
->value
+0.5);
1954 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1955 event
.SetEventObject( win
);
1956 win
->GetEventHandler()->ProcessEvent( event
);
1959 //-----------------------------------------------------------------------------
1960 // "button_press_event" from scrollbar
1961 //-----------------------------------------------------------------------------
1963 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1964 GdkEventButton
*gdk_event
,
1970 wxapp_install_idle_handler();
1973 g_blockEventsOnScroll
= TRUE
;
1974 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1979 //-----------------------------------------------------------------------------
1980 // "button_release_event" from scrollbar
1981 //-----------------------------------------------------------------------------
1983 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1984 GdkEventButton
*WXUNUSED(gdk_event
),
1989 // don't test here as we can release the mouse while being over
1990 // a different window than the slider
1992 // if (gdk_event->window != widget->slider) return FALSE;
1994 g_blockEventsOnScroll
= FALSE
;
1996 if (win
->m_isScrolling
)
1998 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
2002 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
2003 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
2005 value
= (int)(win
->m_hAdjust
->value
+0.5);
2008 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
2010 value
= (int)(win
->m_vAdjust
->value
+0.5);
2014 wxScrollWinEvent
event( command
, value
, dir
);
2015 event
.SetEventObject( win
);
2016 win
->GetEventHandler()->ProcessEvent( event
);
2019 win
->m_isScrolling
= FALSE
;
2024 // ----------------------------------------------------------------------------
2025 // this wxWindowBase function is implemented here (in platform-specific file)
2026 // because it is static and so couldn't be made virtual
2027 // ----------------------------------------------------------------------------
2029 wxWindow
*wxWindowBase::FindFocus()
2031 // the cast is necessary when we compile in wxUniversal mode
2032 return (wxWindow
*)g_focusWindow
;
2035 //-----------------------------------------------------------------------------
2036 // "realize" from m_widget
2037 //-----------------------------------------------------------------------------
2039 /* We cannot set colours and fonts before the widget has
2040 been realized, so we do this directly after realization. */
2043 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
2048 wxapp_install_idle_handler();
2050 if (win
->m_delayedBackgroundColour
)
2051 win
->SetBackgroundColour( win
->GetBackgroundColour() );
2053 if (win
->m_delayedForegroundColour
)
2054 win
->SetForegroundColour( win
->GetForegroundColour() );
2056 wxWindowCreateEvent
event( win
);
2057 event
.SetEventObject( win
);
2058 win
->GetEventHandler()->ProcessEvent( event
);
2063 //-----------------------------------------------------------------------------
2065 //-----------------------------------------------------------------------------
2068 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
2069 GtkAllocation
*WXUNUSED(alloc
),
2073 wxapp_install_idle_handler();
2075 if (!win
->m_hasScrolling
) return;
2077 int client_width
= 0;
2078 int client_height
= 0;
2079 win
->GetClientSize( &client_width
, &client_height
);
2080 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
2083 win
->m_oldClientWidth
= client_width
;
2084 win
->m_oldClientHeight
= client_height
;
2086 if (!win
->m_nativeSizeEvent
)
2088 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
2089 event
.SetEventObject( win
);
2090 win
->GetEventHandler()->ProcessEvent( event
);
2096 #define WXUNUSED_UNLESS_XIM(param) param
2098 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2101 /* Resize XIM window */
2104 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2105 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
2106 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2109 wxapp_install_idle_handler();
2115 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
2119 gdk_window_get_size (widget
->window
, &width
, &height
);
2120 win
->m_icattr
->preedit_area
.width
= width
;
2121 win
->m_icattr
->preedit_area
.height
= height
;
2122 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2127 //-----------------------------------------------------------------------------
2128 // "realize" from m_wxwindow
2129 //-----------------------------------------------------------------------------
2131 /* Initialize XIM support */
2134 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2135 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2138 wxapp_install_idle_handler();
2141 if (win
->m_ic
) return FALSE
;
2142 if (!widget
) return FALSE
;
2143 if (!gdk_im_ready()) return FALSE
;
2145 win
->m_icattr
= gdk_ic_attr_new();
2146 if (!win
->m_icattr
) return FALSE
;
2150 GdkColormap
*colormap
;
2151 GdkICAttr
*attr
= win
->m_icattr
;
2152 unsigned attrmask
= GDK_IC_ALL_REQ
;
2154 GdkIMStyle supported_style
= (GdkIMStyle
)
2155 (GDK_IM_PREEDIT_NONE
|
2156 GDK_IM_PREEDIT_NOTHING
|
2157 GDK_IM_PREEDIT_POSITION
|
2158 GDK_IM_STATUS_NONE
|
2159 GDK_IM_STATUS_NOTHING
);
2161 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2162 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2164 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2165 attr
->client_window
= widget
->window
;
2167 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2168 gtk_widget_get_default_colormap ())
2170 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2171 attr
->preedit_colormap
= colormap
;
2174 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2175 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2176 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2177 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2179 switch (style
& GDK_IM_PREEDIT_MASK
)
2181 case GDK_IM_PREEDIT_POSITION
:
2182 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2184 g_warning ("over-the-spot style requires fontset");
2188 gdk_window_get_size (widget
->window
, &width
, &height
);
2190 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2191 attr
->spot_location
.x
= 0;
2192 attr
->spot_location
.y
= height
;
2193 attr
->preedit_area
.x
= 0;
2194 attr
->preedit_area
.y
= 0;
2195 attr
->preedit_area
.width
= width
;
2196 attr
->preedit_area
.height
= height
;
2197 attr
->preedit_fontset
= widget
->style
->font
;
2202 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2204 if (win
->m_ic
== NULL
)
2205 g_warning ("Can't create input context.");
2208 mask
= gdk_window_get_events (widget
->window
);
2209 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2210 gdk_window_set_events (widget
->window
, mask
);
2212 if (GTK_WIDGET_HAS_FOCUS(widget
))
2213 gdk_im_begin (win
->m_ic
, widget
->window
);
2220 //-----------------------------------------------------------------------------
2221 // InsertChild for wxWindowGTK.
2222 //-----------------------------------------------------------------------------
2224 /* Callback for wxWindowGTK. This very strange beast has to be used because
2225 * C++ has no virtual methods in a constructor. We have to emulate a
2226 * virtual function here as wxNotebook requires a different way to insert
2227 * a child in it. I had opted for creating a wxNotebookPage window class
2228 * which would have made this superfluous (such in the MDI window system),
2229 * but no-one was listening to me... */
2231 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child
)
2233 /* the window might have been scrolled already, do we
2234 have to adapt the position */
2235 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2236 child
->m_x
+= pizza
->xoffset
;
2237 child
->m_y
+= pizza
->yoffset
;
2239 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2240 GTK_WIDGET(child
->m_widget
),
2247 //-----------------------------------------------------------------------------
2249 //-----------------------------------------------------------------------------
2251 wxWindow
*wxGetActiveWindow()
2253 // the cast is necessary when we compile in wxUniversal mode
2254 return (wxWindow
*)g_focusWindow
;
2257 //-----------------------------------------------------------------------------
2259 //-----------------------------------------------------------------------------
2261 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
2263 #ifdef __WXUNIVERSAL__
2264 IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
)
2266 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2267 #endif // __WXUNIVERSAL__/__WXGTK__
2269 void wxWindowGTK::Init()
2275 m_widget
= (GtkWidget
*) NULL
;
2276 m_wxwindow
= (GtkWidget
*) NULL
;
2277 m_focusWidget
= (GtkWidget
*) NULL
;
2287 m_needParent
= TRUE
;
2288 m_isBeingDeleted
= FALSE
;
2291 m_nativeSizeEvent
= FALSE
;
2293 m_hasScrolling
= FALSE
;
2294 m_isScrolling
= FALSE
;
2296 m_hAdjust
= (GtkAdjustment
*) NULL
;
2297 m_vAdjust
= (GtkAdjustment
*) NULL
;
2298 m_oldHorizontalPos
= 0.0;
2299 m_oldVerticalPos
= 0.0;
2302 m_widgetStyle
= (GtkStyle
*) NULL
;
2304 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2306 m_isStaticBox
= FALSE
;
2307 m_isRadioButton
= FALSE
;
2309 m_acceptsFocus
= FALSE
;
2311 m_clipPaintRegion
= FALSE
;
2313 m_cursor
= *wxSTANDARD_CURSOR
;
2315 m_delayedForegroundColour
= FALSE
;
2316 m_delayedBackgroundColour
= FALSE
;
2319 m_ic
= (GdkIC
*) NULL
;
2320 m_icattr
= (GdkICAttr
*) NULL
;
2324 wxWindowGTK::wxWindowGTK()
2329 wxWindowGTK::wxWindowGTK( wxWindow
*parent
,
2334 const wxString
&name
)
2338 Create( parent
, id
, pos
, size
, style
, name
);
2341 bool wxWindowGTK::Create( wxWindow
*parent
,
2346 const wxString
&name
)
2348 if (!PreCreation( parent
, pos
, size
) ||
2349 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2351 wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
2355 m_insertCallback
= wxInsertChildInWindow
;
2357 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2358 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2360 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2362 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2363 scroll_class
->scrollbar_spacing
= 0;
2365 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2367 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2368 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2370 m_wxwindow
= gtk_pizza_new();
2372 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2374 #ifndef __WXUNIVERSAL__
2375 #if (GTK_MINOR_VERSION > 0)
2376 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2378 if (HasFlag(wxRAISED_BORDER
))
2380 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2382 else if (HasFlag(wxSUNKEN_BORDER
))
2384 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2386 else if (HasFlag(wxSIMPLE_BORDER
))
2388 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2392 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2394 #else // GTK_MINOR_VERSION == 0
2395 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2397 if (HasFlag(wxRAISED_BORDER
))
2399 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2401 else if (HasFlag(wxSUNKEN_BORDER
))
2403 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2407 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2409 #endif // GTK_MINOR_VERSION
2410 #endif // __WXUNIVERSAL__
2412 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2413 m_acceptsFocus
= TRUE
;
2415 #if (GTK_MINOR_VERSION == 0)
2416 // shut the viewport up
2417 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2418 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2419 #endif // GTK_MINOR_VERSION == 0
2421 // I _really_ don't want scrollbars in the beginning
2422 m_vAdjust
->lower
= 0.0;
2423 m_vAdjust
->upper
= 1.0;
2424 m_vAdjust
->value
= 0.0;
2425 m_vAdjust
->step_increment
= 1.0;
2426 m_vAdjust
->page_increment
= 1.0;
2427 m_vAdjust
->page_size
= 5.0;
2428 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2429 m_hAdjust
->lower
= 0.0;
2430 m_hAdjust
->upper
= 1.0;
2431 m_hAdjust
->value
= 0.0;
2432 m_hAdjust
->step_increment
= 1.0;
2433 m_hAdjust
->page_increment
= 1.0;
2434 m_hAdjust
->page_size
= 5.0;
2435 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2437 // these handlers block mouse events to any window during scrolling such as
2438 // motion events and prevent GTK and wxWindows from fighting over where the
2441 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2442 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2444 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2445 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2447 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2448 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2450 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2451 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2453 // these handlers get notified when screen updates are required either when
2454 // scrolling or when the window size (and therefore scrollbar configuration)
2457 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2458 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2459 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2460 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2462 gtk_widget_show( m_wxwindow
);
2465 m_parent
->DoAddChild( this );
2467 m_focusWidget
= m_wxwindow
;
2476 wxWindowGTK::~wxWindowGTK()
2478 wxASSERT_MSG( g_capturedWindows
.IndexOf(this) == wxNOT_FOUND
, wxT("trying to destroy window that didn't release focus") );
2480 if (g_focusWindow
== this)
2481 g_focusWindow
= NULL
;
2483 m_isBeingDeleted
= TRUE
;
2492 m_parent
->RemoveChild( this );
2496 gdk_ic_destroy (m_ic
);
2498 gdk_ic_attr_destroy (m_icattr
);
2503 #if DISABLE_STYLE_IF_BROKEN_THEME
2504 // don't delete if it's a pixmap theme style
2505 if (!m_widgetStyle
->engine_data
)
2506 gtk_style_unref( m_widgetStyle
);
2508 m_widgetStyle
= (GtkStyle
*) NULL
;
2513 gtk_widget_destroy( m_wxwindow
);
2514 m_wxwindow
= (GtkWidget
*) NULL
;
2519 gtk_widget_destroy( m_widget
);
2520 m_widget
= (GtkWidget
*) NULL
;
2524 bool wxWindowGTK::PreCreation( wxWindowGTK
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2526 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2528 /* this turns -1 into 20 so that a minimal window is
2529 visible even although -1,-1 has been given as the
2530 size of the window. the same trick is used in other
2531 ports and should make debugging easier */
2532 m_width
= WidthDefault(size
.x
);
2533 m_height
= HeightDefault(size
.y
);
2538 /* some reasonable defaults */
2543 m_x
= (gdk_screen_width () - m_width
) / 2;
2544 if (m_x
< 10) m_x
= 10;
2548 m_y
= (gdk_screen_height () - m_height
) / 2;
2549 if (m_y
< 10) m_y
= 10;
2556 void wxWindowGTK::PostCreation()
2558 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2564 // these get reported to wxWindows -> wxPaintEvent
2566 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2568 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2569 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2571 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2572 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2574 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2576 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2577 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2581 // these are called when the "sunken" or "raised" borders are drawn */
2582 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2583 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2585 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2586 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2591 if (m_focusWidget
== NULL
)
2592 m_focusWidget
= m_widget
;
2595 if (GetClassInfo() && GetClassInfo()->GetClassName())
2596 wxPrintf( GetClassInfo()->GetClassName() );
2600 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event",
2601 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2603 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event",
2604 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2606 // connect to the various key and mouse handlers
2608 GtkWidget
*connect_widget
= GetConnectWidget();
2610 ConnectWidget( connect_widget
);
2612 /* We cannot set colours, fonts and cursors before the widget has
2613 been realized, so we do this directly after realization */
2614 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2615 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2619 // Catch native resize events
2620 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2621 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2623 // Initialize XIM support
2624 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2625 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2627 // And resize XIM window
2628 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2629 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2632 if (!GTK_IS_COMBO(m_widget
))
2634 // This is needed if we want to add our windows into native
2635 // GTK control, such as the toolbar. With this callback, the
2636 // toolbar gets to know the correct size (the one set by the
2637 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2638 // when moving to GTK 2.0.
2639 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2640 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2646 void wxWindowGTK::ConnectWidget( GtkWidget
*widget
)
2648 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2649 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2651 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2652 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2654 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2655 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2657 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2658 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2660 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2661 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2663 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2664 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2666 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2667 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2670 bool wxWindowGTK::Destroy()
2672 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2676 return wxWindowBase::Destroy();
2679 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
)
2681 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2684 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2686 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2687 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") );
2690 printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
2693 if (m_resizing
) return; /* I don't like recursions */
2696 int currentX
, currentY
;
2697 GetPosition(¤tX
, ¤tY
);
2702 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
2704 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2706 /* don't set the size for children of wxNotebook, just take the values. */
2714 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2716 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2718 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2719 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2720 if (width
!= -1) m_width
= width
;
2721 if (height
!= -1) m_height
= height
;
2725 m_x
= x
+ pizza
->xoffset
;
2726 m_y
= y
+ pizza
->yoffset
;
2731 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2733 if (width
== -1) m_width
= 80;
2736 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2738 if (height
== -1) m_height
= 26;
2741 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2742 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2743 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2744 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2747 int bottom_border
= 0;
2749 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2751 /* the default button has a border around it */
2756 DoMoveWindow( m_x
-border
,
2759 m_height
+border
+bottom_border
);
2764 /* Sometimes the client area changes size without the
2765 whole windows's size changing, but if the whole
2766 windows's size doesn't change, no wxSizeEvent will
2767 normally be sent. Here we add an extra test if
2768 the client test has been changed and this will
2770 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2774 wxPrintf( "OnSize sent from " );
2775 if (GetClassInfo() && GetClassInfo()->GetClassName())
2776 wxPrintf( GetClassInfo()->GetClassName() );
2777 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2780 if (!m_nativeSizeEvent
)
2782 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2783 event
.SetEventObject( this );
2784 GetEventHandler()->ProcessEvent( event
);
2790 void wxWindowGTK::OnInternalIdle()
2792 if ( g_sendActivateEvent
!= -1 )
2794 bool activate
= g_sendActivateEvent
!= 0;
2797 g_sendActivateEvent
= -1;
2799 wxTheApp
->SetActive(activate
, (wxWindow
*)g_focusWindowLast
);
2802 wxCursor cursor
= m_cursor
;
2803 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2807 /* I now set the cursor anew in every OnInternalIdle call
2808 as setting the cursor in a parent window also effects the
2809 windows above so that checking for the current cursor is
2814 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2816 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2818 if (!g_globalCursor
.Ok())
2819 cursor
= *wxSTANDARD_CURSOR
;
2821 window
= m_widget
->window
;
2822 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2823 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2829 GdkWindow
*window
= m_widget
->window
;
2830 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2831 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2839 void wxWindowGTK::DoGetSize( int *width
, int *height
) const
2841 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2843 if (width
) (*width
) = m_width
;
2844 if (height
) (*height
) = m_height
;
2847 void wxWindowGTK::DoSetClientSize( int width
, int height
)
2849 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2853 SetSize( width
, height
);
2860 #ifndef __WXUNIVERSAL__
2861 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2863 /* when using GTK 1.2 we set the shadow border size to 2 */
2867 if (HasFlag(wxSIMPLE_BORDER
))
2869 /* when using GTK 1.2 we set the simple border size to 1 */
2873 #endif // __WXUNIVERSAL__
2877 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2879 GtkRequisition vscroll_req
;
2880 vscroll_req
.width
= 2;
2881 vscroll_req
.height
= 2;
2882 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2883 (scroll_window
->vscrollbar
, &vscroll_req
);
2885 GtkRequisition hscroll_req
;
2886 hscroll_req
.width
= 2;
2887 hscroll_req
.height
= 2;
2888 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2889 (scroll_window
->hscrollbar
, &hscroll_req
);
2891 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2893 if (scroll_window
->vscrollbar_visible
)
2895 dw
+= vscroll_req
.width
;
2896 dw
+= scroll_class
->scrollbar_spacing
;
2899 if (scroll_window
->hscrollbar_visible
)
2901 dh
+= hscroll_req
.height
;
2902 dh
+= scroll_class
->scrollbar_spacing
;
2906 SetSize( width
+dw
, height
+dh
);
2910 void wxWindowGTK::DoGetClientSize( int *width
, int *height
) const
2912 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2916 if (width
) (*width
) = m_width
;
2917 if (height
) (*height
) = m_height
;
2924 #ifndef __WXUNIVERSAL__
2925 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2927 /* when using GTK 1.2 we set the shadow border size to 2 */
2931 if (HasFlag(wxSIMPLE_BORDER
))
2933 /* when using GTK 1.2 we set the simple border size to 1 */
2937 #endif // __WXUNIVERSAL__
2941 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2943 GtkRequisition vscroll_req
;
2944 vscroll_req
.width
= 2;
2945 vscroll_req
.height
= 2;
2946 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2947 (scroll_window
->vscrollbar
, &vscroll_req
);
2949 GtkRequisition hscroll_req
;
2950 hscroll_req
.width
= 2;
2951 hscroll_req
.height
= 2;
2952 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2953 (scroll_window
->hscrollbar
, &hscroll_req
);
2955 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2957 if (scroll_window
->vscrollbar_visible
)
2959 dw
+= vscroll_req
.width
;
2960 dw
+= scroll_class
->scrollbar_spacing
;
2963 if (scroll_window
->hscrollbar_visible
)
2965 dh
+= hscroll_req
.height
;
2966 dh
+= scroll_class
->scrollbar_spacing
;
2970 if (width
) (*width
) = m_width
- dw
;
2971 if (height
) (*height
) = m_height
- dh
;
2975 printf( "GetClientSize, name %s ", GetName().c_str() );
2976 if (width) printf( " width = %d", (*width) );
2977 if (height) printf( " height = %d", (*height) );
2982 void wxWindowGTK::DoGetPosition( int *x
, int *y
) const
2984 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2988 if (m_parent
&& m_parent
->m_wxwindow
)
2990 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2991 dx
= pizza
->xoffset
;
2992 dy
= pizza
->yoffset
;
2998 if ( !IsTopLevel() && m_parent
)
3000 // We may be faking the client origin. So a window that's really at (0,
3001 // 30) may appear (to wxWin apps) to be at (0, 0).
3002 wxPoint
pt(m_parent
->GetClientAreaOrigin());
3011 void wxWindowGTK::DoClientToScreen( int *x
, int *y
) const
3013 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3015 if (!m_widget
->window
) return;
3017 GdkWindow
*source
= (GdkWindow
*) NULL
;
3019 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3021 source
= m_widget
->window
;
3025 gdk_window_get_origin( source
, &org_x
, &org_y
);
3029 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3031 org_x
+= m_widget
->allocation
.x
;
3032 org_y
+= m_widget
->allocation
.y
;
3040 void wxWindowGTK::DoScreenToClient( int *x
, int *y
) const
3042 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3044 if (!m_widget
->window
) return;
3046 GdkWindow
*source
= (GdkWindow
*) NULL
;
3048 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3050 source
= m_widget
->window
;
3054 gdk_window_get_origin( source
, &org_x
, &org_y
);
3058 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3060 org_x
+= m_widget
->allocation
.x
;
3061 org_y
+= m_widget
->allocation
.y
;
3069 bool wxWindowGTK::Show( bool show
)
3071 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3073 if (!wxWindowBase::Show(show
))
3080 gtk_widget_show( m_widget
);
3082 gtk_widget_hide( m_widget
);
3087 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
)
3089 win
->OnParentEnable(enable
);
3091 // Recurse, so that children have the opportunity to Do The Right Thing
3092 // and reset colours that have been messed up by a parent's (really ancestor's)
3094 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
3096 node
= node
->GetNext() )
3098 wxWindow
*child
= node
->GetData();
3099 if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
)))
3100 wxWindowNotifyEnable(child
, enable
);
3104 bool wxWindowGTK::Enable( bool enable
)
3106 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3108 if (!wxWindowBase::Enable(enable
))
3114 gtk_widget_set_sensitive( m_widget
, enable
);
3116 gtk_widget_set_sensitive( m_wxwindow
, enable
);
3118 wxWindowNotifyEnable(this, enable
);
3123 int wxWindowGTK::GetCharHeight() const
3125 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
3127 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
3129 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3131 return font
->ascent
+ font
->descent
;
3134 int wxWindowGTK::GetCharWidth() const
3136 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
3138 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
3140 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3142 return gdk_string_width( font
, "H" );
3145 void wxWindowGTK::GetTextExtent( const wxString
& string
,
3149 int *externalLeading
,
3150 const wxFont
*theFont
) const
3152 wxFont fontToUse
= m_font
;
3153 if (theFont
) fontToUse
= *theFont
;
3155 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
3157 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
3158 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
3159 if (y
) (*y
) = font
->ascent
+ font
->descent
;
3160 if (descent
) (*descent
) = font
->descent
;
3161 if (externalLeading
) (*externalLeading
) = 0; // ??
3164 void wxWindowGTK::SetFocus()
3166 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3170 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3171 gtk_widget_grab_focus (m_wxwindow
);
3177 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
3179 gtk_widget_grab_focus (m_widget
);
3181 else if (GTK_IS_CONTAINER(m_widget
))
3183 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
3192 bool wxWindowGTK::AcceptsFocus() const
3194 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3197 bool wxWindowGTK::Reparent( wxWindowBase
*newParentBase
)
3199 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3201 wxWindowGTK
*oldParent
= m_parent
,
3202 *newParent
= (wxWindowGTK
*)newParentBase
;
3204 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3206 if ( !wxWindowBase::Reparent(newParent
) )
3209 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3211 /* prevent GTK from deleting the widget arbitrarily */
3212 gtk_widget_ref( m_widget
);
3216 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3219 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3223 /* insert GTK representation */
3224 (*(newParent
->m_insertCallback
))(newParent
, this);
3227 /* reverse: prevent GTK from deleting the widget arbitrarily */
3228 gtk_widget_unref( m_widget
);
3233 void wxWindowGTK::DoAddChild(wxWindowGTK
*child
)
3235 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3237 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3239 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3244 /* insert GTK representation */
3245 (*m_insertCallback
)(this, child
);
3248 void wxWindowGTK::Raise()
3250 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3252 if (!m_widget
->window
) return;
3254 gdk_window_raise( m_widget
->window
);
3257 void wxWindowGTK::Lower()
3259 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3261 if (!m_widget
->window
) return;
3263 gdk_window_lower( m_widget
->window
);
3266 bool wxWindowGTK::SetCursor( const wxCursor
&cursor
)
3268 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3270 if (cursor
== m_cursor
)
3274 wxapp_install_idle_handler();
3276 if (cursor
== wxNullCursor
)
3277 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3279 return wxWindowBase::SetCursor( cursor
);
3282 void wxWindowGTK::WarpPointer( int x
, int y
)
3284 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3286 /* we provide this function ourselves as it is
3287 missing in GDK (top of this file) */
3289 GdkWindow
*window
= (GdkWindow
*) NULL
;
3291 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3293 window
= GetConnectWidget()->window
;
3296 gdk_window_warp_pointer( window
, x
, y
);
3299 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect
*rect
)
3301 if (!m_widget
) return;
3302 if (!m_widget
->window
) return;
3304 // temporarily hide the caret to avoid nasty interactions between caret
3305 // drawing and the window contents redraw
3306 #if 0 // def wxUSE_CARET -- doesn't seem to help :-(
3307 wxCaretSuspend
cs((wxWindow
*)this);
3308 #endif // wxUSE_CARET
3310 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3314 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3316 rect
->width
, rect
->height
);
3320 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3324 /* there is no GTK equivalent of "draw only, don't clear" so we
3325 invent our own in the GtkPizza widget */
3333 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3334 gboolean old_clear = pizza->clear_on_draw;
3335 gtk_pizza_set_clear( pizza, FALSE );
3336 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3337 gtk_pizza_set_clear( pizza, old_clear );
3339 GdkEventExpose gdk_event
;
3340 gdk_event
.type
= GDK_EXPOSE
;
3341 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3342 gdk_event
.count
= 0;
3343 gdk_event
.area
.x
= 0;
3344 gdk_event
.area
.y
= 0;
3345 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3346 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3347 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, (wxWindow
*)this );
3351 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3360 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3361 gboolean old_clear = pizza->clear_on_draw;
3362 gtk_pizza_set_clear( pizza, FALSE );
3364 GdkRectangle gdk_rect;
3365 gdk_rect.x = rect->x;
3366 gdk_rect.y = rect->y;
3367 gdk_rect.width = rect->width;
3368 gdk_rect.height = rect->height;
3369 gtk_widget_draw( m_wxwindow, &gdk_rect );
3370 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3372 gtk_pizza_set_clear( pizza, old_clear );
3374 GdkEventExpose gdk_event
;
3375 gdk_event
.type
= GDK_EXPOSE
;
3376 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3377 gdk_event
.count
= 0;
3378 gdk_event
.area
.x
= rect
->x
;
3379 gdk_event
.area
.y
= rect
->y
;
3380 gdk_event
.area
.width
= rect
->width
;
3381 gdk_event
.area
.height
= rect
->height
;
3382 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, (wxWindow
*)this );
3386 GdkRectangle gdk_rect
;
3387 gdk_rect
.x
= rect
->x
;
3388 gdk_rect
.y
= rect
->y
;
3389 gdk_rect
.width
= rect
->width
;
3390 gdk_rect
.height
= rect
->height
;
3391 gtk_widget_draw( m_widget
, &gdk_rect
);
3396 void wxWindowGTK::Clear()
3398 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3400 if (!m_widget
->window
) return;
3402 if (m_wxwindow
&& m_wxwindow
->window
)
3404 // gdk_window_clear( m_wxwindow->window );
3409 void wxWindowGTK::DoSetToolTip( wxToolTip
*tip
)
3411 wxWindowBase::DoSetToolTip(tip
);
3414 m_tooltip
->Apply( (wxWindow
*)this );
3417 void wxWindowGTK::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3419 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3421 #endif // wxUSE_TOOLTIPS
3423 bool wxWindowGTK::SetBackgroundColour( const wxColour
&colour
)
3425 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3427 if (!wxWindowBase::SetBackgroundColour(colour
))
3429 // don't leave if the GTK widget has just
3431 if (!m_delayedBackgroundColour
) return FALSE
;
3434 GdkWindow
*window
= (GdkWindow
*) NULL
;
3436 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3438 window
= GetConnectWidget()->window
;
3442 // indicate that a new style has been set
3443 // but it couldn't get applied as the
3444 // widget hasn't been realized yet.
3445 m_delayedBackgroundColour
= TRUE
;
3449 (m_wxwindow
->window
) &&
3450 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3452 /* wxMSW doesn't clear the window here. I don't do that either to
3453 provide compatibility. call Clear() to do the job. */
3455 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3456 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3464 bool wxWindowGTK::SetForegroundColour( const wxColour
&colour
)
3466 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3468 if (!wxWindowBase::SetForegroundColour(colour
))
3470 // don't leave if the GTK widget has just
3472 if (!m_delayedForegroundColour
) return FALSE
;
3475 GdkWindow
*window
= (GdkWindow
*) NULL
;
3477 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3479 window
= GetConnectWidget()->window
;
3483 // indicate that a new style has been set
3484 // but it couldn't get applied as the
3485 // widget hasn't been realized yet.
3486 m_delayedForegroundColour
= TRUE
;
3494 GtkStyle
*wxWindowGTK::GetWidgetStyle()
3498 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3500 /* FIXME: is this necessary? */
3501 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3503 remake
->klass
= m_widgetStyle
->klass
;
3506 gtk_style_unref( m_widgetStyle
);
3507 m_widgetStyle
= remake
;
3511 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3514 def
= gtk_widget_get_default_style();
3516 m_widgetStyle
= gtk_style_copy( def
);
3518 /* FIXME: is this necessary? */
3519 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3521 m_widgetStyle
->klass
= def
->klass
;
3525 return m_widgetStyle
;
3528 void wxWindowGTK::SetWidgetStyle()
3530 #if DISABLE_STYLE_IF_BROKEN_THEM
3531 if (m_widget
->style
->engine_data
)
3533 static bool s_warningPrinted
= FALSE
;
3534 if (!s_warningPrinted
)
3536 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3537 s_warningPrinted
= TRUE
;
3539 m_widgetStyle
= m_widget
->style
;
3544 GtkStyle
*style
= GetWidgetStyle();
3546 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3548 gdk_font_unref( style
->font
);
3549 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3552 if (m_foregroundColour
.Ok())
3554 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3555 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3557 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3558 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3559 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3563 // Try to restore the gtk default style. This is still a little
3564 // oversimplified for what is probably really needed here for controls
3565 // other than buttons, but is better than not being able to (re)set a
3566 // control's foreground colour to *wxBLACK -- RL
3567 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3570 def
= gtk_widget_get_default_style();
3572 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3573 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3574 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3578 if (m_backgroundColour
.Ok())
3580 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3581 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3583 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3584 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3585 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3586 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3587 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3588 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3589 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3590 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3594 // Try to restore the gtk default style. This is still a little
3595 // oversimplified for what is probably really needed here for controls
3596 // other than buttons, but is better than not being able to (re)set a
3597 // control's background colour to default grey and means resetting a
3598 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3600 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3603 def
= gtk_widget_get_default_style();
3605 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3606 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3607 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3608 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3609 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3610 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3611 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3612 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3617 void wxWindowGTK::ApplyWidgetStyle()
3621 //-----------------------------------------------------------------------------
3622 // Pop-up menu stuff
3623 //-----------------------------------------------------------------------------
3625 #if wxUSE_MENUS_NATIVE
3627 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3629 *is_waiting
= FALSE
;
3632 static void SetInvokingWindow( wxMenu
*menu
, wxWindowGTK
*win
)
3634 menu
->SetInvokingWindow( win
);
3635 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3638 wxMenuItem
*menuitem
= node
->GetData();
3639 if (menuitem
->IsSubMenu())
3641 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3644 node
= node
->GetNext();
3648 static gint gs_pop_x
= 0;
3649 static gint gs_pop_y
= 0;
3651 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3655 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3660 bool wxWindowGTK::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3662 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3664 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3666 SetInvokingWindow( menu
, this );
3673 bool is_waiting
= TRUE
;
3675 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3676 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3679 GTK_MENU(menu
->m_menu
),
3680 (GtkWidget
*) NULL
, // parent menu shell
3681 (GtkWidget
*) NULL
, // parent menu item
3682 (GtkMenuPositionFunc
) pop_pos_callback
,
3683 (gpointer
) this, // client data
3684 0, // button used to activate it
3685 gs_timeLastClick
// the time of activation
3690 while (gtk_events_pending())
3691 gtk_main_iteration();
3697 #endif // wxUSE_MENUS_NATIVE
3699 #if wxUSE_DRAG_AND_DROP
3701 void wxWindowGTK::SetDropTarget( wxDropTarget
*dropTarget
)
3703 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3705 GtkWidget
*dnd_widget
= GetConnectWidget();
3707 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3709 if (m_dropTarget
) delete m_dropTarget
;
3710 m_dropTarget
= dropTarget
;
3712 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3715 #endif // wxUSE_DRAG_AND_DROP
3717 GtkWidget
* wxWindowGTK::GetConnectWidget()
3719 GtkWidget
*connect_widget
= m_widget
;
3720 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3722 return connect_widget
;
3725 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow
*window
)
3728 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3730 return (window
== m_widget
->window
);
3733 bool wxWindowGTK::SetFont( const wxFont
&font
)
3735 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3737 if (!wxWindowBase::SetFont(font
))
3742 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3743 if ( sysbg
== m_backgroundColour
)
3745 m_backgroundColour
= wxNullColour
;
3747 m_backgroundColour
= sysbg
;
3757 static void wxDoCaptureMouse(wxWindowGTK
*wnd
)
3759 GdkWindow
*window
= (GdkWindow
*) NULL
;
3760 if (wnd
->m_wxwindow
)
3761 window
= GTK_PIZZA(wnd
->m_wxwindow
)->bin_window
;
3763 window
= wnd
->GetConnectWidget()->window
;
3765 wxCHECK_RET( window
, _T("CaptureMouse() failed") );
3767 wxCursor
* cursor
= &wnd
->GetCursor();
3769 cursor
= wxSTANDARD_CURSOR
;
3771 gdk_pointer_grab( window
, FALSE
,
3773 (GDK_BUTTON_PRESS_MASK
|
3774 GDK_BUTTON_RELEASE_MASK
|
3775 GDK_POINTER_MOTION_HINT_MASK
|
3776 GDK_POINTER_MOTION_MASK
),
3778 cursor
->GetCursor(),
3779 (guint32
)GDK_CURRENT_TIME
);
3780 g_captureWindow
= wnd
;
3781 g_captureWindowHasMouse
= TRUE
;
3782 wxLogDebug("captured %p", wnd
);
3785 static void wxDoReleaseMouse(wxWindowGTK
*wnd
)
3787 wxLogDebug("trying to release %p", wnd
);
3788 wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") );
3790 GdkWindow
*window
= (GdkWindow
*) NULL
;
3791 if (wnd
->m_wxwindow
)
3792 window
= GTK_PIZZA(wnd
->m_wxwindow
)->bin_window
;
3794 window
= wnd
->GetConnectWidget()->window
;
3799 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3800 g_captureWindow
= (wxWindowGTK
*) NULL
;
3801 wxLogDebug("released %p", wnd
);
3804 void wxWindowGTK::CaptureMouse()
3806 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3808 wxLogDebug("CAPTURE %p", this);
3809 wxWindowList::Node
*last
= g_capturedWindows
.GetLast();
3811 wxDoReleaseMouse(last
->GetData());
3813 g_capturedWindows
.Append(this);
3814 wxDoCaptureMouse(this);
3817 void wxWindowGTK::ReleaseMouse()
3819 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3821 wxLogDebug("RELEASE %p", this);
3822 wxDoReleaseMouse(this);
3823 g_capturedWindows
.DeleteObject(this);
3825 wxWindowList::Node
*last
= g_capturedWindows
.GetLast();
3827 wxDoCaptureMouse(last
->GetData());
3831 wxWindow
*wxWindowBase::GetCapture()
3833 return (wxWindow
*)g_captureWindow
;
3836 bool wxWindowGTK::IsRetained() const
3841 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3842 int range
, bool refresh
)
3844 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3846 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3848 m_hasScrolling
= TRUE
;
3850 if (orient
== wxHORIZONTAL
)
3852 float fpos
= (float)pos
;
3853 float frange
= (float)range
;
3854 float fthumb
= (float)thumbVisible
;
3855 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3856 if (fpos
< 0.0) fpos
= 0.0;
3858 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3859 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3861 SetScrollPos( orient
, pos
, refresh
);
3865 m_oldHorizontalPos
= fpos
;
3867 m_hAdjust
->lower
= 0.0;
3868 m_hAdjust
->upper
= frange
;
3869 m_hAdjust
->value
= fpos
;
3870 m_hAdjust
->step_increment
= 1.0;
3871 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3872 m_hAdjust
->page_size
= fthumb
;
3876 float fpos
= (float)pos
;
3877 float frange
= (float)range
;
3878 float fthumb
= (float)thumbVisible
;
3879 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3880 if (fpos
< 0.0) fpos
= 0.0;
3882 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3883 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3885 SetScrollPos( orient
, pos
, refresh
);
3889 m_oldVerticalPos
= fpos
;
3891 m_vAdjust
->lower
= 0.0;
3892 m_vAdjust
->upper
= frange
;
3893 m_vAdjust
->value
= fpos
;
3894 m_vAdjust
->step_increment
= 1.0;
3895 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3896 m_vAdjust
->page_size
= fthumb
;
3899 if (orient
== wxHORIZONTAL
)
3900 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3902 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3905 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3907 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3909 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3911 if (orient
== wxHORIZONTAL
)
3913 float fpos
= (float)pos
;
3914 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3915 if (fpos
< 0.0) fpos
= 0.0;
3916 m_oldHorizontalPos
= fpos
;
3918 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3919 m_hAdjust
->value
= fpos
;
3923 float fpos
= (float)pos
;
3924 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3925 if (fpos
< 0.0) fpos
= 0.0;
3926 m_oldVerticalPos
= fpos
;
3928 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3929 m_vAdjust
->value
= fpos
;
3932 if (m_wxwindow
->window
)
3934 if (orient
== wxHORIZONTAL
)
3936 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3937 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3939 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3941 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3942 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3946 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3947 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3949 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3951 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3952 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3957 int wxWindowGTK::GetScrollThumb( int orient
) const
3959 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3961 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3963 if (orient
== wxHORIZONTAL
)
3964 return (int)(m_hAdjust
->page_size
+0.5);
3966 return (int)(m_vAdjust
->page_size
+0.5);
3969 int wxWindowGTK::GetScrollPos( int orient
) const
3971 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3973 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3975 if (orient
== wxHORIZONTAL
)
3976 return (int)(m_hAdjust
->value
+0.5);
3978 return (int)(m_vAdjust
->value
+0.5);
3981 int wxWindowGTK::GetScrollRange( int orient
) const
3983 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3985 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3987 if (orient
== wxHORIZONTAL
)
3988 return (int)(m_hAdjust
->upper
+0.5);
3990 return (int)(m_vAdjust
->upper
+0.5);
3993 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3995 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3997 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3999 if ((dx
== 0) && (dy
== 0)) return;
4001 m_clipPaintRegion
= TRUE
;
4002 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
4003 m_clipPaintRegion
= FALSE
;
4006 if (m_children.GetCount() > 0)
4008 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
4012 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
4014 pizza->xoffset -= dx;
4015 pizza->yoffset -= dy;
4017 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
4018 gdk_gc_set_exposures( m_scrollGC, TRUE );
4022 GetClientSize( &cw, &ch );
4023 int w = cw - abs(dx);
4024 int h = ch - abs(dy);
4026 if ((h < 0) || (w < 0))
4034 if (dx < 0) s_x = -dx;
4035 if (dy < 0) s_y = -dy;
4038 if (dx > 0) d_x = dx;
4039 if (dy > 0) d_y = dy;
4041 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
4042 pizza->bin_window, s_x, s_y, w, h );
4045 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
4046 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
4047 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
4048 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
4050 Refresh( TRUE, &rect );
4053 gdk_gc_unref( m_scrollGC );
4058 // Find the wxWindow at the current mouse position, also returning the mouse
4060 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
4062 pt
= wxGetMousePosition();
4063 wxWindow
* found
= wxFindWindowAtPoint(pt
);
4067 // Get the current mouse position.
4068 wxPoint
wxGetMousePosition()
4070 /* This crashes when used within wxHelpContext,
4071 so we have to use the X-specific implementation below.
4073 GdkModifierType *mask;
4074 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
4076 return wxPoint(x, y);
4080 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
4082 return wxPoint(-999, -999);
4084 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
4085 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
4086 Window rootReturn
, childReturn
;
4087 int rootX
, rootY
, winX
, winY
;
4088 unsigned int maskReturn
;
4090 XQueryPointer (display
,
4094 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
4095 return wxPoint(rootX
, rootY
);