1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/window.cpp
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #define XWarpPointer XWARPPOINTER
20 #include "wx/window.h"
21 #include "wx/dcclient.h"
24 #include "wx/layout.h"
26 #include "wx/dialog.h"
27 #include "wx/msgdlg.h"
29 #if wxUSE_DRAG_AND_DROP
34 #include "wx/tooltip.h"
42 #include "wx/textctrl.h"
46 #include "wx/statusbr.h"
48 #include "wx/settings.h"
52 #include "wx/thread.h"
59 #include <gdk/gdkprivate.h>
60 #include <gdk/gdkkeysyms.h>
64 #include <gtk/gtkprivate.h>
66 #include "wx/gtk/win_gtk.h"
68 //-----------------------------------------------------------------------------
69 // documentation on internals
70 //-----------------------------------------------------------------------------
73 I have been asked several times about writing some documentation about
74 the GTK port of wxWindows, especially its internal structures. Obviously,
75 you cannot understand wxGTK without knowing a little about the GTK, but
76 some more information about what the wxWindow, which is the base class
77 for all other window classes, does seems required as well.
81 What does wxWindow do? It contains the common interface for the following
82 jobs of its descendants:
84 1) Define the rudimentary behaviour common to all window classes, such as
85 resizing, intercepting user input (so as to make it possible to use these
86 events for special purposes in a derived class), window names etc.
88 2) Provide the possibility to contain and manage children, if the derived
89 class is allowed to contain children, which holds true for those window
90 classes which do not display a native GTK widget. To name them, these
91 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
92 work classes are a special case and are handled a bit differently from
93 the rest. The same holds true for the wxNotebook class.
95 3) Provide the possibility to draw into a client area of a window. This,
96 too, only holds true for classes that do not display a native GTK widget
99 4) Provide the entire mechanism for scrolling widgets. This actual inter-
100 face for this is usually in wxScrolledWindow, but the GTK implementation
103 5) A multitude of helper or extra methods for special purposes, such as
104 Drag'n'Drop, managing validators etc.
106 6) Display a border (sunken, raised, simple or none).
108 Normally one might expect, that one wxWindows window would always correspond
109 to one GTK widget. Under GTK, there is no such allround widget that has all
110 the functionality. Moreover, the GTK defines a client area as a different
111 widget from the actual widget you are handling. Last but not least some
112 special classes (e.g. wxFrame) handle different categories of widgets and
113 still have the possibility to draw something in the client area.
114 It was therefore required to write a special purpose GTK widget, that would
115 represent a client area in the sense of wxWindows capable to do the jobs
116 2), 3) and 4). I have written this class and it resides in win_gtk.c of
119 All windows must have a widget, with which they interact with other under-
120 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
121 thw wxWindow class has a member variable called m_widget which holds a
122 pointer to this widget. When the window class represents a GTK native widget,
123 this is (in most cases) the only GTK widget the class manages. E.g. the
124 wxStatitText class handles only a GtkLabel widget a pointer to which you
125 can find in m_widget (defined in wxWindow)
127 When the class has a client area for drawing into and for containing children
128 it has to handle the client area widget (of the type GtkPizza, defined in
129 win_gtk.c), but there could be any number of widgets, handled by a class
130 The common rule for all windows is only, that the widget that interacts with
131 the rest of GTK must be referenced in m_widget and all other widgets must be
132 children of this widget on the GTK level. The top-most widget, which also
133 represents the client area, must be in the m_wxwindow field and must be of
136 As I said, the window classes that display a GTK native widget only have
137 one widget, so in the case of e.g. the wxButton class m_widget holds a
138 pointer to a GtkButton widget. But windows with client areas (for drawing
139 and children) have a m_widget field that is a pointer to a GtkScrolled-
140 Window and a m_wxwindow field that is pointer to a GtkPizza and this
141 one is (in the GTK sense) a child of the GtkScrolledWindow.
143 If the m_wxwindow field is set, then all input to this widget is inter-
144 cepted and sent to the wxWindows class. If not, all input to the widget
145 that gets pointed to by m_widget gets intercepted and sent to the class.
149 The design of scrolling in wxWindows is markedly different from that offered
150 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
151 clicking on a scrollbar belonging to scrolled window will inevitably move
152 the window. In wxWindows, the scrollbar will only emit an event, send this
153 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
154 which actually moves the window and its subchildren. Note that GtkPizza
155 memorizes how much it has been scrolled but that wxWindows forgets this
156 so that the two coordinates systems have to be kept in synch. This is done
157 in various places using the pizza->xoffset and pizza->yoffset values.
161 Singularily the most broken code in GTK is the code that is supposes to
162 inform subwindows (child windows) about new positions. Very often, duplicate
163 events are sent without changes in size or position, equally often no
164 events are sent at all (All this is due to a bug in the GtkContainer code
165 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
166 GTK's own system and it simply waits for size events for toplevel windows
167 and then iterates down the respective size events to all window. This has
168 the disadvantage, that windows might get size events before the GTK widget
169 actually has the reported size. This doesn't normally pose any problem, but
170 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
171 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
172 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
173 window that is used for OpenGl output really has that size (as reported by
178 If someone at some point of time feels the immense desire to have a look at,
179 change or attempt to optimse the Refresh() logic, this person will need an
180 intimate understanding of what a "draw" and what an "expose" events are and
181 what there are used for, in particular when used in connection with GTK's
182 own windowless widgets. Beware.
186 Cursors, too, have been a constant source of pleasure. The main difficulty
187 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
188 for the parent. To prevent this from doing too much harm, I use idle time
189 to set the cursor over and over again, starting from the toplevel windows
190 and ending with the youngest generation (speaking of parent and child windows).
191 Also don't forget that cursors (like much else) are connected to GdkWindows,
192 not GtkWidgets and that the "window" field of a GtkWidget might very well
193 point to the GdkWindow of the parent widget (-> "window less widget") and
194 that the two obviously have very different meanings.
198 //-----------------------------------------------------------------------------
200 //-----------------------------------------------------------------------------
202 extern wxList wxPendingDelete
;
203 extern bool g_blockEventsOnDrag
;
204 extern bool g_blockEventsOnScroll
;
205 extern wxCursor g_globalCursor
;
207 // mouse capture state: the window which has it and if the mouse is currently
209 static wxWindowGTK
*g_captureWindow
= (wxWindowGTK
*) NULL
;
210 static bool g_captureWindowHasMouse
= FALSE
;
212 /* extern */ wxWindowGTK
*g_focusWindow
= (wxWindowGTK
*) NULL
;
214 // the last window which had the focus - this is normally never NULL (except
215 // if we never had focus at all) as even when g_focusWindow is NULL it still
216 // keeps its previous value
217 static wxWindowGTK
*g_focusWindowLast
= (wxWindowGTK
*)NULL
;
219 // the frame that is currently active (i.e. its child has focus). It is
220 // used to generate wxActivateEvents
221 static wxWindowGTK
*g_activeFrame
= (wxWindowGTK
*)NULL
;
222 static bool g_activeFrameLostFocus
= FALSE
;
224 // if we detect that the app has got/lost the focus, we set this variable to
225 // either TRUE or FALSE and an activate event will be sent during the next
226 // OnIdle() call and it is reset to -1: this value means that we shouldn't
227 // send any activate events at all
228 static int g_sendActivateEvent
= -1;
230 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
231 the last click here */
232 static guint32 gs_timeLastClick
= 0;
234 extern bool g_mainThreadLocked
;
236 //-----------------------------------------------------------------------------
238 //-----------------------------------------------------------------------------
241 #define DISABLE_STYLE_IF_BROKEN_THEME 1
247 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
249 # define DEBUG_MAIN_THREAD
252 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
253 GdkEvent
*WXUNUSED(event
),
254 const wxChar
*WXUNUSED(name
) )
257 static bool s_done = FALSE;
260 wxLog::AddTraceMask("focus");
263 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
269 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
271 // suppress warnings about gtk_debug_focus_in_callback being unused with
276 tmp
+= wxT(" FROM ");
279 wxChar
*s
= new wxChar
[tmp
.Length()+1];
283 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
284 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
289 #define DEBUG_MAIN_THREAD
292 //-----------------------------------------------------------------------------
293 // missing gdk functions
294 //-----------------------------------------------------------------------------
297 gdk_window_warp_pointer (GdkWindow
*window
,
302 GdkWindowPrivate
*priv
;
306 window
= GDK_ROOT_PARENT();
309 if (!GDK_WINDOW_DESTROYED(window
))
311 XWarpPointer (GDK_WINDOW_XDISPLAY(window
),
312 None
, /* not source window -> move from anywhere */
313 GDK_WINDOW_XID(window
), /* dest window */
314 0, 0, 0, 0, /* not source window -> move from anywhere */
318 priv
= (GdkWindowPrivate
*) window
;
320 if (!priv
->destroyed
)
322 XWarpPointer (priv
->xdisplay
,
323 None
, /* not source window -> move from anywhere */
324 priv
->xwindow
, /* dest window */
325 0, 0, 0, 0, /* not source window -> move from anywhere */
331 //-----------------------------------------------------------------------------
333 //-----------------------------------------------------------------------------
335 extern void wxapp_install_idle_handler();
336 extern bool g_isIdle
;
338 //-----------------------------------------------------------------------------
339 // local code (see below)
340 //-----------------------------------------------------------------------------
342 // returns the child of win which currently has focus or NULL if not found
344 // Note: can't be static, needed by textctrl.cpp.
345 wxWindow
*wxFindFocusedChild(wxWindowGTK
*win
)
347 wxWindow
*winFocus
= wxWindowGTK::FindFocus();
349 return (wxWindow
*)NULL
;
351 if ( winFocus
== win
)
352 return (wxWindow
*)win
;
354 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
356 node
= node
->GetNext() )
358 wxWindow
*child
= wxFindFocusedChild(node
->GetData());
363 return (wxWindow
*)NULL
;
366 // Returns toplevel grandparent of given window:
367 static wxWindowGTK
* wxGetTopLevelParent(wxWindowGTK
*win
)
369 wxWindowGTK
*p
= win
;
370 while (p
&& !p
->IsTopLevel())
376 static void draw_frame( GtkWidget
*widget
, wxWindowGTK
*win
)
378 // wxUniversal widgets draw the borders and scrollbars themselves
379 #ifndef __WXUNIVERSAL__
386 if (win
->m_hasScrolling
)
388 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
390 GtkRequisition vscroll_req
;
391 vscroll_req
.width
= 2;
392 vscroll_req
.height
= 2;
393 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
394 (scroll_window
->vscrollbar
, &vscroll_req
);
396 GtkRequisition hscroll_req
;
397 hscroll_req
.width
= 2;
398 hscroll_req
.height
= 2;
399 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
400 (scroll_window
->hscrollbar
, &hscroll_req
);
402 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) );
404 if (scroll_window
->vscrollbar_visible
)
406 dw
+= vscroll_req
.width
;
407 dw
+= scroll_class
->scrollbar_spacing
;
410 if (scroll_window
->hscrollbar_visible
)
412 dh
+= hscroll_req
.height
;
413 dh
+= scroll_class
->scrollbar_spacing
;
419 if (GTK_WIDGET_NO_WINDOW (widget
))
421 dx
+= widget
->allocation
.x
;
422 dy
+= widget
->allocation
.y
;
425 if (win
->HasFlag(wxRAISED_BORDER
))
427 gtk_draw_shadow( widget
->style
,
432 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
436 if (win
->HasFlag(wxSUNKEN_BORDER
))
438 gtk_draw_shadow( widget
->style
,
443 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
447 if (win
->HasFlag(wxSIMPLE_BORDER
))
450 gc
= gdk_gc_new( widget
->window
);
451 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
452 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
454 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
458 #endif // __WXUNIVERSAL__
461 //-----------------------------------------------------------------------------
462 // "expose_event" of m_widget
463 //-----------------------------------------------------------------------------
465 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindowGTK
*win
)
467 if (gdk_event
->count
> 0) return FALSE
;
469 draw_frame( widget
, win
);
474 //-----------------------------------------------------------------------------
475 // "draw" of m_widget
476 //-----------------------------------------------------------------------------
478 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindowGTK
*win
)
480 draw_frame( widget
, win
);
483 //-----------------------------------------------------------------------------
484 // key code mapping routines
485 //-----------------------------------------------------------------------------
487 static long map_to_unmodified_wx_keysym( GdkEventKey
*event
)
489 // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string
490 // but only event->keyval which is quite useless to us, so remember
491 // the last character from GDK_KEY_PRESS and resue it as last resort
493 // NB: should be MT-neutral as always called from main thread only
498 } s_lastKeyPress
= { 0, 0 };
500 KeySym keysym
= event
->keyval
;
506 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
508 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
514 case GDK_Super_R
: key_code
= WXK_ALT
; break;
515 case GDK_Menu
: key_code
= WXK_MENU
; break;
516 case GDK_Help
: key_code
= WXK_HELP
; break;
517 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
518 case GDK_ISO_Left_Tab
:
519 case GDK_Tab
: key_code
= WXK_TAB
; break;
520 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
521 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
522 case GDK_Return
: key_code
= WXK_RETURN
; break;
523 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
524 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
525 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
526 case GDK_Delete
: key_code
= WXK_DELETE
; break;
527 case GDK_Home
: key_code
= WXK_HOME
; break;
528 case GDK_Left
: key_code
= WXK_LEFT
; break;
529 case GDK_Up
: key_code
= WXK_UP
; break;
530 case GDK_Right
: key_code
= WXK_RIGHT
; break;
531 case GDK_Down
: key_code
= WXK_DOWN
; break;
532 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
533 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
534 case GDK_Next
: key_code
= WXK_NEXT
; break;
535 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
536 case GDK_End
: key_code
= WXK_END
; break;
537 case GDK_Begin
: key_code
= WXK_HOME
; break;
538 case GDK_Select
: key_code
= WXK_SELECT
; break;
539 case GDK_Print
: key_code
= WXK_PRINT
; break;
540 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
541 case GDK_Insert
: key_code
= WXK_INSERT
; break;
542 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
544 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
545 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
546 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
547 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
548 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
549 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
550 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
551 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
552 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
553 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
554 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
555 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
556 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
557 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
558 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
559 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
560 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
561 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
562 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
563 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
564 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
565 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
566 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
567 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
568 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
569 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
570 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
571 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
572 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
573 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
574 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
575 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
576 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
577 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
578 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
579 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
580 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
582 case GDK_F1
: key_code
= WXK_F1
; break;
583 case GDK_F2
: key_code
= WXK_F2
; break;
584 case GDK_F3
: key_code
= WXK_F3
; break;
585 case GDK_F4
: key_code
= WXK_F4
; break;
586 case GDK_F5
: key_code
= WXK_F5
; break;
587 case GDK_F6
: key_code
= WXK_F6
; break;
588 case GDK_F7
: key_code
= WXK_F7
; break;
589 case GDK_F8
: key_code
= WXK_F8
; break;
590 case GDK_F9
: key_code
= WXK_F9
; break;
591 case GDK_F10
: key_code
= WXK_F10
; break;
592 case GDK_F11
: key_code
= WXK_F11
; break;
593 case GDK_F12
: key_code
= WXK_F12
; break;
596 // do we have the translation?
597 if ( event
->length
== 1 )
599 keysym
= (KeySym
)event
->string
[0];
601 else if ( (keysym
& 0xFF) != keysym
)
603 // non ASCII key, what to do?
605 if ( event
->type
== GDK_KEY_RELEASE
)
607 // reuse the one from the last keypress if any
608 if ( keysym
== s_lastKeyPress
.keysym
)
610 key_code
= s_lastKeyPress
.keycode
;
617 // ignore this one, we don't know it
620 //else: ASCII key, ok
622 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
623 key_code
= upper
? upper
: keysym
;
625 if ( event
->type
== GDK_KEY_PRESS
)
627 // remember it to be reused below later
628 s_lastKeyPress
.keysym
= keysym
;
629 s_lastKeyPress
.keycode
= key_code
;
637 static long map_to_wx_keysym( GdkEventKey
*event
)
639 KeySym keysym
= event
->keyval
;
644 case GDK_Menu
: key_code
= WXK_MENU
; break;
645 case GDK_Help
: key_code
= WXK_HELP
; break;
646 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
647 case GDK_ISO_Left_Tab
:
648 case GDK_Tab
: key_code
= WXK_TAB
; break;
649 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
650 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
651 case GDK_Return
: key_code
= WXK_RETURN
; break;
652 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
653 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
654 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
655 case GDK_Delete
: key_code
= WXK_DELETE
; break;
656 case GDK_Home
: key_code
= WXK_HOME
; break;
657 case GDK_Left
: key_code
= WXK_LEFT
; break;
658 case GDK_Up
: key_code
= WXK_UP
; break;
659 case GDK_Right
: key_code
= WXK_RIGHT
; break;
660 case GDK_Down
: key_code
= WXK_DOWN
; break;
661 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
662 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
663 case GDK_Next
: key_code
= WXK_NEXT
; break;
664 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
665 case GDK_End
: key_code
= WXK_END
; break;
666 case GDK_Begin
: key_code
= WXK_HOME
; break;
667 case GDK_Select
: key_code
= WXK_SELECT
; break;
668 case GDK_Print
: key_code
= WXK_PRINT
; break;
669 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
670 case GDK_Insert
: key_code
= WXK_INSERT
; break;
671 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
673 case GDK_KP_0
: key_code
= '0'; break;
674 case GDK_KP_1
: key_code
= '1'; break;
675 case GDK_KP_2
: key_code
= '2'; break;
676 case GDK_KP_3
: key_code
= '3'; break;
677 case GDK_KP_4
: key_code
= '4'; break;
678 case GDK_KP_5
: key_code
= '5'; break;
679 case GDK_KP_6
: key_code
= '6'; break;
680 case GDK_KP_7
: key_code
= '7'; break;
681 case GDK_KP_8
: key_code
= '8'; break;
682 case GDK_KP_9
: key_code
= '9'; break;
683 case GDK_KP_Space
: key_code
= ' '; break;
684 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
685 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
686 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
687 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
688 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
689 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
690 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
691 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
692 case GDK_KP_Up
: key_code
= WXK_UP
; break;
693 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
694 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
695 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
696 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
697 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
698 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
699 case GDK_KP_End
: key_code
= WXK_END
; break;
700 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
701 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
702 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
703 case GDK_KP_Equal
: key_code
= '='; break;
704 case GDK_KP_Multiply
: key_code
= '*'; break;
705 case GDK_KP_Add
: key_code
= '+'; break;
706 case GDK_KP_Separator
: key_code
= ','; break;
707 case GDK_KP_Subtract
: key_code
= '-'; break;
708 case GDK_KP_Decimal
: key_code
= '.'; break;
709 case GDK_KP_Divide
: key_code
= '/'; break;
711 case GDK_F1
: key_code
= WXK_F1
; break;
712 case GDK_F2
: key_code
= WXK_F2
; break;
713 case GDK_F3
: key_code
= WXK_F3
; break;
714 case GDK_F4
: key_code
= WXK_F4
; break;
715 case GDK_F5
: key_code
= WXK_F5
; break;
716 case GDK_F6
: key_code
= WXK_F6
; break;
717 case GDK_F7
: key_code
= WXK_F7
; break;
718 case GDK_F8
: key_code
= WXK_F8
; break;
719 case GDK_F9
: key_code
= WXK_F9
; break;
720 case GDK_F10
: key_code
= WXK_F10
; break;
721 case GDK_F11
: key_code
= WXK_F11
; break;
722 case GDK_F12
: key_code
= WXK_F12
; break;
724 if (event
->length
== 1)
726 key_code
= (unsigned char)*event
->string
;
728 else if ((keysym
& 0xFF) == keysym
)
730 key_code
= (guint
)keysym
;
737 //-----------------------------------------------------------------------------
738 // "size_request" of m_widget
739 //-----------------------------------------------------------------------------
741 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
744 win
->GetSize( &w
, &h
);
748 requisition
->height
= h
;
749 requisition
->width
= w
;
752 //-----------------------------------------------------------------------------
753 // "expose_event" of m_wxwindow
754 //-----------------------------------------------------------------------------
756 static int gtk_window_expose_callback( GtkWidget
*widget
,
757 GdkEventExpose
*gdk_event
,
763 wxapp_install_idle_handler();
766 if (win->GetName() == wxT("panel"))
768 wxPrintf( wxT("OnExpose from ") );
769 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
770 wxPrintf( win->GetClassInfo()->GetClassName() );
771 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
772 (int)gdk_event->area.y,
773 (int)gdk_event->area.width,
774 (int)gdk_event->area.height );
778 GtkPizza
*pizza
= GTK_PIZZA (widget
);
780 if (win
->GetThemeEnabled())
782 wxWindow
*parent
= win
->GetParent();
783 while (parent
&& !parent
->IsTopLevel())
784 parent
= parent
->GetParent();
788 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
789 GTK_SHADOW_NONE
, &gdk_event
->area
, parent
->m_widget
, "base", 0, 0, -1, -1);
792 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
794 gdk_event
->area
.width
,
795 gdk_event
->area
.height
);
797 if (gdk_event
->count
== 0)
799 win
->m_clipPaintRegion
= TRUE
;
802 dc
.SetClippingRegion(win
->GetUpdateRegion());
803 wxEraseEvent
eevent( win
->GetId(), &dc
);
804 eevent
.SetEventObject( win
);
806 (void)win
->GetEventHandler()->ProcessEvent(eevent
);
808 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
810 wxClientDC
dc( win
);
811 dc
.SetBrush( wxBrush( win
->GetBackgroundColour(), wxSOLID
) );
812 dc
.SetPen( *wxTRANSPARENT_PEN
);
814 wxRegionIterator
upd( win
->GetUpdateRegion() );
817 dc
.DrawRectangle( upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
823 wxNcPaintEvent
eventNc( win
->GetId() );
824 eventNc
.SetEventObject( win
);
825 win
->GetEventHandler()->ProcessEvent( eventNc
);
827 wxPaintEvent
event( win
->GetId() );
828 event
.SetEventObject( win
);
829 win
->GetEventHandler()->ProcessEvent( event
);
831 win
->GetUpdateRegion().Clear();
833 win
->m_clipPaintRegion
= FALSE
;
836 /* The following code will result in all window-less widgets
837 being redrawn if the wxWindows class is given a chance to
838 paint *anything* because it will then be allowed to paint
839 over the window-less widgets */
840 GList
*children
= pizza
->children
;
843 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
844 children
= children
->next
;
846 GdkEventExpose child_event
= *gdk_event
;
848 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
849 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
850 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
852 child_event
.area
.x
= child
->widget
->allocation
.x
;
853 child_event
.area
.y
= child
->widget
->allocation
.y
;
854 child_event
.area
.width
= child
->widget
->allocation
.width
;
855 child_event
.area
.height
= child
->widget
->allocation
.height
;
856 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
863 //-----------------------------------------------------------------------------
864 // "event" of m_wxwindow
865 //-----------------------------------------------------------------------------
867 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
868 expose events. We need them, of course, so we override the main event
869 procedure in GtkWidget by giving our own handler for all system events.
870 There, we look for expose events ourselves whereas all other events are
873 gint
gtk_window_event_event_callback( GtkWidget
*widget
,
874 GdkEventExpose
*event
,
877 if (event
->type
== GDK_EXPOSE
)
879 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
886 //-----------------------------------------------------------------------------
887 // "draw" of m_wxwindow
888 //-----------------------------------------------------------------------------
890 /* This callback is a complete replacement of the gtk_pizza_draw() function,
893 static void gtk_window_draw_callback( GtkWidget
*widget
,
900 wxapp_install_idle_handler();
902 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
903 (win
->GetChildren().GetCount() == 0))
909 if (win->GetName() == wxT("panel"))
911 wxPrintf( wxT("OnDraw from ") );
912 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
913 wxPrintf( win->GetClassInfo()->GetClassName() );
914 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
921 GtkPizza
*pizza
= GTK_PIZZA (widget
);
923 if (win
->GetThemeEnabled())
925 wxWindow
*parent
= win
->GetParent();
926 while (parent
&& !parent
->IsTopLevel())
927 parent
= parent
->GetParent();
931 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
932 GTK_SHADOW_NONE
, rect
, parent
->m_widget
, "base", 0, 0, -1, -1);
936 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
937 (pizza
->clear_on_draw
))
939 gdk_window_clear_area( pizza
->bin_window
,
940 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
943 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
945 win
->m_clipPaintRegion
= TRUE
;
948 dc
.SetClippingRegion(win
->GetUpdateRegion());
949 wxEraseEvent
eevent( win
->GetId(), &dc
);
950 eevent
.SetEventObject( win
);
953 (void)win
->GetEventHandler()->ProcessEvent(eevent
);
955 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
957 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
959 wxClientDC
dc( win
);
960 dc
.SetBrush( wxBrush( win
->GetBackgroundColour(), wxSOLID
) );
961 dc
.SetPen( *wxTRANSPARENT_PEN
);
963 wxRegionIterator
upd( win
->GetUpdateRegion() );
966 dc
.DrawRectangle( upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
973 wxNcPaintEvent
eventNc( win
->GetId() );
974 eventNc
.SetEventObject( win
);
975 win
->GetEventHandler()->ProcessEvent( eventNc
);
977 wxPaintEvent
event( win
->GetId() );
978 event
.SetEventObject( win
);
979 win
->GetEventHandler()->ProcessEvent( event
);
981 win
->GetUpdateRegion().Clear();
983 win
->m_clipPaintRegion
= FALSE
;
986 GList
*children
= pizza
->children
;
989 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
990 children
= children
->next
;
992 GdkRectangle child_area
;
993 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
995 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
1000 //-----------------------------------------------------------------------------
1001 // "key_press_event" from any window
1002 //-----------------------------------------------------------------------------
1004 // turn on to see the key event codes on the console
1005 #undef DEBUG_KEY_EVENTS
1007 static gint
gtk_window_key_press_callback( GtkWidget
*widget
,
1008 GdkEventKey
*gdk_event
,
1014 wxapp_install_idle_handler();
1016 if (!win
->m_hasVMT
) return FALSE
;
1017 if (g_blockEventsOnDrag
) return FALSE
;
1022 GdkModifierType state
;
1023 if (gdk_event
->window
)
1024 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1028 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
1030 #ifdef DEBUG_KEY_EVENTS
1031 wxPrintf(_T("Key press event: %d => %ld\n"), gdk_event
->keyval
, key_code
);
1032 #endif // DEBUG_KEY_EVENTS
1034 /* sending unknown key events doesn't really make sense */
1038 wxKeyEvent
event( wxEVT_KEY_DOWN
);
1039 event
.SetTimestamp( gdk_event
->time
);
1040 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1041 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1042 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1043 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1044 event
.m_keyCode
= key_code
;
1045 event
.m_scanCode
= gdk_event
->keyval
;
1048 event
.SetEventObject( win
);
1049 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1054 wxWindowGTK
*ancestor
= win
;
1057 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
1060 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
1061 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
1064 if (ancestor
->IsTopLevel())
1066 ancestor
= ancestor
->GetParent();
1069 #endif // wxUSE_ACCEL
1071 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
1072 will only be sent if it is not in an accelerator table. */
1075 key_code
= map_to_wx_keysym( gdk_event
);
1079 #ifdef DEBUG_KEY_EVENTS
1080 wxPrintf(_T("Char event: %ld\n"), key_code
);
1081 #endif // DEBUG_KEY_EVENTS
1083 // reuse the ame event object, just change its type and use the
1084 // translated keycode instead of the raw one
1085 event
.SetEventType(wxEVT_CHAR
);
1086 event
.m_keyCode
= key_code
;
1088 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1092 /* win is a control: tab can be propagated up */
1094 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
1095 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
1096 // have this style, yet choose not to process this particular TAB in which
1097 // case TAB must still work as a navigational character
1099 !win
->HasFlag(wxTE_PROCESS_TAB
) &&
1101 win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
1103 wxNavigationKeyEvent new_event
;
1104 new_event
.SetEventObject( win
->GetParent() );
1105 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
1106 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
1107 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1108 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
1109 new_event
.SetCurrentFocus( win
);
1110 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
1113 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
1115 (gdk_event
->keyval
== GDK_Escape
) )
1117 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
1118 new_event
.SetEventObject( win
);
1119 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
1123 #if 0 // (GTK_MINOR_VERSION > 0)
1124 /* Pressing F10 will activate the menu bar of the top frame. */
1126 (gdk_event
->keyval
== GDK_F10
) )
1128 wxWindowGTK
*ancestor
= win
;
1131 if (wxIsKindOf(ancestor
,wxFrame
))
1133 wxFrame
*frame
= (wxFrame
*) ancestor
;
1134 wxMenuBar
*menubar
= frame
->GetMenuBar();
1137 wxNode
*node
= menubar
->GetMenus().First();
1140 wxMenu
*firstMenu
= (wxMenu
*) node
->Data();
1141 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu
->m_owner
) );
1147 ancestor
= ancestor
->GetParent();
1154 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1161 //-----------------------------------------------------------------------------
1162 // "key_release_event" from any window
1163 //-----------------------------------------------------------------------------
1165 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindowGTK
*win
)
1170 wxapp_install_idle_handler();
1172 if (!win
->m_hasVMT
) return FALSE
;
1173 if (g_blockEventsOnDrag
) return FALSE
;
1175 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
1177 #ifdef DEBUG_KEY_EVENTS
1178 wxPrintf(_T("Key release event: %d => %ld\n"), gdk_event
->keyval
, key_code
);
1179 #endif // DEBUG_KEY_EVENTS
1181 /* sending unknown key events doesn't really make sense */
1182 if (key_code
== 0) return FALSE
;
1186 GdkModifierType state
;
1187 if (gdk_event
->window
)
1188 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1190 wxKeyEvent
event( wxEVT_KEY_UP
);
1191 event
.SetTimestamp( gdk_event
->time
);
1192 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1193 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1194 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1195 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1196 event
.m_keyCode
= key_code
;
1197 event
.m_scanCode
= gdk_event
->keyval
;
1200 event
.SetEventObject( win
);
1202 if (win
->GetEventHandler()->ProcessEvent( event
))
1204 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1211 // ============================================================================
1213 // ============================================================================
1215 // init wxMouseEvent with the info from gdk_event
1216 #define InitMouseEvent(win, event, gdk_event) \
1218 event.SetTimestamp( gdk_event->time ); \
1219 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
1220 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
1221 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
1222 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
1223 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
1224 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
1225 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
1227 wxPoint pt = win->GetClientAreaOrigin(); \
1228 event.m_x = (wxCoord)gdk_event->x - pt.x; \
1229 event.m_y = (wxCoord)gdk_event->y - pt.y; \
1232 // ----------------------------------------------------------------------------
1233 // mouse event processing helper
1234 // ----------------------------------------------------------------------------
1236 static void AdjustEventButtonState(wxMouseEvent
& event
)
1238 // GDK reports the old state of the button for a button press event, but
1239 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1240 // for a LEFT_DOWN event, not FALSE, so we will invert
1241 // left/right/middleDown for the corresponding click events
1243 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1244 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1245 (event
.GetEventType() == wxEVT_LEFT_UP
))
1247 event
.m_leftDown
= !event
.m_leftDown
;
1251 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1252 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1253 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1255 event
.m_middleDown
= !event
.m_middleDown
;
1259 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1260 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1261 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1263 event
.m_rightDown
= !event
.m_rightDown
;
1268 //-----------------------------------------------------------------------------
1269 // "button_press_event"
1270 //-----------------------------------------------------------------------------
1272 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1277 wxapp_install_idle_handler();
1280 wxPrintf( wxT("1) OnButtonPress from ") );
1281 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1282 wxPrintf( win->GetClassInfo()->GetClassName() );
1283 wxPrintf( wxT(".\n") );
1285 if (!win
->m_hasVMT
) return FALSE
;
1286 if (g_blockEventsOnDrag
) return TRUE
;
1287 if (g_blockEventsOnScroll
) return TRUE
;
1289 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1291 if (win
->m_wxwindow
)
1293 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1295 gtk_widget_grab_focus (win
->m_wxwindow
);
1298 wxPrintf( wxT("GrabFocus from ") );
1299 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1300 wxPrintf( win->GetClassInfo()->GetClassName() );
1301 wxPrintf( wxT(".\n") );
1307 wxEventType event_type
= wxEVT_NULL
;
1309 if (gdk_event
->button
== 1)
1311 switch (gdk_event
->type
)
1313 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1314 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1318 else if (gdk_event
->button
== 2)
1320 switch (gdk_event
->type
)
1322 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1323 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1327 else if (gdk_event
->button
== 3)
1329 switch (gdk_event
->type
)
1331 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1332 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1337 if ( event_type
== wxEVT_NULL
)
1339 // unknown mouse button or click type
1343 wxMouseEvent
event( event_type
);
1344 InitMouseEvent( win
, event
, gdk_event
);
1346 AdjustEventButtonState(event
);
1348 // wxListBox actually get mouse events from the item
1350 if (win
->m_isListBox
)
1352 event
.m_x
+= widget
->allocation
.x
;
1353 event
.m_y
+= widget
->allocation
.y
;
1356 // Some control don't have their own X window and thus cannot get
1359 if (!g_captureWindow
)
1361 wxCoord x
= event
.m_x
;
1362 wxCoord y
= event
.m_y
;
1363 if (win
->m_wxwindow
)
1365 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1366 x
+= pizza
->xoffset
;
1367 y
+= pizza
->yoffset
;
1370 wxNode
*node
= win
->GetChildren().First();
1373 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1375 node
= node
->Next();
1376 if (!child
->IsShown())
1379 if (child
->m_isStaticBox
)
1381 // wxStaticBox is transparent in the box itself
1382 int xx1
= child
->m_x
;
1383 int yy1
= child
->m_y
;
1384 int xx2
= child
->m_x
+ child
->m_width
;
1385 int yy2
= child
->m_x
+ child
->m_height
;
1388 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1390 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1392 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1394 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1397 event
.m_x
-= child
->m_x
;
1398 event
.m_y
-= child
->m_y
;
1405 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1406 (child
->m_x
<= x
) &&
1407 (child
->m_y
<= y
) &&
1408 (child
->m_x
+child
->m_width
>= x
) &&
1409 (child
->m_y
+child
->m_height
>= y
))
1412 event
.m_x
-= child
->m_x
;
1413 event
.m_y
-= child
->m_y
;
1420 event
.SetEventObject( win
);
1422 gs_timeLastClick
= gdk_event
->time
;
1425 wxPrintf( wxT("2) OnButtonPress from ") );
1426 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1427 wxPrintf( win->GetClassInfo()->GetClassName() );
1428 wxPrintf( wxT(".\n") );
1431 if (win
->GetEventHandler()->ProcessEvent( event
))
1433 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1440 //-----------------------------------------------------------------------------
1441 // "button_release_event"
1442 //-----------------------------------------------------------------------------
1444 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1449 wxapp_install_idle_handler();
1451 if (!win
->m_hasVMT
) return FALSE
;
1452 if (g_blockEventsOnDrag
) return FALSE
;
1453 if (g_blockEventsOnScroll
) return FALSE
;
1455 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1458 printf( "OnButtonRelease from " );
1459 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1460 printf( win->GetClassInfo()->GetClassName() );
1464 wxEventType event_type
= wxEVT_NULL
;
1466 switch (gdk_event
->button
)
1468 case 1: event_type
= wxEVT_LEFT_UP
; break;
1469 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1470 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1471 default: return FALSE
;
1474 wxMouseEvent
event( event_type
);
1475 InitMouseEvent( win
, event
, gdk_event
);
1477 AdjustEventButtonState(event
);
1479 // wxListBox actually get mouse events from the item
1481 if (win
->m_isListBox
)
1483 event
.m_x
+= widget
->allocation
.x
;
1484 event
.m_y
+= widget
->allocation
.y
;
1487 // Some control don't have their own X window and thus cannot get
1490 if (!g_captureWindow
)
1492 wxCoord x
= event
.m_x
;
1493 wxCoord y
= event
.m_y
;
1494 if (win
->m_wxwindow
)
1496 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1497 x
+= pizza
->xoffset
;
1498 y
+= pizza
->yoffset
;
1501 wxNode
*node
= win
->GetChildren().First();
1504 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1506 node
= node
->Next();
1507 if (!child
->IsShown())
1510 if (child
->m_isStaticBox
)
1512 // wxStaticBox is transparent in the box itself
1513 int xx1
= child
->m_x
;
1514 int yy1
= child
->m_y
;
1515 int xx2
= child
->m_x
+ child
->m_width
;
1516 int yy2
= child
->m_x
+ child
->m_height
;
1519 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1521 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1523 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1525 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1528 event
.m_x
-= child
->m_x
;
1529 event
.m_y
-= child
->m_y
;
1536 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1537 (child
->m_x
<= x
) &&
1538 (child
->m_y
<= y
) &&
1539 (child
->m_x
+child
->m_width
>= x
) &&
1540 (child
->m_y
+child
->m_height
>= y
))
1543 event
.m_x
-= child
->m_x
;
1544 event
.m_y
-= child
->m_y
;
1551 event
.SetEventObject( win
);
1553 if (win
->GetEventHandler()->ProcessEvent( event
))
1555 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1562 //-----------------------------------------------------------------------------
1563 // "motion_notify_event"
1564 //-----------------------------------------------------------------------------
1566 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
,
1567 GdkEventMotion
*gdk_event
,
1573 wxapp_install_idle_handler();
1575 if (!win
->m_hasVMT
) return FALSE
;
1576 if (g_blockEventsOnDrag
) return FALSE
;
1577 if (g_blockEventsOnScroll
) return FALSE
;
1579 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1581 if (gdk_event
->is_hint
)
1585 GdkModifierType state
;
1586 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1592 printf( "OnMotion from " );
1593 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1594 printf( win->GetClassInfo()->GetClassName() );
1598 wxMouseEvent
event( wxEVT_MOTION
);
1599 InitMouseEvent(win
, event
, gdk_event
);
1601 if ( g_captureWindow
)
1603 // synthetize a mouse enter or leave event if needed
1604 GdkWindow
*winUnderMouse
= gdk_window_at_pointer(NULL
, NULL
);
1605 bool hasMouse
= winUnderMouse
== gdk_event
->window
;
1606 if ( hasMouse
!= g_captureWindowHasMouse
)
1608 // the mouse changed window
1609 g_captureWindowHasMouse
= hasMouse
;
1611 wxMouseEvent
event(g_captureWindowHasMouse
? wxEVT_ENTER_WINDOW
1612 : wxEVT_LEAVE_WINDOW
);
1613 InitMouseEvent(win
, event
, gdk_event
);
1614 event
.SetEventObject(win
);
1615 win
->GetEventHandler()->ProcessEvent(event
);
1620 // Some control don't have their own X window and thus cannot get
1623 wxCoord x
= event
.m_x
;
1624 wxCoord y
= event
.m_y
;
1625 if (win
->m_wxwindow
)
1627 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1628 x
+= pizza
->xoffset
;
1629 y
+= pizza
->yoffset
;
1632 wxNode
*node
= win
->GetChildren().First();
1635 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1637 node
= node
->Next();
1638 if (!child
->IsShown())
1641 if (child
->m_isStaticBox
)
1643 // wxStaticBox is transparent in the box itself
1644 int xx1
= child
->m_x
;
1645 int yy1
= child
->m_y
;
1646 int xx2
= child
->m_x
+ child
->m_width
;
1647 int yy2
= child
->m_x
+ child
->m_height
;
1650 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1652 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1654 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1656 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1659 event
.m_x
-= child
->m_x
;
1660 event
.m_y
-= child
->m_y
;
1667 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1668 (child
->m_x
<= x
) &&
1669 (child
->m_y
<= y
) &&
1670 (child
->m_x
+child
->m_width
>= x
) &&
1671 (child
->m_y
+child
->m_height
>= y
))
1674 event
.m_x
-= child
->m_x
;
1675 event
.m_y
-= child
->m_y
;
1682 event
.SetEventObject( win
);
1684 if (win
->GetEventHandler()->ProcessEvent( event
))
1686 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1693 //-----------------------------------------------------------------------------
1695 //-----------------------------------------------------------------------------
1697 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
,
1698 GdkEvent
*WXUNUSED(event
),
1704 wxapp_install_idle_handler();
1706 if (!win
->m_hasVMT
) return FALSE
;
1707 if (g_blockEventsOnDrag
) return FALSE
;
1709 switch ( g_sendActivateEvent
)
1712 // we've got focus from outside, synthetize wxActivateEvent
1713 g_sendActivateEvent
= 1;
1717 // another our window just lost focus, it was already ours before
1718 // - don't send any wxActivateEvent
1719 g_sendActivateEvent
= -1;
1724 g_focusWindow
= win
;
1727 wxPrintf( "OnSetFocus from " );
1728 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
1729 wxPrintf( win
->GetClassInfo()->GetClassName() );
1733 // notify the parent keeping track of focus for the kbd navigation
1734 // purposes that we got it
1735 wxChildFocusEvent
eventFocus(win
);
1736 (void)win
->GetEventHandler()->ProcessEvent(eventFocus
);
1740 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1744 // caret needs to be informed about focus change
1745 wxCaret
*caret
= win
->GetCaret();
1748 caret
->OnSetFocus();
1750 #endif // wxUSE_CARET
1752 wxWindowGTK
*active
= wxGetTopLevelParent(win
);
1753 if ( active
!= g_activeFrame
)
1755 if ( g_activeFrame
)
1757 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame
);
1758 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
1759 event
.SetEventObject(g_activeFrame
);
1760 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1763 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active
);
1764 g_activeFrame
= active
;
1765 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId());
1766 event
.SetEventObject(g_activeFrame
);
1767 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1769 g_activeFrameLostFocus
= FALSE
;
1772 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1773 event
.SetEventObject( win
);
1775 if (win
->GetEventHandler()->ProcessEvent( event
))
1777 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1785 //-----------------------------------------------------------------------------
1786 // "focus_out_event"
1787 //-----------------------------------------------------------------------------
1789 static GtkWidget
*gs_widgetLastFocus
= NULL
;
1791 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindowGTK
*win
)
1796 wxapp_install_idle_handler();
1798 if (!win
->m_hasVMT
) return FALSE
;
1799 if (g_blockEventsOnDrag
) return FALSE
;
1801 // VZ: this is really weird but GTK+ seems to call us from inside
1802 // gtk_widget_grab_focus(), i.e. it first sends "focus_out" signal to
1803 // this widget and then "focus_in". This is totally unexpected and
1804 // completely breaks wxUniv code so ignore this dummy event (we can't
1805 // be losing focus if we're about to acquire it!)
1806 if ( widget
== gs_widgetLastFocus
)
1808 gs_widgetLastFocus
= NULL
;
1813 if ( !g_activeFrameLostFocus
&& g_activeFrame
)
1815 // VZ: commenting this out because it does happen (although not easy
1816 // to reproduce, I only see it when using wxMiniFrame and not
1817 // always) and makes using Mahogany quite annoying
1819 wxASSERT_MSG( wxGetTopLevelParent(win
) == g_activeFrame
,
1820 wxT("unfocusing window that hasn't gained focus properly") )
1823 g_activeFrameLostFocus
= TRUE
;
1826 // if the focus goes out of our app alltogether, OnIdle() will send
1827 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1828 // g_sendActivateEvent to -1
1829 g_sendActivateEvent
= 0;
1831 wxWindowGTK
*winFocus
= wxFindFocusedChild(win
);
1835 g_focusWindow
= (wxWindowGTK
*)NULL
;
1838 wxPrintf( "OnKillFocus from " );
1839 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
1840 wxPrintf( win
->GetClassInfo()->GetClassName() );
1850 // caret needs to be informed about focus change
1851 wxCaret
*caret
= win
->GetCaret();
1854 caret
->OnKillFocus();
1856 #endif // wxUSE_CARET
1858 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1859 event
.SetEventObject( win
);
1861 if (win
->GetEventHandler()->ProcessEvent( event
))
1863 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1870 //-----------------------------------------------------------------------------
1871 // "enter_notify_event"
1872 //-----------------------------------------------------------------------------
1874 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1879 wxapp_install_idle_handler();
1881 if (!win
->m_hasVMT
) return FALSE
;
1882 if (g_blockEventsOnDrag
) return FALSE
;
1884 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1886 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1887 event
.SetTimestamp( gdk_event
->time
);
1888 event
.SetEventObject( win
);
1892 GdkModifierType state
= (GdkModifierType
)0;
1894 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1896 InitMouseEvent(win
, event
, gdk_event
);
1897 wxPoint pt
= win
->GetClientAreaOrigin();
1898 event
.m_x
= x
+ pt
.x
;
1899 event
.m_y
= y
+ pt
.y
;
1901 if (win
->GetEventHandler()->ProcessEvent( event
))
1903 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1910 //-----------------------------------------------------------------------------
1911 // "leave_notify_event"
1912 //-----------------------------------------------------------------------------
1914 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1919 wxapp_install_idle_handler();
1921 if (!win
->m_hasVMT
) return FALSE
;
1922 if (g_blockEventsOnDrag
) return FALSE
;
1924 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1926 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1927 event
.SetTimestamp( gdk_event
->time
);
1928 event
.SetEventObject( win
);
1932 GdkModifierType state
= (GdkModifierType
)0;
1934 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1936 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1937 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1938 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1939 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1940 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1941 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1942 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1944 wxPoint pt
= win
->GetClientAreaOrigin();
1945 event
.m_x
= x
+ pt
.x
;
1946 event
.m_y
= y
+ pt
.y
;
1948 if (win
->GetEventHandler()->ProcessEvent( event
))
1950 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1957 //-----------------------------------------------------------------------------
1958 // "value_changed" from m_vAdjust
1959 //-----------------------------------------------------------------------------
1961 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1966 wxapp_install_idle_handler();
1968 if (g_blockEventsOnDrag
) return;
1970 if (!win
->m_hasVMT
) return;
1972 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1973 if (fabs(diff
) < 0.2) return;
1975 win
->m_oldVerticalPos
= adjust
->value
;
1977 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1978 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1980 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1981 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1982 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1983 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1984 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1986 int value
= (int)(adjust
->value
+0.5);
1988 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1989 event
.SetEventObject( win
);
1990 win
->GetEventHandler()->ProcessEvent( event
);
1993 //-----------------------------------------------------------------------------
1994 // "value_changed" from m_hAdjust
1995 //-----------------------------------------------------------------------------
1997 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
2002 wxapp_install_idle_handler();
2004 if (g_blockEventsOnDrag
) return;
2005 if (!win
->m_hasVMT
) return;
2007 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
2008 if (fabs(diff
) < 0.2) return;
2010 win
->m_oldHorizontalPos
= adjust
->value
;
2012 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
2013 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
2015 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
2016 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
2017 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
2018 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
2019 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
2021 int value
= (int)(adjust
->value
+0.5);
2023 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
2024 event
.SetEventObject( win
);
2025 win
->GetEventHandler()->ProcessEvent( event
);
2028 //-----------------------------------------------------------------------------
2029 // "button_press_event" from scrollbar
2030 //-----------------------------------------------------------------------------
2032 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
2033 GdkEventButton
*gdk_event
,
2039 wxapp_install_idle_handler();
2042 g_blockEventsOnScroll
= TRUE
;
2043 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
2048 //-----------------------------------------------------------------------------
2049 // "button_release_event" from scrollbar
2050 //-----------------------------------------------------------------------------
2052 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
2053 GdkEventButton
*WXUNUSED(gdk_event
),
2058 // don't test here as we can release the mouse while being over
2059 // a different window than the slider
2061 // if (gdk_event->window != widget->slider) return FALSE;
2063 g_blockEventsOnScroll
= FALSE
;
2065 if (win
->m_isScrolling
)
2067 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
2071 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
2072 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
2074 value
= (int)(win
->m_hAdjust
->value
+0.5);
2077 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
2079 value
= (int)(win
->m_vAdjust
->value
+0.5);
2083 wxScrollWinEvent
event( command
, value
, dir
);
2084 event
.SetEventObject( win
);
2085 win
->GetEventHandler()->ProcessEvent( event
);
2088 win
->m_isScrolling
= FALSE
;
2093 // ----------------------------------------------------------------------------
2094 // this wxWindowBase function is implemented here (in platform-specific file)
2095 // because it is static and so couldn't be made virtual
2096 // ----------------------------------------------------------------------------
2098 wxWindow
*wxWindowBase::FindFocus()
2100 // the cast is necessary when we compile in wxUniversal mode
2101 return (wxWindow
*)g_focusWindow
;
2104 //-----------------------------------------------------------------------------
2105 // "realize" from m_widget
2106 //-----------------------------------------------------------------------------
2108 /* We cannot set colours and fonts before the widget has
2109 been realized, so we do this directly after realization. */
2112 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
2117 wxapp_install_idle_handler();
2119 if (win
->m_delayedBackgroundColour
)
2120 win
->SetBackgroundColour( win
->GetBackgroundColour() );
2122 if (win
->m_delayedForegroundColour
)
2123 win
->SetForegroundColour( win
->GetForegroundColour() );
2125 wxWindowCreateEvent
event( win
);
2126 event
.SetEventObject( win
);
2127 win
->GetEventHandler()->ProcessEvent( event
);
2132 //-----------------------------------------------------------------------------
2134 //-----------------------------------------------------------------------------
2137 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
2138 GtkAllocation
*WXUNUSED(alloc
),
2142 wxapp_install_idle_handler();
2144 if (!win
->m_hasScrolling
) return;
2146 int client_width
= 0;
2147 int client_height
= 0;
2148 win
->GetClientSize( &client_width
, &client_height
);
2149 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
2152 win
->m_oldClientWidth
= client_width
;
2153 win
->m_oldClientHeight
= client_height
;
2155 if (!win
->m_nativeSizeEvent
)
2157 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
2158 event
.SetEventObject( win
);
2159 win
->GetEventHandler()->ProcessEvent( event
);
2165 #define WXUNUSED_UNLESS_XIM(param) param
2167 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2170 /* Resize XIM window */
2173 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2174 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
2175 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2178 wxapp_install_idle_handler();
2184 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
2188 gdk_window_get_size (widget
->window
, &width
, &height
);
2189 win
->m_icattr
->preedit_area
.width
= width
;
2190 win
->m_icattr
->preedit_area
.height
= height
;
2191 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2196 //-----------------------------------------------------------------------------
2197 // "realize" from m_wxwindow
2198 //-----------------------------------------------------------------------------
2200 /* Initialize XIM support */
2203 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2204 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2207 wxapp_install_idle_handler();
2210 if (win
->m_ic
) return FALSE
;
2211 if (!widget
) return FALSE
;
2212 if (!gdk_im_ready()) return FALSE
;
2214 win
->m_icattr
= gdk_ic_attr_new();
2215 if (!win
->m_icattr
) return FALSE
;
2219 GdkColormap
*colormap
;
2220 GdkICAttr
*attr
= win
->m_icattr
;
2221 unsigned attrmask
= GDK_IC_ALL_REQ
;
2223 GdkIMStyle supported_style
= (GdkIMStyle
)
2224 (GDK_IM_PREEDIT_NONE
|
2225 GDK_IM_PREEDIT_NOTHING
|
2226 GDK_IM_PREEDIT_POSITION
|
2227 GDK_IM_STATUS_NONE
|
2228 GDK_IM_STATUS_NOTHING
);
2230 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2231 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2233 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2234 attr
->client_window
= widget
->window
;
2236 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2237 gtk_widget_get_default_colormap ())
2239 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2240 attr
->preedit_colormap
= colormap
;
2243 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2244 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2245 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2246 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2248 switch (style
& GDK_IM_PREEDIT_MASK
)
2250 case GDK_IM_PREEDIT_POSITION
:
2251 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2253 g_warning ("over-the-spot style requires fontset");
2257 gdk_window_get_size (widget
->window
, &width
, &height
);
2259 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2260 attr
->spot_location
.x
= 0;
2261 attr
->spot_location
.y
= height
;
2262 attr
->preedit_area
.x
= 0;
2263 attr
->preedit_area
.y
= 0;
2264 attr
->preedit_area
.width
= width
;
2265 attr
->preedit_area
.height
= height
;
2266 attr
->preedit_fontset
= widget
->style
->font
;
2271 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2273 if (win
->m_ic
== NULL
)
2274 g_warning ("Can't create input context.");
2277 mask
= gdk_window_get_events (widget
->window
);
2278 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2279 gdk_window_set_events (widget
->window
, mask
);
2281 if (GTK_WIDGET_HAS_FOCUS(widget
))
2282 gdk_im_begin (win
->m_ic
, widget
->window
);
2289 //-----------------------------------------------------------------------------
2290 // InsertChild for wxWindowGTK.
2291 //-----------------------------------------------------------------------------
2293 /* Callback for wxWindowGTK. This very strange beast has to be used because
2294 * C++ has no virtual methods in a constructor. We have to emulate a
2295 * virtual function here as wxNotebook requires a different way to insert
2296 * a child in it. I had opted for creating a wxNotebookPage window class
2297 * which would have made this superfluous (such in the MDI window system),
2298 * but no-one was listening to me... */
2300 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child
)
2302 /* the window might have been scrolled already, do we
2303 have to adapt the position */
2304 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2305 child
->m_x
+= pizza
->xoffset
;
2306 child
->m_y
+= pizza
->yoffset
;
2308 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2309 GTK_WIDGET(child
->m_widget
),
2316 //-----------------------------------------------------------------------------
2318 //-----------------------------------------------------------------------------
2320 wxWindow
*wxGetActiveWindow()
2322 // the cast is necessary when we compile in wxUniversal mode
2323 return (wxWindow
*)g_focusWindow
;
2326 //-----------------------------------------------------------------------------
2328 //-----------------------------------------------------------------------------
2330 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
2332 #ifdef __WXUNIVERSAL__
2333 IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
)
2335 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2336 #endif // __WXUNIVERSAL__/__WXGTK__
2338 void wxWindowGTK::Init()
2344 m_widget
= (GtkWidget
*) NULL
;
2345 m_wxwindow
= (GtkWidget
*) NULL
;
2346 m_focusWidget
= (GtkWidget
*) NULL
;
2356 m_needParent
= TRUE
;
2357 m_isBeingDeleted
= FALSE
;
2360 m_nativeSizeEvent
= FALSE
;
2362 m_hasScrolling
= FALSE
;
2363 m_isScrolling
= FALSE
;
2365 m_hAdjust
= (GtkAdjustment
*) NULL
;
2366 m_vAdjust
= (GtkAdjustment
*) NULL
;
2367 m_oldHorizontalPos
= 0.0;
2368 m_oldVerticalPos
= 0.0;
2371 m_widgetStyle
= (GtkStyle
*) NULL
;
2373 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2375 m_isStaticBox
= FALSE
;
2376 m_isRadioButton
= FALSE
;
2377 m_isListBox
= FALSE
;
2379 m_acceptsFocus
= FALSE
;
2381 m_clipPaintRegion
= FALSE
;
2383 m_cursor
= *wxSTANDARD_CURSOR
;
2385 m_delayedForegroundColour
= FALSE
;
2386 m_delayedBackgroundColour
= FALSE
;
2389 m_ic
= (GdkIC
*) NULL
;
2390 m_icattr
= (GdkICAttr
*) NULL
;
2394 wxWindowGTK::wxWindowGTK()
2399 wxWindowGTK::wxWindowGTK( wxWindow
*parent
,
2404 const wxString
&name
)
2408 Create( parent
, id
, pos
, size
, style
, name
);
2411 bool wxWindowGTK::Create( wxWindow
*parent
,
2416 const wxString
&name
)
2418 if (!PreCreation( parent
, pos
, size
) ||
2419 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2421 wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
2425 m_insertCallback
= wxInsertChildInWindow
;
2427 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2428 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2430 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2432 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2433 scroll_class
->scrollbar_spacing
= 0;
2435 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2437 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2438 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2440 m_wxwindow
= gtk_pizza_new();
2442 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2444 #ifndef __WXUNIVERSAL__
2445 #if (GTK_MINOR_VERSION > 0)
2446 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2448 if (HasFlag(wxRAISED_BORDER
))
2450 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2452 else if (HasFlag(wxSUNKEN_BORDER
))
2454 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2456 else if (HasFlag(wxSIMPLE_BORDER
))
2458 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2462 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2464 #else // GTK_MINOR_VERSION == 0
2465 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2467 if (HasFlag(wxRAISED_BORDER
))
2469 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2471 else if (HasFlag(wxSUNKEN_BORDER
))
2473 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2477 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2479 #endif // GTK_MINOR_VERSION
2480 #endif // __WXUNIVERSAL__
2482 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2483 m_acceptsFocus
= TRUE
;
2485 #if (GTK_MINOR_VERSION == 0)
2486 // shut the viewport up
2487 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2488 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2489 #endif // GTK_MINOR_VERSION == 0
2491 // I _really_ don't want scrollbars in the beginning
2492 m_vAdjust
->lower
= 0.0;
2493 m_vAdjust
->upper
= 1.0;
2494 m_vAdjust
->value
= 0.0;
2495 m_vAdjust
->step_increment
= 1.0;
2496 m_vAdjust
->page_increment
= 1.0;
2497 m_vAdjust
->page_size
= 5.0;
2498 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2499 m_hAdjust
->lower
= 0.0;
2500 m_hAdjust
->upper
= 1.0;
2501 m_hAdjust
->value
= 0.0;
2502 m_hAdjust
->step_increment
= 1.0;
2503 m_hAdjust
->page_increment
= 1.0;
2504 m_hAdjust
->page_size
= 5.0;
2505 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2507 // these handlers block mouse events to any window during scrolling such as
2508 // motion events and prevent GTK and wxWindows from fighting over where the
2511 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2512 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2514 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2515 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2517 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2518 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2520 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2521 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2523 // these handlers get notified when screen updates are required either when
2524 // scrolling or when the window size (and therefore scrollbar configuration)
2527 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2528 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2529 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2530 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2532 gtk_widget_show( m_wxwindow
);
2535 m_parent
->DoAddChild( this );
2537 m_focusWidget
= m_wxwindow
;
2546 wxWindowGTK::~wxWindowGTK()
2548 if (g_focusWindow
== this)
2549 g_focusWindow
= NULL
;
2551 if (g_activeFrame
== this)
2552 g_activeFrame
= NULL
;
2554 m_isBeingDeleted
= TRUE
;
2563 m_parent
->RemoveChild( this );
2567 gdk_ic_destroy (m_ic
);
2569 gdk_ic_attr_destroy (m_icattr
);
2574 #if DISABLE_STYLE_IF_BROKEN_THEME
2575 // don't delete if it's a pixmap theme style
2576 if (!m_widgetStyle
->engine_data
)
2577 gtk_style_unref( m_widgetStyle
);
2579 m_widgetStyle
= (GtkStyle
*) NULL
;
2584 gtk_widget_destroy( m_wxwindow
);
2585 m_wxwindow
= (GtkWidget
*) NULL
;
2590 gtk_widget_destroy( m_widget
);
2591 m_widget
= (GtkWidget
*) NULL
;
2595 bool wxWindowGTK::PreCreation( wxWindowGTK
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2597 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2599 /* this turns -1 into 20 so that a minimal window is
2600 visible even although -1,-1 has been given as the
2601 size of the window. the same trick is used in other
2602 ports and should make debugging easier */
2603 m_width
= WidthDefault(size
.x
);
2604 m_height
= HeightDefault(size
.y
);
2609 /* some reasonable defaults */
2614 m_x
= (gdk_screen_width () - m_width
) / 2;
2615 if (m_x
< 10) m_x
= 10;
2619 m_y
= (gdk_screen_height () - m_height
) / 2;
2620 if (m_y
< 10) m_y
= 10;
2627 void wxWindowGTK::PostCreation()
2629 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2635 // these get reported to wxWindows -> wxPaintEvent
2637 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2639 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2640 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2642 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2643 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2645 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2647 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2648 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2652 // these are called when the "sunken" or "raised" borders are drawn */
2653 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2654 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2656 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2657 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2662 if (m_focusWidget
== NULL
)
2663 m_focusWidget
= m_widget
;
2666 if (GetClassInfo() && GetClassInfo()->GetClassName())
2667 wxPrintf( GetClassInfo()->GetClassName() );
2671 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event",
2672 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2674 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event",
2675 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2677 // connect to the various key and mouse handlers
2679 GtkWidget
*connect_widget
= GetConnectWidget();
2681 ConnectWidget( connect_widget
);
2683 /* We cannot set colours, fonts and cursors before the widget has
2684 been realized, so we do this directly after realization */
2685 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2686 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2690 // Catch native resize events
2691 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2692 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2694 // Initialize XIM support
2695 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2696 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2698 // And resize XIM window
2699 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2700 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2703 if (!GTK_IS_COMBO(m_widget
))
2705 // This is needed if we want to add our windows into native
2706 // GTK control, such as the toolbar. With this callback, the
2707 // toolbar gets to know the correct size (the one set by the
2708 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2709 // when moving to GTK 2.0.
2710 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2711 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2717 void wxWindowGTK::ConnectWidget( GtkWidget
*widget
)
2719 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2720 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2722 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2723 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2725 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2726 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2728 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2729 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2731 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2732 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2734 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2735 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2737 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2738 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2741 bool wxWindowGTK::Destroy()
2743 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2747 return wxWindowBase::Destroy();
2750 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
)
2752 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2755 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2757 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2758 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") );
2761 printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
2764 if (m_resizing
) return; /* I don't like recursions */
2767 int currentX
, currentY
;
2768 GetPosition(¤tX
, ¤tY
);
2773 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
2775 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2777 /* don't set the size for children of wxNotebook, just take the values. */
2785 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2787 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2789 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2790 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2791 if (width
!= -1) m_width
= width
;
2792 if (height
!= -1) m_height
= height
;
2796 m_x
= x
+ pizza
->xoffset
;
2797 m_y
= y
+ pizza
->yoffset
;
2802 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2804 if (width
== -1) m_width
= 80;
2807 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2809 if (height
== -1) m_height
= 26;
2812 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2813 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2814 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2815 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2818 int bottom_border
= 0;
2820 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2822 /* the default button has a border around it */
2827 DoMoveWindow( m_x
-border
,
2830 m_height
+border
+bottom_border
);
2835 /* Sometimes the client area changes size without the
2836 whole windows's size changing, but if the whole
2837 windows's size doesn't change, no wxSizeEvent will
2838 normally be sent. Here we add an extra test if
2839 the client test has been changed and this will
2841 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2845 wxPrintf( "OnSize sent from " );
2846 if (GetClassInfo() && GetClassInfo()->GetClassName())
2847 wxPrintf( GetClassInfo()->GetClassName() );
2848 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2851 if (!m_nativeSizeEvent
)
2853 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2854 event
.SetEventObject( this );
2855 GetEventHandler()->ProcessEvent( event
);
2861 void wxWindowGTK::OnInternalIdle()
2863 if ( g_sendActivateEvent
!= -1 )
2865 bool activate
= g_sendActivateEvent
!= 0;
2868 g_sendActivateEvent
= -1;
2870 wxTheApp
->SetActive(activate
, (wxWindow
*)g_focusWindowLast
);
2873 if ( g_activeFrameLostFocus
)
2875 if ( g_activeFrame
)
2877 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame
);
2878 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
2879 event
.SetEventObject(g_activeFrame
);
2880 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
2881 g_activeFrame
= NULL
;
2883 g_activeFrameLostFocus
= FALSE
;
2886 wxCursor cursor
= m_cursor
;
2887 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2891 /* I now set the cursor anew in every OnInternalIdle call
2892 as setting the cursor in a parent window also effects the
2893 windows above so that checking for the current cursor is
2898 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2900 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2902 if (!g_globalCursor
.Ok())
2903 cursor
= *wxSTANDARD_CURSOR
;
2905 window
= m_widget
->window
;
2906 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2907 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2913 GdkWindow
*window
= m_widget
->window
;
2914 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2915 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2923 void wxWindowGTK::DoGetSize( int *width
, int *height
) const
2925 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2927 if (width
) (*width
) = m_width
;
2928 if (height
) (*height
) = m_height
;
2931 void wxWindowGTK::DoSetClientSize( int width
, int height
)
2933 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2937 SetSize( width
, height
);
2944 #ifndef __WXUNIVERSAL__
2945 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2947 /* when using GTK 1.2 we set the shadow border size to 2 */
2951 if (HasFlag(wxSIMPLE_BORDER
))
2953 /* when using GTK 1.2 we set the simple border size to 1 */
2957 #endif // __WXUNIVERSAL__
2961 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2963 GtkRequisition vscroll_req
;
2964 vscroll_req
.width
= 2;
2965 vscroll_req
.height
= 2;
2966 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2967 (scroll_window
->vscrollbar
, &vscroll_req
);
2969 GtkRequisition hscroll_req
;
2970 hscroll_req
.width
= 2;
2971 hscroll_req
.height
= 2;
2972 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2973 (scroll_window
->hscrollbar
, &hscroll_req
);
2975 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2977 if (scroll_window
->vscrollbar_visible
)
2979 dw
+= vscroll_req
.width
;
2980 dw
+= scroll_class
->scrollbar_spacing
;
2983 if (scroll_window
->hscrollbar_visible
)
2985 dh
+= hscroll_req
.height
;
2986 dh
+= scroll_class
->scrollbar_spacing
;
2990 SetSize( width
+dw
, height
+dh
);
2994 void wxWindowGTK::DoGetClientSize( int *width
, int *height
) const
2996 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3000 if (width
) (*width
) = m_width
;
3001 if (height
) (*height
) = m_height
;
3008 #ifndef __WXUNIVERSAL__
3009 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
3011 /* when using GTK 1.2 we set the shadow border size to 2 */
3015 if (HasFlag(wxSIMPLE_BORDER
))
3017 /* when using GTK 1.2 we set the simple border size to 1 */
3021 #endif // __WXUNIVERSAL__
3025 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
3027 GtkRequisition vscroll_req
;
3028 vscroll_req
.width
= 2;
3029 vscroll_req
.height
= 2;
3030 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
3031 (scroll_window
->vscrollbar
, &vscroll_req
);
3033 GtkRequisition hscroll_req
;
3034 hscroll_req
.width
= 2;
3035 hscroll_req
.height
= 2;
3036 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
3037 (scroll_window
->hscrollbar
, &hscroll_req
);
3039 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
3041 if (scroll_window
->vscrollbar_visible
)
3043 dw
+= vscroll_req
.width
;
3044 dw
+= scroll_class
->scrollbar_spacing
;
3047 if (scroll_window
->hscrollbar_visible
)
3049 dh
+= hscroll_req
.height
;
3050 dh
+= scroll_class
->scrollbar_spacing
;
3054 if (width
) (*width
) = m_width
- dw
;
3055 if (height
) (*height
) = m_height
- dh
;
3059 printf( "GetClientSize, name %s ", GetName().c_str() );
3060 if (width) printf( " width = %d", (*width) );
3061 if (height) printf( " height = %d", (*height) );
3066 void wxWindowGTK::DoGetPosition( int *x
, int *y
) const
3068 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3072 if (m_parent
&& m_parent
->m_wxwindow
)
3074 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
3075 dx
= pizza
->xoffset
;
3076 dy
= pizza
->yoffset
;
3079 if (x
) (*x
) = m_x
- dx
;
3080 if (y
) (*y
) = m_y
- dy
;
3083 void wxWindowGTK::DoClientToScreen( int *x
, int *y
) const
3085 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3087 if (!m_widget
->window
) return;
3089 GdkWindow
*source
= (GdkWindow
*) NULL
;
3091 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3093 source
= m_widget
->window
;
3097 gdk_window_get_origin( source
, &org_x
, &org_y
);
3101 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3103 org_x
+= m_widget
->allocation
.x
;
3104 org_y
+= m_widget
->allocation
.y
;
3112 void wxWindowGTK::DoScreenToClient( int *x
, int *y
) const
3114 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3116 if (!m_widget
->window
) return;
3118 GdkWindow
*source
= (GdkWindow
*) NULL
;
3120 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3122 source
= m_widget
->window
;
3126 gdk_window_get_origin( source
, &org_x
, &org_y
);
3130 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3132 org_x
+= m_widget
->allocation
.x
;
3133 org_y
+= m_widget
->allocation
.y
;
3141 bool wxWindowGTK::Show( bool show
)
3143 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3145 if (!wxWindowBase::Show(show
))
3152 gtk_widget_show( m_widget
);
3154 gtk_widget_hide( m_widget
);
3159 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
)
3161 win
->OnParentEnable(enable
);
3163 // Recurse, so that children have the opportunity to Do The Right Thing
3164 // and reset colours that have been messed up by a parent's (really ancestor's)
3166 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
3168 node
= node
->GetNext() )
3170 wxWindow
*child
= node
->GetData();
3171 if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
)))
3172 wxWindowNotifyEnable(child
, enable
);
3176 bool wxWindowGTK::Enable( bool enable
)
3178 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3180 if (!wxWindowBase::Enable(enable
))
3186 gtk_widget_set_sensitive( m_widget
, enable
);
3188 gtk_widget_set_sensitive( m_wxwindow
, enable
);
3190 wxWindowNotifyEnable(this, enable
);
3195 int wxWindowGTK::GetCharHeight() const
3197 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
3199 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
3201 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3203 return font
->ascent
+ font
->descent
;
3206 int wxWindowGTK::GetCharWidth() const
3208 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
3210 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
3212 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3214 return gdk_string_width( font
, "H" );
3217 void wxWindowGTK::GetTextExtent( const wxString
& string
,
3221 int *externalLeading
,
3222 const wxFont
*theFont
) const
3224 wxFont fontToUse
= m_font
;
3225 if (theFont
) fontToUse
= *theFont
;
3227 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
3229 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
3230 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
3231 if (y
) (*y
) = font
->ascent
+ font
->descent
;
3232 if (descent
) (*descent
) = font
->descent
;
3233 if (externalLeading
) (*externalLeading
) = 0; // ??
3236 void wxWindowGTK::SetFocus()
3238 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3242 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3244 // see comment in gtk_window_focus_out_callback()
3245 gs_widgetLastFocus
= m_wxwindow
;
3246 gtk_widget_grab_focus (m_wxwindow
);
3251 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
3253 gtk_widget_grab_focus (m_widget
);
3255 else if (GTK_IS_CONTAINER(m_widget
))
3257 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
3266 bool wxWindowGTK::AcceptsFocus() const
3268 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3271 bool wxWindowGTK::Reparent( wxWindowBase
*newParentBase
)
3273 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3275 wxWindowGTK
*oldParent
= m_parent
,
3276 *newParent
= (wxWindowGTK
*)newParentBase
;
3278 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3280 if ( !wxWindowBase::Reparent(newParent
) )
3283 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3285 /* prevent GTK from deleting the widget arbitrarily */
3286 gtk_widget_ref( m_widget
);
3290 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3293 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3297 /* insert GTK representation */
3298 (*(newParent
->m_insertCallback
))(newParent
, this);
3301 /* reverse: prevent GTK from deleting the widget arbitrarily */
3302 gtk_widget_unref( m_widget
);
3307 void wxWindowGTK::DoAddChild(wxWindowGTK
*child
)
3309 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3311 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3313 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3318 /* insert GTK representation */
3319 (*m_insertCallback
)(this, child
);
3322 void wxWindowGTK::Raise()
3324 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3326 if (!m_widget
->window
) return;
3328 gdk_window_raise( m_widget
->window
);
3331 void wxWindowGTK::Lower()
3333 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3335 if (!m_widget
->window
) return;
3337 gdk_window_lower( m_widget
->window
);
3340 bool wxWindowGTK::SetCursor( const wxCursor
&cursor
)
3342 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3344 if (cursor
== m_cursor
)
3348 wxapp_install_idle_handler();
3350 if (cursor
== wxNullCursor
)
3351 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3353 return wxWindowBase::SetCursor( cursor
);
3356 void wxWindowGTK::WarpPointer( int x
, int y
)
3358 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3360 /* we provide this function ourselves as it is
3361 missing in GDK (top of this file) */
3363 GdkWindow
*window
= (GdkWindow
*) NULL
;
3365 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3367 window
= GetConnectWidget()->window
;
3370 gdk_window_warp_pointer( window
, x
, y
);
3373 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect
*rect
)
3375 if (!m_widget
) return;
3376 if (!m_widget
->window
) return;
3378 // temporarily hide the caret to avoid nasty interactions between caret
3379 // drawing and the window contents redraw
3380 #if 0 // def wxUSE_CARET -- doesn't seem to help :-(
3381 wxCaretSuspend
cs((wxWindow
*)this);
3382 #endif // wxUSE_CARET
3384 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3388 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3390 rect
->width
, rect
->height
);
3394 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3398 /* there is no GTK equivalent of "draw only, don't clear" so we
3399 invent our own in the GtkPizza widget */
3407 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3408 gboolean old_clear = pizza->clear_on_draw;
3409 gtk_pizza_set_clear( pizza, FALSE );
3410 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3411 gtk_pizza_set_clear( pizza, old_clear );
3413 GdkEventExpose gdk_event
;
3414 gdk_event
.type
= GDK_EXPOSE
;
3415 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3416 gdk_event
.count
= 0;
3417 gdk_event
.area
.x
= 0;
3418 gdk_event
.area
.y
= 0;
3419 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3420 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3421 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, (wxWindow
*)this );
3425 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3434 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3435 gboolean old_clear = pizza->clear_on_draw;
3436 gtk_pizza_set_clear( pizza, FALSE );
3438 GdkRectangle gdk_rect;
3439 gdk_rect.x = rect->x;
3440 gdk_rect.y = rect->y;
3441 gdk_rect.width = rect->width;
3442 gdk_rect.height = rect->height;
3443 gtk_widget_draw( m_wxwindow, &gdk_rect );
3444 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3446 gtk_pizza_set_clear( pizza, old_clear );
3448 GdkEventExpose gdk_event
;
3449 gdk_event
.type
= GDK_EXPOSE
;
3450 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3451 gdk_event
.count
= 0;
3452 gdk_event
.area
.x
= rect
->x
;
3453 gdk_event
.area
.y
= rect
->y
;
3454 gdk_event
.area
.width
= rect
->width
;
3455 gdk_event
.area
.height
= rect
->height
;
3456 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, (wxWindow
*)this );
3460 GdkRectangle gdk_rect
;
3461 gdk_rect
.x
= rect
->x
;
3462 gdk_rect
.y
= rect
->y
;
3463 gdk_rect
.width
= rect
->width
;
3464 gdk_rect
.height
= rect
->height
;
3465 gtk_widget_draw( m_widget
, &gdk_rect
);
3470 void wxWindowGTK::Clear()
3472 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3474 if (!m_widget
->window
) return;
3476 if (m_wxwindow
&& m_wxwindow
->window
)
3478 // gdk_window_clear( m_wxwindow->window );
3483 void wxWindowGTK::DoSetToolTip( wxToolTip
*tip
)
3485 wxWindowBase::DoSetToolTip(tip
);
3488 m_tooltip
->Apply( (wxWindow
*)this );
3491 void wxWindowGTK::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3493 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3495 #endif // wxUSE_TOOLTIPS
3497 bool wxWindowGTK::SetBackgroundColour( const wxColour
&colour
)
3499 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3501 if (!wxWindowBase::SetBackgroundColour(colour
))
3503 // don't leave if the GTK widget has just
3505 if (!m_delayedBackgroundColour
) return FALSE
;
3508 GdkWindow
*window
= (GdkWindow
*) NULL
;
3510 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3512 window
= GetConnectWidget()->window
;
3516 // indicate that a new style has been set
3517 // but it couldn't get applied as the
3518 // widget hasn't been realized yet.
3519 m_delayedBackgroundColour
= TRUE
;
3523 (m_wxwindow
->window
) &&
3524 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3526 /* wxMSW doesn't clear the window here. I don't do that either to
3527 provide compatibility. call Clear() to do the job. */
3529 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3530 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3538 bool wxWindowGTK::SetForegroundColour( const wxColour
&colour
)
3540 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3542 if (!wxWindowBase::SetForegroundColour(colour
))
3544 // don't leave if the GTK widget has just
3546 if (!m_delayedForegroundColour
) return FALSE
;
3549 GdkWindow
*window
= (GdkWindow
*) NULL
;
3551 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3553 window
= GetConnectWidget()->window
;
3557 // indicate that a new style has been set
3558 // but it couldn't get applied as the
3559 // widget hasn't been realized yet.
3560 m_delayedForegroundColour
= TRUE
;
3568 GtkStyle
*wxWindowGTK::GetWidgetStyle()
3572 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3574 /* FIXME: is this necessary? */
3575 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3577 remake
->klass
= m_widgetStyle
->klass
;
3580 gtk_style_unref( m_widgetStyle
);
3581 m_widgetStyle
= remake
;
3585 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3588 def
= gtk_widget_get_default_style();
3590 m_widgetStyle
= gtk_style_copy( def
);
3592 /* FIXME: is this necessary? */
3593 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3595 m_widgetStyle
->klass
= def
->klass
;
3599 return m_widgetStyle
;
3602 void wxWindowGTK::SetWidgetStyle()
3604 #if DISABLE_STYLE_IF_BROKEN_THEM
3605 if (m_widget
->style
->engine_data
)
3607 static bool s_warningPrinted
= FALSE
;
3608 if (!s_warningPrinted
)
3610 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3611 s_warningPrinted
= TRUE
;
3613 m_widgetStyle
= m_widget
->style
;
3618 GtkStyle
*style
= GetWidgetStyle();
3620 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3622 gdk_font_unref( style
->font
);
3623 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3626 if (m_foregroundColour
.Ok())
3628 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3629 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3631 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3632 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3633 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3637 // Try to restore the gtk default style. This is still a little
3638 // oversimplified for what is probably really needed here for controls
3639 // other than buttons, but is better than not being able to (re)set a
3640 // control's foreground colour to *wxBLACK -- RL
3641 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3644 def
= gtk_widget_get_default_style();
3646 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3647 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3648 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3652 if (m_backgroundColour
.Ok())
3654 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3655 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3657 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3658 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3659 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3660 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3661 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3662 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3663 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3664 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3668 // Try to restore the gtk default style. This is still a little
3669 // oversimplified for what is probably really needed here for controls
3670 // other than buttons, but is better than not being able to (re)set a
3671 // control's background colour to default grey and means resetting a
3672 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3674 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3677 def
= gtk_widget_get_default_style();
3679 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3680 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3681 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3682 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3683 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3684 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3685 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3686 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3691 void wxWindowGTK::ApplyWidgetStyle()
3695 //-----------------------------------------------------------------------------
3696 // Pop-up menu stuff
3697 //-----------------------------------------------------------------------------
3699 #if wxUSE_MENUS_NATIVE
3701 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3703 *is_waiting
= FALSE
;
3706 static void SetInvokingWindow( wxMenu
*menu
, wxWindowGTK
*win
)
3708 menu
->SetInvokingWindow( win
);
3709 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3712 wxMenuItem
*menuitem
= node
->GetData();
3713 if (menuitem
->IsSubMenu())
3715 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3718 node
= node
->GetNext();
3722 // used to pass the coordinates from wxWindowGTK::DoPopupMenu() to
3723 // wxPopupMenuPositionCallback()
3725 // should be safe even in the MT case as the user can hardly popup 2 menus
3726 // simultaneously, can he?
3727 static gint gs_pop_x
= 0;
3728 static gint gs_pop_y
= 0;
3730 static void wxPopupMenuPositionCallback( GtkMenu
*menu
,
3732 gpointer
WXUNUSED(user_data
) )
3734 // ensure that the menu appears entirely on screen
3736 gtk_widget_get_child_requisition(GTK_WIDGET(menu
), &req
);
3738 wxSize sizeScreen
= wxGetDisplaySize();
3740 gint xmax
= sizeScreen
.x
- req
.width
,
3741 ymax
= sizeScreen
.y
- req
.height
;
3743 *x
= gs_pop_x
< xmax
? gs_pop_x
: xmax
;
3744 *y
= gs_pop_y
< ymax
? gs_pop_y
: ymax
;
3747 bool wxWindowGTK::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3749 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3751 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3753 SetInvokingWindow( menu
, this );
3759 ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3761 bool is_waiting
= TRUE
;
3763 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3764 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3767 GTK_MENU(menu
->m_menu
),
3768 (GtkWidget
*) NULL
, // parent menu shell
3769 (GtkWidget
*) NULL
, // parent menu item
3770 wxPopupMenuPositionCallback
, // function to position it
3771 NULL
, // client data
3772 0, // button used to activate it
3773 gs_timeLastClick
// the time of activation
3778 while (gtk_events_pending())
3779 gtk_main_iteration();
3785 #endif // wxUSE_MENUS_NATIVE
3787 #if wxUSE_DRAG_AND_DROP
3789 void wxWindowGTK::SetDropTarget( wxDropTarget
*dropTarget
)
3791 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3793 GtkWidget
*dnd_widget
= GetConnectWidget();
3795 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3797 if (m_dropTarget
) delete m_dropTarget
;
3798 m_dropTarget
= dropTarget
;
3800 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3803 #endif // wxUSE_DRAG_AND_DROP
3805 GtkWidget
* wxWindowGTK::GetConnectWidget()
3807 GtkWidget
*connect_widget
= m_widget
;
3808 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3810 return connect_widget
;
3813 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow
*window
)
3816 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3818 return (window
== m_widget
->window
);
3821 bool wxWindowGTK::SetFont( const wxFont
&font
)
3823 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3825 if (!wxWindowBase::SetFont(font
))
3830 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3831 if ( sysbg
== m_backgroundColour
)
3833 m_backgroundColour
= wxNullColour
;
3835 m_backgroundColour
= sysbg
;
3845 void wxWindowGTK::CaptureMouse()
3847 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3849 GdkWindow
*window
= (GdkWindow
*) NULL
;
3851 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3853 window
= GetConnectWidget()->window
;
3855 wxCHECK_RET( window
, _T("CaptureMouse() failed") );
3857 wxCursor
* cursor
= & m_cursor
;
3859 cursor
= wxSTANDARD_CURSOR
;
3861 gdk_pointer_grab( window
, FALSE
,
3863 (GDK_BUTTON_PRESS_MASK
|
3864 GDK_BUTTON_RELEASE_MASK
|
3865 GDK_POINTER_MOTION_HINT_MASK
|
3866 GDK_POINTER_MOTION_MASK
),
3868 cursor
->GetCursor(),
3869 (guint32
)GDK_CURRENT_TIME
);
3870 g_captureWindow
= this;
3871 g_captureWindowHasMouse
= TRUE
;
3874 void wxWindowGTK::ReleaseMouse()
3876 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3878 wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") );
3880 GdkWindow
*window
= (GdkWindow
*) NULL
;
3882 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3884 window
= GetConnectWidget()->window
;
3889 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3890 g_captureWindow
= (wxWindowGTK
*) NULL
;
3894 wxWindow
*wxWindowBase::GetCapture()
3896 return (wxWindow
*)g_captureWindow
;
3899 bool wxWindowGTK::IsRetained() const
3904 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3905 int range
, bool refresh
)
3907 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3909 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3911 m_hasScrolling
= TRUE
;
3913 if (orient
== wxHORIZONTAL
)
3915 float fpos
= (float)pos
;
3916 float frange
= (float)range
;
3917 float fthumb
= (float)thumbVisible
;
3918 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3919 if (fpos
< 0.0) fpos
= 0.0;
3921 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3922 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3924 SetScrollPos( orient
, pos
, refresh
);
3928 m_oldHorizontalPos
= fpos
;
3930 m_hAdjust
->lower
= 0.0;
3931 m_hAdjust
->upper
= frange
;
3932 m_hAdjust
->value
= fpos
;
3933 m_hAdjust
->step_increment
= 1.0;
3934 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3935 m_hAdjust
->page_size
= fthumb
;
3939 float fpos
= (float)pos
;
3940 float frange
= (float)range
;
3941 float fthumb
= (float)thumbVisible
;
3942 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3943 if (fpos
< 0.0) fpos
= 0.0;
3945 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3946 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3948 SetScrollPos( orient
, pos
, refresh
);
3952 m_oldVerticalPos
= fpos
;
3954 m_vAdjust
->lower
= 0.0;
3955 m_vAdjust
->upper
= frange
;
3956 m_vAdjust
->value
= fpos
;
3957 m_vAdjust
->step_increment
= 1.0;
3958 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3959 m_vAdjust
->page_size
= fthumb
;
3962 if (orient
== wxHORIZONTAL
)
3963 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3965 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3968 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3970 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3972 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3974 if (orient
== wxHORIZONTAL
)
3976 float fpos
= (float)pos
;
3977 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3978 if (fpos
< 0.0) fpos
= 0.0;
3979 m_oldHorizontalPos
= fpos
;
3981 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3982 m_hAdjust
->value
= fpos
;
3986 float fpos
= (float)pos
;
3987 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3988 if (fpos
< 0.0) fpos
= 0.0;
3989 m_oldVerticalPos
= fpos
;
3991 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3992 m_vAdjust
->value
= fpos
;
3995 if (m_wxwindow
->window
)
3997 if (orient
== wxHORIZONTAL
)
3999 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
4000 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
4002 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
4004 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
4005 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
4009 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
4010 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4012 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
4014 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
4015 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
4020 int wxWindowGTK::GetScrollThumb( int orient
) const
4022 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4024 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4026 if (orient
== wxHORIZONTAL
)
4027 return (int)(m_hAdjust
->page_size
+0.5);
4029 return (int)(m_vAdjust
->page_size
+0.5);
4032 int wxWindowGTK::GetScrollPos( int orient
) const
4034 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4036 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4038 if (orient
== wxHORIZONTAL
)
4039 return (int)(m_hAdjust
->value
+0.5);
4041 return (int)(m_vAdjust
->value
+0.5);
4044 int wxWindowGTK::GetScrollRange( int orient
) const
4046 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
4048 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
4050 if (orient
== wxHORIZONTAL
)
4051 return (int)(m_hAdjust
->upper
+0.5);
4053 return (int)(m_vAdjust
->upper
+0.5);
4056 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
4058 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4060 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4062 if ((dx
== 0) && (dy
== 0)) return;
4064 m_clipPaintRegion
= TRUE
;
4065 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
4066 m_clipPaintRegion
= FALSE
;
4069 if (m_children.GetCount() > 0)
4071 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
4075 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
4077 pizza->xoffset -= dx;
4078 pizza->yoffset -= dy;
4080 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
4081 gdk_gc_set_exposures( m_scrollGC, TRUE );
4085 GetClientSize( &cw, &ch );
4086 int w = cw - abs(dx);
4087 int h = ch - abs(dy);
4089 if ((h < 0) || (w < 0))
4097 if (dx < 0) s_x = -dx;
4098 if (dy < 0) s_y = -dy;
4101 if (dx > 0) d_x = dx;
4102 if (dy > 0) d_y = dy;
4104 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
4105 pizza->bin_window, s_x, s_y, w, h );
4108 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
4109 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
4110 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
4111 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
4113 Refresh( TRUE, &rect );
4116 gdk_gc_unref( m_scrollGC );
4121 // Find the wxWindow at the current mouse position, also returning the mouse
4123 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
4125 pt
= wxGetMousePosition();
4126 wxWindow
* found
= wxFindWindowAtPoint(pt
);
4130 // Get the current mouse position.
4131 wxPoint
wxGetMousePosition()
4133 /* This crashes when used within wxHelpContext,
4134 so we have to use the X-specific implementation below.
4136 GdkModifierType *mask;
4137 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
4139 return wxPoint(x, y);
4143 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
4145 return wxPoint(-999, -999);
4147 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
4148 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
4149 Window rootReturn
, childReturn
;
4150 int rootX
, rootY
, winX
, winY
;
4151 unsigned int maskReturn
;
4153 XQueryPointer (display
,
4157 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
4158 return wxPoint(rootX
, rootY
);