1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/window.cpp
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #define XWarpPointer XWARPPOINTER
20 #include "wx/window.h"
21 #include "wx/dcclient.h"
24 #include "wx/layout.h"
26 #include "wx/dialog.h"
27 #include "wx/msgdlg.h"
29 #if wxUSE_DRAG_AND_DROP
34 #include "wx/tooltip.h"
42 #include "wx/textctrl.h"
46 #include "wx/statusbr.h"
48 #include "wx/settings.h"
52 #include "wx/thread.h"
59 #include <gdk/gdkprivate.h>
60 #include <gdk/gdkkeysyms.h>
64 #include <gtk/gtkprivate.h>
66 #include "wx/gtk/win_gtk.h"
68 //-----------------------------------------------------------------------------
69 // documentation on internals
70 //-----------------------------------------------------------------------------
73 I have been asked several times about writing some documentation about
74 the GTK port of wxWindows, especially its internal structures. Obviously,
75 you cannot understand wxGTK without knowing a little about the GTK, but
76 some more information about what the wxWindow, which is the base class
77 for all other window classes, does seems required as well.
81 What does wxWindow do? It contains the common interface for the following
82 jobs of its descendants:
84 1) Define the rudimentary behaviour common to all window classes, such as
85 resizing, intercepting user input (so as to make it possible to use these
86 events for special purposes in a derived class), window names etc.
88 2) Provide the possibility to contain and manage children, if the derived
89 class is allowed to contain children, which holds true for those window
90 classes which do not display a native GTK widget. To name them, these
91 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
92 work classes are a special case and are handled a bit differently from
93 the rest. The same holds true for the wxNotebook class.
95 3) Provide the possibility to draw into a client area of a window. This,
96 too, only holds true for classes that do not display a native GTK widget
99 4) Provide the entire mechanism for scrolling widgets. This actual inter-
100 face for this is usually in wxScrolledWindow, but the GTK implementation
103 5) A multitude of helper or extra methods for special purposes, such as
104 Drag'n'Drop, managing validators etc.
106 6) Display a border (sunken, raised, simple or none).
108 Normally one might expect, that one wxWindows window would always correspond
109 to one GTK widget. Under GTK, there is no such allround widget that has all
110 the functionality. Moreover, the GTK defines a client area as a different
111 widget from the actual widget you are handling. Last but not least some
112 special classes (e.g. wxFrame) handle different categories of widgets and
113 still have the possibility to draw something in the client area.
114 It was therefore required to write a special purpose GTK widget, that would
115 represent a client area in the sense of wxWindows capable to do the jobs
116 2), 3) and 4). I have written this class and it resides in win_gtk.c of
119 All windows must have a widget, with which they interact with other under-
120 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
121 thw wxWindow class has a member variable called m_widget which holds a
122 pointer to this widget. When the window class represents a GTK native widget,
123 this is (in most cases) the only GTK widget the class manages. E.g. the
124 wxStatitText class handles only a GtkLabel widget a pointer to which you
125 can find in m_widget (defined in wxWindow)
127 When the class has a client area for drawing into and for containing children
128 it has to handle the client area widget (of the type GtkPizza, defined in
129 win_gtk.c), but there could be any number of widgets, handled by a class
130 The common rule for all windows is only, that the widget that interacts with
131 the rest of GTK must be referenced in m_widget and all other widgets must be
132 children of this widget on the GTK level. The top-most widget, which also
133 represents the client area, must be in the m_wxwindow field and must be of
136 As I said, the window classes that display a GTK native widget only have
137 one widget, so in the case of e.g. the wxButton class m_widget holds a
138 pointer to a GtkButton widget. But windows with client areas (for drawing
139 and children) have a m_widget field that is a pointer to a GtkScrolled-
140 Window and a m_wxwindow field that is pointer to a GtkPizza and this
141 one is (in the GTK sense) a child of the GtkScrolledWindow.
143 If the m_wxwindow field is set, then all input to this widget is inter-
144 cepted and sent to the wxWindows class. If not, all input to the widget
145 that gets pointed to by m_widget gets intercepted and sent to the class.
149 The design of scrolling in wxWindows is markedly different from that offered
150 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
151 clicking on a scrollbar belonging to scrolled window will inevitably move
152 the window. In wxWindows, the scrollbar will only emit an event, send this
153 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
154 which actually moves the window and its subchildren. Note that GtkPizza
155 memorizes how much it has been scrolled but that wxWindows forgets this
156 so that the two coordinates systems have to be kept in synch. This is done
157 in various places using the pizza->xoffset and pizza->yoffset values.
161 Singularily the most broken code in GTK is the code that is supposes to
162 inform subwindows (child windows) about new positions. Very often, duplicate
163 events are sent without changes in size or position, equally often no
164 events are sent at all (All this is due to a bug in the GtkContainer code
165 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
166 GTK's own system and it simply waits for size events for toplevel windows
167 and then iterates down the respective size events to all window. This has
168 the disadvantage, that windows might get size events before the GTK widget
169 actually has the reported size. This doesn't normally pose any problem, but
170 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
171 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
172 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
173 window that is used for OpenGl output really has that size (as reported by
178 If someone at some point of time feels the immense desire to have a look at,
179 change or attempt to optimse the Refresh() logic, this person will need an
180 intimate understanding of what a "draw" and what an "expose" events are and
181 what there are used for, in particular when used in connection with GTK's
182 own windowless widgets. Beware.
186 Cursors, too, have been a constant source of pleasure. The main difficulty
187 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
188 for the parent. To prevent this from doing too much harm, I use idle time
189 to set the cursor over and over again, starting from the toplevel windows
190 and ending with the youngest generation (speaking of parent and child windows).
191 Also don't forget that cursors (like much else) are connected to GdkWindows,
192 not GtkWidgets and that the "window" field of a GtkWidget might very well
193 point to the GdkWindow of the parent widget (-> "window less widget") and
194 that the two obviously have very different meanings.
198 //-----------------------------------------------------------------------------
200 //-----------------------------------------------------------------------------
202 extern wxList wxPendingDelete
;
203 extern bool g_blockEventsOnDrag
;
204 extern bool g_blockEventsOnScroll
;
205 extern wxCursor g_globalCursor
;
207 // mouse capture state: the window which has it and if the mouse is currently
209 static wxWindowGTK
*g_captureWindow
= (wxWindowGTK
*) NULL
;
210 static bool g_captureWindowHasMouse
= FALSE
;
212 /* extern */ wxWindowGTK
*g_focusWindow
= (wxWindowGTK
*) NULL
;
214 // the last window which had the focus - this is normally never NULL (except
215 // if we never had focus at all) as even when g_focusWindow is NULL it still
216 // keeps its previous value
217 static wxWindowGTK
*g_focusWindowLast
= (wxWindowGTK
*)NULL
;
219 // the frame that is currently active (i.e. its child has focus). It is
220 // used to generate wxActivateEvents
221 static wxWindowGTK
*g_activeFrame
= (wxWindowGTK
*)NULL
;
222 static bool g_activeFrameLostFocus
= FALSE
;
224 // if we detect that the app has got/lost the focus, we set this variable to
225 // either TRUE or FALSE and an activate event will be sent during the next
226 // OnIdle() call and it is reset to -1: this value means that we shouldn't
227 // send any activate events at all
228 static int g_sendActivateEvent
= -1;
230 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
231 the last click here */
232 static guint32 gs_timeLastClick
= 0;
234 extern bool g_mainThreadLocked
;
236 //-----------------------------------------------------------------------------
238 //-----------------------------------------------------------------------------
241 #define DISABLE_STYLE_IF_BROKEN_THEME 1
247 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
249 # define DEBUG_MAIN_THREAD
252 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
253 GdkEvent
*WXUNUSED(event
),
254 const wxChar
*WXUNUSED(name
) )
257 static bool s_done = FALSE;
260 wxLog::AddTraceMask("focus");
263 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
269 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
271 // suppress warnings about gtk_debug_focus_in_callback being unused with
276 tmp
+= wxT(" FROM ");
279 wxChar
*s
= new wxChar
[tmp
.Length()+1];
283 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
284 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
289 #define DEBUG_MAIN_THREAD
292 //-----------------------------------------------------------------------------
293 // missing gdk functions
294 //-----------------------------------------------------------------------------
297 gdk_window_warp_pointer (GdkWindow
*window
,
302 GdkWindowPrivate
*priv
;
306 window
= GDK_ROOT_PARENT();
309 if (!GDK_WINDOW_DESTROYED(window
))
311 XWarpPointer (GDK_WINDOW_XDISPLAY(window
),
312 None
, /* not source window -> move from anywhere */
313 GDK_WINDOW_XID(window
), /* dest window */
314 0, 0, 0, 0, /* not source window -> move from anywhere */
318 priv
= (GdkWindowPrivate
*) window
;
320 if (!priv
->destroyed
)
322 XWarpPointer (priv
->xdisplay
,
323 None
, /* not source window -> move from anywhere */
324 priv
->xwindow
, /* dest window */
325 0, 0, 0, 0, /* not source window -> move from anywhere */
331 //-----------------------------------------------------------------------------
333 //-----------------------------------------------------------------------------
335 extern void wxapp_install_idle_handler();
336 extern bool g_isIdle
;
338 //-----------------------------------------------------------------------------
339 // local code (see below)
340 //-----------------------------------------------------------------------------
342 // returns the child of win which currently has focus or NULL if not found
344 // Note: can't be static, needed by textctrl.cpp.
345 wxWindow
*wxFindFocusedChild(wxWindowGTK
*win
)
347 wxWindow
*winFocus
= wxWindowGTK::FindFocus();
349 return (wxWindow
*)NULL
;
351 if ( winFocus
== win
)
352 return (wxWindow
*)win
;
354 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
356 node
= node
->GetNext() )
358 wxWindow
*child
= wxFindFocusedChild(node
->GetData());
363 return (wxWindow
*)NULL
;
366 // Returns toplevel grandparent of given window:
367 static wxWindowGTK
* wxGetTopLevelParent(wxWindowGTK
*win
)
369 wxWindowGTK
*p
= win
;
370 while (p
&& !p
->IsTopLevel())
376 static void draw_frame( GtkWidget
*widget
, wxWindowGTK
*win
)
378 // wxUniversal widgets draw the borders and scrollbars themselves
379 #ifndef __WXUNIVERSAL__
386 if (win
->m_hasScrolling
)
388 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
390 GtkRequisition vscroll_req
;
391 vscroll_req
.width
= 2;
392 vscroll_req
.height
= 2;
393 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
394 (scroll_window
->vscrollbar
, &vscroll_req
);
396 GtkRequisition hscroll_req
;
397 hscroll_req
.width
= 2;
398 hscroll_req
.height
= 2;
399 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
400 (scroll_window
->hscrollbar
, &hscroll_req
);
402 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) );
404 if (scroll_window
->vscrollbar_visible
)
406 dw
+= vscroll_req
.width
;
407 dw
+= scroll_class
->scrollbar_spacing
;
410 if (scroll_window
->hscrollbar_visible
)
412 dh
+= hscroll_req
.height
;
413 dh
+= scroll_class
->scrollbar_spacing
;
419 if (GTK_WIDGET_NO_WINDOW (widget
))
421 dx
+= widget
->allocation
.x
;
422 dy
+= widget
->allocation
.y
;
425 if (win
->HasFlag(wxRAISED_BORDER
))
427 gtk_draw_shadow( widget
->style
,
432 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
436 if (win
->HasFlag(wxSUNKEN_BORDER
))
438 gtk_draw_shadow( widget
->style
,
443 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
447 if (win
->HasFlag(wxSIMPLE_BORDER
))
450 gc
= gdk_gc_new( widget
->window
);
451 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
452 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
454 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
458 #endif // __WXUNIVERSAL__
461 //-----------------------------------------------------------------------------
462 // "expose_event" of m_widget
463 //-----------------------------------------------------------------------------
465 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindowGTK
*win
)
467 if (gdk_event
->count
> 0) return FALSE
;
469 draw_frame( widget
, win
);
474 //-----------------------------------------------------------------------------
475 // "draw" of m_widget
476 //-----------------------------------------------------------------------------
478 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindowGTK
*win
)
480 draw_frame( widget
, win
);
483 //-----------------------------------------------------------------------------
484 // key code mapping routines
485 //-----------------------------------------------------------------------------
487 static long map_to_unmodified_wx_keysym( GdkEventKey
*event
)
489 // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string
490 // but only event->keyval which is quite useless to us, so remember
491 // the last character from GDK_KEY_PRESS and resue it as last resort
493 // NB: should be MT-neutral as always called from main thread only
498 } s_lastKeyPress
= { 0, 0 };
500 KeySym keysym
= event
->keyval
;
506 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
508 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
514 case GDK_Super_R
: key_code
= WXK_ALT
; break;
515 case GDK_Menu
: key_code
= WXK_MENU
; break;
516 case GDK_Help
: key_code
= WXK_HELP
; break;
517 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
518 case GDK_ISO_Left_Tab
:
519 case GDK_Tab
: key_code
= WXK_TAB
; break;
520 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
521 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
522 case GDK_Return
: key_code
= WXK_RETURN
; break;
523 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
524 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
525 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
526 case GDK_Delete
: key_code
= WXK_DELETE
; break;
527 case GDK_Home
: key_code
= WXK_HOME
; break;
528 case GDK_Left
: key_code
= WXK_LEFT
; break;
529 case GDK_Up
: key_code
= WXK_UP
; break;
530 case GDK_Right
: key_code
= WXK_RIGHT
; break;
531 case GDK_Down
: key_code
= WXK_DOWN
; break;
532 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
533 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
534 case GDK_Next
: key_code
= WXK_NEXT
; break;
535 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
536 case GDK_End
: key_code
= WXK_END
; break;
537 case GDK_Begin
: key_code
= WXK_HOME
; break;
538 case GDK_Select
: key_code
= WXK_SELECT
; break;
539 case GDK_Print
: key_code
= WXK_PRINT
; break;
540 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
541 case GDK_Insert
: key_code
= WXK_INSERT
; break;
542 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
544 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
545 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
546 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
547 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
548 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
549 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
550 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
551 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
552 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
553 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
554 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
555 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
556 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
557 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
558 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
559 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
560 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
561 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
562 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
563 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
564 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
565 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
566 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
567 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
568 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
569 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
570 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
571 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
572 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
573 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
574 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
575 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
576 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
577 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
578 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
579 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
580 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
582 case GDK_F1
: key_code
= WXK_F1
; break;
583 case GDK_F2
: key_code
= WXK_F2
; break;
584 case GDK_F3
: key_code
= WXK_F3
; break;
585 case GDK_F4
: key_code
= WXK_F4
; break;
586 case GDK_F5
: key_code
= WXK_F5
; break;
587 case GDK_F6
: key_code
= WXK_F6
; break;
588 case GDK_F7
: key_code
= WXK_F7
; break;
589 case GDK_F8
: key_code
= WXK_F8
; break;
590 case GDK_F9
: key_code
= WXK_F9
; break;
591 case GDK_F10
: key_code
= WXK_F10
; break;
592 case GDK_F11
: key_code
= WXK_F11
; break;
593 case GDK_F12
: key_code
= WXK_F12
; break;
596 // do we have the translation?
597 if ( event
->length
== 1 )
599 keysym
= (KeySym
)event
->string
[0];
601 else if ( (keysym
& 0xFF) != keysym
)
603 // non ASCII key, what to do?
605 if ( event
->type
== GDK_KEY_RELEASE
)
607 // reuse the one from the last keypress if any
608 if ( keysym
== s_lastKeyPress
.keysym
)
610 key_code
= s_lastKeyPress
.keycode
;
617 // ignore this one, we don't know it
620 //else: ASCII key, ok
622 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
623 key_code
= upper
? upper
: keysym
;
625 if ( event
->type
== GDK_KEY_PRESS
)
627 // remember it to be reused below later
628 s_lastKeyPress
.keysym
= keysym
;
629 s_lastKeyPress
.keycode
= key_code
;
637 static long map_to_wx_keysym( GdkEventKey
*event
)
639 KeySym keysym
= event
->keyval
;
644 case GDK_Menu
: key_code
= WXK_MENU
; break;
645 case GDK_Help
: key_code
= WXK_HELP
; break;
646 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
647 case GDK_ISO_Left_Tab
:
648 case GDK_Tab
: key_code
= WXK_TAB
; break;
649 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
650 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
651 case GDK_Return
: key_code
= WXK_RETURN
; break;
652 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
653 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
654 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
655 case GDK_Delete
: key_code
= WXK_DELETE
; break;
656 case GDK_Home
: key_code
= WXK_HOME
; break;
657 case GDK_Left
: key_code
= WXK_LEFT
; break;
658 case GDK_Up
: key_code
= WXK_UP
; break;
659 case GDK_Right
: key_code
= WXK_RIGHT
; break;
660 case GDK_Down
: key_code
= WXK_DOWN
; break;
661 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
662 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
663 case GDK_Next
: key_code
= WXK_NEXT
; break;
664 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
665 case GDK_End
: key_code
= WXK_END
; break;
666 case GDK_Begin
: key_code
= WXK_HOME
; break;
667 case GDK_Select
: key_code
= WXK_SELECT
; break;
668 case GDK_Print
: key_code
= WXK_PRINT
; break;
669 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
670 case GDK_Insert
: key_code
= WXK_INSERT
; break;
671 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
673 case GDK_KP_0
: key_code
= '0'; break;
674 case GDK_KP_1
: key_code
= '1'; break;
675 case GDK_KP_2
: key_code
= '2'; break;
676 case GDK_KP_3
: key_code
= '3'; break;
677 case GDK_KP_4
: key_code
= '4'; break;
678 case GDK_KP_5
: key_code
= '5'; break;
679 case GDK_KP_6
: key_code
= '6'; break;
680 case GDK_KP_7
: key_code
= '7'; break;
681 case GDK_KP_8
: key_code
= '8'; break;
682 case GDK_KP_9
: key_code
= '9'; break;
683 case GDK_KP_Space
: key_code
= ' '; break;
684 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
685 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
686 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
687 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
688 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
689 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
690 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
691 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
692 case GDK_KP_Up
: key_code
= WXK_UP
; break;
693 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
694 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
695 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
696 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
697 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
698 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
699 case GDK_KP_End
: key_code
= WXK_END
; break;
700 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
701 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
702 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
703 case GDK_KP_Equal
: key_code
= '='; break;
704 case GDK_KP_Multiply
: key_code
= '*'; break;
705 case GDK_KP_Add
: key_code
= '+'; break;
706 case GDK_KP_Separator
: key_code
= ','; break;
707 case GDK_KP_Subtract
: key_code
= '-'; break;
708 case GDK_KP_Decimal
: key_code
= '.'; break;
709 case GDK_KP_Divide
: key_code
= '/'; break;
711 case GDK_F1
: key_code
= WXK_F1
; break;
712 case GDK_F2
: key_code
= WXK_F2
; break;
713 case GDK_F3
: key_code
= WXK_F3
; break;
714 case GDK_F4
: key_code
= WXK_F4
; break;
715 case GDK_F5
: key_code
= WXK_F5
; break;
716 case GDK_F6
: key_code
= WXK_F6
; break;
717 case GDK_F7
: key_code
= WXK_F7
; break;
718 case GDK_F8
: key_code
= WXK_F8
; break;
719 case GDK_F9
: key_code
= WXK_F9
; break;
720 case GDK_F10
: key_code
= WXK_F10
; break;
721 case GDK_F11
: key_code
= WXK_F11
; break;
722 case GDK_F12
: key_code
= WXK_F12
; break;
724 if (event
->length
== 1)
726 key_code
= (unsigned char)*event
->string
;
728 else if ((keysym
& 0xFF) == keysym
)
730 key_code
= (guint
)keysym
;
737 //-----------------------------------------------------------------------------
738 // "size_request" of m_widget
739 //-----------------------------------------------------------------------------
741 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
744 win
->GetSize( &w
, &h
);
748 requisition
->height
= h
;
749 requisition
->width
= w
;
752 //-----------------------------------------------------------------------------
753 // "expose_event" of m_wxwindow
754 //-----------------------------------------------------------------------------
756 static int gtk_window_expose_callback( GtkWidget
*widget
,
757 GdkEventExpose
*gdk_event
,
763 wxapp_install_idle_handler();
766 if (win->GetName() == wxT("panel"))
768 wxPrintf( wxT("OnExpose from ") );
769 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
770 wxPrintf( win->GetClassInfo()->GetClassName() );
771 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
772 (int)gdk_event->area.y,
773 (int)gdk_event->area.width,
774 (int)gdk_event->area.height );
778 GtkPizza
*pizza
= GTK_PIZZA (widget
);
780 if (win
->GetThemeEnabled())
782 wxWindow
*parent
= win
->GetParent();
783 while (parent
&& !parent
->IsTopLevel())
784 parent
= parent
->GetParent();
788 gtk_paint_flat_box (parent
->m_widget
->style
,
798 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
800 gdk_event
->area
.width
,
801 gdk_event
->area
.height
);
803 // Actually send the various events based on the
804 // current update region.
805 if (gdk_event
->count
== 0)
806 win
->GtkSendPaintEvents();
808 // The following code will result in all window-less widgets
809 // being redrawn if the wxWindows class is given a chance to
810 // paint *anything* because it will then be allowed to paint
811 // over the window-less widgets.
812 GList
*children
= pizza
->children
;
815 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
816 children
= children
->next
;
818 GdkEventExpose child_event
= *gdk_event
;
820 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
821 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
822 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
824 child_event
.area
.x
= child
->widget
->allocation
.x
;
825 child_event
.area
.y
= child
->widget
->allocation
.y
;
826 child_event
.area
.width
= child
->widget
->allocation
.width
;
827 child_event
.area
.height
= child
->widget
->allocation
.height
;
828 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
835 //-----------------------------------------------------------------------------
836 // "event" of m_wxwindow
837 //-----------------------------------------------------------------------------
839 // GTK thinks it is clever and filters out a certain amount of "unneeded"
840 // expose events. We need them, of course, so we override the main event
841 // procedure in GtkWidget by giving our own handler for all system events.
842 // There, we look for expose events ourselves whereas all other events are
845 gint
gtk_window_event_event_callback( GtkWidget
*widget
,
846 GdkEventExpose
*event
,
849 if (event
->type
== GDK_EXPOSE
)
851 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
858 //-----------------------------------------------------------------------------
859 // "draw" of m_wxwindow
860 //-----------------------------------------------------------------------------
862 // This callback is a complete replacement of the gtk_pizza_draw() function,
865 static void gtk_window_draw_callback( GtkWidget
*widget
,
872 wxapp_install_idle_handler();
874 // The wxNO_FULL_REPAINT_ON_RESIZE flag only works if
875 // there are no child windows.
876 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
877 (win
->GetChildren().GetCount() == 0))
883 if (win->GetName() == wxT("panel"))
885 wxPrintf( wxT("OnDraw from ") );
886 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
887 wxPrintf( win->GetClassInfo()->GetClassName() );
888 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
895 GtkPizza
*pizza
= GTK_PIZZA (widget
);
897 if (win
->GetThemeEnabled())
899 wxWindow
*parent
= win
->GetParent();
900 while (parent
&& !parent
->IsTopLevel())
901 parent
= parent
->GetParent();
905 gtk_paint_flat_box (parent
->m_widget
->style
,
916 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
917 (pizza
->clear_on_draw
))
919 gdk_window_clear_area( pizza
->bin_window
,
920 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
923 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
925 // Actually send the various events based on the
926 // current update region.
927 win
->GtkSendPaintEvents();
929 // Redraw child widgets
930 GList
*children
= pizza
->children
;
933 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
934 children
= children
->next
;
936 GdkRectangle child_area
;
937 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
939 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
944 //-----------------------------------------------------------------------------
945 // "key_press_event" from any window
946 //-----------------------------------------------------------------------------
948 // turn on to see the key event codes on the console
949 #undef DEBUG_KEY_EVENTS
951 static gint
gtk_window_key_press_callback( GtkWidget
*widget
,
952 GdkEventKey
*gdk_event
,
958 wxapp_install_idle_handler();
960 if (!win
->m_hasVMT
) return FALSE
;
961 if (g_blockEventsOnDrag
) return FALSE
;
966 GdkModifierType state
;
967 if (gdk_event
->window
)
968 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
972 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
974 #ifdef DEBUG_KEY_EVENTS
975 wxPrintf(_T("Key press event: %d => %ld\n"), gdk_event
->keyval
, key_code
);
976 #endif // DEBUG_KEY_EVENTS
978 /* sending unknown key events doesn't really make sense */
982 wxKeyEvent
event( wxEVT_KEY_DOWN
);
983 event
.SetTimestamp( gdk_event
->time
);
984 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
985 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
986 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
987 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
988 event
.m_keyCode
= key_code
;
989 event
.m_scanCode
= gdk_event
->keyval
;
992 event
.SetEventObject( win
);
993 ret
= win
->GetEventHandler()->ProcessEvent( event
);
998 wxWindowGTK
*ancestor
= win
;
1001 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
1004 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
1005 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
1008 if (ancestor
->IsTopLevel())
1010 ancestor
= ancestor
->GetParent();
1013 #endif // wxUSE_ACCEL
1015 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
1016 will only be sent if it is not in an accelerator table. */
1019 key_code
= map_to_wx_keysym( gdk_event
);
1023 #ifdef DEBUG_KEY_EVENTS
1024 wxPrintf(_T("Char event: %ld\n"), key_code
);
1025 #endif // DEBUG_KEY_EVENTS
1027 // reuse the ame event object, just change its type and use the
1028 // translated keycode instead of the raw one
1029 event
.SetEventType(wxEVT_CHAR
);
1030 event
.m_keyCode
= key_code
;
1032 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1036 /* win is a control: tab can be propagated up */
1038 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
1039 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
1040 // have this style, yet choose not to process this particular TAB in which
1041 // case TAB must still work as a navigational character
1043 !win
->HasFlag(wxTE_PROCESS_TAB
) &&
1045 win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
1047 wxNavigationKeyEvent new_event
;
1048 new_event
.SetEventObject( win
->GetParent() );
1049 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
1050 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
1051 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1052 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
1053 new_event
.SetCurrentFocus( win
);
1054 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
1057 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
1059 (gdk_event
->keyval
== GDK_Escape
) )
1061 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
1062 new_event
.SetEventObject( win
);
1063 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
1067 #if 0 // (GTK_MINOR_VERSION > 0)
1068 /* Pressing F10 will activate the menu bar of the top frame. */
1070 (gdk_event
->keyval
== GDK_F10
) )
1072 wxWindowGTK
*ancestor
= win
;
1075 if (wxIsKindOf(ancestor
,wxFrame
))
1077 wxFrame
*frame
= (wxFrame
*) ancestor
;
1078 wxMenuBar
*menubar
= frame
->GetMenuBar();
1081 wxNode
*node
= menubar
->GetMenus().First();
1084 wxMenu
*firstMenu
= (wxMenu
*) node
->Data();
1085 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu
->m_owner
) );
1091 ancestor
= ancestor
->GetParent();
1098 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1105 //-----------------------------------------------------------------------------
1106 // "key_release_event" from any window
1107 //-----------------------------------------------------------------------------
1109 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindowGTK
*win
)
1114 wxapp_install_idle_handler();
1116 if (!win
->m_hasVMT
) return FALSE
;
1117 if (g_blockEventsOnDrag
) return FALSE
;
1119 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
1121 #ifdef DEBUG_KEY_EVENTS
1122 wxPrintf(_T("Key release event: %d => %ld\n"), gdk_event
->keyval
, key_code
);
1123 #endif // DEBUG_KEY_EVENTS
1125 /* sending unknown key events doesn't really make sense */
1126 if (key_code
== 0) return FALSE
;
1130 GdkModifierType state
;
1131 if (gdk_event
->window
)
1132 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1134 wxKeyEvent
event( wxEVT_KEY_UP
);
1135 event
.SetTimestamp( gdk_event
->time
);
1136 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1137 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1138 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1139 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1140 event
.m_keyCode
= key_code
;
1141 event
.m_scanCode
= gdk_event
->keyval
;
1144 event
.SetEventObject( win
);
1146 if (win
->GetEventHandler()->ProcessEvent( event
))
1148 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1155 // ============================================================================
1157 // ============================================================================
1159 // init wxMouseEvent with the info from gdk_event
1160 #define InitMouseEvent(win, event, gdk_event) \
1162 event.SetTimestamp( gdk_event->time ); \
1163 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
1164 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
1165 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
1166 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
1167 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
1168 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
1169 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
1171 wxPoint pt = win->GetClientAreaOrigin(); \
1172 event.m_x = (wxCoord)gdk_event->x - pt.x; \
1173 event.m_y = (wxCoord)gdk_event->y - pt.y; \
1176 // ----------------------------------------------------------------------------
1177 // mouse event processing helper
1178 // ----------------------------------------------------------------------------
1180 static void AdjustEventButtonState(wxMouseEvent
& event
)
1182 // GDK reports the old state of the button for a button press event, but
1183 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1184 // for a LEFT_DOWN event, not FALSE, so we will invert
1185 // left/right/middleDown for the corresponding click events
1187 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1188 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1189 (event
.GetEventType() == wxEVT_LEFT_UP
))
1191 event
.m_leftDown
= !event
.m_leftDown
;
1195 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1196 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1197 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1199 event
.m_middleDown
= !event
.m_middleDown
;
1203 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1204 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1205 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1207 event
.m_rightDown
= !event
.m_rightDown
;
1212 //-----------------------------------------------------------------------------
1213 // "button_press_event"
1214 //-----------------------------------------------------------------------------
1216 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1221 wxapp_install_idle_handler();
1224 wxPrintf( wxT("1) OnButtonPress from ") );
1225 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1226 wxPrintf( win->GetClassInfo()->GetClassName() );
1227 wxPrintf( wxT(".\n") );
1229 if (!win
->m_hasVMT
) return FALSE
;
1230 if (g_blockEventsOnDrag
) return TRUE
;
1231 if (g_blockEventsOnScroll
) return TRUE
;
1233 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1235 if (win
->m_wxwindow
)
1237 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1239 gtk_widget_grab_focus (win
->m_wxwindow
);
1242 wxPrintf( wxT("GrabFocus from ") );
1243 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1244 wxPrintf( win->GetClassInfo()->GetClassName() );
1245 wxPrintf( wxT(".\n") );
1251 wxEventType event_type
= wxEVT_NULL
;
1253 if (gdk_event
->button
== 1)
1255 switch (gdk_event
->type
)
1257 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1258 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1262 else if (gdk_event
->button
== 2)
1264 switch (gdk_event
->type
)
1266 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1267 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1271 else if (gdk_event
->button
== 3)
1273 switch (gdk_event
->type
)
1275 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1276 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1281 if ( event_type
== wxEVT_NULL
)
1283 // unknown mouse button or click type
1287 wxMouseEvent
event( event_type
);
1288 InitMouseEvent( win
, event
, gdk_event
);
1290 AdjustEventButtonState(event
);
1292 // wxListBox actually get mouse events from the item
1294 if (win
->m_isListBox
)
1296 event
.m_x
+= widget
->allocation
.x
;
1297 event
.m_y
+= widget
->allocation
.y
;
1300 // Some control don't have their own X window and thus cannot get
1303 if (!g_captureWindow
)
1305 wxCoord x
= event
.m_x
;
1306 wxCoord y
= event
.m_y
;
1307 if (win
->m_wxwindow
)
1309 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1310 x
+= pizza
->xoffset
;
1311 y
+= pizza
->yoffset
;
1314 wxNode
*node
= win
->GetChildren().First();
1317 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1319 node
= node
->Next();
1320 if (!child
->IsShown())
1323 if (child
->m_isStaticBox
)
1325 // wxStaticBox is transparent in the box itself
1326 int xx1
= child
->m_x
;
1327 int yy1
= child
->m_y
;
1328 int xx2
= child
->m_x
+ child
->m_width
;
1329 int yy2
= child
->m_x
+ child
->m_height
;
1332 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1334 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1336 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1338 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1341 event
.m_x
-= child
->m_x
;
1342 event
.m_y
-= child
->m_y
;
1349 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1350 (child
->m_x
<= x
) &&
1351 (child
->m_y
<= y
) &&
1352 (child
->m_x
+child
->m_width
>= x
) &&
1353 (child
->m_y
+child
->m_height
>= y
))
1356 event
.m_x
-= child
->m_x
;
1357 event
.m_y
-= child
->m_y
;
1364 event
.SetEventObject( win
);
1366 gs_timeLastClick
= gdk_event
->time
;
1369 wxPrintf( wxT("2) OnButtonPress from ") );
1370 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1371 wxPrintf( win->GetClassInfo()->GetClassName() );
1372 wxPrintf( wxT(".\n") );
1375 if (win
->GetEventHandler()->ProcessEvent( event
))
1377 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1384 //-----------------------------------------------------------------------------
1385 // "button_release_event"
1386 //-----------------------------------------------------------------------------
1388 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1393 wxapp_install_idle_handler();
1395 if (!win
->m_hasVMT
) return FALSE
;
1396 if (g_blockEventsOnDrag
) return FALSE
;
1397 if (g_blockEventsOnScroll
) return FALSE
;
1399 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1402 printf( "OnButtonRelease from " );
1403 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1404 printf( win->GetClassInfo()->GetClassName() );
1408 wxEventType event_type
= wxEVT_NULL
;
1410 switch (gdk_event
->button
)
1412 case 1: event_type
= wxEVT_LEFT_UP
; break;
1413 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1414 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1415 default: return FALSE
;
1418 wxMouseEvent
event( event_type
);
1419 InitMouseEvent( win
, event
, gdk_event
);
1421 AdjustEventButtonState(event
);
1423 // wxListBox actually get mouse events from the item
1425 if (win
->m_isListBox
)
1427 event
.m_x
+= widget
->allocation
.x
;
1428 event
.m_y
+= widget
->allocation
.y
;
1431 // Some control don't have their own X window and thus cannot get
1434 if (!g_captureWindow
)
1436 wxCoord x
= event
.m_x
;
1437 wxCoord y
= event
.m_y
;
1438 if (win
->m_wxwindow
)
1440 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1441 x
+= pizza
->xoffset
;
1442 y
+= pizza
->yoffset
;
1445 wxNode
*node
= win
->GetChildren().First();
1448 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1450 node
= node
->Next();
1451 if (!child
->IsShown())
1454 if (child
->m_isStaticBox
)
1456 // wxStaticBox is transparent in the box itself
1457 int xx1
= child
->m_x
;
1458 int yy1
= child
->m_y
;
1459 int xx2
= child
->m_x
+ child
->m_width
;
1460 int yy2
= child
->m_x
+ child
->m_height
;
1463 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1465 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1467 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1469 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1472 event
.m_x
-= child
->m_x
;
1473 event
.m_y
-= child
->m_y
;
1480 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1481 (child
->m_x
<= x
) &&
1482 (child
->m_y
<= y
) &&
1483 (child
->m_x
+child
->m_width
>= x
) &&
1484 (child
->m_y
+child
->m_height
>= y
))
1487 event
.m_x
-= child
->m_x
;
1488 event
.m_y
-= child
->m_y
;
1495 event
.SetEventObject( win
);
1497 if (win
->GetEventHandler()->ProcessEvent( event
))
1499 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1506 //-----------------------------------------------------------------------------
1507 // "motion_notify_event"
1508 //-----------------------------------------------------------------------------
1510 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
,
1511 GdkEventMotion
*gdk_event
,
1517 wxapp_install_idle_handler();
1519 if (!win
->m_hasVMT
) return FALSE
;
1520 if (g_blockEventsOnDrag
) return FALSE
;
1521 if (g_blockEventsOnScroll
) return FALSE
;
1523 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1525 if (gdk_event
->is_hint
)
1529 GdkModifierType state
;
1530 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1536 printf( "OnMotion from " );
1537 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1538 printf( win->GetClassInfo()->GetClassName() );
1542 wxMouseEvent
event( wxEVT_MOTION
);
1543 InitMouseEvent(win
, event
, gdk_event
);
1545 if ( g_captureWindow
)
1547 // synthetize a mouse enter or leave event if needed
1548 GdkWindow
*winUnderMouse
= gdk_window_at_pointer(NULL
, NULL
);
1549 bool hasMouse
= winUnderMouse
== gdk_event
->window
;
1550 if ( hasMouse
!= g_captureWindowHasMouse
)
1552 // the mouse changed window
1553 g_captureWindowHasMouse
= hasMouse
;
1555 wxMouseEvent
event(g_captureWindowHasMouse
? wxEVT_ENTER_WINDOW
1556 : wxEVT_LEAVE_WINDOW
);
1557 InitMouseEvent(win
, event
, gdk_event
);
1558 event
.SetEventObject(win
);
1559 win
->GetEventHandler()->ProcessEvent(event
);
1564 // Some control don't have their own X window and thus cannot get
1567 wxCoord x
= event
.m_x
;
1568 wxCoord y
= event
.m_y
;
1569 if (win
->m_wxwindow
)
1571 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1572 x
+= pizza
->xoffset
;
1573 y
+= pizza
->yoffset
;
1576 wxNode
*node
= win
->GetChildren().First();
1579 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1581 node
= node
->Next();
1582 if (!child
->IsShown())
1585 if (child
->m_isStaticBox
)
1587 // wxStaticBox is transparent in the box itself
1588 int xx1
= child
->m_x
;
1589 int yy1
= child
->m_y
;
1590 int xx2
= child
->m_x
+ child
->m_width
;
1591 int yy2
= child
->m_x
+ child
->m_height
;
1594 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1596 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1598 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1600 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1603 event
.m_x
-= child
->m_x
;
1604 event
.m_y
-= child
->m_y
;
1611 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1612 (child
->m_x
<= x
) &&
1613 (child
->m_y
<= y
) &&
1614 (child
->m_x
+child
->m_width
>= x
) &&
1615 (child
->m_y
+child
->m_height
>= y
))
1618 event
.m_x
-= child
->m_x
;
1619 event
.m_y
-= child
->m_y
;
1626 event
.SetEventObject( win
);
1628 if (win
->GetEventHandler()->ProcessEvent( event
))
1630 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1637 //-----------------------------------------------------------------------------
1639 //-----------------------------------------------------------------------------
1641 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
,
1642 GdkEvent
*WXUNUSED(event
),
1648 wxapp_install_idle_handler();
1650 if (!win
->m_hasVMT
) return FALSE
;
1651 if (g_blockEventsOnDrag
) return FALSE
;
1653 switch ( g_sendActivateEvent
)
1656 // we've got focus from outside, synthetize wxActivateEvent
1657 g_sendActivateEvent
= 1;
1661 // another our window just lost focus, it was already ours before
1662 // - don't send any wxActivateEvent
1663 g_sendActivateEvent
= -1;
1668 g_focusWindow
= win
;
1671 wxPrintf( "OnSetFocus from " );
1672 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
1673 wxPrintf( win
->GetClassInfo()->GetClassName() );
1677 // notify the parent keeping track of focus for the kbd navigation
1678 // purposes that we got it
1679 wxChildFocusEvent
eventFocus(win
);
1680 (void)win
->GetEventHandler()->ProcessEvent(eventFocus
);
1684 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1688 // caret needs to be informed about focus change
1689 wxCaret
*caret
= win
->GetCaret();
1692 caret
->OnSetFocus();
1694 #endif // wxUSE_CARET
1696 wxWindowGTK
*active
= wxGetTopLevelParent(win
);
1697 if ( active
!= g_activeFrame
)
1699 if ( g_activeFrame
)
1701 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame
);
1702 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
1703 event
.SetEventObject(g_activeFrame
);
1704 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1707 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active
);
1708 g_activeFrame
= active
;
1709 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId());
1710 event
.SetEventObject(g_activeFrame
);
1711 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1713 g_activeFrameLostFocus
= FALSE
;
1716 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1717 event
.SetEventObject( win
);
1719 if (win
->GetEventHandler()->ProcessEvent( event
))
1721 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1729 //-----------------------------------------------------------------------------
1730 // "focus_out_event"
1731 //-----------------------------------------------------------------------------
1733 static GtkWidget
*gs_widgetLastFocus
= NULL
;
1735 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindowGTK
*win
)
1740 wxapp_install_idle_handler();
1742 if (!win
->m_hasVMT
) return FALSE
;
1743 if (g_blockEventsOnDrag
) return FALSE
;
1745 // VZ: this is really weird but GTK+ seems to call us from inside
1746 // gtk_widget_grab_focus(), i.e. it first sends "focus_out" signal to
1747 // this widget and then "focus_in". This is totally unexpected and
1748 // completely breaks wxUniv code so ignore this dummy event (we can't
1749 // be losing focus if we're about to acquire it!)
1750 if ( widget
== gs_widgetLastFocus
)
1752 gs_widgetLastFocus
= NULL
;
1757 if ( !g_activeFrameLostFocus
&& g_activeFrame
)
1759 // VZ: commenting this out because it does happen (although not easy
1760 // to reproduce, I only see it when using wxMiniFrame and not
1761 // always) and makes using Mahogany quite annoying
1763 wxASSERT_MSG( wxGetTopLevelParent(win
) == g_activeFrame
,
1764 wxT("unfocusing window that hasn't gained focus properly") )
1767 g_activeFrameLostFocus
= TRUE
;
1770 // if the focus goes out of our app alltogether, OnIdle() will send
1771 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1772 // g_sendActivateEvent to -1
1773 g_sendActivateEvent
= 0;
1775 wxWindowGTK
*winFocus
= wxFindFocusedChild(win
);
1779 g_focusWindow
= (wxWindowGTK
*)NULL
;
1782 wxPrintf( "OnKillFocus from " );
1783 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
1784 wxPrintf( win
->GetClassInfo()->GetClassName() );
1794 // caret needs to be informed about focus change
1795 wxCaret
*caret
= win
->GetCaret();
1798 caret
->OnKillFocus();
1800 #endif // wxUSE_CARET
1802 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1803 event
.SetEventObject( win
);
1805 if (win
->GetEventHandler()->ProcessEvent( event
))
1807 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1814 //-----------------------------------------------------------------------------
1815 // "enter_notify_event"
1816 //-----------------------------------------------------------------------------
1818 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1823 wxapp_install_idle_handler();
1825 if (!win
->m_hasVMT
) return FALSE
;
1826 if (g_blockEventsOnDrag
) return FALSE
;
1828 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1830 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1831 event
.SetTimestamp( gdk_event
->time
);
1832 event
.SetEventObject( win
);
1836 GdkModifierType state
= (GdkModifierType
)0;
1838 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1840 InitMouseEvent(win
, event
, gdk_event
);
1841 wxPoint pt
= win
->GetClientAreaOrigin();
1842 event
.m_x
= x
+ pt
.x
;
1843 event
.m_y
= y
+ pt
.y
;
1845 if (win
->GetEventHandler()->ProcessEvent( event
))
1847 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1854 //-----------------------------------------------------------------------------
1855 // "leave_notify_event"
1856 //-----------------------------------------------------------------------------
1858 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1863 wxapp_install_idle_handler();
1865 if (!win
->m_hasVMT
) return FALSE
;
1866 if (g_blockEventsOnDrag
) return FALSE
;
1868 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1870 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1871 event
.SetTimestamp( gdk_event
->time
);
1872 event
.SetEventObject( win
);
1876 GdkModifierType state
= (GdkModifierType
)0;
1878 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1880 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1881 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1882 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1883 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1884 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1885 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1886 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1888 wxPoint pt
= win
->GetClientAreaOrigin();
1889 event
.m_x
= x
+ pt
.x
;
1890 event
.m_y
= y
+ pt
.y
;
1892 if (win
->GetEventHandler()->ProcessEvent( event
))
1894 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1901 //-----------------------------------------------------------------------------
1902 // "value_changed" from m_vAdjust
1903 //-----------------------------------------------------------------------------
1905 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1910 wxapp_install_idle_handler();
1912 if (g_blockEventsOnDrag
) return;
1914 if (!win
->m_hasVMT
) return;
1916 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1917 if (fabs(diff
) < 0.2) return;
1919 win
->m_oldVerticalPos
= adjust
->value
;
1921 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1922 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1924 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1925 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1926 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1927 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1928 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1930 int value
= (int)(adjust
->value
+0.5);
1932 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1933 event
.SetEventObject( win
);
1934 win
->GetEventHandler()->ProcessEvent( event
);
1937 //-----------------------------------------------------------------------------
1938 // "value_changed" from m_hAdjust
1939 //-----------------------------------------------------------------------------
1941 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1946 wxapp_install_idle_handler();
1948 if (g_blockEventsOnDrag
) return;
1949 if (!win
->m_hasVMT
) return;
1951 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1952 if (fabs(diff
) < 0.2) return;
1954 win
->m_oldHorizontalPos
= adjust
->value
;
1956 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1957 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1959 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1960 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1961 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1962 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1963 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1965 int value
= (int)(adjust
->value
+0.5);
1967 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1968 event
.SetEventObject( win
);
1969 win
->GetEventHandler()->ProcessEvent( event
);
1972 //-----------------------------------------------------------------------------
1973 // "button_press_event" from scrollbar
1974 //-----------------------------------------------------------------------------
1976 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1977 GdkEventButton
*gdk_event
,
1983 wxapp_install_idle_handler();
1986 g_blockEventsOnScroll
= TRUE
;
1987 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1992 //-----------------------------------------------------------------------------
1993 // "button_release_event" from scrollbar
1994 //-----------------------------------------------------------------------------
1996 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1997 GdkEventButton
*WXUNUSED(gdk_event
),
2002 // don't test here as we can release the mouse while being over
2003 // a different window than the slider
2005 // if (gdk_event->window != widget->slider) return FALSE;
2007 g_blockEventsOnScroll
= FALSE
;
2009 if (win
->m_isScrolling
)
2011 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
2015 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
2016 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
2018 value
= (int)(win
->m_hAdjust
->value
+0.5);
2021 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
2023 value
= (int)(win
->m_vAdjust
->value
+0.5);
2027 wxScrollWinEvent
event( command
, value
, dir
);
2028 event
.SetEventObject( win
);
2029 win
->GetEventHandler()->ProcessEvent( event
);
2032 win
->m_isScrolling
= FALSE
;
2037 // ----------------------------------------------------------------------------
2038 // this wxWindowBase function is implemented here (in platform-specific file)
2039 // because it is static and so couldn't be made virtual
2040 // ----------------------------------------------------------------------------
2042 wxWindow
*wxWindowBase::FindFocus()
2044 // the cast is necessary when we compile in wxUniversal mode
2045 return (wxWindow
*)g_focusWindow
;
2048 //-----------------------------------------------------------------------------
2049 // "realize" from m_widget
2050 //-----------------------------------------------------------------------------
2052 /* We cannot set colours and fonts before the widget has
2053 been realized, so we do this directly after realization. */
2056 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
2061 wxapp_install_idle_handler();
2063 if (win
->m_delayedBackgroundColour
)
2064 win
->SetBackgroundColour( win
->GetBackgroundColour() );
2066 if (win
->m_delayedForegroundColour
)
2067 win
->SetForegroundColour( win
->GetForegroundColour() );
2069 wxWindowCreateEvent
event( win
);
2070 event
.SetEventObject( win
);
2071 win
->GetEventHandler()->ProcessEvent( event
);
2076 //-----------------------------------------------------------------------------
2078 //-----------------------------------------------------------------------------
2081 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
2082 GtkAllocation
*WXUNUSED(alloc
),
2086 wxapp_install_idle_handler();
2088 if (!win
->m_hasScrolling
) return;
2090 int client_width
= 0;
2091 int client_height
= 0;
2092 win
->GetClientSize( &client_width
, &client_height
);
2093 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
2096 win
->m_oldClientWidth
= client_width
;
2097 win
->m_oldClientHeight
= client_height
;
2099 if (!win
->m_nativeSizeEvent
)
2101 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
2102 event
.SetEventObject( win
);
2103 win
->GetEventHandler()->ProcessEvent( event
);
2109 #define WXUNUSED_UNLESS_XIM(param) param
2111 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2114 /* Resize XIM window */
2117 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2118 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
2119 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2122 wxapp_install_idle_handler();
2128 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
2132 gdk_window_get_size (widget
->window
, &width
, &height
);
2133 win
->m_icattr
->preedit_area
.width
= width
;
2134 win
->m_icattr
->preedit_area
.height
= height
;
2135 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2140 //-----------------------------------------------------------------------------
2141 // "realize" from m_wxwindow
2142 //-----------------------------------------------------------------------------
2144 /* Initialize XIM support */
2147 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2148 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2151 wxapp_install_idle_handler();
2154 if (win
->m_ic
) return FALSE
;
2155 if (!widget
) return FALSE
;
2156 if (!gdk_im_ready()) return FALSE
;
2158 win
->m_icattr
= gdk_ic_attr_new();
2159 if (!win
->m_icattr
) return FALSE
;
2163 GdkColormap
*colormap
;
2164 GdkICAttr
*attr
= win
->m_icattr
;
2165 unsigned attrmask
= GDK_IC_ALL_REQ
;
2167 GdkIMStyle supported_style
= (GdkIMStyle
)
2168 (GDK_IM_PREEDIT_NONE
|
2169 GDK_IM_PREEDIT_NOTHING
|
2170 GDK_IM_PREEDIT_POSITION
|
2171 GDK_IM_STATUS_NONE
|
2172 GDK_IM_STATUS_NOTHING
);
2174 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2175 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2177 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2178 attr
->client_window
= widget
->window
;
2180 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2181 gtk_widget_get_default_colormap ())
2183 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2184 attr
->preedit_colormap
= colormap
;
2187 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2188 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2189 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2190 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2192 switch (style
& GDK_IM_PREEDIT_MASK
)
2194 case GDK_IM_PREEDIT_POSITION
:
2195 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2197 g_warning ("over-the-spot style requires fontset");
2201 gdk_window_get_size (widget
->window
, &width
, &height
);
2203 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2204 attr
->spot_location
.x
= 0;
2205 attr
->spot_location
.y
= height
;
2206 attr
->preedit_area
.x
= 0;
2207 attr
->preedit_area
.y
= 0;
2208 attr
->preedit_area
.width
= width
;
2209 attr
->preedit_area
.height
= height
;
2210 attr
->preedit_fontset
= widget
->style
->font
;
2215 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2217 if (win
->m_ic
== NULL
)
2218 g_warning ("Can't create input context.");
2221 mask
= gdk_window_get_events (widget
->window
);
2222 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2223 gdk_window_set_events (widget
->window
, mask
);
2225 if (GTK_WIDGET_HAS_FOCUS(widget
))
2226 gdk_im_begin (win
->m_ic
, widget
->window
);
2233 //-----------------------------------------------------------------------------
2234 // InsertChild for wxWindowGTK.
2235 //-----------------------------------------------------------------------------
2237 /* Callback for wxWindowGTK. This very strange beast has to be used because
2238 * C++ has no virtual methods in a constructor. We have to emulate a
2239 * virtual function here as wxNotebook requires a different way to insert
2240 * a child in it. I had opted for creating a wxNotebookPage window class
2241 * which would have made this superfluous (such in the MDI window system),
2242 * but no-one was listening to me... */
2244 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child
)
2246 /* the window might have been scrolled already, do we
2247 have to adapt the position */
2248 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2249 child
->m_x
+= pizza
->xoffset
;
2250 child
->m_y
+= pizza
->yoffset
;
2252 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2253 GTK_WIDGET(child
->m_widget
),
2260 //-----------------------------------------------------------------------------
2262 //-----------------------------------------------------------------------------
2264 wxWindow
*wxGetActiveWindow()
2266 // the cast is necessary when we compile in wxUniversal mode
2267 return (wxWindow
*)g_focusWindow
;
2270 //-----------------------------------------------------------------------------
2272 //-----------------------------------------------------------------------------
2274 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
2276 #ifdef __WXUNIVERSAL__
2277 IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
)
2279 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2280 #endif // __WXUNIVERSAL__/__WXGTK__
2282 void wxWindowGTK::Init()
2288 m_widget
= (GtkWidget
*) NULL
;
2289 m_wxwindow
= (GtkWidget
*) NULL
;
2290 m_focusWidget
= (GtkWidget
*) NULL
;
2300 m_needParent
= TRUE
;
2301 m_isBeingDeleted
= FALSE
;
2304 m_nativeSizeEvent
= FALSE
;
2306 m_hasScrolling
= FALSE
;
2307 m_isScrolling
= FALSE
;
2309 m_hAdjust
= (GtkAdjustment
*) NULL
;
2310 m_vAdjust
= (GtkAdjustment
*) NULL
;
2311 m_oldHorizontalPos
= 0.0;
2312 m_oldVerticalPos
= 0.0;
2315 m_widgetStyle
= (GtkStyle
*) NULL
;
2317 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2319 m_isStaticBox
= FALSE
;
2320 m_isRadioButton
= FALSE
;
2321 m_isListBox
= FALSE
;
2323 m_acceptsFocus
= FALSE
;
2325 m_clipPaintRegion
= FALSE
;
2327 m_cursor
= *wxSTANDARD_CURSOR
;
2329 m_delayedForegroundColour
= FALSE
;
2330 m_delayedBackgroundColour
= FALSE
;
2333 m_ic
= (GdkIC
*) NULL
;
2334 m_icattr
= (GdkICAttr
*) NULL
;
2338 wxWindowGTK::wxWindowGTK()
2343 wxWindowGTK::wxWindowGTK( wxWindow
*parent
,
2348 const wxString
&name
)
2352 Create( parent
, id
, pos
, size
, style
, name
);
2355 bool wxWindowGTK::Create( wxWindow
*parent
,
2360 const wxString
&name
)
2362 if (!PreCreation( parent
, pos
, size
) ||
2363 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2365 wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
2369 m_insertCallback
= wxInsertChildInWindow
;
2371 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2372 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2374 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2376 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2377 scroll_class
->scrollbar_spacing
= 0;
2379 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2381 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2382 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2384 m_wxwindow
= gtk_pizza_new();
2386 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2388 #ifndef __WXUNIVERSAL__
2389 #if (GTK_MINOR_VERSION > 0)
2390 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2392 if (HasFlag(wxRAISED_BORDER
))
2394 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2396 else if (HasFlag(wxSUNKEN_BORDER
))
2398 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2400 else if (HasFlag(wxSIMPLE_BORDER
))
2402 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2406 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2408 #else // GTK_MINOR_VERSION == 0
2409 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2411 if (HasFlag(wxRAISED_BORDER
))
2413 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2415 else if (HasFlag(wxSUNKEN_BORDER
))
2417 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2421 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2423 #endif // GTK_MINOR_VERSION
2424 #endif // __WXUNIVERSAL__
2426 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2427 m_acceptsFocus
= TRUE
;
2429 #if (GTK_MINOR_VERSION == 0)
2430 // shut the viewport up
2431 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2432 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2433 #endif // GTK_MINOR_VERSION == 0
2435 // I _really_ don't want scrollbars in the beginning
2436 m_vAdjust
->lower
= 0.0;
2437 m_vAdjust
->upper
= 1.0;
2438 m_vAdjust
->value
= 0.0;
2439 m_vAdjust
->step_increment
= 1.0;
2440 m_vAdjust
->page_increment
= 1.0;
2441 m_vAdjust
->page_size
= 5.0;
2442 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2443 m_hAdjust
->lower
= 0.0;
2444 m_hAdjust
->upper
= 1.0;
2445 m_hAdjust
->value
= 0.0;
2446 m_hAdjust
->step_increment
= 1.0;
2447 m_hAdjust
->page_increment
= 1.0;
2448 m_hAdjust
->page_size
= 5.0;
2449 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2451 // these handlers block mouse events to any window during scrolling such as
2452 // motion events and prevent GTK and wxWindows from fighting over where the
2455 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2456 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2458 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2459 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2461 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2462 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2464 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2465 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2467 // these handlers get notified when screen updates are required either when
2468 // scrolling or when the window size (and therefore scrollbar configuration)
2471 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2472 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2473 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2474 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2476 gtk_widget_show( m_wxwindow
);
2479 m_parent
->DoAddChild( this );
2481 m_focusWidget
= m_wxwindow
;
2490 wxWindowGTK::~wxWindowGTK()
2492 if (g_focusWindow
== this)
2493 g_focusWindow
= NULL
;
2495 if (g_activeFrame
== this)
2496 g_activeFrame
= NULL
;
2498 m_isBeingDeleted
= TRUE
;
2507 m_parent
->RemoveChild( this );
2511 gdk_ic_destroy (m_ic
);
2513 gdk_ic_attr_destroy (m_icattr
);
2518 #if DISABLE_STYLE_IF_BROKEN_THEME
2519 // don't delete if it's a pixmap theme style
2520 if (!m_widgetStyle
->engine_data
)
2521 gtk_style_unref( m_widgetStyle
);
2523 m_widgetStyle
= (GtkStyle
*) NULL
;
2528 gtk_widget_destroy( m_wxwindow
);
2529 m_wxwindow
= (GtkWidget
*) NULL
;
2534 gtk_widget_destroy( m_widget
);
2535 m_widget
= (GtkWidget
*) NULL
;
2539 bool wxWindowGTK::PreCreation( wxWindowGTK
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2541 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2543 /* this turns -1 into 20 so that a minimal window is
2544 visible even although -1,-1 has been given as the
2545 size of the window. the same trick is used in other
2546 ports and should make debugging easier */
2547 m_width
= WidthDefault(size
.x
);
2548 m_height
= HeightDefault(size
.y
);
2553 /* some reasonable defaults */
2558 m_x
= (gdk_screen_width () - m_width
) / 2;
2559 if (m_x
< 10) m_x
= 10;
2563 m_y
= (gdk_screen_height () - m_height
) / 2;
2564 if (m_y
< 10) m_y
= 10;
2571 void wxWindowGTK::PostCreation()
2573 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2579 // these get reported to wxWindows -> wxPaintEvent
2581 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2583 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2584 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2586 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2587 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2589 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2591 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2592 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2596 // these are called when the "sunken" or "raised" borders are drawn */
2597 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2598 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2600 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2601 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2606 if (m_focusWidget
== NULL
)
2607 m_focusWidget
= m_widget
;
2610 if (GetClassInfo() && GetClassInfo()->GetClassName())
2611 wxPrintf( GetClassInfo()->GetClassName() );
2615 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event",
2616 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2618 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event",
2619 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2621 // connect to the various key and mouse handlers
2623 GtkWidget
*connect_widget
= GetConnectWidget();
2625 ConnectWidget( connect_widget
);
2627 /* We cannot set colours, fonts and cursors before the widget has
2628 been realized, so we do this directly after realization */
2629 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2630 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2634 // Catch native resize events
2635 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2636 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2638 // Initialize XIM support
2639 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2640 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2642 // And resize XIM window
2643 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2644 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2647 if (!GTK_IS_COMBO(m_widget
))
2649 // This is needed if we want to add our windows into native
2650 // GTK control, such as the toolbar. With this callback, the
2651 // toolbar gets to know the correct size (the one set by the
2652 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2653 // when moving to GTK 2.0.
2654 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2655 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2661 void wxWindowGTK::ConnectWidget( GtkWidget
*widget
)
2663 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2664 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2666 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2667 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2669 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2670 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2672 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2673 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2675 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2676 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2678 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2679 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2681 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2682 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2685 bool wxWindowGTK::Destroy()
2687 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2691 return wxWindowBase::Destroy();
2694 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
)
2696 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2699 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2701 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2702 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") );
2705 printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
2708 if (m_resizing
) return; /* I don't like recursions */
2711 int currentX
, currentY
;
2712 GetPosition(¤tX
, ¤tY
);
2717 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
2719 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2721 /* don't set the size for children of wxNotebook, just take the values. */
2729 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2731 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2733 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2734 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2735 if (width
!= -1) m_width
= width
;
2736 if (height
!= -1) m_height
= height
;
2740 m_x
= x
+ pizza
->xoffset
;
2741 m_y
= y
+ pizza
->yoffset
;
2746 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2748 if (width
== -1) m_width
= 80;
2751 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2753 if (height
== -1) m_height
= 26;
2756 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2757 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2758 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2759 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2762 int bottom_border
= 0;
2764 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2766 /* the default button has a border around it */
2771 DoMoveWindow( m_x
-border
,
2774 m_height
+border
+bottom_border
);
2779 /* Sometimes the client area changes size without the
2780 whole windows's size changing, but if the whole
2781 windows's size doesn't change, no wxSizeEvent will
2782 normally be sent. Here we add an extra test if
2783 the client test has been changed and this will
2785 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2789 wxPrintf( "OnSize sent from " );
2790 if (GetClassInfo() && GetClassInfo()->GetClassName())
2791 wxPrintf( GetClassInfo()->GetClassName() );
2792 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2795 if (!m_nativeSizeEvent
)
2797 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2798 event
.SetEventObject( this );
2799 GetEventHandler()->ProcessEvent( event
);
2805 void wxWindowGTK::OnInternalIdle()
2807 // Update invalidated regions.
2810 // Synthetize activate events.
2811 if ( g_sendActivateEvent
!= -1 )
2813 bool activate
= g_sendActivateEvent
!= 0;
2816 g_sendActivateEvent
= -1;
2818 wxTheApp
->SetActive(activate
, (wxWindow
*)g_focusWindowLast
);
2821 if ( g_activeFrameLostFocus
)
2823 if ( g_activeFrame
)
2825 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame
);
2826 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
2827 event
.SetEventObject(g_activeFrame
);
2828 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
2829 g_activeFrame
= NULL
;
2831 g_activeFrameLostFocus
= FALSE
;
2834 wxCursor cursor
= m_cursor
;
2835 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2839 /* I now set the cursor anew in every OnInternalIdle call
2840 as setting the cursor in a parent window also effects the
2841 windows above so that checking for the current cursor is
2846 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2848 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2850 if (!g_globalCursor
.Ok())
2851 cursor
= *wxSTANDARD_CURSOR
;
2853 window
= m_widget
->window
;
2854 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2855 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2861 GdkWindow
*window
= m_widget
->window
;
2862 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2863 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2871 void wxWindowGTK::DoGetSize( int *width
, int *height
) const
2873 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2875 if (width
) (*width
) = m_width
;
2876 if (height
) (*height
) = m_height
;
2879 void wxWindowGTK::DoSetClientSize( int width
, int height
)
2881 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2885 SetSize( width
, height
);
2892 #ifndef __WXUNIVERSAL__
2893 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2895 /* when using GTK 1.2 we set the shadow border size to 2 */
2899 if (HasFlag(wxSIMPLE_BORDER
))
2901 /* when using GTK 1.2 we set the simple border size to 1 */
2905 #endif // __WXUNIVERSAL__
2909 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2911 GtkRequisition vscroll_req
;
2912 vscroll_req
.width
= 2;
2913 vscroll_req
.height
= 2;
2914 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2915 (scroll_window
->vscrollbar
, &vscroll_req
);
2917 GtkRequisition hscroll_req
;
2918 hscroll_req
.width
= 2;
2919 hscroll_req
.height
= 2;
2920 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2921 (scroll_window
->hscrollbar
, &hscroll_req
);
2923 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2925 if (scroll_window
->vscrollbar_visible
)
2927 dw
+= vscroll_req
.width
;
2928 dw
+= scroll_class
->scrollbar_spacing
;
2931 if (scroll_window
->hscrollbar_visible
)
2933 dh
+= hscroll_req
.height
;
2934 dh
+= scroll_class
->scrollbar_spacing
;
2938 SetSize( width
+dw
, height
+dh
);
2942 void wxWindowGTK::DoGetClientSize( int *width
, int *height
) const
2944 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2948 if (width
) (*width
) = m_width
;
2949 if (height
) (*height
) = m_height
;
2956 #ifndef __WXUNIVERSAL__
2957 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2959 /* when using GTK 1.2 we set the shadow border size to 2 */
2963 if (HasFlag(wxSIMPLE_BORDER
))
2965 /* when using GTK 1.2 we set the simple border size to 1 */
2969 #endif // __WXUNIVERSAL__
2973 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2975 GtkRequisition vscroll_req
;
2976 vscroll_req
.width
= 2;
2977 vscroll_req
.height
= 2;
2978 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2979 (scroll_window
->vscrollbar
, &vscroll_req
);
2981 GtkRequisition hscroll_req
;
2982 hscroll_req
.width
= 2;
2983 hscroll_req
.height
= 2;
2984 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2985 (scroll_window
->hscrollbar
, &hscroll_req
);
2987 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2989 if (scroll_window
->vscrollbar_visible
)
2991 dw
+= vscroll_req
.width
;
2992 dw
+= scroll_class
->scrollbar_spacing
;
2995 if (scroll_window
->hscrollbar_visible
)
2997 dh
+= hscroll_req
.height
;
2998 dh
+= scroll_class
->scrollbar_spacing
;
3002 if (width
) (*width
) = m_width
- dw
;
3003 if (height
) (*height
) = m_height
- dh
;
3007 printf( "GetClientSize, name %s ", GetName().c_str() );
3008 if (width) printf( " width = %d", (*width) );
3009 if (height) printf( " height = %d", (*height) );
3014 void wxWindowGTK::DoGetPosition( int *x
, int *y
) const
3016 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3020 if (m_parent
&& m_parent
->m_wxwindow
)
3022 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
3023 dx
= pizza
->xoffset
;
3024 dy
= pizza
->yoffset
;
3027 if (x
) (*x
) = m_x
- dx
;
3028 if (y
) (*y
) = m_y
- dy
;
3031 void wxWindowGTK::DoClientToScreen( int *x
, int *y
) const
3033 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3035 if (!m_widget
->window
) return;
3037 GdkWindow
*source
= (GdkWindow
*) NULL
;
3039 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3041 source
= m_widget
->window
;
3045 gdk_window_get_origin( source
, &org_x
, &org_y
);
3049 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3051 org_x
+= m_widget
->allocation
.x
;
3052 org_y
+= m_widget
->allocation
.y
;
3060 void wxWindowGTK::DoScreenToClient( int *x
, int *y
) const
3062 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3064 if (!m_widget
->window
) return;
3066 GdkWindow
*source
= (GdkWindow
*) NULL
;
3068 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3070 source
= m_widget
->window
;
3074 gdk_window_get_origin( source
, &org_x
, &org_y
);
3078 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3080 org_x
+= m_widget
->allocation
.x
;
3081 org_y
+= m_widget
->allocation
.y
;
3089 bool wxWindowGTK::Show( bool show
)
3091 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3093 if (!wxWindowBase::Show(show
))
3100 gtk_widget_show( m_widget
);
3102 gtk_widget_hide( m_widget
);
3107 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
)
3109 win
->OnParentEnable(enable
);
3111 // Recurse, so that children have the opportunity to Do The Right Thing
3112 // and reset colours that have been messed up by a parent's (really ancestor's)
3114 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
3116 node
= node
->GetNext() )
3118 wxWindow
*child
= node
->GetData();
3119 if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
)))
3120 wxWindowNotifyEnable(child
, enable
);
3124 bool wxWindowGTK::Enable( bool enable
)
3126 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3128 if (!wxWindowBase::Enable(enable
))
3134 gtk_widget_set_sensitive( m_widget
, enable
);
3136 gtk_widget_set_sensitive( m_wxwindow
, enable
);
3138 wxWindowNotifyEnable(this, enable
);
3143 int wxWindowGTK::GetCharHeight() const
3145 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
3147 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
3149 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3151 return font
->ascent
+ font
->descent
;
3154 int wxWindowGTK::GetCharWidth() const
3156 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
3158 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
3160 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3162 return gdk_string_width( font
, "H" );
3165 void wxWindowGTK::GetTextExtent( const wxString
& string
,
3169 int *externalLeading
,
3170 const wxFont
*theFont
) const
3172 wxFont fontToUse
= m_font
;
3173 if (theFont
) fontToUse
= *theFont
;
3175 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
3177 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
3178 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
3179 if (y
) (*y
) = font
->ascent
+ font
->descent
;
3180 if (descent
) (*descent
) = font
->descent
;
3181 if (externalLeading
) (*externalLeading
) = 0; // ??
3184 void wxWindowGTK::SetFocus()
3186 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3189 wxPrintf( "SetFocus from " );
3190 if (GetClassInfo() && GetClassInfo()->GetClassName())
3191 wxPrintf( GetClassInfo()->GetClassName() );
3197 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3199 // see comment in gtk_window_focus_out_callback()
3200 gs_widgetLastFocus
= m_wxwindow
;
3201 gtk_widget_grab_focus (m_wxwindow
);
3206 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
3208 gtk_widget_grab_focus (m_widget
);
3210 else if (GTK_IS_CONTAINER(m_widget
))
3212 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
3221 wxPrintf( "SetFocus finished in " );
3222 if (GetClassInfo() && GetClassInfo()->GetClassName())
3223 wxPrintf( GetClassInfo()->GetClassName() );
3229 bool wxWindowGTK::AcceptsFocus() const
3231 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3234 bool wxWindowGTK::Reparent( wxWindowBase
*newParentBase
)
3236 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3238 wxWindowGTK
*oldParent
= m_parent
,
3239 *newParent
= (wxWindowGTK
*)newParentBase
;
3241 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3243 if ( !wxWindowBase::Reparent(newParent
) )
3246 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3248 /* prevent GTK from deleting the widget arbitrarily */
3249 gtk_widget_ref( m_widget
);
3253 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3256 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3260 /* insert GTK representation */
3261 (*(newParent
->m_insertCallback
))(newParent
, this);
3264 /* reverse: prevent GTK from deleting the widget arbitrarily */
3265 gtk_widget_unref( m_widget
);
3270 void wxWindowGTK::DoAddChild(wxWindowGTK
*child
)
3272 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3274 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3276 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3281 /* insert GTK representation */
3282 (*m_insertCallback
)(this, child
);
3285 void wxWindowGTK::Raise()
3287 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3289 if (!m_widget
->window
) return;
3291 gdk_window_raise( m_widget
->window
);
3294 void wxWindowGTK::Lower()
3296 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3298 if (!m_widget
->window
) return;
3300 gdk_window_lower( m_widget
->window
);
3303 bool wxWindowGTK::SetCursor( const wxCursor
&cursor
)
3305 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3307 if (cursor
== m_cursor
)
3311 wxapp_install_idle_handler();
3313 if (cursor
== wxNullCursor
)
3314 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3316 return wxWindowBase::SetCursor( cursor
);
3319 void wxWindowGTK::WarpPointer( int x
, int y
)
3321 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3323 // We provide this function ourselves as it is
3324 // missing in GDK (top of this file).
3326 GdkWindow
*window
= (GdkWindow
*) NULL
;
3328 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3330 window
= GetConnectWidget()->window
;
3333 gdk_window_warp_pointer( window
, x
, y
);
3336 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect
*rect
)
3338 if (!m_widget
) return;
3339 if (!m_widget
->window
) return;
3341 // temporarily hide the caret to avoid nasty interactions between caret
3342 // drawing and the window contents redraw
3343 #if 0 // def wxUSE_CARET -- doesn't seem to help :-(
3344 wxCaretSuspend
cs((wxWindow
*)this);
3345 #endif // wxUSE_CARET
3347 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3351 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3352 m_clearRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
3356 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3357 m_clearRegion
.Clear();
3358 m_clearRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height
);
3366 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3367 m_updateRegion
.Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
3371 GdkRectangle gdk_rect
;
3372 gdk_rect
.x
= rect
->x
;
3373 gdk_rect
.y
= rect
->y
;
3374 gdk_rect
.width
= rect
->width
;
3375 gdk_rect
.height
= rect
->height
;
3376 gtk_widget_draw( m_widget
, &gdk_rect
);
3383 // Schedule for later Updating in ::Update() or ::OnInternalIdle().
3384 m_updateRegion
.Clear();
3385 m_updateRegion
.Union( 0, 0, m_wxwindow
->allocation
.width
, m_wxwindow
->allocation
.height
);
3389 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3394 void wxWindowGTK::Update()
3396 if (!m_updateRegion
.IsEmpty())
3398 GtkSendPaintEvents();
3402 void wxWindowGTK::GtkSendPaintEvents()
3406 m_clearRegion
.Clear();
3407 m_updateRegion
.Clear();
3411 m_clipPaintRegion
= TRUE
;
3413 if (!m_clearRegion
.IsEmpty())
3415 wxWindowDC
dc( (wxWindow
*)this );
3416 dc
.SetClippingRegion( m_clearRegion
);
3418 wxEraseEvent
erase_event( GetId(), &dc
);
3419 erase_event
.SetEventObject( this );
3421 if (!GetEventHandler()->ProcessEvent(erase_event
))
3423 wxRegionIterator
upd( m_clearRegion
);
3426 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3427 upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
3431 m_clearRegion
.Clear();
3434 wxNcPaintEvent
nc_paint_event( GetId() );
3435 nc_paint_event
.SetEventObject( this );
3436 GetEventHandler()->ProcessEvent( nc_paint_event
);
3438 wxPaintEvent
paint_event( GetId() );
3439 paint_event
.SetEventObject( this );
3440 GetEventHandler()->ProcessEvent( paint_event
);
3442 m_updateRegion
.Clear();
3444 m_clipPaintRegion
= FALSE
;
3447 void wxWindowGTK::Clear()
3449 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3451 if (!m_widget
->window
) return;
3453 if (m_wxwindow
&& m_wxwindow
->window
)
3455 // gdk_window_clear( m_wxwindow->window );
3460 void wxWindowGTK::DoSetToolTip( wxToolTip
*tip
)
3462 wxWindowBase::DoSetToolTip(tip
);
3465 m_tooltip
->Apply( (wxWindow
*)this );
3468 void wxWindowGTK::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3470 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3472 #endif // wxUSE_TOOLTIPS
3474 bool wxWindowGTK::SetBackgroundColour( const wxColour
&colour
)
3476 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3478 if (!wxWindowBase::SetBackgroundColour(colour
))
3480 // don't leave if the GTK widget has just
3482 if (!m_delayedBackgroundColour
) return FALSE
;
3485 GdkWindow
*window
= (GdkWindow
*) NULL
;
3487 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3489 window
= GetConnectWidget()->window
;
3493 // indicate that a new style has been set
3494 // but it couldn't get applied as the
3495 // widget hasn't been realized yet.
3496 m_delayedBackgroundColour
= TRUE
;
3500 (m_wxwindow
->window
) &&
3501 (m_backgroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
)))
3503 /* wxMSW doesn't clear the window here. I don't do that either to
3504 provide compatibility. call Clear() to do the job. */
3506 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3507 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3515 bool wxWindowGTK::SetForegroundColour( const wxColour
&colour
)
3517 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3519 if (!wxWindowBase::SetForegroundColour(colour
))
3521 // don't leave if the GTK widget has just
3523 if (!m_delayedForegroundColour
) return FALSE
;
3526 GdkWindow
*window
= (GdkWindow
*) NULL
;
3528 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3530 window
= GetConnectWidget()->window
;
3534 // indicate that a new style has been set
3535 // but it couldn't get applied as the
3536 // widget hasn't been realized yet.
3537 m_delayedForegroundColour
= TRUE
;
3545 GtkStyle
*wxWindowGTK::GetWidgetStyle()
3549 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3551 /* FIXME: is this necessary? */
3552 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3554 remake
->klass
= m_widgetStyle
->klass
;
3557 gtk_style_unref( m_widgetStyle
);
3558 m_widgetStyle
= remake
;
3562 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3565 def
= gtk_widget_get_default_style();
3567 m_widgetStyle
= gtk_style_copy( def
);
3569 /* FIXME: is this necessary? */
3570 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3572 m_widgetStyle
->klass
= def
->klass
;
3576 return m_widgetStyle
;
3579 void wxWindowGTK::SetWidgetStyle()
3581 #if DISABLE_STYLE_IF_BROKEN_THEM
3582 if (m_widget
->style
->engine_data
)
3584 static bool s_warningPrinted
= FALSE
;
3585 if (!s_warningPrinted
)
3587 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3588 s_warningPrinted
= TRUE
;
3590 m_widgetStyle
= m_widget
->style
;
3595 GtkStyle
*style
= GetWidgetStyle();
3597 if (m_font
!= wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT
))
3599 gdk_font_unref( style
->font
);
3600 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3603 if (m_foregroundColour
.Ok())
3605 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3606 if (m_foregroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT
))
3608 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3609 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3610 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3614 // Try to restore the gtk default style. This is still a little
3615 // oversimplified for what is probably really needed here for controls
3616 // other than buttons, but is better than not being able to (re)set a
3617 // control's foreground colour to *wxBLACK -- RL
3618 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3621 def
= gtk_widget_get_default_style();
3623 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3624 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3625 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3629 if (m_backgroundColour
.Ok())
3631 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3632 if (m_backgroundColour
!= wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
))
3634 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3635 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3636 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3637 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3638 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3639 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3640 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3641 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3645 // Try to restore the gtk default style. This is still a little
3646 // oversimplified for what is probably really needed here for controls
3647 // other than buttons, but is better than not being able to (re)set a
3648 // control's background colour to default grey and means resetting a
3649 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3651 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3654 def
= gtk_widget_get_default_style();
3656 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3657 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3658 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3659 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3660 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3661 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3662 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3663 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3668 void wxWindowGTK::ApplyWidgetStyle()
3672 //-----------------------------------------------------------------------------
3673 // Pop-up menu stuff
3674 //-----------------------------------------------------------------------------
3676 #if wxUSE_MENUS_NATIVE
3679 void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3681 *is_waiting
= FALSE
;
3684 static void SetInvokingWindow( wxMenu
*menu
, wxWindowGTK
*win
)
3686 menu
->SetInvokingWindow( win
);
3687 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3690 wxMenuItem
*menuitem
= node
->GetData();
3691 if (menuitem
->IsSubMenu())
3693 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3696 node
= node
->GetNext();
3700 // used to pass the coordinates from wxWindowGTK::DoPopupMenu() to
3701 // wxPopupMenuPositionCallback()
3703 // should be safe even in the MT case as the user can hardly popup 2 menus
3704 // simultaneously, can he?
3705 static gint gs_pop_x
= 0;
3706 static gint gs_pop_y
= 0;
3708 extern "C" void wxPopupMenuPositionCallback( GtkMenu
*menu
,
3710 gpointer
WXUNUSED(user_data
) )
3712 // ensure that the menu appears entirely on screen
3714 gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
);
3716 wxSize sizeScreen
= wxGetDisplaySize();
3718 gint xmax
= sizeScreen
.x
- req
.width
,
3719 ymax
= sizeScreen
.y
- req
.height
;
3721 *x
= gs_pop_x
< xmax
? gs_pop_x
: xmax
;
3722 *y
= gs_pop_y
< ymax
? gs_pop_y
: ymax
;
3725 bool wxWindowGTK::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3727 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3729 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3731 SetInvokingWindow( menu
, this );
3737 ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3739 bool is_waiting
= TRUE
;
3741 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
),
3743 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
),
3744 (gpointer
)&is_waiting
);
3747 GTK_MENU(menu
->m_menu
),
3748 (GtkWidget
*) NULL
, // parent menu shell
3749 (GtkWidget
*) NULL
, // parent menu item
3750 wxPopupMenuPositionCallback
, // function to position it
3751 NULL
, // client data
3752 0, // button used to activate it
3753 gs_timeLastClick
// the time of activation
3758 while (gtk_events_pending())
3759 gtk_main_iteration();
3765 #endif // wxUSE_MENUS_NATIVE
3767 #if wxUSE_DRAG_AND_DROP
3769 void wxWindowGTK::SetDropTarget( wxDropTarget
*dropTarget
)
3771 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3773 GtkWidget
*dnd_widget
= GetConnectWidget();
3775 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3777 if (m_dropTarget
) delete m_dropTarget
;
3778 m_dropTarget
= dropTarget
;
3780 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3783 #endif // wxUSE_DRAG_AND_DROP
3785 GtkWidget
* wxWindowGTK::GetConnectWidget()
3787 GtkWidget
*connect_widget
= m_widget
;
3788 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3790 return connect_widget
;
3793 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow
*window
)
3796 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3798 return (window
== m_widget
->window
);
3801 bool wxWindowGTK::SetFont( const wxFont
&font
)
3803 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3805 if (!wxWindowBase::SetFont(font
))
3810 wxColour sysbg
= wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE
);
3811 if ( sysbg
== m_backgroundColour
)
3813 m_backgroundColour
= wxNullColour
;
3815 m_backgroundColour
= sysbg
;
3825 void wxWindowGTK::DoCaptureMouse()
3827 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3829 GdkWindow
*window
= (GdkWindow
*) NULL
;
3831 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3833 window
= GetConnectWidget()->window
;
3835 wxCHECK_RET( window
, _T("CaptureMouse() failed") );
3837 wxCursor
* cursor
= & m_cursor
;
3839 cursor
= wxSTANDARD_CURSOR
;
3841 gdk_pointer_grab( window
, FALSE
,
3843 (GDK_BUTTON_PRESS_MASK
|
3844 GDK_BUTTON_RELEASE_MASK
|
3845 GDK_POINTER_MOTION_HINT_MASK
|
3846 GDK_POINTER_MOTION_MASK
),
3848 cursor
->GetCursor(),
3849 (guint32
)GDK_CURRENT_TIME
);
3850 g_captureWindow
= this;
3851 g_captureWindowHasMouse
= TRUE
;
3854 void wxWindowGTK::DoReleaseMouse()
3856 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3858 wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") );
3860 g_captureWindow
= (wxWindowGTK
*) NULL
;
3862 GdkWindow
*window
= (GdkWindow
*) NULL
;
3864 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3866 window
= GetConnectWidget()->window
;
3871 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3875 wxWindow
*wxWindowBase::GetCapture()
3877 return (wxWindow
*)g_captureWindow
;
3880 bool wxWindowGTK::IsRetained() const
3885 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3886 int range
, bool refresh
)
3888 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3890 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3892 m_hasScrolling
= TRUE
;
3894 if (orient
== wxHORIZONTAL
)
3896 float fpos
= (float)pos
;
3897 float frange
= (float)range
;
3898 float fthumb
= (float)thumbVisible
;
3899 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3900 if (fpos
< 0.0) fpos
= 0.0;
3902 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3903 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3905 SetScrollPos( orient
, pos
, refresh
);
3909 m_oldHorizontalPos
= fpos
;
3911 m_hAdjust
->lower
= 0.0;
3912 m_hAdjust
->upper
= frange
;
3913 m_hAdjust
->value
= fpos
;
3914 m_hAdjust
->step_increment
= 1.0;
3915 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3916 m_hAdjust
->page_size
= fthumb
;
3920 float fpos
= (float)pos
;
3921 float frange
= (float)range
;
3922 float fthumb
= (float)thumbVisible
;
3923 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3924 if (fpos
< 0.0) fpos
= 0.0;
3926 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3927 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3929 SetScrollPos( orient
, pos
, refresh
);
3933 m_oldVerticalPos
= fpos
;
3935 m_vAdjust
->lower
= 0.0;
3936 m_vAdjust
->upper
= frange
;
3937 m_vAdjust
->value
= fpos
;
3938 m_vAdjust
->step_increment
= 1.0;
3939 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3940 m_vAdjust
->page_size
= fthumb
;
3943 if (orient
== wxHORIZONTAL
)
3944 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3946 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3949 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3951 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3953 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3955 if (orient
== wxHORIZONTAL
)
3957 float fpos
= (float)pos
;
3958 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3959 if (fpos
< 0.0) fpos
= 0.0;
3960 m_oldHorizontalPos
= fpos
;
3962 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3963 m_hAdjust
->value
= fpos
;
3967 float fpos
= (float)pos
;
3968 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3969 if (fpos
< 0.0) fpos
= 0.0;
3970 m_oldVerticalPos
= fpos
;
3972 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3973 m_vAdjust
->value
= fpos
;
3976 if (m_wxwindow
->window
)
3978 if (orient
== wxHORIZONTAL
)
3980 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3981 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3983 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3985 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3986 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3990 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3991 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3993 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3995 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3996 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4001 int wxWindowGTK::GetScrollThumb( int orient
) const
4003 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4005 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4007 if (orient
== wxHORIZONTAL
)
4008 return (int)(m_hAdjust
->page_size
+0.5);
4010 return (int)(m_vAdjust
->page_size
+0.5);
4013 int wxWindowGTK::GetScrollPos( int orient
) const
4015 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4017 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4019 if (orient
== wxHORIZONTAL
)
4020 return (int)(m_hAdjust
->value
+0.5);
4022 return (int)(m_vAdjust
->value
+0.5);
4025 int wxWindowGTK::GetScrollRange( int orient
) const
4027 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4029 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4031 if (orient
== wxHORIZONTAL
)
4032 return (int)(m_hAdjust
->upper
+0.5);
4034 return (int)(m_vAdjust
->upper
+0.5);
4037 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
4039 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4041 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4043 // No scrolling requested.
4044 if ((dx
== 0) && (dy
== 0)) return;
4046 if (!m_updateRegion
.IsEmpty())
4048 m_updateRegion
.Offset( dx
, dy
);
4052 GetClientSize( &cw
, &ch
);
4053 m_updateRegion
.Intersect( 0, 0, cw
, ch
);
4056 if (!m_clearRegion
.IsEmpty())
4058 m_clearRegion
.Offset( dx
, dy
);
4062 GetClientSize( &cw
, &ch
);
4063 m_clearRegion
.Intersect( 0, 0, cw
, ch
);
4068 m_clipPaintRegion
= TRUE
;
4070 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
4072 m_clipPaintRegion
= FALSE
;
4076 if (m_children
.GetCount() > 0)
4078 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
4082 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
4084 pizza
->xoffset
-= dx
;
4085 pizza
->yoffset
-= dy
;
4087 GdkGC
*m_scrollGC
= gdk_gc_new( pizza
->bin_window
);
4088 gdk_gc_set_exposures( m_scrollGC
, TRUE
);
4092 GetClientSize( &cw
, &ch
);
4093 int w
= cw
- abs(dx
);
4094 int h
= ch
- abs(dy
);
4096 if ((h
< 0) || (w
< 0))
4104 if (dx
< 0) s_x
= -dx
;
4105 if (dy
< 0) s_y
= -dy
;
4108 if (dx
> 0) d_x
= dx
;
4109 if (dy
> 0) d_y
= dy
;
4111 gdk_window_copy_area( pizza
->bin_window
, m_scrollGC
, d_x
, d_y
,
4112 pizza
->bin_window
, s_x
, s_y
, w
, h
);
4115 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
4116 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
4117 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
4118 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
4120 Refresh( TRUE
, &rect
);
4123 gdk_gc_unref( m_scrollGC
);
4128 // Find the wxWindow at the current mouse position, also returning the mouse
4130 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
4132 pt
= wxGetMousePosition();
4133 wxWindow
* found
= wxFindWindowAtPoint(pt
);
4137 // Get the current mouse position.
4138 wxPoint
wxGetMousePosition()
4140 /* This crashes when used within wxHelpContext,
4141 so we have to use the X-specific implementation below.
4143 GdkModifierType *mask;
4144 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
4146 return wxPoint(x, y);
4150 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
4152 return wxPoint(-999, -999);
4154 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
4155 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
4156 Window rootReturn
, childReturn
;
4157 int rootX
, rootY
, winX
, winY
;
4158 unsigned int maskReturn
;
4160 XQueryPointer (display
,
4164 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
4165 return wxPoint(rootX
, rootY
);