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 KeySym keysym
= event
->keyval
;
495 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
497 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
503 case GDK_Super_R
: key_code
= WXK_ALT
; break;
504 case GDK_Menu
: key_code
= WXK_MENU
; break;
505 case GDK_Help
: key_code
= WXK_HELP
; break;
506 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
507 case GDK_ISO_Left_Tab
:
508 case GDK_Tab
: key_code
= WXK_TAB
; break;
509 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
510 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
511 case GDK_Return
: key_code
= WXK_RETURN
; break;
512 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
513 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
514 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
515 case GDK_Delete
: key_code
= WXK_DELETE
; break;
516 case GDK_Home
: key_code
= WXK_HOME
; break;
517 case GDK_Left
: key_code
= WXK_LEFT
; break;
518 case GDK_Up
: key_code
= WXK_UP
; break;
519 case GDK_Right
: key_code
= WXK_RIGHT
; break;
520 case GDK_Down
: key_code
= WXK_DOWN
; break;
521 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
522 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
523 case GDK_Next
: key_code
= WXK_NEXT
; break;
524 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
525 case GDK_End
: key_code
= WXK_END
; break;
526 case GDK_Begin
: key_code
= WXK_HOME
; break;
527 case GDK_Select
: key_code
= WXK_SELECT
; break;
528 case GDK_Print
: key_code
= WXK_PRINT
; break;
529 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
530 case GDK_Insert
: key_code
= WXK_INSERT
; break;
531 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
533 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
534 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
535 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
536 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
537 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
538 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
539 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
540 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
541 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
542 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
543 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
544 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
545 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
546 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
547 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
548 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
549 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
550 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
551 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
552 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
553 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
554 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
555 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
556 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
557 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
558 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
559 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
560 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
561 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
562 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
563 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
564 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
565 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
566 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
567 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
568 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
569 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
571 case GDK_F1
: key_code
= WXK_F1
; break;
572 case GDK_F2
: key_code
= WXK_F2
; break;
573 case GDK_F3
: key_code
= WXK_F3
; break;
574 case GDK_F4
: key_code
= WXK_F4
; break;
575 case GDK_F5
: key_code
= WXK_F5
; break;
576 case GDK_F6
: key_code
= WXK_F6
; break;
577 case GDK_F7
: key_code
= WXK_F7
; break;
578 case GDK_F8
: key_code
= WXK_F8
; break;
579 case GDK_F9
: key_code
= WXK_F9
; break;
580 case GDK_F10
: key_code
= WXK_F10
; break;
581 case GDK_F11
: key_code
= WXK_F11
; break;
582 case GDK_F12
: key_code
= WXK_F12
; break;
584 if ( (keysym
& 0xFF) == keysym
)
586 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
587 key_code
= upper
? upper
: keysym
;
599 static long map_to_wx_keysym( GdkEventKey
*event
)
601 KeySym keysym
= event
->keyval
;
606 case GDK_Menu
: key_code
= WXK_MENU
; break;
607 case GDK_Help
: key_code
= WXK_HELP
; break;
608 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
609 case GDK_ISO_Left_Tab
:
610 case GDK_Tab
: key_code
= WXK_TAB
; break;
611 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
612 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
613 case GDK_Return
: key_code
= WXK_RETURN
; break;
614 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
615 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
616 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
617 case GDK_Delete
: key_code
= WXK_DELETE
; break;
618 case GDK_Home
: key_code
= WXK_HOME
; break;
619 case GDK_Left
: key_code
= WXK_LEFT
; break;
620 case GDK_Up
: key_code
= WXK_UP
; break;
621 case GDK_Right
: key_code
= WXK_RIGHT
; break;
622 case GDK_Down
: key_code
= WXK_DOWN
; break;
623 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
624 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
625 case GDK_Next
: key_code
= WXK_NEXT
; break;
626 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
627 case GDK_End
: key_code
= WXK_END
; break;
628 case GDK_Begin
: key_code
= WXK_HOME
; break;
629 case GDK_Select
: key_code
= WXK_SELECT
; break;
630 case GDK_Print
: key_code
= WXK_PRINT
; break;
631 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
632 case GDK_Insert
: key_code
= WXK_INSERT
; break;
633 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
635 case GDK_KP_0
: key_code
= '0'; break;
636 case GDK_KP_1
: key_code
= '1'; break;
637 case GDK_KP_2
: key_code
= '2'; break;
638 case GDK_KP_3
: key_code
= '3'; break;
639 case GDK_KP_4
: key_code
= '4'; break;
640 case GDK_KP_5
: key_code
= '5'; break;
641 case GDK_KP_6
: key_code
= '6'; break;
642 case GDK_KP_7
: key_code
= '7'; break;
643 case GDK_KP_8
: key_code
= '8'; break;
644 case GDK_KP_9
: key_code
= '9'; break;
645 case GDK_KP_Space
: key_code
= ' '; break;
646 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
647 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
648 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
649 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
650 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
651 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
652 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
653 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
654 case GDK_KP_Up
: key_code
= WXK_UP
; break;
655 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
656 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
657 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
658 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
659 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
660 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
661 case GDK_KP_End
: key_code
= WXK_END
; break;
662 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
663 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
664 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
665 case GDK_KP_Equal
: key_code
= '='; break;
666 case GDK_KP_Multiply
: key_code
= '*'; break;
667 case GDK_KP_Add
: key_code
= '+'; break;
668 case GDK_KP_Separator
: key_code
= ','; break;
669 case GDK_KP_Subtract
: key_code
= '-'; break;
670 case GDK_KP_Decimal
: key_code
= '.'; break;
671 case GDK_KP_Divide
: key_code
= '/'; break;
673 case GDK_F1
: key_code
= WXK_F1
; break;
674 case GDK_F2
: key_code
= WXK_F2
; break;
675 case GDK_F3
: key_code
= WXK_F3
; break;
676 case GDK_F4
: key_code
= WXK_F4
; break;
677 case GDK_F5
: key_code
= WXK_F5
; break;
678 case GDK_F6
: key_code
= WXK_F6
; break;
679 case GDK_F7
: key_code
= WXK_F7
; break;
680 case GDK_F8
: key_code
= WXK_F8
; break;
681 case GDK_F9
: key_code
= WXK_F9
; break;
682 case GDK_F10
: key_code
= WXK_F10
; break;
683 case GDK_F11
: key_code
= WXK_F11
; break;
684 case GDK_F12
: key_code
= WXK_F12
; break;
687 if (event
->length
== 1)
689 key_code
= (unsigned char)*event
->string
;
691 else if ((keysym
& 0xFF) == keysym
)
693 key_code
= (guint
)keysym
;
701 //-----------------------------------------------------------------------------
702 // "size_request" of m_widget
703 //-----------------------------------------------------------------------------
705 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
708 win
->GetSize( &w
, &h
);
712 requisition
->height
= h
;
713 requisition
->width
= w
;
716 //-----------------------------------------------------------------------------
717 // "expose_event" of m_wxwindow
718 //-----------------------------------------------------------------------------
720 static int gtk_window_expose_callback( GtkWidget
*widget
,
721 GdkEventExpose
*gdk_event
,
727 wxapp_install_idle_handler();
730 if (win->GetName() == wxT("panel"))
732 wxPrintf( wxT("OnExpose from ") );
733 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
734 wxPrintf( win->GetClassInfo()->GetClassName() );
735 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
736 (int)gdk_event->area.y,
737 (int)gdk_event->area.width,
738 (int)gdk_event->area.height );
742 GtkPizza
*pizza
= GTK_PIZZA (widget
);
744 if (win
->GetThemeEnabled())
746 wxWindow
*parent
= win
->GetParent();
747 while (parent
&& !parent
->IsTopLevel())
748 parent
= parent
->GetParent();
752 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
753 GTK_SHADOW_NONE
, &gdk_event
->area
, parent
->m_widget
, "base", 0, 0, -1, -1);
756 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
758 gdk_event
->area
.width
,
759 gdk_event
->area
.height
);
761 if (gdk_event
->count
== 0)
763 win
->m_clipPaintRegion
= TRUE
;
766 dc
.SetClippingRegion(win
->GetUpdateRegion());
767 wxEraseEvent
eevent( win
->GetId(), &dc
);
768 eevent
.SetEventObject( win
);
770 (void)win
->GetEventHandler()->ProcessEvent(eevent
);
772 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
774 wxClientDC
dc( win
);
775 dc
.SetBrush( wxBrush( win
->GetBackgroundColour(), wxSOLID
) );
776 dc
.SetPen( *wxTRANSPARENT_PEN
);
778 wxRegionIterator
upd( win
->GetUpdateRegion() );
781 dc
.DrawRectangle( upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
787 wxNcPaintEvent
eventNc( win
->GetId() );
788 eventNc
.SetEventObject( win
);
789 win
->GetEventHandler()->ProcessEvent( eventNc
);
791 wxPaintEvent
event( win
->GetId() );
792 event
.SetEventObject( win
);
793 win
->GetEventHandler()->ProcessEvent( event
);
795 win
->GetUpdateRegion().Clear();
797 win
->m_clipPaintRegion
= FALSE
;
800 /* The following code will result in all window-less widgets
801 being redrawn if the wxWindows class is given a chance to
802 paint *anything* because it will then be allowed to paint
803 over the window-less widgets */
804 GList
*children
= pizza
->children
;
807 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
808 children
= children
->next
;
810 GdkEventExpose child_event
= *gdk_event
;
812 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
813 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
814 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
816 child_event
.area
.x
= child
->widget
->allocation
.x
;
817 child_event
.area
.y
= child
->widget
->allocation
.y
;
818 child_event
.area
.width
= child
->widget
->allocation
.width
;
819 child_event
.area
.height
= child
->widget
->allocation
.height
;
820 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
827 //-----------------------------------------------------------------------------
828 // "event" of m_wxwindow
829 //-----------------------------------------------------------------------------
831 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
832 expose events. We need them, of course, so we override the main event
833 procedure in GtkWidget by giving our own handler for all system events.
834 There, we look for expose events ourselves whereas all other events are
837 gint
gtk_window_event_event_callback( GtkWidget
*widget
,
838 GdkEventExpose
*event
,
841 if (event
->type
== GDK_EXPOSE
)
843 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
850 //-----------------------------------------------------------------------------
851 // "draw" of m_wxwindow
852 //-----------------------------------------------------------------------------
854 /* This callback is a complete replacement of the gtk_pizza_draw() function,
857 static void gtk_window_draw_callback( GtkWidget
*widget
,
864 wxapp_install_idle_handler();
866 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
867 (win
->GetChildren().GetCount() == 0))
873 if (win->GetName() == wxT("panel"))
875 wxPrintf( wxT("OnDraw from ") );
876 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
877 wxPrintf( win->GetClassInfo()->GetClassName() );
878 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
885 GtkPizza
*pizza
= GTK_PIZZA (widget
);
887 if (win
->GetThemeEnabled())
889 wxWindow
*parent
= win
->GetParent();
890 while (parent
&& !parent
->IsTopLevel())
891 parent
= parent
->GetParent();
895 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
896 GTK_SHADOW_NONE
, rect
, parent
->m_widget
, "base", 0, 0, -1, -1);
900 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
901 (pizza
->clear_on_draw
))
903 gdk_window_clear_area( pizza
->bin_window
,
904 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
907 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
909 win
->m_clipPaintRegion
= TRUE
;
912 dc
.SetClippingRegion(win
->GetUpdateRegion());
913 wxEraseEvent
eevent( win
->GetId(), &dc
);
914 eevent
.SetEventObject( win
);
917 (void)win
->GetEventHandler()->ProcessEvent(eevent
);
919 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
921 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
923 wxClientDC
dc( win
);
924 dc
.SetBrush( wxBrush( win
->GetBackgroundColour(), wxSOLID
) );
925 dc
.SetPen( *wxTRANSPARENT_PEN
);
927 wxRegionIterator
upd( win
->GetUpdateRegion() );
930 dc
.DrawRectangle( upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
937 wxNcPaintEvent
eventNc( win
->GetId() );
938 eventNc
.SetEventObject( win
);
939 win
->GetEventHandler()->ProcessEvent( eventNc
);
941 wxPaintEvent
event( win
->GetId() );
942 event
.SetEventObject( win
);
943 win
->GetEventHandler()->ProcessEvent( event
);
945 win
->GetUpdateRegion().Clear();
947 win
->m_clipPaintRegion
= FALSE
;
950 GList
*children
= pizza
->children
;
953 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
954 children
= children
->next
;
956 GdkRectangle child_area
;
957 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
959 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
964 //-----------------------------------------------------------------------------
965 // "key_press_event" from any window
966 //-----------------------------------------------------------------------------
968 // turn on to see the key event codes on the console
969 #undef DEBUG_KEY_EVENTS
971 static gint
gtk_window_key_press_callback( GtkWidget
*widget
,
972 GdkEventKey
*gdk_event
,
978 wxapp_install_idle_handler();
980 if (!win
->m_hasVMT
) return FALSE
;
981 if (g_blockEventsOnDrag
) return FALSE
;
986 GdkModifierType state
;
987 if (gdk_event
->window
)
988 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
992 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
994 #ifdef DEBUG_KEY_EVENTS
995 wxPrintf(_T("Key press event: %d => %ld\n"), gdk_event
->keyval
, key_code
);
996 #endif // DEBUG_KEY_EVENTS
998 /* sending unknown key events doesn't really make sense */
1002 wxKeyEvent
event( wxEVT_KEY_DOWN
);
1003 event
.SetTimestamp( gdk_event
->time
);
1004 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1005 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1006 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1007 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1008 event
.m_keyCode
= key_code
;
1009 event
.m_scanCode
= gdk_event
->keyval
;
1012 event
.SetEventObject( win
);
1013 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1018 wxWindowGTK
*ancestor
= win
;
1021 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
1024 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
1025 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
1028 if (ancestor
->IsTopLevel())
1030 ancestor
= ancestor
->GetParent();
1033 #endif // wxUSE_ACCEL
1035 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
1036 will only be sent if it is not in an accelerator table. */
1039 key_code
= map_to_wx_keysym( gdk_event
);
1043 #ifdef DEBUG_KEY_EVENTS
1044 wxPrintf(_T("Char event: %ld\n"), key_code
);
1045 #endif // DEBUG_KEY_EVENTS
1047 // reuse the ame event object, just change its type and use the
1048 // translated keycode instead of the raw one
1049 event
.SetEventType(wxEVT_CHAR
);
1050 event
.m_keyCode
= key_code
;
1052 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1056 /* win is a control: tab can be propagated up */
1058 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
1059 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
1060 // have this style, yet choose not to process this particular TAB in which
1061 // case TAB must still work as a navigational character
1063 !win
->HasFlag(wxTE_PROCESS_TAB
) &&
1065 win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
1067 wxNavigationKeyEvent new_event
;
1068 new_event
.SetEventObject( win
->GetParent() );
1069 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
1070 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
1071 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1072 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
1073 new_event
.SetCurrentFocus( win
);
1074 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
1077 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
1079 (gdk_event
->keyval
== GDK_Escape
) )
1081 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
1082 new_event
.SetEventObject( win
);
1083 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
1087 #if 0 // (GTK_MINOR_VERSION > 0)
1088 /* Pressing F10 will activate the menu bar of the top frame. */
1090 (gdk_event
->keyval
== GDK_F10
) )
1092 wxWindowGTK
*ancestor
= win
;
1095 if (wxIsKindOf(ancestor
,wxFrame
))
1097 wxFrame
*frame
= (wxFrame
*) ancestor
;
1098 wxMenuBar
*menubar
= frame
->GetMenuBar();
1101 wxNode
*node
= menubar
->GetMenus().First();
1104 wxMenu
*firstMenu
= (wxMenu
*) node
->Data();
1105 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu
->m_owner
) );
1111 ancestor
= ancestor
->GetParent();
1118 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1125 //-----------------------------------------------------------------------------
1126 // "key_release_event" from any window
1127 //-----------------------------------------------------------------------------
1129 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindowGTK
*win
)
1134 wxapp_install_idle_handler();
1136 if (!win
->m_hasVMT
) return FALSE
;
1137 if (g_blockEventsOnDrag
) return FALSE
;
1139 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
1141 #ifdef DEBUG_KEY_EVENTS
1142 wxPrintf(_T("Key release event: %d => %ld\n"), gdk_event
->keyval
, key_code
);
1143 #endif // DEBUG_KEY_EVENTS
1145 /* sending unknown key events doesn't really make sense */
1146 if (key_code
== 0) return FALSE
;
1150 GdkModifierType state
;
1151 if (gdk_event
->window
)
1152 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1154 wxKeyEvent
event( wxEVT_KEY_UP
);
1155 event
.SetTimestamp( gdk_event
->time
);
1156 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1157 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1158 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1159 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1160 event
.m_keyCode
= key_code
;
1161 event
.m_scanCode
= gdk_event
->keyval
;
1164 event
.SetEventObject( win
);
1166 if (win
->GetEventHandler()->ProcessEvent( event
))
1168 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1175 // ----------------------------------------------------------------------------
1176 // mouse event processing helper
1177 // ----------------------------------------------------------------------------
1179 static void AdjustEventButtonState(wxMouseEvent
& event
)
1181 // GDK reports the old state of the button for a button press event, but
1182 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1183 // for a LEFT_DOWN event, not FALSE, so we will invert
1184 // left/right/middleDown for the corresponding click events
1186 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1187 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1188 (event
.GetEventType() == wxEVT_LEFT_UP
))
1190 event
.m_leftDown
= !event
.m_leftDown
;
1194 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1195 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1196 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1198 event
.m_middleDown
= !event
.m_middleDown
;
1202 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1203 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1204 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1206 event
.m_rightDown
= !event
.m_rightDown
;
1211 //-----------------------------------------------------------------------------
1212 // "button_press_event"
1213 //-----------------------------------------------------------------------------
1215 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1220 wxapp_install_idle_handler();
1223 wxPrintf( wxT("1) OnButtonPress from ") );
1224 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1225 wxPrintf( win->GetClassInfo()->GetClassName() );
1226 wxPrintf( wxT(".\n") );
1228 if (!win
->m_hasVMT
) return FALSE
;
1229 if (g_blockEventsOnDrag
) return TRUE
;
1230 if (g_blockEventsOnScroll
) return TRUE
;
1232 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1234 if (win
->m_wxwindow
)
1236 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1238 gtk_widget_grab_focus (win
->m_wxwindow
);
1241 wxPrintf( wxT("GrabFocus from ") );
1242 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1243 wxPrintf( win->GetClassInfo()->GetClassName() );
1244 wxPrintf( wxT(".\n") );
1250 wxEventType event_type
= wxEVT_NULL
;
1252 if (gdk_event
->button
== 1)
1254 switch (gdk_event
->type
)
1256 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1257 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1261 else if (gdk_event
->button
== 2)
1263 switch (gdk_event
->type
)
1265 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1266 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1270 else if (gdk_event
->button
== 3)
1272 switch (gdk_event
->type
)
1274 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1275 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1280 if ( event_type
== wxEVT_NULL
)
1282 // unknown mouse button or click type
1286 wxMouseEvent
event( event_type
);
1287 event
.SetTimestamp( gdk_event
->time
);
1288 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1289 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1290 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1291 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1292 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1293 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1294 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1296 event
.m_x
= (wxCoord
)gdk_event
->x
;
1297 event
.m_y
= (wxCoord
)gdk_event
->y
;
1299 AdjustEventButtonState(event
);
1301 // Some control don't have their own X window and thus cannot get
1304 if (!g_captureWindow
)
1306 wxCoord x
= event
.m_x
;
1307 wxCoord y
= event
.m_y
;
1308 if (win
->m_wxwindow
)
1310 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1311 x
+= pizza
->xoffset
;
1312 y
+= pizza
->yoffset
;
1315 wxNode
*node
= win
->GetChildren().First();
1318 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1320 node
= node
->Next();
1321 if (!child
->IsShown())
1324 if (child
->m_isStaticBox
)
1326 // wxStaticBox is transparent in the box itself
1327 int xx1
= child
->m_x
;
1328 int yy1
= child
->m_y
;
1329 int xx2
= child
->m_x
+ child
->m_width
;
1330 int yy2
= child
->m_x
+ child
->m_height
;
1333 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1335 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1337 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1339 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1342 event
.m_x
-= child
->m_x
;
1343 event
.m_y
-= child
->m_y
;
1350 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1351 (child
->m_x
<= x
) &&
1352 (child
->m_y
<= y
) &&
1353 (child
->m_x
+child
->m_width
>= x
) &&
1354 (child
->m_y
+child
->m_height
>= y
))
1357 event
.m_x
-= child
->m_x
;
1358 event
.m_y
-= child
->m_y
;
1365 event
.SetEventObject( win
);
1367 gs_timeLastClick
= gdk_event
->time
;
1370 wxPrintf( wxT("2) OnButtonPress from ") );
1371 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1372 wxPrintf( win->GetClassInfo()->GetClassName() );
1373 wxPrintf( wxT(".\n") );
1376 if (win
->GetEventHandler()->ProcessEvent( event
))
1378 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1385 //-----------------------------------------------------------------------------
1386 // "button_release_event"
1387 //-----------------------------------------------------------------------------
1389 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1394 wxapp_install_idle_handler();
1396 if (!win
->m_hasVMT
) return FALSE
;
1397 if (g_blockEventsOnDrag
) return FALSE
;
1398 if (g_blockEventsOnScroll
) return FALSE
;
1400 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1403 printf( "OnButtonRelease from " );
1404 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1405 printf( win->GetClassInfo()->GetClassName() );
1409 wxEventType event_type
= wxEVT_NULL
;
1411 switch (gdk_event
->button
)
1413 case 1: event_type
= wxEVT_LEFT_UP
; break;
1414 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1415 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1416 default: return FALSE
;
1419 wxMouseEvent
event( event_type
);
1420 event
.SetTimestamp( gdk_event
->time
);
1421 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1422 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1423 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1424 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1425 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1426 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1427 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1428 event
.m_x
= (wxCoord
)gdk_event
->x
;
1429 event
.m_y
= (wxCoord
)gdk_event
->y
;
1431 AdjustEventButtonState(event
);
1433 // Some control don't have their own X window and thus cannot get
1436 if (!g_captureWindow
)
1438 wxCoord x
= event
.m_x
;
1439 wxCoord y
= event
.m_y
;
1440 if (win
->m_wxwindow
)
1442 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1443 x
+= pizza
->xoffset
;
1444 y
+= pizza
->yoffset
;
1447 wxNode
*node
= win
->GetChildren().First();
1450 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1452 node
= node
->Next();
1453 if (!child
->IsShown())
1456 if (child
->m_isStaticBox
)
1458 // wxStaticBox is transparent in the box itself
1459 int xx1
= child
->m_x
;
1460 int yy1
= child
->m_y
;
1461 int xx2
= child
->m_x
+ child
->m_width
;
1462 int yy2
= child
->m_x
+ child
->m_height
;
1465 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1467 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1469 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1471 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1474 event
.m_x
-= child
->m_x
;
1475 event
.m_y
-= child
->m_y
;
1482 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1483 (child
->m_x
<= x
) &&
1484 (child
->m_y
<= y
) &&
1485 (child
->m_x
+child
->m_width
>= x
) &&
1486 (child
->m_y
+child
->m_height
>= y
))
1489 event
.m_x
-= child
->m_x
;
1490 event
.m_y
-= child
->m_y
;
1497 event
.SetEventObject( win
);
1499 if (win
->GetEventHandler()->ProcessEvent( event
))
1501 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1508 // ============================================================================
1510 // ============================================================================
1512 // init wxMouseEvent with the info from gdk_event
1513 #define InitMouseEvent(event, gdk_event) \
1514 event.SetTimestamp( gdk_event->time ); \
1515 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
1516 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
1517 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
1518 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
1519 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
1520 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
1521 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
1523 event.m_x = (wxCoord)gdk_event->x; \
1524 event.m_y = (wxCoord)gdk_event->y \
1526 //-----------------------------------------------------------------------------
1527 // "motion_notify_event"
1528 //-----------------------------------------------------------------------------
1530 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
,
1531 GdkEventMotion
*gdk_event
,
1537 wxapp_install_idle_handler();
1539 if (!win
->m_hasVMT
) return FALSE
;
1540 if (g_blockEventsOnDrag
) return FALSE
;
1541 if (g_blockEventsOnScroll
) return FALSE
;
1543 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1545 if (gdk_event
->is_hint
)
1549 GdkModifierType state
;
1550 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1556 printf( "OnMotion from " );
1557 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1558 printf( win->GetClassInfo()->GetClassName() );
1562 wxMouseEvent
event( wxEVT_MOTION
);
1563 InitMouseEvent(event
, gdk_event
);
1565 if ( g_captureWindow
)
1567 // synthetize a mouse enter or leave event if needed
1568 GdkWindow
*winUnderMouse
= gdk_window_at_pointer(NULL
, NULL
);
1569 bool hasMouse
= winUnderMouse
== gdk_event
->window
;
1570 if ( hasMouse
!= g_captureWindowHasMouse
)
1572 // the mouse changed window
1573 g_captureWindowHasMouse
= hasMouse
;
1575 wxMouseEvent
event(g_captureWindowHasMouse
? wxEVT_ENTER_WINDOW
1576 : wxEVT_LEAVE_WINDOW
);
1577 InitMouseEvent(event
, gdk_event
);
1578 event
.SetEventObject(win
);
1579 win
->GetEventHandler()->ProcessEvent(event
);
1584 // Some control don't have their own X window and thus cannot get
1587 wxCoord x
= event
.m_x
;
1588 wxCoord y
= event
.m_y
;
1589 if (win
->m_wxwindow
)
1591 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1592 x
+= pizza
->xoffset
;
1593 y
+= pizza
->yoffset
;
1596 wxNode
*node
= win
->GetChildren().First();
1599 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1601 node
= node
->Next();
1602 if (!child
->IsShown())
1605 if (child
->m_isStaticBox
)
1607 // wxStaticBox is transparent in the box itself
1608 int xx1
= child
->m_x
;
1609 int yy1
= child
->m_y
;
1610 int xx2
= child
->m_x
+ child
->m_width
;
1611 int yy2
= child
->m_x
+ child
->m_height
;
1614 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1616 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1618 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1620 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1623 event
.m_x
-= child
->m_x
;
1624 event
.m_y
-= child
->m_y
;
1631 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1632 (child
->m_x
<= x
) &&
1633 (child
->m_y
<= y
) &&
1634 (child
->m_x
+child
->m_width
>= x
) &&
1635 (child
->m_y
+child
->m_height
>= y
))
1638 event
.m_x
-= child
->m_x
;
1639 event
.m_y
-= child
->m_y
;
1646 event
.SetEventObject( win
);
1648 if (win
->GetEventHandler()->ProcessEvent( event
))
1650 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1657 //-----------------------------------------------------------------------------
1659 //-----------------------------------------------------------------------------
1661 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
,
1662 GdkEvent
*WXUNUSED(event
),
1668 wxapp_install_idle_handler();
1670 if (!win
->m_hasVMT
) return FALSE
;
1671 if (g_blockEventsOnDrag
) return FALSE
;
1673 switch ( g_sendActivateEvent
)
1676 // we've got focus from outside, synthetize wxActivateEvent
1677 g_sendActivateEvent
= 1;
1681 // another our window just lost focus, it was already ours before
1682 // - don't send any wxActivateEvent
1683 g_sendActivateEvent
= -1;
1688 g_focusWindow
= win
;
1691 wxPrintf( "OnSetFocus from " );
1692 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
1693 wxPrintf( win
->GetClassInfo()->GetClassName() );
1697 // notify the parent keeping track of focus for the kbd navigation
1698 // purposes that we got it
1699 wxChildFocusEvent
eventFocus(win
);
1700 (void)win
->GetEventHandler()->ProcessEvent(eventFocus
);
1704 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1708 // caret needs to be informed about focus change
1709 wxCaret
*caret
= win
->GetCaret();
1712 caret
->OnSetFocus();
1714 #endif // wxUSE_CARET
1717 wxWindowGTK
*active
= wxGetTopLevelParent(win
);
1718 if ( active
!= g_activeFrame
)
1720 if ( g_activeFrame
)
1722 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
1723 event
.SetEventObject(g_activeFrame
);
1724 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1727 g_activeFrame
= active
;
1728 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId());
1729 event
.SetEventObject(g_activeFrame
);
1730 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1732 g_activeFrameLostFocus
= FALSE
;
1735 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1736 event
.SetEventObject( win
);
1738 if (win
->GetEventHandler()->ProcessEvent( event
))
1740 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1748 //-----------------------------------------------------------------------------
1749 // "focus_out_event"
1750 //-----------------------------------------------------------------------------
1752 static GtkWidget
*gs_widgetLastFocus
= NULL
;
1754 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindowGTK
*win
)
1759 wxapp_install_idle_handler();
1761 if (!win
->m_hasVMT
) return FALSE
;
1762 if (g_blockEventsOnDrag
) return FALSE
;
1764 //wxASSERT_MSG( wxGetTopLevelParent(win) == g_activeFrame, wxT("unfocusing window that haven't gained focus properly") )
1765 g_activeFrameLostFocus
= TRUE
;
1767 // VZ: this is really weird but GTK+ seems to call us from inside
1768 // gtk_widget_grab_focus(), i.e. it first sends "focus_out" signal to
1769 // this widget and then "focus_in". This is totally unexpected and
1770 // completely breaks wxUniv code so ignore this dummy event (we can't
1771 // be losing focus if we're about to acquire it!)
1772 if ( widget
== gs_widgetLastFocus
)
1774 gs_widgetLastFocus
= NULL
;
1779 // if the focus goes out of our app alltogether, OnIdle() will send
1780 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1781 // g_sendActivateEvent to -1
1782 g_sendActivateEvent
= 0;
1784 wxWindowGTK
*winFocus
= wxFindFocusedChild(win
);
1788 g_focusWindow
= (wxWindowGTK
*)NULL
;
1791 wxPrintf( "OnKillFocus from " );
1792 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
1793 wxPrintf( win
->GetClassInfo()->GetClassName() );
1803 // caret needs to be informed about focus change
1804 wxCaret
*caret
= win
->GetCaret();
1807 caret
->OnKillFocus();
1809 #endif // wxUSE_CARET
1811 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1812 event
.SetEventObject( win
);
1814 if (win
->GetEventHandler()->ProcessEvent( event
))
1816 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1823 //-----------------------------------------------------------------------------
1824 // "enter_notify_event"
1825 //-----------------------------------------------------------------------------
1827 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1832 wxapp_install_idle_handler();
1834 if (!win
->m_hasVMT
) return FALSE
;
1835 if (g_blockEventsOnDrag
) return FALSE
;
1837 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1839 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1840 event
.SetTimestamp( gdk_event
->time
);
1841 event
.SetEventObject( win
);
1845 GdkModifierType state
= (GdkModifierType
)0;
1847 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1849 InitMouseEvent(event
, gdk_event
);
1854 if (win
->GetEventHandler()->ProcessEvent( event
))
1856 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1863 //-----------------------------------------------------------------------------
1864 // "leave_notify_event"
1865 //-----------------------------------------------------------------------------
1867 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1872 wxapp_install_idle_handler();
1874 if (!win
->m_hasVMT
) return FALSE
;
1875 if (g_blockEventsOnDrag
) return FALSE
;
1877 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1879 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1880 event
.SetTimestamp( gdk_event
->time
);
1881 event
.SetEventObject( win
);
1885 GdkModifierType state
= (GdkModifierType
)0;
1887 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1889 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1890 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1891 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1892 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1893 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1894 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1895 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1900 if (win
->GetEventHandler()->ProcessEvent( event
))
1902 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1909 //-----------------------------------------------------------------------------
1910 // "value_changed" from m_vAdjust
1911 //-----------------------------------------------------------------------------
1913 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1918 wxapp_install_idle_handler();
1920 if (g_blockEventsOnDrag
) return;
1922 if (!win
->m_hasVMT
) return;
1924 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1925 if (fabs(diff
) < 0.2) return;
1927 win
->m_oldVerticalPos
= adjust
->value
;
1929 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1930 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1932 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1933 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1934 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1935 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1936 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1938 int value
= (int)(adjust
->value
+0.5);
1940 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1941 event
.SetEventObject( win
);
1942 win
->GetEventHandler()->ProcessEvent( event
);
1945 //-----------------------------------------------------------------------------
1946 // "value_changed" from m_hAdjust
1947 //-----------------------------------------------------------------------------
1949 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1954 wxapp_install_idle_handler();
1956 if (g_blockEventsOnDrag
) return;
1957 if (!win
->m_hasVMT
) return;
1959 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1960 if (fabs(diff
) < 0.2) return;
1962 win
->m_oldHorizontalPos
= adjust
->value
;
1964 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1965 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1967 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1968 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1969 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1970 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1971 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1973 int value
= (int)(adjust
->value
+0.5);
1975 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1976 event
.SetEventObject( win
);
1977 win
->GetEventHandler()->ProcessEvent( event
);
1980 //-----------------------------------------------------------------------------
1981 // "button_press_event" from scrollbar
1982 //-----------------------------------------------------------------------------
1984 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1985 GdkEventButton
*gdk_event
,
1991 wxapp_install_idle_handler();
1994 g_blockEventsOnScroll
= TRUE
;
1995 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
2000 //-----------------------------------------------------------------------------
2001 // "button_release_event" from scrollbar
2002 //-----------------------------------------------------------------------------
2004 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
2005 GdkEventButton
*WXUNUSED(gdk_event
),
2010 // don't test here as we can release the mouse while being over
2011 // a different window than the slider
2013 // if (gdk_event->window != widget->slider) return FALSE;
2015 g_blockEventsOnScroll
= FALSE
;
2017 if (win
->m_isScrolling
)
2019 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
2023 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
2024 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
2026 value
= (int)(win
->m_hAdjust
->value
+0.5);
2029 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
2031 value
= (int)(win
->m_vAdjust
->value
+0.5);
2035 wxScrollWinEvent
event( command
, value
, dir
);
2036 event
.SetEventObject( win
);
2037 win
->GetEventHandler()->ProcessEvent( event
);
2040 win
->m_isScrolling
= FALSE
;
2045 // ----------------------------------------------------------------------------
2046 // this wxWindowBase function is implemented here (in platform-specific file)
2047 // because it is static and so couldn't be made virtual
2048 // ----------------------------------------------------------------------------
2050 wxWindow
*wxWindowBase::FindFocus()
2052 // the cast is necessary when we compile in wxUniversal mode
2053 return (wxWindow
*)g_focusWindow
;
2056 //-----------------------------------------------------------------------------
2057 // "realize" from m_widget
2058 //-----------------------------------------------------------------------------
2060 /* We cannot set colours and fonts before the widget has
2061 been realized, so we do this directly after realization. */
2064 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
2069 wxapp_install_idle_handler();
2071 if (win
->m_delayedBackgroundColour
)
2072 win
->SetBackgroundColour( win
->GetBackgroundColour() );
2074 if (win
->m_delayedForegroundColour
)
2075 win
->SetForegroundColour( win
->GetForegroundColour() );
2077 wxWindowCreateEvent
event( win
);
2078 event
.SetEventObject( win
);
2079 win
->GetEventHandler()->ProcessEvent( event
);
2084 //-----------------------------------------------------------------------------
2086 //-----------------------------------------------------------------------------
2089 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
2090 GtkAllocation
*WXUNUSED(alloc
),
2094 wxapp_install_idle_handler();
2096 if (!win
->m_hasScrolling
) return;
2098 int client_width
= 0;
2099 int client_height
= 0;
2100 win
->GetClientSize( &client_width
, &client_height
);
2101 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
2104 win
->m_oldClientWidth
= client_width
;
2105 win
->m_oldClientHeight
= client_height
;
2107 if (!win
->m_nativeSizeEvent
)
2109 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
2110 event
.SetEventObject( win
);
2111 win
->GetEventHandler()->ProcessEvent( event
);
2117 #define WXUNUSED_UNLESS_XIM(param) param
2119 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2122 /* Resize XIM window */
2125 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2126 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
2127 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2130 wxapp_install_idle_handler();
2136 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
2140 gdk_window_get_size (widget
->window
, &width
, &height
);
2141 win
->m_icattr
->preedit_area
.width
= width
;
2142 win
->m_icattr
->preedit_area
.height
= height
;
2143 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2148 //-----------------------------------------------------------------------------
2149 // "realize" from m_wxwindow
2150 //-----------------------------------------------------------------------------
2152 /* Initialize XIM support */
2155 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2156 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2159 wxapp_install_idle_handler();
2162 if (win
->m_ic
) return FALSE
;
2163 if (!widget
) return FALSE
;
2164 if (!gdk_im_ready()) return FALSE
;
2166 win
->m_icattr
= gdk_ic_attr_new();
2167 if (!win
->m_icattr
) return FALSE
;
2171 GdkColormap
*colormap
;
2172 GdkICAttr
*attr
= win
->m_icattr
;
2173 unsigned attrmask
= GDK_IC_ALL_REQ
;
2175 GdkIMStyle supported_style
= (GdkIMStyle
)
2176 (GDK_IM_PREEDIT_NONE
|
2177 GDK_IM_PREEDIT_NOTHING
|
2178 GDK_IM_PREEDIT_POSITION
|
2179 GDK_IM_STATUS_NONE
|
2180 GDK_IM_STATUS_NOTHING
);
2182 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2183 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2185 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2186 attr
->client_window
= widget
->window
;
2188 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2189 gtk_widget_get_default_colormap ())
2191 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2192 attr
->preedit_colormap
= colormap
;
2195 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2196 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2197 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2198 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2200 switch (style
& GDK_IM_PREEDIT_MASK
)
2202 case GDK_IM_PREEDIT_POSITION
:
2203 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2205 g_warning ("over-the-spot style requires fontset");
2209 gdk_window_get_size (widget
->window
, &width
, &height
);
2211 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2212 attr
->spot_location
.x
= 0;
2213 attr
->spot_location
.y
= height
;
2214 attr
->preedit_area
.x
= 0;
2215 attr
->preedit_area
.y
= 0;
2216 attr
->preedit_area
.width
= width
;
2217 attr
->preedit_area
.height
= height
;
2218 attr
->preedit_fontset
= widget
->style
->font
;
2223 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2225 if (win
->m_ic
== NULL
)
2226 g_warning ("Can't create input context.");
2229 mask
= gdk_window_get_events (widget
->window
);
2230 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2231 gdk_window_set_events (widget
->window
, mask
);
2233 if (GTK_WIDGET_HAS_FOCUS(widget
))
2234 gdk_im_begin (win
->m_ic
, widget
->window
);
2241 //-----------------------------------------------------------------------------
2242 // InsertChild for wxWindowGTK.
2243 //-----------------------------------------------------------------------------
2245 /* Callback for wxWindowGTK. This very strange beast has to be used because
2246 * C++ has no virtual methods in a constructor. We have to emulate a
2247 * virtual function here as wxNotebook requires a different way to insert
2248 * a child in it. I had opted for creating a wxNotebookPage window class
2249 * which would have made this superfluous (such in the MDI window system),
2250 * but no-one was listening to me... */
2252 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child
)
2254 /* the window might have been scrolled already, do we
2255 have to adapt the position */
2256 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2257 child
->m_x
+= pizza
->xoffset
;
2258 child
->m_y
+= pizza
->yoffset
;
2260 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2261 GTK_WIDGET(child
->m_widget
),
2268 //-----------------------------------------------------------------------------
2270 //-----------------------------------------------------------------------------
2272 wxWindow
*wxGetActiveWindow()
2274 // the cast is necessary when we compile in wxUniversal mode
2275 return (wxWindow
*)g_focusWindow
;
2278 //-----------------------------------------------------------------------------
2280 //-----------------------------------------------------------------------------
2282 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
2284 #ifdef __WXUNIVERSAL__
2285 IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
)
2287 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2288 #endif // __WXUNIVERSAL__/__WXGTK__
2290 void wxWindowGTK::Init()
2296 m_widget
= (GtkWidget
*) NULL
;
2297 m_wxwindow
= (GtkWidget
*) NULL
;
2298 m_focusWidget
= (GtkWidget
*) NULL
;
2308 m_needParent
= TRUE
;
2309 m_isBeingDeleted
= FALSE
;
2312 m_nativeSizeEvent
= FALSE
;
2314 m_hasScrolling
= FALSE
;
2315 m_isScrolling
= FALSE
;
2317 m_hAdjust
= (GtkAdjustment
*) NULL
;
2318 m_vAdjust
= (GtkAdjustment
*) NULL
;
2319 m_oldHorizontalPos
= 0.0;
2320 m_oldVerticalPos
= 0.0;
2323 m_widgetStyle
= (GtkStyle
*) NULL
;
2325 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2327 m_isStaticBox
= FALSE
;
2328 m_isRadioButton
= FALSE
;
2330 m_acceptsFocus
= FALSE
;
2332 m_clipPaintRegion
= FALSE
;
2334 m_cursor
= *wxSTANDARD_CURSOR
;
2336 m_delayedForegroundColour
= FALSE
;
2337 m_delayedBackgroundColour
= FALSE
;
2340 m_ic
= (GdkIC
*) NULL
;
2341 m_icattr
= (GdkICAttr
*) NULL
;
2345 wxWindowGTK::wxWindowGTK()
2350 wxWindowGTK::wxWindowGTK( wxWindow
*parent
,
2355 const wxString
&name
)
2359 Create( parent
, id
, pos
, size
, style
, name
);
2362 bool wxWindowGTK::Create( wxWindow
*parent
,
2367 const wxString
&name
)
2369 if (!PreCreation( parent
, pos
, size
) ||
2370 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2372 wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
2376 m_insertCallback
= wxInsertChildInWindow
;
2378 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2379 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2381 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2383 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2384 scroll_class
->scrollbar_spacing
= 0;
2386 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2388 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2389 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2391 m_wxwindow
= gtk_pizza_new();
2393 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2395 #ifndef __WXUNIVERSAL__
2396 #if (GTK_MINOR_VERSION > 0)
2397 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2399 if (HasFlag(wxRAISED_BORDER
))
2401 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2403 else if (HasFlag(wxSUNKEN_BORDER
))
2405 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2407 else if (HasFlag(wxSIMPLE_BORDER
))
2409 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2413 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2415 #else // GTK_MINOR_VERSION == 0
2416 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2418 if (HasFlag(wxRAISED_BORDER
))
2420 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2422 else if (HasFlag(wxSUNKEN_BORDER
))
2424 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2428 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2430 #endif // GTK_MINOR_VERSION
2431 #endif // __WXUNIVERSAL__
2433 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2434 m_acceptsFocus
= TRUE
;
2436 #if (GTK_MINOR_VERSION == 0)
2437 // shut the viewport up
2438 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2439 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2440 #endif // GTK_MINOR_VERSION == 0
2442 // I _really_ don't want scrollbars in the beginning
2443 m_vAdjust
->lower
= 0.0;
2444 m_vAdjust
->upper
= 1.0;
2445 m_vAdjust
->value
= 0.0;
2446 m_vAdjust
->step_increment
= 1.0;
2447 m_vAdjust
->page_increment
= 1.0;
2448 m_vAdjust
->page_size
= 5.0;
2449 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2450 m_hAdjust
->lower
= 0.0;
2451 m_hAdjust
->upper
= 1.0;
2452 m_hAdjust
->value
= 0.0;
2453 m_hAdjust
->step_increment
= 1.0;
2454 m_hAdjust
->page_increment
= 1.0;
2455 m_hAdjust
->page_size
= 5.0;
2456 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2458 // these handlers block mouse events to any window during scrolling such as
2459 // motion events and prevent GTK and wxWindows from fighting over where the
2462 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2463 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2465 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2466 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2468 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2469 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2471 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2472 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2474 // these handlers get notified when screen updates are required either when
2475 // scrolling or when the window size (and therefore scrollbar configuration)
2478 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2479 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2480 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2481 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2483 gtk_widget_show( m_wxwindow
);
2486 m_parent
->DoAddChild( this );
2488 m_focusWidget
= m_wxwindow
;
2497 wxWindowGTK::~wxWindowGTK()
2499 if (g_focusWindow
== this)
2500 g_focusWindow
= NULL
;
2502 if (g_activeFrame
== this)
2503 g_activeFrame
= NULL
;
2505 m_isBeingDeleted
= TRUE
;
2514 m_parent
->RemoveChild( this );
2518 gdk_ic_destroy (m_ic
);
2520 gdk_ic_attr_destroy (m_icattr
);
2525 #if DISABLE_STYLE_IF_BROKEN_THEME
2526 // don't delete if it's a pixmap theme style
2527 if (!m_widgetStyle
->engine_data
)
2528 gtk_style_unref( m_widgetStyle
);
2530 m_widgetStyle
= (GtkStyle
*) NULL
;
2535 gtk_widget_destroy( m_wxwindow
);
2536 m_wxwindow
= (GtkWidget
*) NULL
;
2541 gtk_widget_destroy( m_widget
);
2542 m_widget
= (GtkWidget
*) NULL
;
2546 bool wxWindowGTK::PreCreation( wxWindowGTK
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2548 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2550 /* this turns -1 into 20 so that a minimal window is
2551 visible even although -1,-1 has been given as the
2552 size of the window. the same trick is used in other
2553 ports and should make debugging easier */
2554 m_width
= WidthDefault(size
.x
);
2555 m_height
= HeightDefault(size
.y
);
2560 /* some reasonable defaults */
2565 m_x
= (gdk_screen_width () - m_width
) / 2;
2566 if (m_x
< 10) m_x
= 10;
2570 m_y
= (gdk_screen_height () - m_height
) / 2;
2571 if (m_y
< 10) m_y
= 10;
2578 void wxWindowGTK::PostCreation()
2580 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2586 // these get reported to wxWindows -> wxPaintEvent
2588 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2590 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2591 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2593 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2594 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2596 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2598 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2599 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2603 // these are called when the "sunken" or "raised" borders are drawn */
2604 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2605 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2607 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2608 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2613 if (m_focusWidget
== NULL
)
2614 m_focusWidget
= m_widget
;
2617 if (GetClassInfo() && GetClassInfo()->GetClassName())
2618 wxPrintf( GetClassInfo()->GetClassName() );
2622 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event",
2623 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2625 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event",
2626 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2628 // connect to the various key and mouse handlers
2630 GtkWidget
*connect_widget
= GetConnectWidget();
2632 ConnectWidget( connect_widget
);
2634 /* We cannot set colours, fonts and cursors before the widget has
2635 been realized, so we do this directly after realization */
2636 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2637 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2641 // Catch native resize events
2642 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2643 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2645 // Initialize XIM support
2646 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2647 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2649 // And resize XIM window
2650 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2651 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2654 if (!GTK_IS_COMBO(m_widget
))
2656 // This is needed if we want to add our windows into native
2657 // GTK control, such as the toolbar. With this callback, the
2658 // toolbar gets to know the correct size (the one set by the
2659 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2660 // when moving to GTK 2.0.
2661 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2662 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2668 void wxWindowGTK::ConnectWidget( GtkWidget
*widget
)
2670 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2671 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2673 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2674 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2676 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2677 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2679 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2680 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2682 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2683 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2685 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2686 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2688 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2689 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2692 bool wxWindowGTK::Destroy()
2694 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2698 return wxWindowBase::Destroy();
2701 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
)
2703 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2706 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2708 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2709 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") );
2712 printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
2715 if (m_resizing
) return; /* I don't like recursions */
2718 int currentX
, currentY
;
2719 GetPosition(¤tX
, ¤tY
);
2724 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
2726 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2728 /* don't set the size for children of wxNotebook, just take the values. */
2736 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2738 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2740 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2741 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2742 if (width
!= -1) m_width
= width
;
2743 if (height
!= -1) m_height
= height
;
2747 m_x
= x
+ pizza
->xoffset
;
2748 m_y
= y
+ pizza
->yoffset
;
2753 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2755 if (width
== -1) m_width
= 80;
2758 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2760 if (height
== -1) m_height
= 26;
2763 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2764 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2765 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2766 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2769 int bottom_border
= 0;
2771 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2773 /* the default button has a border around it */
2778 DoMoveWindow( m_x
-border
,
2781 m_height
+border
+bottom_border
);
2786 /* Sometimes the client area changes size without the
2787 whole windows's size changing, but if the whole
2788 windows's size doesn't change, no wxSizeEvent will
2789 normally be sent. Here we add an extra test if
2790 the client test has been changed and this will
2792 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2796 wxPrintf( "OnSize sent from " );
2797 if (GetClassInfo() && GetClassInfo()->GetClassName())
2798 wxPrintf( GetClassInfo()->GetClassName() );
2799 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2802 if (!m_nativeSizeEvent
)
2804 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2805 event
.SetEventObject( this );
2806 GetEventHandler()->ProcessEvent( event
);
2812 void wxWindowGTK::OnInternalIdle()
2814 if ( g_sendActivateEvent
!= -1 )
2816 bool activate
= g_sendActivateEvent
!= 0;
2819 g_sendActivateEvent
= -1;
2821 wxTheApp
->SetActive(activate
, (wxWindow
*)g_focusWindowLast
);
2824 if ( g_activeFrameLostFocus
)
2826 if ( g_activeFrame
)
2828 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
2829 event
.SetEventObject(g_activeFrame
);
2830 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
2831 g_activeFrame
= NULL
;
2833 g_activeFrameLostFocus
= FALSE
;
2836 wxCursor cursor
= m_cursor
;
2837 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2841 /* I now set the cursor anew in every OnInternalIdle call
2842 as setting the cursor in a parent window also effects the
2843 windows above so that checking for the current cursor is
2848 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2850 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2852 if (!g_globalCursor
.Ok())
2853 cursor
= *wxSTANDARD_CURSOR
;
2855 window
= m_widget
->window
;
2856 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2857 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2863 GdkWindow
*window
= m_widget
->window
;
2864 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2865 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2873 void wxWindowGTK::DoGetSize( int *width
, int *height
) const
2875 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2877 if (width
) (*width
) = m_width
;
2878 if (height
) (*height
) = m_height
;
2881 void wxWindowGTK::DoSetClientSize( int width
, int height
)
2883 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2887 SetSize( width
, height
);
2894 #ifndef __WXUNIVERSAL__
2895 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2897 /* when using GTK 1.2 we set the shadow border size to 2 */
2901 if (HasFlag(wxSIMPLE_BORDER
))
2903 /* when using GTK 1.2 we set the simple border size to 1 */
2907 #endif // __WXUNIVERSAL__
2911 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2913 GtkRequisition vscroll_req
;
2914 vscroll_req
.width
= 2;
2915 vscroll_req
.height
= 2;
2916 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2917 (scroll_window
->vscrollbar
, &vscroll_req
);
2919 GtkRequisition hscroll_req
;
2920 hscroll_req
.width
= 2;
2921 hscroll_req
.height
= 2;
2922 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2923 (scroll_window
->hscrollbar
, &hscroll_req
);
2925 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2927 if (scroll_window
->vscrollbar_visible
)
2929 dw
+= vscroll_req
.width
;
2930 dw
+= scroll_class
->scrollbar_spacing
;
2933 if (scroll_window
->hscrollbar_visible
)
2935 dh
+= hscroll_req
.height
;
2936 dh
+= scroll_class
->scrollbar_spacing
;
2940 SetSize( width
+dw
, height
+dh
);
2944 void wxWindowGTK::DoGetClientSize( int *width
, int *height
) const
2946 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2950 if (width
) (*width
) = m_width
;
2951 if (height
) (*height
) = m_height
;
2958 #ifndef __WXUNIVERSAL__
2959 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2961 /* when using GTK 1.2 we set the shadow border size to 2 */
2965 if (HasFlag(wxSIMPLE_BORDER
))
2967 /* when using GTK 1.2 we set the simple border size to 1 */
2971 #endif // __WXUNIVERSAL__
2975 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2977 GtkRequisition vscroll_req
;
2978 vscroll_req
.width
= 2;
2979 vscroll_req
.height
= 2;
2980 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2981 (scroll_window
->vscrollbar
, &vscroll_req
);
2983 GtkRequisition hscroll_req
;
2984 hscroll_req
.width
= 2;
2985 hscroll_req
.height
= 2;
2986 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2987 (scroll_window
->hscrollbar
, &hscroll_req
);
2989 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2991 if (scroll_window
->vscrollbar_visible
)
2993 dw
+= vscroll_req
.width
;
2994 dw
+= scroll_class
->scrollbar_spacing
;
2997 if (scroll_window
->hscrollbar_visible
)
2999 dh
+= hscroll_req
.height
;
3000 dh
+= scroll_class
->scrollbar_spacing
;
3004 if (width
) (*width
) = m_width
- dw
;
3005 if (height
) (*height
) = m_height
- dh
;
3009 printf( "GetClientSize, name %s ", GetName().c_str() );
3010 if (width) printf( " width = %d", (*width) );
3011 if (height) printf( " height = %d", (*height) );
3016 void wxWindowGTK::DoGetPosition( int *x
, int *y
) const
3018 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3022 if (m_parent
&& m_parent
->m_wxwindow
)
3024 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
3025 dx
= pizza
->xoffset
;
3026 dy
= pizza
->yoffset
;
3029 if (x
) (*x
) = m_x
- dx
;
3030 if (y
) (*y
) = m_y
- dy
;
3033 void wxWindowGTK::DoClientToScreen( int *x
, int *y
) const
3035 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3037 if (!m_widget
->window
) return;
3039 GdkWindow
*source
= (GdkWindow
*) NULL
;
3041 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3043 source
= m_widget
->window
;
3047 gdk_window_get_origin( source
, &org_x
, &org_y
);
3051 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3053 org_x
+= m_widget
->allocation
.x
;
3054 org_y
+= m_widget
->allocation
.y
;
3062 void wxWindowGTK::DoScreenToClient( int *x
, int *y
) const
3064 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3066 if (!m_widget
->window
) return;
3068 GdkWindow
*source
= (GdkWindow
*) NULL
;
3070 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3072 source
= m_widget
->window
;
3076 gdk_window_get_origin( source
, &org_x
, &org_y
);
3080 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3082 org_x
+= m_widget
->allocation
.x
;
3083 org_y
+= m_widget
->allocation
.y
;
3091 bool wxWindowGTK::Show( bool show
)
3093 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3095 if (!wxWindowBase::Show(show
))
3102 gtk_widget_show( m_widget
);
3104 gtk_widget_hide( m_widget
);
3109 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
)
3111 win
->OnParentEnable(enable
);
3113 // Recurse, so that children have the opportunity to Do The Right Thing
3114 // and reset colours that have been messed up by a parent's (really ancestor's)
3116 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
3118 node
= node
->GetNext() )
3120 wxWindow
*child
= node
->GetData();
3121 if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
)))
3122 wxWindowNotifyEnable(child
, enable
);
3126 bool wxWindowGTK::Enable( bool enable
)
3128 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3130 if (!wxWindowBase::Enable(enable
))
3136 gtk_widget_set_sensitive( m_widget
, enable
);
3138 gtk_widget_set_sensitive( m_wxwindow
, enable
);
3140 wxWindowNotifyEnable(this, enable
);
3145 int wxWindowGTK::GetCharHeight() const
3147 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
3149 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
3151 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3153 return font
->ascent
+ font
->descent
;
3156 int wxWindowGTK::GetCharWidth() const
3158 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
3160 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
3162 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3164 return gdk_string_width( font
, "H" );
3167 void wxWindowGTK::GetTextExtent( const wxString
& string
,
3171 int *externalLeading
,
3172 const wxFont
*theFont
) const
3174 wxFont fontToUse
= m_font
;
3175 if (theFont
) fontToUse
= *theFont
;
3177 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
3179 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
3180 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
3181 if (y
) (*y
) = font
->ascent
+ font
->descent
;
3182 if (descent
) (*descent
) = font
->descent
;
3183 if (externalLeading
) (*externalLeading
) = 0; // ??
3186 void wxWindowGTK::SetFocus()
3188 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3192 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3194 // see comment in gtk_window_focus_out_callback()
3195 gs_widgetLastFocus
= m_wxwindow
;
3196 gtk_widget_grab_focus (m_wxwindow
);
3201 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
3203 gtk_widget_grab_focus (m_widget
);
3205 else if (GTK_IS_CONTAINER(m_widget
))
3207 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
3216 bool wxWindowGTK::AcceptsFocus() const
3218 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3221 bool wxWindowGTK::Reparent( wxWindowBase
*newParentBase
)
3223 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3225 wxWindowGTK
*oldParent
= m_parent
,
3226 *newParent
= (wxWindowGTK
*)newParentBase
;
3228 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3230 if ( !wxWindowBase::Reparent(newParent
) )
3233 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3235 /* prevent GTK from deleting the widget arbitrarily */
3236 gtk_widget_ref( m_widget
);
3240 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3243 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3247 /* insert GTK representation */
3248 (*(newParent
->m_insertCallback
))(newParent
, this);
3251 /* reverse: prevent GTK from deleting the widget arbitrarily */
3252 gtk_widget_unref( m_widget
);
3257 void wxWindowGTK::DoAddChild(wxWindowGTK
*child
)
3259 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3261 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3263 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3268 /* insert GTK representation */
3269 (*m_insertCallback
)(this, child
);
3272 void wxWindowGTK::Raise()
3274 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3276 if (!m_widget
->window
) return;
3278 gdk_window_raise( m_widget
->window
);
3281 void wxWindowGTK::Lower()
3283 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3285 if (!m_widget
->window
) return;
3287 gdk_window_lower( m_widget
->window
);
3290 bool wxWindowGTK::SetCursor( const wxCursor
&cursor
)
3292 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3294 if (cursor
== m_cursor
)
3298 wxapp_install_idle_handler();
3300 if (cursor
== wxNullCursor
)
3301 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3303 return wxWindowBase::SetCursor( cursor
);
3306 void wxWindowGTK::WarpPointer( int x
, int y
)
3308 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3310 /* we provide this function ourselves as it is
3311 missing in GDK (top of this file) */
3313 GdkWindow
*window
= (GdkWindow
*) NULL
;
3315 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3317 window
= GetConnectWidget()->window
;
3320 gdk_window_warp_pointer( window
, x
, y
);
3323 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect
*rect
)
3325 if (!m_widget
) return;
3326 if (!m_widget
->window
) return;
3328 // temporarily hide the caret to avoid nasty interactions between caret
3329 // drawing and the window contents redraw
3330 #if 0 // def wxUSE_CARET -- doesn't seem to help :-(
3331 wxCaretSuspend
cs((wxWindow
*)this);
3332 #endif // wxUSE_CARET
3334 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3338 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3340 rect
->width
, rect
->height
);
3344 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3348 /* there is no GTK equivalent of "draw only, don't clear" so we
3349 invent our own in the GtkPizza widget */
3357 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3358 gboolean old_clear = pizza->clear_on_draw;
3359 gtk_pizza_set_clear( pizza, FALSE );
3360 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3361 gtk_pizza_set_clear( pizza, old_clear );
3363 GdkEventExpose gdk_event
;
3364 gdk_event
.type
= GDK_EXPOSE
;
3365 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3366 gdk_event
.count
= 0;
3367 gdk_event
.area
.x
= 0;
3368 gdk_event
.area
.y
= 0;
3369 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3370 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3371 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, (wxWindow
*)this );
3375 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3384 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3385 gboolean old_clear = pizza->clear_on_draw;
3386 gtk_pizza_set_clear( pizza, FALSE );
3388 GdkRectangle gdk_rect;
3389 gdk_rect.x = rect->x;
3390 gdk_rect.y = rect->y;
3391 gdk_rect.width = rect->width;
3392 gdk_rect.height = rect->height;
3393 gtk_widget_draw( m_wxwindow, &gdk_rect );
3394 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3396 gtk_pizza_set_clear( pizza, old_clear );
3398 GdkEventExpose gdk_event
;
3399 gdk_event
.type
= GDK_EXPOSE
;
3400 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3401 gdk_event
.count
= 0;
3402 gdk_event
.area
.x
= rect
->x
;
3403 gdk_event
.area
.y
= rect
->y
;
3404 gdk_event
.area
.width
= rect
->width
;
3405 gdk_event
.area
.height
= rect
->height
;
3406 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, (wxWindow
*)this );
3410 GdkRectangle gdk_rect
;
3411 gdk_rect
.x
= rect
->x
;
3412 gdk_rect
.y
= rect
->y
;
3413 gdk_rect
.width
= rect
->width
;
3414 gdk_rect
.height
= rect
->height
;
3415 gtk_widget_draw( m_widget
, &gdk_rect
);
3420 void wxWindowGTK::Clear()
3422 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3424 if (!m_widget
->window
) return;
3426 if (m_wxwindow
&& m_wxwindow
->window
)
3428 // gdk_window_clear( m_wxwindow->window );
3433 void wxWindowGTK::DoSetToolTip( wxToolTip
*tip
)
3435 wxWindowBase::DoSetToolTip(tip
);
3438 m_tooltip
->Apply( (wxWindow
*)this );
3441 void wxWindowGTK::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3443 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3445 #endif // wxUSE_TOOLTIPS
3447 bool wxWindowGTK::SetBackgroundColour( const wxColour
&colour
)
3449 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3451 if (!wxWindowBase::SetBackgroundColour(colour
))
3453 // don't leave if the GTK widget has just
3455 if (!m_delayedBackgroundColour
) return FALSE
;
3458 GdkWindow
*window
= (GdkWindow
*) NULL
;
3460 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3462 window
= GetConnectWidget()->window
;
3466 // indicate that a new style has been set
3467 // but it couldn't get applied as the
3468 // widget hasn't been realized yet.
3469 m_delayedBackgroundColour
= TRUE
;
3473 (m_wxwindow
->window
) &&
3474 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3476 /* wxMSW doesn't clear the window here. I don't do that either to
3477 provide compatibility. call Clear() to do the job. */
3479 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3480 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3488 bool wxWindowGTK::SetForegroundColour( const wxColour
&colour
)
3490 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3492 if (!wxWindowBase::SetForegroundColour(colour
))
3494 // don't leave if the GTK widget has just
3496 if (!m_delayedForegroundColour
) return FALSE
;
3499 GdkWindow
*window
= (GdkWindow
*) NULL
;
3501 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3503 window
= GetConnectWidget()->window
;
3507 // indicate that a new style has been set
3508 // but it couldn't get applied as the
3509 // widget hasn't been realized yet.
3510 m_delayedForegroundColour
= TRUE
;
3518 GtkStyle
*wxWindowGTK::GetWidgetStyle()
3522 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3524 /* FIXME: is this necessary? */
3525 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3527 remake
->klass
= m_widgetStyle
->klass
;
3530 gtk_style_unref( m_widgetStyle
);
3531 m_widgetStyle
= remake
;
3535 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3538 def
= gtk_widget_get_default_style();
3540 m_widgetStyle
= gtk_style_copy( def
);
3542 /* FIXME: is this necessary? */
3543 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3545 m_widgetStyle
->klass
= def
->klass
;
3549 return m_widgetStyle
;
3552 void wxWindowGTK::SetWidgetStyle()
3554 #if DISABLE_STYLE_IF_BROKEN_THEM
3555 if (m_widget
->style
->engine_data
)
3557 static bool s_warningPrinted
= FALSE
;
3558 if (!s_warningPrinted
)
3560 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3561 s_warningPrinted
= TRUE
;
3563 m_widgetStyle
= m_widget
->style
;
3568 GtkStyle
*style
= GetWidgetStyle();
3570 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3572 gdk_font_unref( style
->font
);
3573 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3576 if (m_foregroundColour
.Ok())
3578 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3579 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3581 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3582 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3583 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3587 // Try to restore the gtk default style. This is still a little
3588 // oversimplified for what is probably really needed here for controls
3589 // other than buttons, but is better than not being able to (re)set a
3590 // control's foreground colour to *wxBLACK -- RL
3591 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3594 def
= gtk_widget_get_default_style();
3596 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3597 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3598 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3602 if (m_backgroundColour
.Ok())
3604 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3605 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3607 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3608 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3609 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3610 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3611 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3612 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3613 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3614 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3618 // Try to restore the gtk default style. This is still a little
3619 // oversimplified for what is probably really needed here for controls
3620 // other than buttons, but is better than not being able to (re)set a
3621 // control's background colour to default grey and means resetting a
3622 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3624 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3627 def
= gtk_widget_get_default_style();
3629 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3630 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3631 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3632 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3633 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3634 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3635 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3636 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3641 void wxWindowGTK::ApplyWidgetStyle()
3645 //-----------------------------------------------------------------------------
3646 // Pop-up menu stuff
3647 //-----------------------------------------------------------------------------
3649 #if wxUSE_MENUS_NATIVE
3651 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3653 *is_waiting
= FALSE
;
3656 static void SetInvokingWindow( wxMenu
*menu
, wxWindowGTK
*win
)
3658 menu
->SetInvokingWindow( win
);
3659 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3662 wxMenuItem
*menuitem
= node
->GetData();
3663 if (menuitem
->IsSubMenu())
3665 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3668 node
= node
->GetNext();
3672 static gint gs_pop_x
= 0;
3673 static gint gs_pop_y
= 0;
3675 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3679 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3684 bool wxWindowGTK::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3686 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3688 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3690 SetInvokingWindow( menu
, this );
3697 bool is_waiting
= TRUE
;
3699 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3700 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3703 GTK_MENU(menu
->m_menu
),
3704 (GtkWidget
*) NULL
, // parent menu shell
3705 (GtkWidget
*) NULL
, // parent menu item
3706 (GtkMenuPositionFunc
) pop_pos_callback
,
3707 (gpointer
) this, // client data
3708 0, // button used to activate it
3709 gs_timeLastClick
// the time of activation
3714 while (gtk_events_pending())
3715 gtk_main_iteration();
3721 #endif // wxUSE_MENUS_NATIVE
3723 #if wxUSE_DRAG_AND_DROP
3725 void wxWindowGTK::SetDropTarget( wxDropTarget
*dropTarget
)
3727 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3729 GtkWidget
*dnd_widget
= GetConnectWidget();
3731 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3733 if (m_dropTarget
) delete m_dropTarget
;
3734 m_dropTarget
= dropTarget
;
3736 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3739 #endif // wxUSE_DRAG_AND_DROP
3741 GtkWidget
* wxWindowGTK::GetConnectWidget()
3743 GtkWidget
*connect_widget
= m_widget
;
3744 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3746 return connect_widget
;
3749 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow
*window
)
3752 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3754 return (window
== m_widget
->window
);
3757 bool wxWindowGTK::SetFont( const wxFont
&font
)
3759 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3761 if (!wxWindowBase::SetFont(font
))
3766 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3767 if ( sysbg
== m_backgroundColour
)
3769 m_backgroundColour
= wxNullColour
;
3771 m_backgroundColour
= sysbg
;
3781 void wxWindowGTK::CaptureMouse()
3783 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3785 GdkWindow
*window
= (GdkWindow
*) NULL
;
3787 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3789 window
= GetConnectWidget()->window
;
3791 wxCHECK_RET( window
, _T("CaptureMouse() failed") );
3793 wxCursor
* cursor
= & m_cursor
;
3795 cursor
= wxSTANDARD_CURSOR
;
3797 gdk_pointer_grab( window
, FALSE
,
3799 (GDK_BUTTON_PRESS_MASK
|
3800 GDK_BUTTON_RELEASE_MASK
|
3801 GDK_POINTER_MOTION_HINT_MASK
|
3802 GDK_POINTER_MOTION_MASK
),
3804 cursor
->GetCursor(),
3805 (guint32
)GDK_CURRENT_TIME
);
3806 g_captureWindow
= this;
3807 g_captureWindowHasMouse
= TRUE
;
3810 void wxWindowGTK::ReleaseMouse()
3812 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3814 wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") );
3816 GdkWindow
*window
= (GdkWindow
*) NULL
;
3818 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3820 window
= GetConnectWidget()->window
;
3825 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3826 g_captureWindow
= (wxWindowGTK
*) NULL
;
3830 wxWindow
*wxWindowBase::GetCapture()
3832 return (wxWindow
*)g_captureWindow
;
3835 bool wxWindowGTK::IsRetained() const
3840 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3841 int range
, bool refresh
)
3843 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3845 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3847 m_hasScrolling
= TRUE
;
3849 if (orient
== wxHORIZONTAL
)
3851 float fpos
= (float)pos
;
3852 float frange
= (float)range
;
3853 float fthumb
= (float)thumbVisible
;
3854 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3855 if (fpos
< 0.0) fpos
= 0.0;
3857 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3858 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3860 SetScrollPos( orient
, pos
, refresh
);
3864 m_oldHorizontalPos
= fpos
;
3866 m_hAdjust
->lower
= 0.0;
3867 m_hAdjust
->upper
= frange
;
3868 m_hAdjust
->value
= fpos
;
3869 m_hAdjust
->step_increment
= 1.0;
3870 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3871 m_hAdjust
->page_size
= fthumb
;
3875 float fpos
= (float)pos
;
3876 float frange
= (float)range
;
3877 float fthumb
= (float)thumbVisible
;
3878 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3879 if (fpos
< 0.0) fpos
= 0.0;
3881 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3882 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3884 SetScrollPos( orient
, pos
, refresh
);
3888 m_oldVerticalPos
= fpos
;
3890 m_vAdjust
->lower
= 0.0;
3891 m_vAdjust
->upper
= frange
;
3892 m_vAdjust
->value
= fpos
;
3893 m_vAdjust
->step_increment
= 1.0;
3894 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3895 m_vAdjust
->page_size
= fthumb
;
3898 if (orient
== wxHORIZONTAL
)
3899 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3901 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3904 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3906 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3908 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3910 if (orient
== wxHORIZONTAL
)
3912 float fpos
= (float)pos
;
3913 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3914 if (fpos
< 0.0) fpos
= 0.0;
3915 m_oldHorizontalPos
= fpos
;
3917 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3918 m_hAdjust
->value
= fpos
;
3922 float fpos
= (float)pos
;
3923 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3924 if (fpos
< 0.0) fpos
= 0.0;
3925 m_oldVerticalPos
= fpos
;
3927 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3928 m_vAdjust
->value
= fpos
;
3931 if (m_wxwindow
->window
)
3933 if (orient
== wxHORIZONTAL
)
3935 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3936 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3938 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3940 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3941 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3945 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3946 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3948 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3950 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3951 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3956 int wxWindowGTK::GetScrollThumb( int orient
) const
3958 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3960 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3962 if (orient
== wxHORIZONTAL
)
3963 return (int)(m_hAdjust
->page_size
+0.5);
3965 return (int)(m_vAdjust
->page_size
+0.5);
3968 int wxWindowGTK::GetScrollPos( int orient
) const
3970 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3972 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3974 if (orient
== wxHORIZONTAL
)
3975 return (int)(m_hAdjust
->value
+0.5);
3977 return (int)(m_vAdjust
->value
+0.5);
3980 int wxWindowGTK::GetScrollRange( int orient
) const
3982 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3984 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3986 if (orient
== wxHORIZONTAL
)
3987 return (int)(m_hAdjust
->upper
+0.5);
3989 return (int)(m_vAdjust
->upper
+0.5);
3992 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3994 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3996 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3998 if ((dx
== 0) && (dy
== 0)) return;
4000 m_clipPaintRegion
= TRUE
;
4001 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
4002 m_clipPaintRegion
= FALSE
;
4005 if (m_children.GetCount() > 0)
4007 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
4011 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
4013 pizza->xoffset -= dx;
4014 pizza->yoffset -= dy;
4016 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
4017 gdk_gc_set_exposures( m_scrollGC, TRUE );
4021 GetClientSize( &cw, &ch );
4022 int w = cw - abs(dx);
4023 int h = ch - abs(dy);
4025 if ((h < 0) || (w < 0))
4033 if (dx < 0) s_x = -dx;
4034 if (dy < 0) s_y = -dy;
4037 if (dx > 0) d_x = dx;
4038 if (dy > 0) d_y = dy;
4040 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
4041 pizza->bin_window, s_x, s_y, w, h );
4044 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
4045 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
4046 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
4047 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
4049 Refresh( TRUE, &rect );
4052 gdk_gc_unref( m_scrollGC );
4057 // Find the wxWindow at the current mouse position, also returning the mouse
4059 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
4061 pt
= wxGetMousePosition();
4062 wxWindow
* found
= wxFindWindowAtPoint(pt
);
4066 // Get the current mouse position.
4067 wxPoint
wxGetMousePosition()
4069 /* This crashes when used within wxHelpContext,
4070 so we have to use the X-specific implementation below.
4072 GdkModifierType *mask;
4073 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
4075 return wxPoint(x, y);
4079 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
4081 return wxPoint(-999, -999);
4083 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
4084 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
4085 Window rootReturn
, childReturn
;
4086 int rootX
, rootY
, winX
, winY
;
4087 unsigned int maskReturn
;
4089 XQueryPointer (display
,
4093 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
4094 return wxPoint(rootX
, rootY
);