1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/window.cpp
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #define XWarpPointer XWARPPOINTER
20 #include "wx/window.h"
21 #include "wx/dcclient.h"
24 #include "wx/layout.h"
26 #include "wx/dialog.h"
27 #include "wx/msgdlg.h"
29 #if wxUSE_DRAG_AND_DROP
34 #include "wx/tooltip.h"
42 #include "wx/textctrl.h"
46 #include "wx/statusbr.h"
48 #include "wx/settings.h"
52 #include "wx/thread.h"
59 #include <gdk/gdkprivate.h>
60 #include <gdk/gdkkeysyms.h>
64 #include <gtk/gtkprivate.h>
66 #include "wx/gtk/win_gtk.h"
68 //-----------------------------------------------------------------------------
69 // documentation on internals
70 //-----------------------------------------------------------------------------
73 I have been asked several times about writing some documentation about
74 the GTK port of wxWindows, especially its internal structures. Obviously,
75 you cannot understand wxGTK without knowing a little about the GTK, but
76 some more information about what the wxWindow, which is the base class
77 for all other window classes, does seems required as well.
81 What does wxWindow do? It contains the common interface for the following
82 jobs of its descendants:
84 1) Define the rudimentary behaviour common to all window classes, such as
85 resizing, intercepting user input (so as to make it possible to use these
86 events for special purposes in a derived class), window names etc.
88 2) Provide the possibility to contain and manage children, if the derived
89 class is allowed to contain children, which holds true for those window
90 classes which do not display a native GTK widget. To name them, these
91 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
92 work classes are a special case and are handled a bit differently from
93 the rest. The same holds true for the wxNotebook class.
95 3) Provide the possibility to draw into a client area of a window. This,
96 too, only holds true for classes that do not display a native GTK widget
99 4) Provide the entire mechanism for scrolling widgets. This actual inter-
100 face for this is usually in wxScrolledWindow, but the GTK implementation
103 5) A multitude of helper or extra methods for special purposes, such as
104 Drag'n'Drop, managing validators etc.
106 6) Display a border (sunken, raised, simple or none).
108 Normally one might expect, that one wxWindows window would always correspond
109 to one GTK widget. Under GTK, there is no such allround widget that has all
110 the functionality. Moreover, the GTK defines a client area as a different
111 widget from the actual widget you are handling. Last but not least some
112 special classes (e.g. wxFrame) handle different categories of widgets and
113 still have the possibility to draw something in the client area.
114 It was therefore required to write a special purpose GTK widget, that would
115 represent a client area in the sense of wxWindows capable to do the jobs
116 2), 3) and 4). I have written this class and it resides in win_gtk.c of
119 All windows must have a widget, with which they interact with other under-
120 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
121 thw wxWindow class has a member variable called m_widget which holds a
122 pointer to this widget. When the window class represents a GTK native widget,
123 this is (in most cases) the only GTK widget the class manages. E.g. the
124 wxStatitText class handles only a GtkLabel widget a pointer to which you
125 can find in m_widget (defined in wxWindow)
127 When the class has a client area for drawing into and for containing children
128 it has to handle the client area widget (of the type GtkPizza, defined in
129 win_gtk.c), but there could be any number of widgets, handled by a class
130 The common rule for all windows is only, that the widget that interacts with
131 the rest of GTK must be referenced in m_widget and all other widgets must be
132 children of this widget on the GTK level. The top-most widget, which also
133 represents the client area, must be in the m_wxwindow field and must be of
136 As I said, the window classes that display a GTK native widget only have
137 one widget, so in the case of e.g. the wxButton class m_widget holds a
138 pointer to a GtkButton widget. But windows with client areas (for drawing
139 and children) have a m_widget field that is a pointer to a GtkScrolled-
140 Window and a m_wxwindow field that is pointer to a GtkPizza and this
141 one is (in the GTK sense) a child of the GtkScrolledWindow.
143 If the m_wxwindow field is set, then all input to this widget is inter-
144 cepted and sent to the wxWindows class. If not, all input to the widget
145 that gets pointed to by m_widget gets intercepted and sent to the class.
149 The design of scrolling in wxWindows is markedly different from that offered
150 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
151 clicking on a scrollbar belonging to scrolled window will inevitably move
152 the window. In wxWindows, the scrollbar will only emit an event, send this
153 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
154 which actually moves the window and its subchildren. Note that GtkPizza
155 memorizes how much it has been scrolled but that wxWindows forgets this
156 so that the two coordinates systems have to be kept in synch. This is done
157 in various places using the pizza->xoffset and pizza->yoffset values.
161 Singularily the most broken code in GTK is the code that is supposes to
162 inform subwindows (child windows) about new positions. Very often, duplicate
163 events are sent without changes in size or position, equally often no
164 events are sent at all (All this is due to a bug in the GtkContainer code
165 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
166 GTK's own system and it simply waits for size events for toplevel windows
167 and then iterates down the respective size events to all window. This has
168 the disadvantage, that windows might get size events before the GTK widget
169 actually has the reported size. This doesn't normally pose any problem, but
170 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
171 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
172 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
173 window that is used for OpenGl output really has that size (as reported by
178 If someone at some point of time feels the immense desire to have a look at,
179 change or attempt to optimse the Refresh() logic, this person will need an
180 intimate understanding of what a "draw" and what an "expose" events are and
181 what there are used for, in particular when used in connection with GTK's
182 own windowless widgets. Beware.
186 Cursors, too, have been a constant source of pleasure. The main difficulty
187 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
188 for the parent. To prevent this from doing too much harm, I use idle time
189 to set the cursor over and over again, starting from the toplevel windows
190 and ending with the youngest generation (speaking of parent and child windows).
191 Also don't forget that cursors (like much else) are connected to GdkWindows,
192 not GtkWidgets and that the "window" field of a GtkWidget might very well
193 point to the GdkWindow of the parent widget (-> "window less widget") and
194 that the two obviously have very different meanings.
198 //-----------------------------------------------------------------------------
200 //-----------------------------------------------------------------------------
202 extern wxList wxPendingDelete
;
203 extern bool g_blockEventsOnDrag
;
204 extern bool g_blockEventsOnScroll
;
205 extern wxCursor g_globalCursor
;
207 // mouse capture state: the window which has it and if the mouse is currently
209 static wxWindowGTK
*g_captureWindow
= (wxWindowGTK
*) NULL
;
210 static bool g_captureWindowHasMouse
= FALSE
;
212 /* extern */ wxWindowGTK
*g_focusWindow
= (wxWindowGTK
*) NULL
;
214 // the last window which had the focus - this is normally never NULL (except
215 // if we never had focus at all) as even when g_focusWindow is NULL it still
216 // keeps its previous value
217 static wxWindowGTK
*g_focusWindowLast
= (wxWindowGTK
*)NULL
;
219 // the frame that is currently active (i.e. its child has focus). It is
220 // used to generate wxActivateEvents
221 static wxWindowGTK
*g_activeFrame
= (wxWindowGTK
*)NULL
;
222 static bool g_activeFrameLostFocus
= FALSE
;
224 // if we detect that the app has got/lost the focus, we set this variable to
225 // either TRUE or FALSE and an activate event will be sent during the next
226 // OnIdle() call and it is reset to -1: this value means that we shouldn't
227 // send any activate events at all
228 static int g_sendActivateEvent
= -1;
230 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
231 the last click here */
232 static guint32 gs_timeLastClick
= 0;
234 extern bool g_mainThreadLocked
;
236 //-----------------------------------------------------------------------------
238 //-----------------------------------------------------------------------------
241 #define DISABLE_STYLE_IF_BROKEN_THEME 1
247 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
249 # define DEBUG_MAIN_THREAD
252 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
253 GdkEvent
*WXUNUSED(event
),
254 const wxChar
*WXUNUSED(name
) )
257 static bool s_done = FALSE;
260 wxLog::AddTraceMask("focus");
263 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
269 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
271 // suppress warnings about gtk_debug_focus_in_callback being unused with
276 tmp
+= wxT(" FROM ");
279 wxChar
*s
= new wxChar
[tmp
.Length()+1];
283 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
284 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
289 #define DEBUG_MAIN_THREAD
292 //-----------------------------------------------------------------------------
293 // missing gdk functions
294 //-----------------------------------------------------------------------------
297 gdk_window_warp_pointer (GdkWindow
*window
,
302 GdkWindowPrivate
*priv
;
306 window
= GDK_ROOT_PARENT();
309 if (!GDK_WINDOW_DESTROYED(window
))
311 XWarpPointer (GDK_WINDOW_XDISPLAY(window
),
312 None
, /* not source window -> move from anywhere */
313 GDK_WINDOW_XID(window
), /* dest window */
314 0, 0, 0, 0, /* not source window -> move from anywhere */
318 priv
= (GdkWindowPrivate
*) window
;
320 if (!priv
->destroyed
)
322 XWarpPointer (priv
->xdisplay
,
323 None
, /* not source window -> move from anywhere */
324 priv
->xwindow
, /* dest window */
325 0, 0, 0, 0, /* not source window -> move from anywhere */
331 //-----------------------------------------------------------------------------
333 //-----------------------------------------------------------------------------
335 extern void wxapp_install_idle_handler();
336 extern bool g_isIdle
;
338 //-----------------------------------------------------------------------------
339 // local code (see below)
340 //-----------------------------------------------------------------------------
342 // returns the child of win which currently has focus or NULL if not found
344 // Note: can't be static, needed by textctrl.cpp.
345 wxWindow
*wxFindFocusedChild(wxWindowGTK
*win
)
347 wxWindow
*winFocus
= wxWindowGTK::FindFocus();
349 return (wxWindow
*)NULL
;
351 if ( winFocus
== win
)
352 return (wxWindow
*)win
;
354 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
356 node
= node
->GetNext() )
358 wxWindow
*child
= wxFindFocusedChild(node
->GetData());
363 return (wxWindow
*)NULL
;
366 // Returns toplevel grandparent of given window:
367 static wxWindowGTK
* wxGetTopLevelParent(wxWindowGTK
*win
)
369 wxWindowGTK
*p
= win
;
370 while (p
&& !p
->IsTopLevel())
376 static void draw_frame( GtkWidget
*widget
, wxWindowGTK
*win
)
378 // wxUniversal widgets draw the borders and scrollbars themselves
379 #ifndef __WXUNIVERSAL__
386 if (win
->m_hasScrolling
)
388 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
390 GtkRequisition vscroll_req
;
391 vscroll_req
.width
= 2;
392 vscroll_req
.height
= 2;
393 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
394 (scroll_window
->vscrollbar
, &vscroll_req
);
396 GtkRequisition hscroll_req
;
397 hscroll_req
.width
= 2;
398 hscroll_req
.height
= 2;
399 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
400 (scroll_window
->hscrollbar
, &hscroll_req
);
402 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) );
404 if (scroll_window
->vscrollbar_visible
)
406 dw
+= vscroll_req
.width
;
407 dw
+= scroll_class
->scrollbar_spacing
;
410 if (scroll_window
->hscrollbar_visible
)
412 dh
+= hscroll_req
.height
;
413 dh
+= scroll_class
->scrollbar_spacing
;
419 if (GTK_WIDGET_NO_WINDOW (widget
))
421 dx
+= widget
->allocation
.x
;
422 dy
+= widget
->allocation
.y
;
425 if (win
->HasFlag(wxRAISED_BORDER
))
427 gtk_draw_shadow( widget
->style
,
432 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
436 if (win
->HasFlag(wxSUNKEN_BORDER
))
438 gtk_draw_shadow( widget
->style
,
443 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
447 if (win
->HasFlag(wxSIMPLE_BORDER
))
450 gc
= gdk_gc_new( widget
->window
);
451 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
452 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
454 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
458 #endif // __WXUNIVERSAL__
461 //-----------------------------------------------------------------------------
462 // "expose_event" of m_widget
463 //-----------------------------------------------------------------------------
465 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindowGTK
*win
)
467 if (gdk_event
->count
> 0) return FALSE
;
469 draw_frame( widget
, win
);
474 //-----------------------------------------------------------------------------
475 // "draw" of m_widget
476 //-----------------------------------------------------------------------------
478 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindowGTK
*win
)
480 draw_frame( widget
, win
);
483 //-----------------------------------------------------------------------------
484 // key code mapping routines
485 //-----------------------------------------------------------------------------
487 static long map_to_unmodified_wx_keysym( GdkEventKey
*event
)
489 // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string
490 // but only event->keyval which is quite useless to us, so remember
491 // the last character from GDK_KEY_PRESS and resue it as last resort
493 // NB: should be MT-neutral as always called from main thread only
498 } s_lastKeyPress
= { 0, 0 };
500 KeySym keysym
= event
->keyval
;
506 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
508 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
514 case GDK_Super_R
: key_code
= WXK_ALT
; break;
515 case GDK_Menu
: key_code
= WXK_MENU
; break;
516 case GDK_Help
: key_code
= WXK_HELP
; break;
517 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
518 case GDK_ISO_Left_Tab
:
519 case GDK_Tab
: key_code
= WXK_TAB
; break;
520 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
521 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
522 case GDK_Return
: key_code
= WXK_RETURN
; break;
523 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
524 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
525 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
526 case GDK_Delete
: key_code
= WXK_DELETE
; break;
527 case GDK_Home
: key_code
= WXK_HOME
; break;
528 case GDK_Left
: key_code
= WXK_LEFT
; break;
529 case GDK_Up
: key_code
= WXK_UP
; break;
530 case GDK_Right
: key_code
= WXK_RIGHT
; break;
531 case GDK_Down
: key_code
= WXK_DOWN
; break;
532 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
533 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
534 case GDK_Next
: key_code
= WXK_NEXT
; break;
535 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
536 case GDK_End
: key_code
= WXK_END
; break;
537 case GDK_Begin
: key_code
= WXK_HOME
; break;
538 case GDK_Select
: key_code
= WXK_SELECT
; break;
539 case GDK_Print
: key_code
= WXK_PRINT
; break;
540 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
541 case GDK_Insert
: key_code
= WXK_INSERT
; break;
542 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
544 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
545 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
546 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
547 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
548 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
549 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
550 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
551 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
552 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
553 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
554 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
555 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
556 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
557 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
558 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
559 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
560 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
561 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
562 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
563 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
564 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
565 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
566 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
567 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
568 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
569 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
570 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
571 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
572 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
573 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
574 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
575 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
576 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
577 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
578 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
579 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
580 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
582 case GDK_F1
: key_code
= WXK_F1
; break;
583 case GDK_F2
: key_code
= WXK_F2
; break;
584 case GDK_F3
: key_code
= WXK_F3
; break;
585 case GDK_F4
: key_code
= WXK_F4
; break;
586 case GDK_F5
: key_code
= WXK_F5
; break;
587 case GDK_F6
: key_code
= WXK_F6
; break;
588 case GDK_F7
: key_code
= WXK_F7
; break;
589 case GDK_F8
: key_code
= WXK_F8
; break;
590 case GDK_F9
: key_code
= WXK_F9
; break;
591 case GDK_F10
: key_code
= WXK_F10
; break;
592 case GDK_F11
: key_code
= WXK_F11
; break;
593 case GDK_F12
: key_code
= WXK_F12
; break;
596 // do we have the translation?
597 if ( event
->length
== 1 )
599 keysym
= (KeySym
)event
->string
[0];
601 else if ( (keysym
& 0xFF) != keysym
)
603 // non ASCII key, what to do?
605 if ( event
->type
== GDK_KEY_RELEASE
)
607 // reuse the one from the last keypress if any
608 if ( keysym
== s_lastKeyPress
.keysym
)
610 key_code
= s_lastKeyPress
.keycode
;
617 // ignore this one, we don't know it
620 //else: ASCII key, ok
622 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
623 key_code
= upper
? upper
: keysym
;
625 if ( event
->type
== GDK_KEY_PRESS
)
627 // remember it to be reused below later
628 s_lastKeyPress
.keysym
= keysym
;
629 s_lastKeyPress
.keycode
= key_code
;
637 static long map_to_wx_keysym( GdkEventKey
*event
)
639 KeySym keysym
= event
->keyval
;
644 case GDK_Menu
: key_code
= WXK_MENU
; break;
645 case GDK_Help
: key_code
= WXK_HELP
; break;
646 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
647 case GDK_ISO_Left_Tab
:
648 case GDK_Tab
: key_code
= WXK_TAB
; break;
649 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
650 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
651 case GDK_Return
: key_code
= WXK_RETURN
; break;
652 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
653 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
654 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
655 case GDK_Delete
: key_code
= WXK_DELETE
; break;
656 case GDK_Home
: key_code
= WXK_HOME
; break;
657 case GDK_Left
: key_code
= WXK_LEFT
; break;
658 case GDK_Up
: key_code
= WXK_UP
; break;
659 case GDK_Right
: key_code
= WXK_RIGHT
; break;
660 case GDK_Down
: key_code
= WXK_DOWN
; break;
661 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
662 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
663 case GDK_Next
: key_code
= WXK_NEXT
; break;
664 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
665 case GDK_End
: key_code
= WXK_END
; break;
666 case GDK_Begin
: key_code
= WXK_HOME
; break;
667 case GDK_Select
: key_code
= WXK_SELECT
; break;
668 case GDK_Print
: key_code
= WXK_PRINT
; break;
669 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
670 case GDK_Insert
: key_code
= WXK_INSERT
; break;
671 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
673 case GDK_KP_0
: key_code
= '0'; break;
674 case GDK_KP_1
: key_code
= '1'; break;
675 case GDK_KP_2
: key_code
= '2'; break;
676 case GDK_KP_3
: key_code
= '3'; break;
677 case GDK_KP_4
: key_code
= '4'; break;
678 case GDK_KP_5
: key_code
= '5'; break;
679 case GDK_KP_6
: key_code
= '6'; break;
680 case GDK_KP_7
: key_code
= '7'; break;
681 case GDK_KP_8
: key_code
= '8'; break;
682 case GDK_KP_9
: key_code
= '9'; break;
683 case GDK_KP_Space
: key_code
= ' '; break;
684 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
685 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
686 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
687 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
688 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
689 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
690 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
691 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
692 case GDK_KP_Up
: key_code
= WXK_UP
; break;
693 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
694 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
695 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
696 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
697 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
698 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
699 case GDK_KP_End
: key_code
= WXK_END
; break;
700 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
701 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
702 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
703 case GDK_KP_Equal
: key_code
= '='; break;
704 case GDK_KP_Multiply
: key_code
= '*'; break;
705 case GDK_KP_Add
: key_code
= '+'; break;
706 case GDK_KP_Separator
: key_code
= ','; break;
707 case GDK_KP_Subtract
: key_code
= '-'; break;
708 case GDK_KP_Decimal
: key_code
= '.'; break;
709 case GDK_KP_Divide
: key_code
= '/'; break;
711 case GDK_F1
: key_code
= WXK_F1
; break;
712 case GDK_F2
: key_code
= WXK_F2
; break;
713 case GDK_F3
: key_code
= WXK_F3
; break;
714 case GDK_F4
: key_code
= WXK_F4
; break;
715 case GDK_F5
: key_code
= WXK_F5
; break;
716 case GDK_F6
: key_code
= WXK_F6
; break;
717 case GDK_F7
: key_code
= WXK_F7
; break;
718 case GDK_F8
: key_code
= WXK_F8
; break;
719 case GDK_F9
: key_code
= WXK_F9
; break;
720 case GDK_F10
: key_code
= WXK_F10
; break;
721 case GDK_F11
: key_code
= WXK_F11
; break;
722 case GDK_F12
: key_code
= WXK_F12
; break;
724 if (event
->length
== 1)
726 key_code
= (unsigned char)*event
->string
;
728 else if ((keysym
& 0xFF) == keysym
)
730 key_code
= (guint
)keysym
;
737 //-----------------------------------------------------------------------------
738 // "size_request" of m_widget
739 //-----------------------------------------------------------------------------
741 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
744 win
->GetSize( &w
, &h
);
748 requisition
->height
= h
;
749 requisition
->width
= w
;
752 //-----------------------------------------------------------------------------
753 // "expose_event" of m_wxwindow
754 //-----------------------------------------------------------------------------
756 static int gtk_window_expose_callback( GtkWidget
*widget
,
757 GdkEventExpose
*gdk_event
,
763 wxapp_install_idle_handler();
766 if (win->GetName() == wxT("panel"))
768 wxPrintf( wxT("OnExpose from ") );
769 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
770 wxPrintf( win->GetClassInfo()->GetClassName() );
771 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
772 (int)gdk_event->area.y,
773 (int)gdk_event->area.width,
774 (int)gdk_event->area.height );
778 #ifndef __WXUNIVERSAL__
779 GtkPizza
*pizza
= GTK_PIZZA (widget
);
781 if (win
->GetThemeEnabled())
783 wxWindow
*parent
= win
->GetParent();
784 while (parent
&& !parent
->IsTopLevel())
785 parent
= parent
->GetParent();
789 gtk_paint_flat_box (parent
->m_widget
->style
,
800 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
802 gdk_event
->area
.width
,
803 gdk_event
->area
.height
);
805 // Actual redrawing takes place in idle time.
811 //-----------------------------------------------------------------------------
812 // "event" of m_wxwindow
813 //-----------------------------------------------------------------------------
815 // GTK thinks it is clever and filters out a certain amount of "unneeded"
816 // expose events. We need them, of course, so we override the main event
817 // procedure in GtkWidget by giving our own handler for all system events.
818 // There, we look for expose events ourselves whereas all other events are
821 gint
gtk_window_event_event_callback( GtkWidget
*widget
,
822 GdkEventExpose
*event
,
825 if (event
->type
== GDK_EXPOSE
)
827 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
834 //-----------------------------------------------------------------------------
835 // "draw" of m_wxwindow
836 //-----------------------------------------------------------------------------
838 // This callback is a complete replacement of the gtk_pizza_draw() function,
841 static void gtk_window_draw_callback( GtkWidget
*widget
,
848 wxapp_install_idle_handler();
850 // The wxNO_FULL_REPAINT_ON_RESIZE flag only works if
851 // there are no child windows.
852 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
853 (win
->GetChildren().GetCount() == 0))
859 if (win->GetName() == wxT("panel"))
861 wxPrintf( wxT("OnDraw from ") );
862 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
863 wxPrintf( win->GetClassInfo()->GetClassName() );
864 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
871 #ifndef __WXUNIVERSAL__
872 GtkPizza
*pizza
= GTK_PIZZA (widget
);
874 if (win
->GetThemeEnabled())
876 wxWindow
*parent
= win
->GetParent();
877 while (parent
&& !parent
->IsTopLevel())
878 parent
= parent
->GetParent();
882 gtk_paint_flat_box (parent
->m_widget
->style
,
893 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
894 (pizza
->clear_on_draw
))
896 gdk_window_clear_area( pizza
->bin_window
,
897 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
901 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
903 // Actual redrawing takes place in idle time.
907 #ifndef __WXUNIVERSAL__
908 // Redraw child widgets
909 GList
*children
= pizza
->children
;
912 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
913 children
= children
->next
;
915 GdkRectangle child_area
;
916 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
918 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
924 //-----------------------------------------------------------------------------
925 // "key_press_event" from any window
926 //-----------------------------------------------------------------------------
928 // turn on to see the key event codes on the console
929 #undef DEBUG_KEY_EVENTS
931 static gint
gtk_window_key_press_callback( GtkWidget
*widget
,
932 GdkEventKey
*gdk_event
,
938 wxapp_install_idle_handler();
940 if (!win
->m_hasVMT
) return FALSE
;
941 if (g_blockEventsOnDrag
) return FALSE
;
946 GdkModifierType state
;
947 if (gdk_event
->window
)
948 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
952 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
954 #ifdef DEBUG_KEY_EVENTS
955 wxPrintf(_T("Key press event: %d => %ld\n"), gdk_event
->keyval
, key_code
);
956 #endif // DEBUG_KEY_EVENTS
958 /* sending unknown key events doesn't really make sense */
962 wxKeyEvent
event( wxEVT_KEY_DOWN
);
963 event
.SetTimestamp( gdk_event
->time
);
964 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
965 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
966 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
967 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
968 event
.m_keyCode
= key_code
;
969 event
.m_scanCode
= gdk_event
->keyval
;
972 event
.SetEventObject( win
);
973 ret
= win
->GetEventHandler()->ProcessEvent( event
);
978 wxWindowGTK
*ancestor
= win
;
981 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
984 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
985 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
988 if (ancestor
->IsTopLevel())
990 ancestor
= ancestor
->GetParent();
993 #endif // wxUSE_ACCEL
995 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
996 will only be sent if it is not in an accelerator table. */
999 key_code
= map_to_wx_keysym( gdk_event
);
1003 #ifdef DEBUG_KEY_EVENTS
1004 wxPrintf(_T("Char event: %ld\n"), key_code
);
1005 #endif // DEBUG_KEY_EVENTS
1007 // reuse the ame event object, just change its type and use the
1008 // translated keycode instead of the raw one
1009 event
.SetEventType(wxEVT_CHAR
);
1010 event
.m_keyCode
= key_code
;
1012 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1016 /* win is a control: tab can be propagated up */
1018 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
1019 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
1020 // have this style, yet choose not to process this particular TAB in which
1021 // case TAB must still work as a navigational character
1023 !win
->HasFlag(wxTE_PROCESS_TAB
) &&
1025 win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
1027 wxNavigationKeyEvent new_event
;
1028 new_event
.SetEventObject( win
->GetParent() );
1029 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
1030 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
1031 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1032 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
1033 new_event
.SetCurrentFocus( win
);
1034 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
1037 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
1039 (gdk_event
->keyval
== GDK_Escape
) )
1041 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
1042 new_event
.SetEventObject( win
);
1043 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
1047 #if 0 // (GTK_MINOR_VERSION > 0)
1048 /* Pressing F10 will activate the menu bar of the top frame. */
1050 (gdk_event
->keyval
== GDK_F10
) )
1052 wxWindowGTK
*ancestor
= win
;
1055 if (wxIsKindOf(ancestor
,wxFrame
))
1057 wxFrame
*frame
= (wxFrame
*) ancestor
;
1058 wxMenuBar
*menubar
= frame
->GetMenuBar();
1061 wxNode
*node
= menubar
->GetMenus().First();
1064 wxMenu
*firstMenu
= (wxMenu
*) node
->Data();
1065 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu
->m_owner
) );
1071 ancestor
= ancestor
->GetParent();
1078 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1085 //-----------------------------------------------------------------------------
1086 // "key_release_event" from any window
1087 //-----------------------------------------------------------------------------
1089 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindowGTK
*win
)
1094 wxapp_install_idle_handler();
1096 if (!win
->m_hasVMT
) return FALSE
;
1097 if (g_blockEventsOnDrag
) return FALSE
;
1099 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
1101 #ifdef DEBUG_KEY_EVENTS
1102 wxPrintf(_T("Key release event: %d => %ld\n"), gdk_event
->keyval
, key_code
);
1103 #endif // DEBUG_KEY_EVENTS
1105 /* sending unknown key events doesn't really make sense */
1106 if (key_code
== 0) return FALSE
;
1110 GdkModifierType state
;
1111 if (gdk_event
->window
)
1112 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1114 wxKeyEvent
event( wxEVT_KEY_UP
);
1115 event
.SetTimestamp( gdk_event
->time
);
1116 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1117 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1118 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1119 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1120 event
.m_keyCode
= key_code
;
1121 event
.m_scanCode
= gdk_event
->keyval
;
1124 event
.SetEventObject( win
);
1126 if (win
->GetEventHandler()->ProcessEvent( event
))
1128 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1135 // ============================================================================
1137 // ============================================================================
1139 // init wxMouseEvent with the info from gdk_event
1140 #define InitMouseEvent(win, event, gdk_event) \
1142 event.SetTimestamp( gdk_event->time ); \
1143 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
1144 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
1145 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
1146 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
1147 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
1148 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
1149 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
1151 wxPoint pt = win->GetClientAreaOrigin(); \
1152 event.m_x = (wxCoord)gdk_event->x - pt.x; \
1153 event.m_y = (wxCoord)gdk_event->y - pt.y; \
1156 // ----------------------------------------------------------------------------
1157 // mouse event processing helper
1158 // ----------------------------------------------------------------------------
1160 static void AdjustEventButtonState(wxMouseEvent
& event
)
1162 // GDK reports the old state of the button for a button press event, but
1163 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1164 // for a LEFT_DOWN event, not FALSE, so we will invert
1165 // left/right/middleDown for the corresponding click events
1167 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1168 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1169 (event
.GetEventType() == wxEVT_LEFT_UP
))
1171 event
.m_leftDown
= !event
.m_leftDown
;
1175 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1176 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1177 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1179 event
.m_middleDown
= !event
.m_middleDown
;
1183 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1184 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1185 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1187 event
.m_rightDown
= !event
.m_rightDown
;
1192 //-----------------------------------------------------------------------------
1193 // "button_press_event"
1194 //-----------------------------------------------------------------------------
1196 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1201 wxapp_install_idle_handler();
1204 wxPrintf( wxT("1) OnButtonPress from ") );
1205 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1206 wxPrintf( win->GetClassInfo()->GetClassName() );
1207 wxPrintf( wxT(".\n") );
1209 if (!win
->m_hasVMT
) return FALSE
;
1210 if (g_blockEventsOnDrag
) return TRUE
;
1211 if (g_blockEventsOnScroll
) return TRUE
;
1213 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1215 if (win
->m_wxwindow
&& (g_focusWindow
!= win
) && win
->AcceptsFocus())
1217 gtk_widget_grab_focus( win
->m_wxwindow
);
1219 wxPrintf( wxT("GrabFocus from ") );
1220 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1221 wxPrintf( win->GetClassInfo()->GetClassName() );
1222 wxPrintf( wxT(".\n") );
1226 wxEventType event_type
= wxEVT_NULL
;
1228 if (gdk_event
->button
== 1)
1230 switch (gdk_event
->type
)
1232 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1233 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1237 else if (gdk_event
->button
== 2)
1239 switch (gdk_event
->type
)
1241 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1242 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1246 else if (gdk_event
->button
== 3)
1248 switch (gdk_event
->type
)
1250 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1251 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1256 if ( event_type
== wxEVT_NULL
)
1258 // unknown mouse button or click type
1262 wxMouseEvent
event( event_type
);
1263 InitMouseEvent( win
, event
, gdk_event
);
1265 AdjustEventButtonState(event
);
1267 // wxListBox actually get mouse events from the item
1269 if (win
->m_isListBox
)
1271 event
.m_x
+= widget
->allocation
.x
;
1272 event
.m_y
+= widget
->allocation
.y
;
1275 // Some control don't have their own X window and thus cannot get
1278 if (!g_captureWindow
)
1280 wxCoord x
= event
.m_x
;
1281 wxCoord y
= event
.m_y
;
1282 if (win
->m_wxwindow
)
1284 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1285 x
+= pizza
->xoffset
;
1286 y
+= pizza
->yoffset
;
1289 wxNode
*node
= win
->GetChildren().First();
1292 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1294 node
= node
->Next();
1295 if (!child
->IsShown())
1298 if (child
->m_isStaticBox
)
1300 // wxStaticBox is transparent in the box itself
1301 int xx1
= child
->m_x
;
1302 int yy1
= child
->m_y
;
1303 int xx2
= child
->m_x
+ child
->m_width
;
1304 int yy2
= child
->m_x
+ child
->m_height
;
1307 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1309 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1311 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1313 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1316 event
.m_x
-= child
->m_x
;
1317 event
.m_y
-= child
->m_y
;
1324 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1325 (child
->m_x
<= x
) &&
1326 (child
->m_y
<= y
) &&
1327 (child
->m_x
+child
->m_width
>= x
) &&
1328 (child
->m_y
+child
->m_height
>= y
))
1331 event
.m_x
-= child
->m_x
;
1332 event
.m_y
-= child
->m_y
;
1339 event
.SetEventObject( win
);
1341 gs_timeLastClick
= gdk_event
->time
;
1344 wxPrintf( wxT("2) OnButtonPress from ") );
1345 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1346 wxPrintf( win->GetClassInfo()->GetClassName() );
1347 wxPrintf( wxT(".\n") );
1350 if (win
->GetEventHandler()->ProcessEvent( event
))
1352 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1359 //-----------------------------------------------------------------------------
1360 // "button_release_event"
1361 //-----------------------------------------------------------------------------
1363 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1368 wxapp_install_idle_handler();
1370 if (!win
->m_hasVMT
) return FALSE
;
1371 if (g_blockEventsOnDrag
) return FALSE
;
1372 if (g_blockEventsOnScroll
) return FALSE
;
1374 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1377 printf( "OnButtonRelease from " );
1378 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1379 printf( win->GetClassInfo()->GetClassName() );
1383 wxEventType event_type
= wxEVT_NULL
;
1385 switch (gdk_event
->button
)
1387 case 1: event_type
= wxEVT_LEFT_UP
; break;
1388 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1389 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1390 default: return FALSE
;
1393 wxMouseEvent
event( event_type
);
1394 InitMouseEvent( win
, event
, gdk_event
);
1396 AdjustEventButtonState(event
);
1398 // wxListBox actually get mouse events from the item
1400 if (win
->m_isListBox
)
1402 event
.m_x
+= widget
->allocation
.x
;
1403 event
.m_y
+= widget
->allocation
.y
;
1406 // Some control don't have their own X window and thus cannot get
1409 if (!g_captureWindow
)
1411 wxCoord x
= event
.m_x
;
1412 wxCoord y
= event
.m_y
;
1413 if (win
->m_wxwindow
)
1415 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1416 x
+= pizza
->xoffset
;
1417 y
+= pizza
->yoffset
;
1420 wxNode
*node
= win
->GetChildren().First();
1423 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1425 node
= node
->Next();
1426 if (!child
->IsShown())
1429 if (child
->m_isStaticBox
)
1431 // wxStaticBox is transparent in the box itself
1432 int xx1
= child
->m_x
;
1433 int yy1
= child
->m_y
;
1434 int xx2
= child
->m_x
+ child
->m_width
;
1435 int yy2
= child
->m_x
+ child
->m_height
;
1438 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1440 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1442 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1444 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1447 event
.m_x
-= child
->m_x
;
1448 event
.m_y
-= child
->m_y
;
1455 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1456 (child
->m_x
<= x
) &&
1457 (child
->m_y
<= y
) &&
1458 (child
->m_x
+child
->m_width
>= x
) &&
1459 (child
->m_y
+child
->m_height
>= y
))
1462 event
.m_x
-= child
->m_x
;
1463 event
.m_y
-= child
->m_y
;
1470 event
.SetEventObject( win
);
1472 if (win
->GetEventHandler()->ProcessEvent( event
))
1474 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1481 //-----------------------------------------------------------------------------
1482 // "motion_notify_event"
1483 //-----------------------------------------------------------------------------
1485 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
,
1486 GdkEventMotion
*gdk_event
,
1492 wxapp_install_idle_handler();
1494 if (!win
->m_hasVMT
) return FALSE
;
1495 if (g_blockEventsOnDrag
) return FALSE
;
1496 if (g_blockEventsOnScroll
) return FALSE
;
1498 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1500 if (gdk_event
->is_hint
)
1504 GdkModifierType state
;
1505 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1511 printf( "OnMotion from " );
1512 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1513 printf( win->GetClassInfo()->GetClassName() );
1517 wxMouseEvent
event( wxEVT_MOTION
);
1518 InitMouseEvent(win
, event
, gdk_event
);
1520 if ( g_captureWindow
)
1522 // synthetize a mouse enter or leave event if needed
1523 GdkWindow
*winUnderMouse
= gdk_window_at_pointer(NULL
, NULL
);
1524 bool hasMouse
= winUnderMouse
== gdk_event
->window
;
1525 if ( hasMouse
!= g_captureWindowHasMouse
)
1527 // the mouse changed window
1528 g_captureWindowHasMouse
= hasMouse
;
1530 wxMouseEvent
event(g_captureWindowHasMouse
? wxEVT_ENTER_WINDOW
1531 : wxEVT_LEAVE_WINDOW
);
1532 InitMouseEvent(win
, event
, gdk_event
);
1533 event
.SetEventObject(win
);
1534 win
->GetEventHandler()->ProcessEvent(event
);
1539 // Some control don't have their own X window and thus cannot get
1542 wxCoord x
= event
.m_x
;
1543 wxCoord y
= event
.m_y
;
1544 if (win
->m_wxwindow
)
1546 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1547 x
+= pizza
->xoffset
;
1548 y
+= pizza
->yoffset
;
1551 wxNode
*node
= win
->GetChildren().First();
1554 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1556 node
= node
->Next();
1557 if (!child
->IsShown())
1560 if (child
->m_isStaticBox
)
1562 // wxStaticBox is transparent in the box itself
1563 int xx1
= child
->m_x
;
1564 int yy1
= child
->m_y
;
1565 int xx2
= child
->m_x
+ child
->m_width
;
1566 int yy2
= child
->m_x
+ child
->m_height
;
1569 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1571 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1573 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1575 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1578 event
.m_x
-= child
->m_x
;
1579 event
.m_y
-= child
->m_y
;
1586 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1587 (child
->m_x
<= x
) &&
1588 (child
->m_y
<= y
) &&
1589 (child
->m_x
+child
->m_width
>= x
) &&
1590 (child
->m_y
+child
->m_height
>= y
))
1593 event
.m_x
-= child
->m_x
;
1594 event
.m_y
-= child
->m_y
;
1601 event
.SetEventObject( win
);
1603 if (win
->GetEventHandler()->ProcessEvent( event
))
1605 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1612 //-----------------------------------------------------------------------------
1614 //-----------------------------------------------------------------------------
1616 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
,
1617 GdkEvent
*WXUNUSED(event
),
1623 wxapp_install_idle_handler();
1625 if (!win
->m_hasVMT
) return FALSE
;
1626 if (g_blockEventsOnDrag
) return FALSE
;
1628 switch ( g_sendActivateEvent
)
1631 // we've got focus from outside, synthetize wxActivateEvent
1632 g_sendActivateEvent
= 1;
1636 // another our window just lost focus, it was already ours before
1637 // - don't send any wxActivateEvent
1638 g_sendActivateEvent
= -1;
1643 g_focusWindow
= win
;
1646 wxLogDebug( wxT("OnSetFocus from %s\n"), win
->GetName().c_str() );
1649 // notify the parent keeping track of focus for the kbd navigation
1650 // purposes that we got it
1651 wxChildFocusEvent
eventFocus(win
);
1652 (void)win
->GetEventHandler()->ProcessEvent(eventFocus
);
1656 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1660 // caret needs to be informed about focus change
1661 wxCaret
*caret
= win
->GetCaret();
1664 caret
->OnSetFocus();
1666 #endif // wxUSE_CARET
1668 wxWindowGTK
*active
= wxGetTopLevelParent(win
);
1669 if ( active
!= g_activeFrame
)
1671 if ( g_activeFrame
)
1673 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame
);
1674 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
1675 event
.SetEventObject(g_activeFrame
);
1676 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1679 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active
);
1680 g_activeFrame
= active
;
1681 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId());
1682 event
.SetEventObject(g_activeFrame
);
1683 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1685 g_activeFrameLostFocus
= FALSE
;
1688 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1689 event
.SetEventObject( win
);
1691 if (win
->GetEventHandler()->ProcessEvent( event
))
1693 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1701 //-----------------------------------------------------------------------------
1702 // "focus_out_event"
1703 //-----------------------------------------------------------------------------
1705 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEventFocus
*gdk_event
, wxWindowGTK
*win
)
1710 wxapp_install_idle_handler();
1712 if (!win
->m_hasVMT
) return FALSE
;
1713 if (g_blockEventsOnDrag
) return FALSE
;
1716 wxLogDebug( wxT("OnKillFocus from %s"), win
->GetName().c_str() );
1719 if ( !g_activeFrameLostFocus
&& g_activeFrame
)
1721 // VZ: commenting this out because it does happen (although not easy
1722 // to reproduce, I only see it when using wxMiniFrame and not
1723 // always) and makes using Mahogany quite annoying
1725 wxASSERT_MSG( wxGetTopLevelParent(win
) == g_activeFrame
,
1726 wxT("unfocusing window that hasn't gained focus properly") )
1729 g_activeFrameLostFocus
= TRUE
;
1732 // if the focus goes out of our app alltogether, OnIdle() will send
1733 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1734 // g_sendActivateEvent to -1
1735 g_sendActivateEvent
= 0;
1737 wxWindowGTK
*winFocus
= wxFindFocusedChild(win
);
1741 g_focusWindow
= (wxWindowGTK
*)NULL
;
1749 // caret needs to be informed about focus change
1750 wxCaret
*caret
= win
->GetCaret();
1753 caret
->OnKillFocus();
1755 #endif // wxUSE_CARET
1757 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1758 event
.SetEventObject( win
);
1760 if (win
->GetEventHandler()->ProcessEvent( event
))
1762 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1769 //-----------------------------------------------------------------------------
1770 // "enter_notify_event"
1771 //-----------------------------------------------------------------------------
1773 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1778 wxapp_install_idle_handler();
1780 if (!win
->m_hasVMT
) return FALSE
;
1781 if (g_blockEventsOnDrag
) return FALSE
;
1783 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1785 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1786 event
.SetTimestamp( gdk_event
->time
);
1787 event
.SetEventObject( win
);
1791 GdkModifierType state
= (GdkModifierType
)0;
1793 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1795 InitMouseEvent(win
, event
, gdk_event
);
1796 wxPoint pt
= win
->GetClientAreaOrigin();
1797 event
.m_x
= x
+ pt
.x
;
1798 event
.m_y
= y
+ pt
.y
;
1800 if (win
->GetEventHandler()->ProcessEvent( event
))
1802 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1809 //-----------------------------------------------------------------------------
1810 // "leave_notify_event"
1811 //-----------------------------------------------------------------------------
1813 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1818 wxapp_install_idle_handler();
1820 if (!win
->m_hasVMT
) return FALSE
;
1821 if (g_blockEventsOnDrag
) return FALSE
;
1823 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1825 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1826 event
.SetTimestamp( gdk_event
->time
);
1827 event
.SetEventObject( win
);
1831 GdkModifierType state
= (GdkModifierType
)0;
1833 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1835 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1836 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1837 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1838 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1839 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1840 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1841 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1843 wxPoint pt
= win
->GetClientAreaOrigin();
1844 event
.m_x
= x
+ pt
.x
;
1845 event
.m_y
= y
+ pt
.y
;
1847 if (win
->GetEventHandler()->ProcessEvent( event
))
1849 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1856 //-----------------------------------------------------------------------------
1857 // "value_changed" from m_vAdjust
1858 //-----------------------------------------------------------------------------
1860 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1865 wxapp_install_idle_handler();
1867 if (g_blockEventsOnDrag
) return;
1869 if (!win
->m_hasVMT
) return;
1871 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1872 if (fabs(diff
) < 0.2) return;
1874 win
->m_oldVerticalPos
= adjust
->value
;
1876 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1877 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1879 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1880 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1881 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1882 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1883 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1885 int value
= (int)(adjust
->value
+0.5);
1887 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1888 event
.SetEventObject( win
);
1889 win
->GetEventHandler()->ProcessEvent( event
);
1892 //-----------------------------------------------------------------------------
1893 // "value_changed" from m_hAdjust
1894 //-----------------------------------------------------------------------------
1896 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1901 wxapp_install_idle_handler();
1903 if (g_blockEventsOnDrag
) return;
1904 if (!win
->m_hasVMT
) return;
1906 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1907 if (fabs(diff
) < 0.2) return;
1909 win
->m_oldHorizontalPos
= adjust
->value
;
1911 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1912 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1914 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1915 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1916 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1917 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1918 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1920 int value
= (int)(adjust
->value
+0.5);
1922 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1923 event
.SetEventObject( win
);
1924 win
->GetEventHandler()->ProcessEvent( event
);
1927 //-----------------------------------------------------------------------------
1928 // "button_press_event" from scrollbar
1929 //-----------------------------------------------------------------------------
1931 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1932 GdkEventButton
*gdk_event
,
1938 wxapp_install_idle_handler();
1941 g_blockEventsOnScroll
= TRUE
;
1942 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1947 //-----------------------------------------------------------------------------
1948 // "button_release_event" from scrollbar
1949 //-----------------------------------------------------------------------------
1951 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1952 GdkEventButton
*WXUNUSED(gdk_event
),
1957 // don't test here as we can release the mouse while being over
1958 // a different window than the slider
1960 // if (gdk_event->window != widget->slider) return FALSE;
1962 g_blockEventsOnScroll
= FALSE
;
1964 if (win
->m_isScrolling
)
1966 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
1970 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1971 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1973 value
= (int)(win
->m_hAdjust
->value
+0.5);
1976 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1978 value
= (int)(win
->m_vAdjust
->value
+0.5);
1982 wxScrollWinEvent
event( command
, value
, dir
);
1983 event
.SetEventObject( win
);
1984 win
->GetEventHandler()->ProcessEvent( event
);
1987 win
->m_isScrolling
= FALSE
;
1992 // ----------------------------------------------------------------------------
1993 // this wxWindowBase function is implemented here (in platform-specific file)
1994 // because it is static and so couldn't be made virtual
1995 // ----------------------------------------------------------------------------
1997 wxWindow
*wxWindowBase::FindFocus()
1999 // the cast is necessary when we compile in wxUniversal mode
2000 return (wxWindow
*)g_focusWindow
;
2003 //-----------------------------------------------------------------------------
2004 // "realize" from m_widget
2005 //-----------------------------------------------------------------------------
2007 /* We cannot set colours and fonts before the widget has
2008 been realized, so we do this directly after realization. */
2011 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
2016 wxapp_install_idle_handler();
2018 if (win
->m_delayedBackgroundColour
)
2019 win
->SetBackgroundColour( win
->GetBackgroundColour() );
2021 if (win
->m_delayedForegroundColour
)
2022 win
->SetForegroundColour( win
->GetForegroundColour() );
2024 wxWindowCreateEvent
event( win
);
2025 event
.SetEventObject( win
);
2026 win
->GetEventHandler()->ProcessEvent( event
);
2031 //-----------------------------------------------------------------------------
2033 //-----------------------------------------------------------------------------
2036 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
2037 GtkAllocation
*WXUNUSED(alloc
),
2041 wxapp_install_idle_handler();
2043 if (!win
->m_hasScrolling
) return;
2045 int client_width
= 0;
2046 int client_height
= 0;
2047 win
->GetClientSize( &client_width
, &client_height
);
2048 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
2051 win
->m_oldClientWidth
= client_width
;
2052 win
->m_oldClientHeight
= client_height
;
2054 if (!win
->m_nativeSizeEvent
)
2056 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
2057 event
.SetEventObject( win
);
2058 win
->GetEventHandler()->ProcessEvent( event
);
2064 #define WXUNUSED_UNLESS_XIM(param) param
2066 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2069 /* Resize XIM window */
2072 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2073 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
2074 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2077 wxapp_install_idle_handler();
2083 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
2087 gdk_window_get_size (widget
->window
, &width
, &height
);
2088 win
->m_icattr
->preedit_area
.width
= width
;
2089 win
->m_icattr
->preedit_area
.height
= height
;
2090 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2095 //-----------------------------------------------------------------------------
2096 // "realize" from m_wxwindow
2097 //-----------------------------------------------------------------------------
2099 /* Initialize XIM support */
2102 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2103 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2106 wxapp_install_idle_handler();
2109 if (win
->m_ic
) return FALSE
;
2110 if (!widget
) return FALSE
;
2111 if (!gdk_im_ready()) return FALSE
;
2113 win
->m_icattr
= gdk_ic_attr_new();
2114 if (!win
->m_icattr
) return FALSE
;
2118 GdkColormap
*colormap
;
2119 GdkICAttr
*attr
= win
->m_icattr
;
2120 unsigned attrmask
= GDK_IC_ALL_REQ
;
2122 GdkIMStyle supported_style
= (GdkIMStyle
)
2123 (GDK_IM_PREEDIT_NONE
|
2124 GDK_IM_PREEDIT_NOTHING
|
2125 GDK_IM_PREEDIT_POSITION
|
2126 GDK_IM_STATUS_NONE
|
2127 GDK_IM_STATUS_NOTHING
);
2129 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2130 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2132 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2133 attr
->client_window
= widget
->window
;
2135 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2136 gtk_widget_get_default_colormap ())
2138 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2139 attr
->preedit_colormap
= colormap
;
2142 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2143 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2144 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2145 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2147 switch (style
& GDK_IM_PREEDIT_MASK
)
2149 case GDK_IM_PREEDIT_POSITION
:
2150 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2152 g_warning ("over-the-spot style requires fontset");
2156 gdk_window_get_size (widget
->window
, &width
, &height
);
2158 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2159 attr
->spot_location
.x
= 0;
2160 attr
->spot_location
.y
= height
;
2161 attr
->preedit_area
.x
= 0;
2162 attr
->preedit_area
.y
= 0;
2163 attr
->preedit_area
.width
= width
;
2164 attr
->preedit_area
.height
= height
;
2165 attr
->preedit_fontset
= widget
->style
->font
;
2170 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2172 if (win
->m_ic
== NULL
)
2173 g_warning ("Can't create input context.");
2176 mask
= gdk_window_get_events (widget
->window
);
2177 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2178 gdk_window_set_events (widget
->window
, mask
);
2180 if (GTK_WIDGET_HAS_FOCUS(widget
))
2181 gdk_im_begin (win
->m_ic
, widget
->window
);
2188 //-----------------------------------------------------------------------------
2189 // InsertChild for wxWindowGTK.
2190 //-----------------------------------------------------------------------------
2192 /* Callback for wxWindowGTK. This very strange beast has to be used because
2193 * C++ has no virtual methods in a constructor. We have to emulate a
2194 * virtual function here as wxNotebook requires a different way to insert
2195 * a child in it. I had opted for creating a wxNotebookPage window class
2196 * which would have made this superfluous (such in the MDI window system),
2197 * but no-one was listening to me... */
2199 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child
)
2201 /* the window might have been scrolled already, do we
2202 have to adapt the position */
2203 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2204 child
->m_x
+= pizza
->xoffset
;
2205 child
->m_y
+= pizza
->yoffset
;
2207 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2208 GTK_WIDGET(child
->m_widget
),
2215 //-----------------------------------------------------------------------------
2217 //-----------------------------------------------------------------------------
2219 wxWindow
*wxGetActiveWindow()
2221 // the cast is necessary when we compile in wxUniversal mode
2222 return (wxWindow
*)g_focusWindow
;
2225 //-----------------------------------------------------------------------------
2227 //-----------------------------------------------------------------------------
2229 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
2231 #ifdef __WXUNIVERSAL__
2232 IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
)
2234 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2235 #endif // __WXUNIVERSAL__/__WXGTK__
2237 void wxWindowGTK::Init()
2243 m_widget
= (GtkWidget
*) NULL
;
2244 m_wxwindow
= (GtkWidget
*) NULL
;
2245 m_focusWidget
= (GtkWidget
*) NULL
;
2255 m_needParent
= TRUE
;
2256 m_isBeingDeleted
= FALSE
;
2259 m_nativeSizeEvent
= FALSE
;
2261 m_hasScrolling
= FALSE
;
2262 m_isScrolling
= FALSE
;
2264 m_hAdjust
= (GtkAdjustment
*) NULL
;
2265 m_vAdjust
= (GtkAdjustment
*) NULL
;
2266 m_oldHorizontalPos
= 0.0;
2267 m_oldVerticalPos
= 0.0;
2270 m_widgetStyle
= (GtkStyle
*) NULL
;
2272 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2274 m_isStaticBox
= FALSE
;
2275 m_isRadioButton
= FALSE
;
2276 m_isListBox
= FALSE
;
2278 m_acceptsFocus
= FALSE
;
2280 m_clipPaintRegion
= FALSE
;
2282 m_cursor
= *wxSTANDARD_CURSOR
;
2284 m_delayedForegroundColour
= FALSE
;
2285 m_delayedBackgroundColour
= FALSE
;
2288 m_ic
= (GdkIC
*) NULL
;
2289 m_icattr
= (GdkICAttr
*) NULL
;
2293 wxWindowGTK::wxWindowGTK()
2298 wxWindowGTK::wxWindowGTK( wxWindow
*parent
,
2303 const wxString
&name
)
2307 Create( parent
, id
, pos
, size
, style
, name
);
2310 bool wxWindowGTK::Create( wxWindow
*parent
,
2315 const wxString
&name
)
2317 if (!PreCreation( parent
, pos
, size
) ||
2318 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2320 wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
2324 m_insertCallback
= wxInsertChildInWindow
;
2326 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2327 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2329 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2331 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2332 scroll_class
->scrollbar_spacing
= 0;
2334 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2336 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2337 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2339 m_wxwindow
= gtk_pizza_new();
2341 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2343 #ifndef __WXUNIVERSAL__
2344 #if (GTK_MINOR_VERSION > 0)
2345 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2347 if (HasFlag(wxRAISED_BORDER
))
2349 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2351 else if (HasFlag(wxSUNKEN_BORDER
))
2353 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2355 else if (HasFlag(wxSIMPLE_BORDER
))
2357 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2361 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2363 #else // GTK_MINOR_VERSION == 0
2364 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2366 if (HasFlag(wxRAISED_BORDER
))
2368 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2370 else if (HasFlag(wxSUNKEN_BORDER
))
2372 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2376 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2378 #endif // GTK_MINOR_VERSION
2379 #endif // __WXUNIVERSAL__
2381 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2382 m_acceptsFocus
= TRUE
;
2384 #if (GTK_MINOR_VERSION == 0)
2385 // shut the viewport up
2386 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2387 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2388 #endif // GTK_MINOR_VERSION == 0
2390 // I _really_ don't want scrollbars in the beginning
2391 m_vAdjust
->lower
= 0.0;
2392 m_vAdjust
->upper
= 1.0;
2393 m_vAdjust
->value
= 0.0;
2394 m_vAdjust
->step_increment
= 1.0;
2395 m_vAdjust
->page_increment
= 1.0;
2396 m_vAdjust
->page_size
= 5.0;
2397 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2398 m_hAdjust
->lower
= 0.0;
2399 m_hAdjust
->upper
= 1.0;
2400 m_hAdjust
->value
= 0.0;
2401 m_hAdjust
->step_increment
= 1.0;
2402 m_hAdjust
->page_increment
= 1.0;
2403 m_hAdjust
->page_size
= 5.0;
2404 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2406 // these handlers block mouse events to any window during scrolling such as
2407 // motion events and prevent GTK and wxWindows from fighting over where the
2410 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2411 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2413 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2414 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2416 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2417 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2419 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2420 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2422 // these handlers get notified when screen updates are required either when
2423 // scrolling or when the window size (and therefore scrollbar configuration)
2426 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2427 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2428 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2429 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2431 gtk_widget_show( m_wxwindow
);
2434 m_parent
->DoAddChild( this );
2436 m_focusWidget
= m_wxwindow
;
2445 wxWindowGTK::~wxWindowGTK()
2447 if (g_focusWindow
== this)
2448 g_focusWindow
= NULL
;
2450 if (g_activeFrame
== this)
2451 g_activeFrame
= NULL
;
2453 m_isBeingDeleted
= TRUE
;
2462 m_parent
->RemoveChild( this );
2466 gdk_ic_destroy (m_ic
);
2468 gdk_ic_attr_destroy (m_icattr
);
2473 #if DISABLE_STYLE_IF_BROKEN_THEME
2474 // don't delete if it's a pixmap theme style
2475 if (!m_widgetStyle
->engine_data
)
2476 gtk_style_unref( m_widgetStyle
);
2478 m_widgetStyle
= (GtkStyle
*) NULL
;
2483 gtk_widget_destroy( m_wxwindow
);
2484 m_wxwindow
= (GtkWidget
*) NULL
;
2489 gtk_widget_destroy( m_widget
);
2490 m_widget
= (GtkWidget
*) NULL
;
2494 bool wxWindowGTK::PreCreation( wxWindowGTK
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2496 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2498 /* this turns -1 into 20 so that a minimal window is
2499 visible even although -1,-1 has been given as the
2500 size of the window. the same trick is used in other
2501 ports and should make debugging easier */
2502 m_width
= WidthDefault(size
.x
);
2503 m_height
= HeightDefault(size
.y
);
2508 /* some reasonable defaults */
2513 m_x
= (gdk_screen_width () - m_width
) / 2;
2514 if (m_x
< 10) m_x
= 10;
2518 m_y
= (gdk_screen_height () - m_height
) / 2;
2519 if (m_y
< 10) m_y
= 10;
2526 void wxWindowGTK::PostCreation()
2528 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2534 // these get reported to wxWindows -> wxPaintEvent
2536 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2538 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2539 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2541 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2542 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2544 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2546 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2547 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2551 // these are called when the "sunken" or "raised" borders are drawn */
2552 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2553 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2555 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2556 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2561 if (m_focusWidget
== NULL
)
2562 m_focusWidget
= m_widget
;
2565 if (GetClassInfo() && GetClassInfo()->GetClassName())
2566 wxPrintf( GetClassInfo()->GetClassName() );
2570 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event",
2571 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2573 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event",
2574 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2576 // connect to the various key and mouse handlers
2578 GtkWidget
*connect_widget
= GetConnectWidget();
2580 ConnectWidget( connect_widget
);
2582 /* We cannot set colours, fonts and cursors before the widget has
2583 been realized, so we do this directly after realization */
2584 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2585 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2589 // Catch native resize events
2590 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2591 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2593 // Initialize XIM support
2594 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2595 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2597 // And resize XIM window
2598 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2599 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2602 if (!GTK_IS_COMBO(m_widget
))
2604 // This is needed if we want to add our windows into native
2605 // GTK control, such as the toolbar. With this callback, the
2606 // toolbar gets to know the correct size (the one set by the
2607 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2608 // when moving to GTK 2.0.
2609 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2610 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2616 void wxWindowGTK::ConnectWidget( GtkWidget
*widget
)
2618 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2619 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2621 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2622 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2624 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2625 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2627 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2628 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2630 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2631 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2633 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2634 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2636 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2637 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2640 bool wxWindowGTK::Destroy()
2642 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2646 return wxWindowBase::Destroy();
2649 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
)
2651 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2654 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2656 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2657 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") );
2660 printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
2663 if (m_resizing
) return; /* I don't like recursions */
2666 int currentX
, currentY
;
2667 GetPosition(¤tX
, ¤tY
);
2672 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
2674 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2676 /* don't set the size for children of wxNotebook, just take the values. */
2684 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2686 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2688 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2689 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2690 if (width
!= -1) m_width
= width
;
2691 if (height
!= -1) m_height
= height
;
2695 m_x
= x
+ pizza
->xoffset
;
2696 m_y
= y
+ pizza
->yoffset
;
2701 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2703 if (width
== -1) m_width
= 80;
2706 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2708 if (height
== -1) m_height
= 26;
2711 int minWidth
= GetMinWidth(),
2712 minHeight
= GetMinHeight(),
2713 maxWidth
= GetMaxWidth(),
2714 maxHeight
= GetMaxHeight();
2716 if ((minWidth
!= -1) && (m_width
< minWidth
)) m_width
= minWidth
;
2717 if ((minHeight
!= -1) && (m_height
< minHeight
)) m_height
= minHeight
;
2718 if ((maxWidth
!= -1) && (m_width
> maxWidth
)) m_width
= maxWidth
;
2719 if ((maxHeight
!= -1) && (m_height
> maxHeight
)) m_height
= maxHeight
;
2722 int bottom_border
= 0;
2724 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2726 /* the default button has a border around it */
2731 DoMoveWindow( m_x
-border
,
2734 m_height
+border
+bottom_border
);
2739 /* Sometimes the client area changes size without the
2740 whole windows's size changing, but if the whole
2741 windows's size doesn't change, no wxSizeEvent will
2742 normally be sent. Here we add an extra test if
2743 the client test has been changed and this will
2745 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2749 wxPrintf( "OnSize sent from " );
2750 if (GetClassInfo() && GetClassInfo()->GetClassName())
2751 wxPrintf( GetClassInfo()->GetClassName() );
2752 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2755 if (!m_nativeSizeEvent
)
2757 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2758 event
.SetEventObject( this );
2759 GetEventHandler()->ProcessEvent( event
);
2765 void wxWindowGTK::OnInternalIdle()
2767 // Update invalidated regions.
2770 // Synthetize activate events.
2771 if ( g_sendActivateEvent
!= -1 )
2773 bool activate
= g_sendActivateEvent
!= 0;
2776 g_sendActivateEvent
= -1;
2778 wxTheApp
->SetActive(activate
, (wxWindow
*)g_focusWindowLast
);
2781 if ( g_activeFrameLostFocus
)
2783 if ( g_activeFrame
)
2785 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame
);
2786 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
2787 event
.SetEventObject(g_activeFrame
);
2788 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
2789 g_activeFrame
= NULL
;
2791 g_activeFrameLostFocus
= FALSE
;
2794 wxCursor cursor
= m_cursor
;
2795 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2799 /* I now set the cursor anew in every OnInternalIdle call
2800 as setting the cursor in a parent window also effects the
2801 windows above so that checking for the current cursor is
2806 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2808 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2810 if (!g_globalCursor
.Ok())
2811 cursor
= *wxSTANDARD_CURSOR
;
2813 window
= m_widget
->window
;
2814 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2815 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2821 GdkWindow
*window
= m_widget
->window
;
2822 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2823 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2831 void wxWindowGTK::DoGetSize( int *width
, int *height
) const
2833 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2835 if (width
) (*width
) = m_width
;
2836 if (height
) (*height
) = m_height
;
2839 void wxWindowGTK::DoSetClientSize( int width
, int height
)
2841 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2845 SetSize( width
, height
);
2852 #ifndef __WXUNIVERSAL__
2853 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2855 /* when using GTK 1.2 we set the shadow border size to 2 */
2859 if (HasFlag(wxSIMPLE_BORDER
))
2861 /* when using GTK 1.2 we set the simple border size to 1 */
2865 #endif // __WXUNIVERSAL__
2869 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2871 GtkRequisition vscroll_req
;
2872 vscroll_req
.width
= 2;
2873 vscroll_req
.height
= 2;
2874 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2875 (scroll_window
->vscrollbar
, &vscroll_req
);
2877 GtkRequisition hscroll_req
;
2878 hscroll_req
.width
= 2;
2879 hscroll_req
.height
= 2;
2880 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2881 (scroll_window
->hscrollbar
, &hscroll_req
);
2883 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2885 if (scroll_window
->vscrollbar_visible
)
2887 dw
+= vscroll_req
.width
;
2888 dw
+= scroll_class
->scrollbar_spacing
;
2891 if (scroll_window
->hscrollbar_visible
)
2893 dh
+= hscroll_req
.height
;
2894 dh
+= scroll_class
->scrollbar_spacing
;
2898 SetSize( width
+dw
, height
+dh
);
2902 void wxWindowGTK::DoGetClientSize( int *width
, int *height
) const
2904 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2908 if (width
) (*width
) = m_width
;
2909 if (height
) (*height
) = m_height
;
2916 #ifndef __WXUNIVERSAL__
2917 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2919 /* when using GTK 1.2 we set the shadow border size to 2 */
2923 if (HasFlag(wxSIMPLE_BORDER
))
2925 /* when using GTK 1.2 we set the simple border size to 1 */
2929 #endif // __WXUNIVERSAL__
2933 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2935 GtkRequisition vscroll_req
;
2936 vscroll_req
.width
= 2;
2937 vscroll_req
.height
= 2;
2938 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2939 (scroll_window
->vscrollbar
, &vscroll_req
);
2941 GtkRequisition hscroll_req
;
2942 hscroll_req
.width
= 2;
2943 hscroll_req
.height
= 2;
2944 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2945 (scroll_window
->hscrollbar
, &hscroll_req
);
2947 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2949 if (scroll_window
->vscrollbar_visible
)
2951 dw
+= vscroll_req
.width
;
2952 dw
+= scroll_class
->scrollbar_spacing
;
2955 if (scroll_window
->hscrollbar_visible
)
2957 dh
+= hscroll_req
.height
;
2958 dh
+= scroll_class
->scrollbar_spacing
;
2962 if (width
) (*width
) = m_width
- dw
;
2963 if (height
) (*height
) = m_height
- dh
;
2967 printf( "GetClientSize, name %s ", GetName().c_str() );
2968 if (width) printf( " width = %d", (*width) );
2969 if (height) printf( " height = %d", (*height) );
2974 void wxWindowGTK::DoGetPosition( int *x
, int *y
) const
2976 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2980 if (m_parent
&& m_parent
->m_wxwindow
)
2982 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2983 dx
= pizza
->xoffset
;
2984 dy
= pizza
->yoffset
;
2987 if (x
) (*x
) = m_x
- dx
;
2988 if (y
) (*y
) = m_y
- dy
;
2991 void wxWindowGTK::DoClientToScreen( int *x
, int *y
) const
2993 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2995 if (!m_widget
->window
) return;
2997 GdkWindow
*source
= (GdkWindow
*) NULL
;
2999 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3001 source
= m_widget
->window
;
3005 gdk_window_get_origin( source
, &org_x
, &org_y
);
3009 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3011 org_x
+= m_widget
->allocation
.x
;
3012 org_y
+= m_widget
->allocation
.y
;
3020 void wxWindowGTK::DoScreenToClient( int *x
, int *y
) const
3022 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3024 if (!m_widget
->window
) return;
3026 GdkWindow
*source
= (GdkWindow
*) NULL
;
3028 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3030 source
= m_widget
->window
;
3034 gdk_window_get_origin( source
, &org_x
, &org_y
);
3038 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3040 org_x
+= m_widget
->allocation
.x
;
3041 org_y
+= m_widget
->allocation
.y
;
3049 bool wxWindowGTK::Show( bool show
)
3051 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3053 if (!wxWindowBase::Show(show
))
3060 gtk_widget_show( m_widget
);
3062 gtk_widget_hide( m_widget
);
3067 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
)
3069 win
->OnParentEnable(enable
);
3071 // Recurse, so that children have the opportunity to Do The Right Thing
3072 // and reset colours that have been messed up by a parent's (really ancestor's)
3074 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
3076 node
= node
->GetNext() )
3078 wxWindow
*child
= node
->GetData();
3079 if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
)))
3080 wxWindowNotifyEnable(child
, enable
);
3084 bool wxWindowGTK::Enable( bool enable
)
3086 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3088 if (!wxWindowBase::Enable(enable
))
3094 gtk_widget_set_sensitive( m_widget
, enable
);
3096 gtk_widget_set_sensitive( m_wxwindow
, enable
);
3098 wxWindowNotifyEnable(this, enable
);
3103 int wxWindowGTK::GetCharHeight() const
3105 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
3107 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
3109 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3111 return font
->ascent
+ font
->descent
;
3114 int wxWindowGTK::GetCharWidth() const
3116 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
3118 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
3120 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3122 return gdk_string_width( font
, "H" );
3125 void wxWindowGTK::GetTextExtent( const wxString
& string
,
3129 int *externalLeading
,
3130 const wxFont
*theFont
) const
3132 wxFont fontToUse
= m_font
;
3133 if (theFont
) fontToUse
= *theFont
;
3135 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
3137 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
3138 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
3139 if (y
) (*y
) = font
->ascent
+ font
->descent
;
3140 if (descent
) (*descent
) = font
->descent
;
3141 if (externalLeading
) (*externalLeading
) = 0; // ??
3144 void wxWindowGTK::SetFocus()
3146 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3149 wxPrintf( "SetFocus from " );
3150 if (GetClassInfo() && GetClassInfo()->GetClassName())
3151 wxPrintf( GetClassInfo()->GetClassName() );
3157 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3159 gtk_widget_grab_focus (m_wxwindow
);
3164 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
3166 gtk_widget_grab_focus (m_widget
);
3168 else if (GTK_IS_CONTAINER(m_widget
))
3170 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
3179 bool wxWindowGTK::AcceptsFocus() const
3181 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3184 bool wxWindowGTK::Reparent( wxWindowBase
*newParentBase
)
3186 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3188 wxWindowGTK
*oldParent
= m_parent
,
3189 *newParent
= (wxWindowGTK
*)newParentBase
;
3191 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3193 if ( !wxWindowBase::Reparent(newParent
) )
3196 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3198 /* prevent GTK from deleting the widget arbitrarily */
3199 gtk_widget_ref( m_widget
);
3203 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3206 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3210 /* insert GTK representation */
3211 (*(newParent
->m_insertCallback
))(newParent
, this);
3214 /* reverse: prevent GTK from deleting the widget arbitrarily */
3215 gtk_widget_unref( m_widget
);
3220 void wxWindowGTK::DoAddChild(wxWindowGTK
*child
)
3222 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3224 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3226 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3231 /* insert GTK representation */
3232 (*m_insertCallback
)(this, child
);
3235 void wxWindowGTK::Raise()
3237 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3239 if (!m_widget
->window
) return;
3241 gdk_window_raise( m_widget
->window
);
3244 void wxWindowGTK::Lower()
3246 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3248 if (!m_widget
->window
) return;
3250 gdk_window_lower( m_widget
->window
);
3253 bool wxWindowGTK::SetCursor( const wxCursor
&cursor
)
3255 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3257 if (cursor
== m_cursor
)
3261 wxapp_install_idle_handler();
3263 if (cursor
== wxNullCursor
)
3264 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3266 return wxWindowBase::SetCursor( cursor
);
3269 void wxWindowGTK::WarpPointer( int x
, int y
)
3271 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3273 // We provide this function ourselves as it is
3274 // missing in GDK (top of this file).
3276 GdkWindow
*window
= (GdkWindow
*) NULL
;
3278 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3280 window
= GetConnectWidget()->window
;
3283 gdk_window_warp_pointer( window
, x
, y
);
3286 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect
*rect
)
3288 if (!m_widget
) return;
3289 if (!m_widget
->window
) return;
3291 // temporarily hide the caret to avoid nasty interactions between caret
3292 // drawing and the window contents redraw
3293 #if 0 // def wxUSE_CARET -- doesn't seem to help :-(
3294 wxCaretSuspend
cs((wxWindow
*)this);
3295 #endif // wxUSE_CARET
3297 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3301 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3302 m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
3306 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3307 m_clearRegion
.Clear();
3308 m_clearRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height
);
3316 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3317 m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
3321 GdkRectangle gdk_rect
;
3322 gdk_rect
.x
= rect
->x
;
3323 gdk_rect
.y
= rect
->y
;
3324 gdk_rect
.width
= rect
->width
;
3325 gdk_rect
.height
= rect
->height
;
3326 gtk_widget_draw( m_widget
, &gdk_rect
);
3333 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3334 m_updateRegion
.Clear();
3335 m_updateRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height
);
3339 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3344 void wxWindowGTK::Update()
3346 if (!m_updateRegion
.IsEmpty())
3348 GtkSendPaintEvents();
3352 void wxWindowGTK::GtkSendPaintEvents()
3356 m_clearRegion
.Clear();
3357 m_updateRegion
.Clear();
3361 m_clipPaintRegion
= TRUE
;
3363 // if (!m_clearRegion.IsEmpty()) // always send an erase event
3365 wxWindowDC
dc( (wxWindow
*)this );
3366 dc
.SetClippingRegion( m_clearRegion
);
3368 wxEraseEvent
erase_event( GetId(), &dc
);
3369 erase_event
.SetEventObject( this );
3371 if (!GetEventHandler()->ProcessEvent(erase_event
))
3373 wxRegionIterator
upd( m_clearRegion
);
3376 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3377 upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
3381 m_clearRegion
.Clear();
3384 wxNcPaintEvent
nc_paint_event( GetId() );
3385 nc_paint_event
.SetEventObject( this );
3386 GetEventHandler()->ProcessEvent( nc_paint_event
);
3388 wxPaintEvent
paint_event( GetId() );
3389 paint_event
.SetEventObject( this );
3390 GetEventHandler()->ProcessEvent( paint_event
);
3392 m_clipPaintRegion
= FALSE
;
3394 #ifndef __WXUNIVERSAL__
3395 // The following code will result in all window-less widgets
3396 // being redrawn because the wxWindows class is allowed to
3397 // paint over the window-less widgets.
3399 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
3401 GList
*children
= pizza
->children
;
3404 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
3405 children
= children
->next
;
3407 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
3408 GTK_WIDGET_DRAWABLE (child
->widget
))
3410 // Get intersection of widget area and update region
3411 wxRegion
region( m_updateRegion
);
3413 GdkEventExpose gdk_event
;
3414 gdk_event
.type
= GDK_EXPOSE
;
3415 gdk_event
.window
= pizza
->bin_window
;
3416 gdk_event
.count
= 0;
3418 wxRegionIterator
upd( m_updateRegion
);
3422 rect
.x
= upd
.GetX();
3423 rect
.y
= upd
.GetY();
3424 rect
.width
= upd
.GetWidth();
3425 rect
.height
= upd
.GetHeight();
3427 if (gtk_widget_intersect (child
->widget
, &rect
, &gdk_event
.area
))
3429 gtk_widget_event (child
->widget
, (GdkEvent
*) &gdk_event
);
3438 m_updateRegion
.Clear();
3441 void wxWindowGTK::Clear()
3443 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3445 if (!m_widget
->window
) return;
3447 if (m_wxwindow
&& m_wxwindow
->window
)
3449 // gdk_window_clear( m_wxwindow->window );
3454 void wxWindowGTK::DoSetToolTip( wxToolTip
*tip
)
3456 wxWindowBase::DoSetToolTip(tip
);
3459 m_tooltip
->Apply( (wxWindow
*)this );
3462 void wxWindowGTK::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3464 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3466 #endif // wxUSE_TOOLTIPS
3468 bool wxWindowGTK::SetBackgroundColour( const wxColour
&colour
)
3470 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3472 if (!wxWindowBase::SetBackgroundColour(colour
))
3474 // don't leave if the GTK widget has just
3476 if (!m_delayedBackgroundColour
) return FALSE
;
3479 GdkWindow
*window
= (GdkWindow
*) NULL
;
3481 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3483 window
= GetConnectWidget()->window
;
3487 // indicate that a new style has been set
3488 // but it couldn't get applied as the
3489 // widget hasn't been realized yet.
3490 m_delayedBackgroundColour
= TRUE
;
3494 (m_wxwindow
->window
) &&
3495 (m_backgroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
)))
3497 /* wxMSW doesn't clear the window here. I don't do that either to
3498 provide compatibility. call Clear() to do the job. */
3500 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3501 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3509 bool wxWindowGTK::SetForegroundColour( const wxColour
&colour
)
3511 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3513 if (!wxWindowBase::SetForegroundColour(colour
))
3515 // don't leave if the GTK widget has just
3517 if (!m_delayedForegroundColour
) return FALSE
;
3520 GdkWindow
*window
= (GdkWindow
*) NULL
;
3522 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3524 window
= GetConnectWidget()->window
;
3528 // indicate that a new style has been set
3529 // but it couldn't get applied as the
3530 // widget hasn't been realized yet.
3531 m_delayedForegroundColour
= TRUE
;
3539 GtkStyle
*wxWindowGTK::GetWidgetStyle()
3543 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3545 /* FIXME: is this necessary? */
3546 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3548 remake
->klass
= m_widgetStyle
->klass
;
3551 gtk_style_unref( m_widgetStyle
);
3552 m_widgetStyle
= remake
;
3556 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3559 def
= gtk_widget_get_default_style();
3561 m_widgetStyle
= gtk_style_copy( def
);
3563 /* FIXME: is this necessary? */
3564 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3566 m_widgetStyle
->klass
= def
->klass
;
3570 return m_widgetStyle
;
3573 void wxWindowGTK::SetWidgetStyle()
3575 #if DISABLE_STYLE_IF_BROKEN_THEME
3576 if (m_widget
->style
->engine_data
)
3578 static bool s_warningPrinted
= FALSE
;
3579 if (!s_warningPrinted
)
3581 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3582 s_warningPrinted
= TRUE
;
3584 m_widgetStyle
= m_widget
->style
;
3589 GtkStyle
*style
= GetWidgetStyle();
3591 if (m_font
!= wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT
))
3593 gdk_font_unref( style
->font
);
3594 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3597 if (m_foregroundColour
.Ok())
3599 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3600 if (m_foregroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT
))
3602 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3603 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3604 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3608 // Try to restore the gtk default style. This is still a little
3609 // oversimplified for what is probably really needed here for controls
3610 // other than buttons, but is better than not being able to (re)set a
3611 // control's foreground colour to *wxBLACK -- RL
3612 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3615 def
= gtk_widget_get_default_style();
3617 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3618 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3619 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3623 if (m_backgroundColour
.Ok())
3625 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3626 if (m_backgroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
))
3628 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3629 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3630 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3631 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3632 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3633 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3634 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3635 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3639 // Try to restore the gtk default style. This is still a little
3640 // oversimplified for what is probably really needed here for controls
3641 // other than buttons, but is better than not being able to (re)set a
3642 // control's background colour to default grey and means resetting a
3643 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3645 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3648 def
= gtk_widget_get_default_style();
3650 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3651 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3652 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3653 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3654 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3655 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3656 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3657 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3662 void wxWindowGTK::ApplyWidgetStyle()
3666 //-----------------------------------------------------------------------------
3667 // Pop-up menu stuff
3668 //-----------------------------------------------------------------------------
3670 #if wxUSE_MENUS_NATIVE
3673 void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3675 *is_waiting
= FALSE
;
3678 static void SetInvokingWindow( wxMenu
*menu
, wxWindowGTK
*win
)
3680 menu
->SetInvokingWindow( win
);
3681 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3684 wxMenuItem
*menuitem
= node
->GetData();
3685 if (menuitem
->IsSubMenu())
3687 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3690 node
= node
->GetNext();
3694 // used to pass the coordinates from wxWindowGTK::DoPopupMenu() to
3695 // wxPopupMenuPositionCallback()
3697 // should be safe even in the MT case as the user can hardly popup 2 menus
3698 // simultaneously, can he?
3699 static gint gs_pop_x
= 0;
3700 static gint gs_pop_y
= 0;
3702 extern "C" void wxPopupMenuPositionCallback( GtkMenu
*menu
,
3704 gpointer
WXUNUSED(user_data
) )
3706 // ensure that the menu appears entirely on screen
3708 gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
);
3710 wxSize sizeScreen
= wxGetDisplaySize();
3712 gint xmax
= sizeScreen
.x
- req
.width
,
3713 ymax
= sizeScreen
.y
- req
.height
;
3715 *x
= gs_pop_x
< xmax
? gs_pop_x
: xmax
;
3716 *y
= gs_pop_y
< ymax
? gs_pop_y
: ymax
;
3719 bool wxWindowGTK::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3721 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3723 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3725 SetInvokingWindow( menu
, this );
3731 ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3733 bool is_waiting
= TRUE
;
3735 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
),
3737 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
),
3738 (gpointer
)&is_waiting
);
3741 GTK_MENU(menu
->m_menu
),
3742 (GtkWidget
*) NULL
, // parent menu shell
3743 (GtkWidget
*) NULL
, // parent menu item
3744 wxPopupMenuPositionCallback
, // function to position it
3745 NULL
, // client data
3746 0, // button used to activate it
3747 gs_timeLastClick
// the time of activation
3752 while (gtk_events_pending())
3753 gtk_main_iteration();
3759 #endif // wxUSE_MENUS_NATIVE
3761 #if wxUSE_DRAG_AND_DROP
3763 void wxWindowGTK::SetDropTarget( wxDropTarget
*dropTarget
)
3765 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3767 GtkWidget
*dnd_widget
= GetConnectWidget();
3769 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3771 if (m_dropTarget
) delete m_dropTarget
;
3772 m_dropTarget
= dropTarget
;
3774 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3777 #endif // wxUSE_DRAG_AND_DROP
3779 GtkWidget
* wxWindowGTK::GetConnectWidget()
3781 GtkWidget
*connect_widget
= m_widget
;
3782 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3784 return connect_widget
;
3787 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow
*window
)
3790 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3792 return (window
== m_widget
->window
);
3795 bool wxWindowGTK::SetFont( const wxFont
&font
)
3797 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3799 if (!wxWindowBase::SetFont(font
))
3804 wxColour sysbg
= wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE
);
3805 if ( sysbg
== m_backgroundColour
)
3807 m_backgroundColour
= wxNullColour
;
3809 m_backgroundColour
= sysbg
;
3819 void wxWindowGTK::DoCaptureMouse()
3821 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3823 GdkWindow
*window
= (GdkWindow
*) NULL
;
3825 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3827 window
= GetConnectWidget()->window
;
3829 wxCHECK_RET( window
, _T("CaptureMouse() failed") );
3831 wxCursor
* cursor
= & m_cursor
;
3833 cursor
= wxSTANDARD_CURSOR
;
3835 gdk_pointer_grab( window
, FALSE
,
3837 (GDK_BUTTON_PRESS_MASK
|
3838 GDK_BUTTON_RELEASE_MASK
|
3839 GDK_POINTER_MOTION_HINT_MASK
|
3840 GDK_POINTER_MOTION_MASK
),
3842 cursor
->GetCursor(),
3843 (guint32
)GDK_CURRENT_TIME
);
3844 g_captureWindow
= this;
3845 g_captureWindowHasMouse
= TRUE
;
3848 void wxWindowGTK::DoReleaseMouse()
3850 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3852 wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") );
3854 g_captureWindow
= (wxWindowGTK
*) NULL
;
3856 GdkWindow
*window
= (GdkWindow
*) NULL
;
3858 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3860 window
= GetConnectWidget()->window
;
3865 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3869 wxWindow
*wxWindowBase::GetCapture()
3871 return (wxWindow
*)g_captureWindow
;
3874 bool wxWindowGTK::IsRetained() const
3879 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3880 int range
, bool refresh
)
3882 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3884 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3886 m_hasScrolling
= TRUE
;
3888 if (orient
== wxHORIZONTAL
)
3890 float fpos
= (float)pos
;
3891 float frange
= (float)range
;
3892 float fthumb
= (float)thumbVisible
;
3893 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3894 if (fpos
< 0.0) fpos
= 0.0;
3896 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3897 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3899 SetScrollPos( orient
, pos
, refresh
);
3903 m_oldHorizontalPos
= fpos
;
3905 m_hAdjust
->lower
= 0.0;
3906 m_hAdjust
->upper
= frange
;
3907 m_hAdjust
->value
= fpos
;
3908 m_hAdjust
->step_increment
= 1.0;
3909 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3910 m_hAdjust
->page_size
= fthumb
;
3914 float fpos
= (float)pos
;
3915 float frange
= (float)range
;
3916 float fthumb
= (float)thumbVisible
;
3917 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3918 if (fpos
< 0.0) fpos
= 0.0;
3920 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3921 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3923 SetScrollPos( orient
, pos
, refresh
);
3927 m_oldVerticalPos
= fpos
;
3929 m_vAdjust
->lower
= 0.0;
3930 m_vAdjust
->upper
= frange
;
3931 m_vAdjust
->value
= fpos
;
3932 m_vAdjust
->step_increment
= 1.0;
3933 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3934 m_vAdjust
->page_size
= fthumb
;
3937 if (orient
== wxHORIZONTAL
)
3938 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3940 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3943 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3945 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3947 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3949 if (orient
== wxHORIZONTAL
)
3951 float fpos
= (float)pos
;
3952 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3953 if (fpos
< 0.0) fpos
= 0.0;
3954 m_oldHorizontalPos
= fpos
;
3956 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3957 m_hAdjust
->value
= fpos
;
3961 float fpos
= (float)pos
;
3962 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3963 if (fpos
< 0.0) fpos
= 0.0;
3964 m_oldVerticalPos
= fpos
;
3966 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3967 m_vAdjust
->value
= fpos
;
3970 if (m_wxwindow
->window
)
3972 if (orient
== wxHORIZONTAL
)
3974 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3975 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3977 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3979 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3980 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3984 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3985 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3987 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3989 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3990 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3995 int wxWindowGTK::GetScrollThumb( int orient
) const
3997 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3999 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4001 if (orient
== wxHORIZONTAL
)
4002 return (int)(m_hAdjust
->page_size
+0.5);
4004 return (int)(m_vAdjust
->page_size
+0.5);
4007 int wxWindowGTK::GetScrollPos( int orient
) const
4009 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4011 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4013 if (orient
== wxHORIZONTAL
)
4014 return (int)(m_hAdjust
->value
+0.5);
4016 return (int)(m_vAdjust
->value
+0.5);
4019 int wxWindowGTK::GetScrollRange( int orient
) const
4021 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4023 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4025 if (orient
== wxHORIZONTAL
)
4026 return (int)(m_hAdjust
->upper
+0.5);
4028 return (int)(m_vAdjust
->upper
+0.5);
4031 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
4033 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4035 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4037 // No scrolling requested.
4038 if ((dx
== 0) && (dy
== 0)) return;
4040 if (!m_updateRegion
.IsEmpty())
4042 m_updateRegion
.Offset( dx
, dy
);
4046 GetClientSize( &cw
, &ch
);
4047 m_updateRegion
.Intersect( 0, 0, cw
, ch
);
4050 if (!m_clearRegion
.IsEmpty())
4052 m_clearRegion
.Offset( dx
, dy
);
4056 GetClientSize( &cw
, &ch
);
4057 m_clearRegion
.Intersect( 0, 0, cw
, ch
);
4062 m_clipPaintRegion
= TRUE
;
4064 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
4066 m_clipPaintRegion
= FALSE
;
4070 if (m_children
.GetCount() > 0)
4072 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
4076 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
4078 pizza
->xoffset
-= dx
;
4079 pizza
->yoffset
-= dy
;
4081 GdkGC
*m_scrollGC
= gdk_gc_new( pizza
->bin_window
);
4082 gdk_gc_set_exposures( m_scrollGC
, TRUE
);
4086 GetClientSize( &cw
, &ch
);
4087 int w
= cw
- abs(dx
);
4088 int h
= ch
- abs(dy
);
4090 if ((h
< 0) || (w
< 0))
4098 if (dx
< 0) s_x
= -dx
;
4099 if (dy
< 0) s_y
= -dy
;
4102 if (dx
> 0) d_x
= dx
;
4103 if (dy
> 0) d_y
= dy
;
4105 gdk_window_copy_area( pizza
->bin_window
, m_scrollGC
, d_x
, d_y
,
4106 pizza
->bin_window
, s_x
, s_y
, w
, h
);
4109 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
4110 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
4111 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
4112 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
4114 Refresh( TRUE
, &rect
);
4117 gdk_gc_unref( m_scrollGC
);
4122 // Find the wxWindow at the current mouse position, also returning the mouse
4124 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
4126 pt
= wxGetMousePosition();
4127 wxWindow
* found
= wxFindWindowAtPoint(pt
);
4131 // Get the current mouse position.
4132 wxPoint
wxGetMousePosition()
4134 /* This crashes when used within wxHelpContext,
4135 so we have to use the X-specific implementation below.
4137 GdkModifierType *mask;
4138 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
4140 return wxPoint(x, y);
4144 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
4146 return wxPoint(-999, -999);
4148 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
4149 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
4150 Window rootReturn
, childReturn
;
4151 int rootX
, rootY
, winX
, winY
;
4152 unsigned int maskReturn
;
4154 XQueryPointer (display
,
4158 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
4159 return wxPoint(rootX
, rootY
);