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;
686 if (event
->length
== 1)
688 key_code
= (unsigned char)*event
->string
;
690 else if ((keysym
& 0xFF) == keysym
)
692 key_code
= (guint
)keysym
;
699 //-----------------------------------------------------------------------------
700 // "size_request" of m_widget
701 //-----------------------------------------------------------------------------
703 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
706 win
->GetSize( &w
, &h
);
710 requisition
->height
= h
;
711 requisition
->width
= w
;
714 //-----------------------------------------------------------------------------
715 // "expose_event" of m_wxwindow
716 //-----------------------------------------------------------------------------
718 static int gtk_window_expose_callback( GtkWidget
*widget
,
719 GdkEventExpose
*gdk_event
,
725 wxapp_install_idle_handler();
728 if (win->GetName() == wxT("panel"))
730 wxPrintf( wxT("OnExpose from ") );
731 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
732 wxPrintf( win->GetClassInfo()->GetClassName() );
733 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
734 (int)gdk_event->area.y,
735 (int)gdk_event->area.width,
736 (int)gdk_event->area.height );
740 GtkPizza
*pizza
= GTK_PIZZA (widget
);
742 if (win
->GetThemeEnabled())
744 wxWindow
*parent
= win
->GetParent();
745 while (parent
&& !parent
->IsTopLevel())
746 parent
= parent
->GetParent();
750 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
751 GTK_SHADOW_NONE
, &gdk_event
->area
, parent
->m_widget
, "base", 0, 0, -1, -1);
754 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
756 gdk_event
->area
.width
,
757 gdk_event
->area
.height
);
759 if (gdk_event
->count
== 0)
761 win
->m_clipPaintRegion
= TRUE
;
764 dc
.SetClippingRegion(win
->GetUpdateRegion());
765 wxEraseEvent
eevent( win
->GetId(), &dc
);
766 eevent
.SetEventObject( win
);
768 (void)win
->GetEventHandler()->ProcessEvent(eevent
);
770 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
772 wxClientDC
dc( win
);
773 dc
.SetBrush( wxBrush( win
->GetBackgroundColour(), wxSOLID
) );
774 dc
.SetPen( *wxTRANSPARENT_PEN
);
776 wxRegionIterator
upd( win
->GetUpdateRegion() );
779 dc
.DrawRectangle( upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
785 wxNcPaintEvent
eventNc( win
->GetId() );
786 eventNc
.SetEventObject( win
);
787 win
->GetEventHandler()->ProcessEvent( eventNc
);
789 wxPaintEvent
event( win
->GetId() );
790 event
.SetEventObject( win
);
791 win
->GetEventHandler()->ProcessEvent( event
);
793 win
->GetUpdateRegion().Clear();
795 win
->m_clipPaintRegion
= FALSE
;
798 /* The following code will result in all window-less widgets
799 being redrawn if the wxWindows class is given a chance to
800 paint *anything* because it will then be allowed to paint
801 over the window-less widgets */
802 GList
*children
= pizza
->children
;
805 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
806 children
= children
->next
;
808 GdkEventExpose child_event
= *gdk_event
;
810 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
811 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
812 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
814 child_event
.area
.x
= child
->widget
->allocation
.x
;
815 child_event
.area
.y
= child
->widget
->allocation
.y
;
816 child_event
.area
.width
= child
->widget
->allocation
.width
;
817 child_event
.area
.height
= child
->widget
->allocation
.height
;
818 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
825 //-----------------------------------------------------------------------------
826 // "event" of m_wxwindow
827 //-----------------------------------------------------------------------------
829 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
830 expose events. We need them, of course, so we override the main event
831 procedure in GtkWidget by giving our own handler for all system events.
832 There, we look for expose events ourselves whereas all other events are
835 gint
gtk_window_event_event_callback( GtkWidget
*widget
,
836 GdkEventExpose
*event
,
839 if (event
->type
== GDK_EXPOSE
)
841 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
848 //-----------------------------------------------------------------------------
849 // "draw" of m_wxwindow
850 //-----------------------------------------------------------------------------
852 /* This callback is a complete replacement of the gtk_pizza_draw() function,
855 static void gtk_window_draw_callback( GtkWidget
*widget
,
862 wxapp_install_idle_handler();
864 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
865 (win
->GetChildren().GetCount() == 0))
871 if (win->GetName() == wxT("panel"))
873 wxPrintf( wxT("OnDraw from ") );
874 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
875 wxPrintf( win->GetClassInfo()->GetClassName() );
876 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
883 GtkPizza
*pizza
= GTK_PIZZA (widget
);
885 if (win
->GetThemeEnabled())
887 wxWindow
*parent
= win
->GetParent();
888 while (parent
&& !parent
->IsTopLevel())
889 parent
= parent
->GetParent();
893 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
894 GTK_SHADOW_NONE
, rect
, parent
->m_widget
, "base", 0, 0, -1, -1);
898 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
899 (pizza
->clear_on_draw
))
901 gdk_window_clear_area( pizza
->bin_window
,
902 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
905 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
907 win
->m_clipPaintRegion
= TRUE
;
910 dc
.SetClippingRegion(win
->GetUpdateRegion());
911 wxEraseEvent
eevent( win
->GetId(), &dc
);
912 eevent
.SetEventObject( win
);
915 (void)win
->GetEventHandler()->ProcessEvent(eevent
);
917 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
919 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
921 wxClientDC
dc( win
);
922 dc
.SetBrush( wxBrush( win
->GetBackgroundColour(), wxSOLID
) );
923 dc
.SetPen( *wxTRANSPARENT_PEN
);
925 wxRegionIterator
upd( win
->GetUpdateRegion() );
928 dc
.DrawRectangle( upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
935 wxNcPaintEvent
eventNc( win
->GetId() );
936 eventNc
.SetEventObject( win
);
937 win
->GetEventHandler()->ProcessEvent( eventNc
);
939 wxPaintEvent
event( win
->GetId() );
940 event
.SetEventObject( win
);
941 win
->GetEventHandler()->ProcessEvent( event
);
943 win
->GetUpdateRegion().Clear();
945 win
->m_clipPaintRegion
= FALSE
;
948 GList
*children
= pizza
->children
;
951 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
952 children
= children
->next
;
954 GdkRectangle child_area
;
955 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
957 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
962 //-----------------------------------------------------------------------------
963 // "key_press_event" from any window
964 //-----------------------------------------------------------------------------
966 // turn on to see the key event codes on the console
967 #undef DEBUG_KEY_EVENTS
969 static gint
gtk_window_key_press_callback( GtkWidget
*widget
,
970 GdkEventKey
*gdk_event
,
976 wxapp_install_idle_handler();
978 if (!win
->m_hasVMT
) return FALSE
;
979 if (g_blockEventsOnDrag
) return FALSE
;
984 GdkModifierType state
;
985 if (gdk_event
->window
)
986 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
990 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
992 #ifdef DEBUG_KEY_EVENTS
993 wxPrintf(_T("Key press event: %d => %ld\n"), gdk_event
->keyval
, key_code
);
994 #endif // DEBUG_KEY_EVENTS
996 /* sending unknown key events doesn't really make sense */
1000 wxKeyEvent
event( wxEVT_KEY_DOWN
);
1001 event
.SetTimestamp( gdk_event
->time
);
1002 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1003 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1004 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1005 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1006 event
.m_keyCode
= key_code
;
1007 event
.m_scanCode
= gdk_event
->keyval
;
1010 event
.SetEventObject( win
);
1011 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1016 wxWindowGTK
*ancestor
= win
;
1019 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
1022 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
1023 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
1026 if (ancestor
->IsTopLevel())
1028 ancestor
= ancestor
->GetParent();
1031 #endif // wxUSE_ACCEL
1033 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
1034 will only be sent if it is not in an accelerator table. */
1037 key_code
= map_to_wx_keysym( gdk_event
);
1041 #ifdef DEBUG_KEY_EVENTS
1042 wxPrintf(_T("Char event: %ld\n"), key_code
);
1043 #endif // DEBUG_KEY_EVENTS
1045 // reuse the ame event object, just change its type and use the
1046 // translated keycode instead of the raw one
1047 event
.SetEventType(wxEVT_CHAR
);
1048 event
.m_keyCode
= key_code
;
1050 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1054 /* win is a control: tab can be propagated up */
1056 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
1057 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
1058 // have this style, yet choose not to process this particular TAB in which
1059 // case TAB must still work as a navigational character
1061 !win
->HasFlag(wxTE_PROCESS_TAB
) &&
1063 win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
1065 wxNavigationKeyEvent new_event
;
1066 new_event
.SetEventObject( win
->GetParent() );
1067 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
1068 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
1069 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1070 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
1071 new_event
.SetCurrentFocus( win
);
1072 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
1075 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
1077 (gdk_event
->keyval
== GDK_Escape
) )
1079 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
1080 new_event
.SetEventObject( win
);
1081 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
1085 #if 0 // (GTK_MINOR_VERSION > 0)
1086 /* Pressing F10 will activate the menu bar of the top frame. */
1088 (gdk_event
->keyval
== GDK_F10
) )
1090 wxWindowGTK
*ancestor
= win
;
1093 if (wxIsKindOf(ancestor
,wxFrame
))
1095 wxFrame
*frame
= (wxFrame
*) ancestor
;
1096 wxMenuBar
*menubar
= frame
->GetMenuBar();
1099 wxNode
*node
= menubar
->GetMenus().First();
1102 wxMenu
*firstMenu
= (wxMenu
*) node
->Data();
1103 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu
->m_owner
) );
1109 ancestor
= ancestor
->GetParent();
1116 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1123 //-----------------------------------------------------------------------------
1124 // "key_release_event" from any window
1125 //-----------------------------------------------------------------------------
1127 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindowGTK
*win
)
1132 wxapp_install_idle_handler();
1134 if (!win
->m_hasVMT
) return FALSE
;
1135 if (g_blockEventsOnDrag
) return FALSE
;
1137 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
1139 #ifdef DEBUG_KEY_EVENTS
1140 wxPrintf(_T("Key release event: %d => %ld\n"), gdk_event
->keyval
, key_code
);
1141 #endif // DEBUG_KEY_EVENTS
1143 /* sending unknown key events doesn't really make sense */
1144 if (key_code
== 0) return FALSE
;
1148 GdkModifierType state
;
1149 if (gdk_event
->window
)
1150 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1152 wxKeyEvent
event( wxEVT_KEY_UP
);
1153 event
.SetTimestamp( gdk_event
->time
);
1154 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1155 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1156 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1157 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1158 event
.m_keyCode
= key_code
;
1159 event
.m_scanCode
= gdk_event
->keyval
;
1162 event
.SetEventObject( win
);
1164 if (win
->GetEventHandler()->ProcessEvent( event
))
1166 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1173 // ----------------------------------------------------------------------------
1174 // mouse event processing helper
1175 // ----------------------------------------------------------------------------
1177 static void AdjustEventButtonState(wxMouseEvent
& event
)
1179 // GDK reports the old state of the button for a button press event, but
1180 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1181 // for a LEFT_DOWN event, not FALSE, so we will invert
1182 // left/right/middleDown for the corresponding click events
1184 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1185 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1186 (event
.GetEventType() == wxEVT_LEFT_UP
))
1188 event
.m_leftDown
= !event
.m_leftDown
;
1192 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1193 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1194 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1196 event
.m_middleDown
= !event
.m_middleDown
;
1200 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1201 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1202 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1204 event
.m_rightDown
= !event
.m_rightDown
;
1209 //-----------------------------------------------------------------------------
1210 // "button_press_event"
1211 //-----------------------------------------------------------------------------
1213 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1218 wxapp_install_idle_handler();
1221 wxPrintf( wxT("1) OnButtonPress from ") );
1222 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1223 wxPrintf( win->GetClassInfo()->GetClassName() );
1224 wxPrintf( wxT(".\n") );
1226 if (!win
->m_hasVMT
) return FALSE
;
1227 if (g_blockEventsOnDrag
) return TRUE
;
1228 if (g_blockEventsOnScroll
) return TRUE
;
1230 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1232 if (win
->m_wxwindow
)
1234 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1236 gtk_widget_grab_focus (win
->m_wxwindow
);
1239 wxPrintf( wxT("GrabFocus from ") );
1240 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1241 wxPrintf( win->GetClassInfo()->GetClassName() );
1242 wxPrintf( wxT(".\n") );
1248 wxEventType event_type
= wxEVT_NULL
;
1250 if (gdk_event
->button
== 1)
1252 switch (gdk_event
->type
)
1254 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1255 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1259 else if (gdk_event
->button
== 2)
1261 switch (gdk_event
->type
)
1263 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1264 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1268 else if (gdk_event
->button
== 3)
1270 switch (gdk_event
->type
)
1272 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1273 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1278 if ( event_type
== wxEVT_NULL
)
1280 // unknown mouse button or click type
1284 wxMouseEvent
event( event_type
);
1285 event
.SetTimestamp( gdk_event
->time
);
1286 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1287 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1288 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1289 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1290 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1291 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1292 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1294 event
.m_x
= (wxCoord
)gdk_event
->x
;
1295 event
.m_y
= (wxCoord
)gdk_event
->y
;
1297 AdjustEventButtonState(event
);
1299 // Some control don't have their own X window and thus cannot get
1302 if (!g_captureWindow
)
1304 wxCoord x
= event
.m_x
;
1305 wxCoord y
= event
.m_y
;
1306 if (win
->m_wxwindow
)
1308 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1309 x
+= pizza
->xoffset
;
1310 y
+= pizza
->yoffset
;
1313 wxNode
*node
= win
->GetChildren().First();
1316 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1318 node
= node
->Next();
1319 if (!child
->IsShown())
1322 if (child
->m_isStaticBox
)
1324 // wxStaticBox is transparent in the box itself
1325 int xx1
= child
->m_x
;
1326 int yy1
= child
->m_y
;
1327 int xx2
= child
->m_x
+ child
->m_width
;
1328 int yy2
= child
->m_x
+ child
->m_height
;
1331 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1333 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1335 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1337 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1340 event
.m_x
-= child
->m_x
;
1341 event
.m_y
-= child
->m_y
;
1348 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1349 (child
->m_x
<= x
) &&
1350 (child
->m_y
<= y
) &&
1351 (child
->m_x
+child
->m_width
>= x
) &&
1352 (child
->m_y
+child
->m_height
>= y
))
1355 event
.m_x
-= child
->m_x
;
1356 event
.m_y
-= child
->m_y
;
1363 event
.SetEventObject( win
);
1365 gs_timeLastClick
= gdk_event
->time
;
1368 wxPrintf( wxT("2) OnButtonPress from ") );
1369 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1370 wxPrintf( win->GetClassInfo()->GetClassName() );
1371 wxPrintf( wxT(".\n") );
1374 if (win
->GetEventHandler()->ProcessEvent( event
))
1376 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1383 //-----------------------------------------------------------------------------
1384 // "button_release_event"
1385 //-----------------------------------------------------------------------------
1387 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1392 wxapp_install_idle_handler();
1394 if (!win
->m_hasVMT
) return FALSE
;
1395 if (g_blockEventsOnDrag
) return FALSE
;
1396 if (g_blockEventsOnScroll
) return FALSE
;
1398 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1401 printf( "OnButtonRelease from " );
1402 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1403 printf( win->GetClassInfo()->GetClassName() );
1407 wxEventType event_type
= wxEVT_NULL
;
1409 switch (gdk_event
->button
)
1411 case 1: event_type
= wxEVT_LEFT_UP
; break;
1412 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1413 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1414 default: return FALSE
;
1417 wxMouseEvent
event( event_type
);
1418 event
.SetTimestamp( gdk_event
->time
);
1419 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1420 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1421 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1422 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1423 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1424 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1425 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1426 event
.m_x
= (wxCoord
)gdk_event
->x
;
1427 event
.m_y
= (wxCoord
)gdk_event
->y
;
1429 AdjustEventButtonState(event
);
1431 // Some control don't have their own X window and thus cannot get
1434 if (!g_captureWindow
)
1436 wxCoord x
= event
.m_x
;
1437 wxCoord y
= event
.m_y
;
1438 if (win
->m_wxwindow
)
1440 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1441 x
+= pizza
->xoffset
;
1442 y
+= pizza
->yoffset
;
1445 wxNode
*node
= win
->GetChildren().First();
1448 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1450 node
= node
->Next();
1451 if (!child
->IsShown())
1454 if (child
->m_isStaticBox
)
1456 // wxStaticBox is transparent in the box itself
1457 int xx1
= child
->m_x
;
1458 int yy1
= child
->m_y
;
1459 int xx2
= child
->m_x
+ child
->m_width
;
1460 int yy2
= child
->m_x
+ child
->m_height
;
1463 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1465 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1467 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1469 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1472 event
.m_x
-= child
->m_x
;
1473 event
.m_y
-= child
->m_y
;
1480 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1481 (child
->m_x
<= x
) &&
1482 (child
->m_y
<= y
) &&
1483 (child
->m_x
+child
->m_width
>= x
) &&
1484 (child
->m_y
+child
->m_height
>= y
))
1487 event
.m_x
-= child
->m_x
;
1488 event
.m_y
-= child
->m_y
;
1495 event
.SetEventObject( win
);
1497 if (win
->GetEventHandler()->ProcessEvent( event
))
1499 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1506 // ============================================================================
1508 // ============================================================================
1510 // init wxMouseEvent with the info from gdk_event
1511 #define InitMouseEvent(event, gdk_event) \
1512 event.SetTimestamp( gdk_event->time ); \
1513 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
1514 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
1515 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
1516 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
1517 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
1518 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
1519 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
1521 event.m_x = (wxCoord)gdk_event->x; \
1522 event.m_y = (wxCoord)gdk_event->y \
1524 //-----------------------------------------------------------------------------
1525 // "motion_notify_event"
1526 //-----------------------------------------------------------------------------
1528 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
,
1529 GdkEventMotion
*gdk_event
,
1535 wxapp_install_idle_handler();
1537 if (!win
->m_hasVMT
) return FALSE
;
1538 if (g_blockEventsOnDrag
) return FALSE
;
1539 if (g_blockEventsOnScroll
) return FALSE
;
1541 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1543 if (gdk_event
->is_hint
)
1547 GdkModifierType state
;
1548 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1554 printf( "OnMotion from " );
1555 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1556 printf( win->GetClassInfo()->GetClassName() );
1560 wxMouseEvent
event( wxEVT_MOTION
);
1561 InitMouseEvent(event
, gdk_event
);
1563 if ( g_captureWindow
)
1565 // synthetize a mouse enter or leave event if needed
1566 GdkWindow
*winUnderMouse
= gdk_window_at_pointer(NULL
, NULL
);
1567 bool hasMouse
= winUnderMouse
== gdk_event
->window
;
1568 if ( hasMouse
!= g_captureWindowHasMouse
)
1570 // the mouse changed window
1571 g_captureWindowHasMouse
= hasMouse
;
1573 wxMouseEvent
event(g_captureWindowHasMouse
? wxEVT_ENTER_WINDOW
1574 : wxEVT_LEAVE_WINDOW
);
1575 InitMouseEvent(event
, gdk_event
);
1576 event
.SetEventObject(win
);
1577 win
->GetEventHandler()->ProcessEvent(event
);
1582 // Some control don't have their own X window and thus cannot get
1585 wxCoord x
= event
.m_x
;
1586 wxCoord y
= event
.m_y
;
1587 if (win
->m_wxwindow
)
1589 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1590 x
+= pizza
->xoffset
;
1591 y
+= pizza
->yoffset
;
1594 wxNode
*node
= win
->GetChildren().First();
1597 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1599 node
= node
->Next();
1600 if (!child
->IsShown())
1603 if (child
->m_isStaticBox
)
1605 // wxStaticBox is transparent in the box itself
1606 int xx1
= child
->m_x
;
1607 int yy1
= child
->m_y
;
1608 int xx2
= child
->m_x
+ child
->m_width
;
1609 int yy2
= child
->m_x
+ child
->m_height
;
1612 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1614 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1616 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1618 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1621 event
.m_x
-= child
->m_x
;
1622 event
.m_y
-= child
->m_y
;
1629 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1630 (child
->m_x
<= x
) &&
1631 (child
->m_y
<= y
) &&
1632 (child
->m_x
+child
->m_width
>= x
) &&
1633 (child
->m_y
+child
->m_height
>= y
))
1636 event
.m_x
-= child
->m_x
;
1637 event
.m_y
-= child
->m_y
;
1644 event
.SetEventObject( win
);
1646 if (win
->GetEventHandler()->ProcessEvent( event
))
1648 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1655 //-----------------------------------------------------------------------------
1657 //-----------------------------------------------------------------------------
1659 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
,
1660 GdkEvent
*WXUNUSED(event
),
1666 wxapp_install_idle_handler();
1668 if (!win
->m_hasVMT
) return FALSE
;
1669 if (g_blockEventsOnDrag
) return FALSE
;
1671 switch ( g_sendActivateEvent
)
1674 // we've got focus from outside, synthetize wxActivateEvent
1675 g_sendActivateEvent
= 1;
1679 // another our window just lost focus, it was already ours before
1680 // - don't send any wxActivateEvent
1681 g_sendActivateEvent
= -1;
1686 g_focusWindow
= win
;
1689 wxPrintf( "OnSetFocus from " );
1690 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
1691 wxPrintf( win
->GetClassInfo()->GetClassName() );
1695 // notify the parent keeping track of focus for the kbd navigation
1696 // purposes that we got it
1697 wxChildFocusEvent
eventFocus(win
);
1698 (void)win
->GetEventHandler()->ProcessEvent(eventFocus
);
1702 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1706 // caret needs to be informed about focus change
1707 wxCaret
*caret
= win
->GetCaret();
1710 caret
->OnSetFocus();
1712 #endif // wxUSE_CARET
1714 wxWindowGTK
*active
= wxGetTopLevelParent(win
);
1715 if ( active
!= g_activeFrame
)
1717 if ( g_activeFrame
)
1719 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame
);
1720 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
1721 event
.SetEventObject(g_activeFrame
);
1722 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1725 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active
);
1726 g_activeFrame
= active
;
1727 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId());
1728 event
.SetEventObject(g_activeFrame
);
1729 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1731 g_activeFrameLostFocus
= FALSE
;
1734 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1735 event
.SetEventObject( win
);
1737 if (win
->GetEventHandler()->ProcessEvent( event
))
1739 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1747 //-----------------------------------------------------------------------------
1748 // "focus_out_event"
1749 //-----------------------------------------------------------------------------
1751 static GtkWidget
*gs_widgetLastFocus
= NULL
;
1753 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindowGTK
*win
)
1758 wxapp_install_idle_handler();
1760 if (!win
->m_hasVMT
) return FALSE
;
1761 if (g_blockEventsOnDrag
) return FALSE
;
1763 // VZ: this is really weird but GTK+ seems to call us from inside
1764 // gtk_widget_grab_focus(), i.e. it first sends "focus_out" signal to
1765 // this widget and then "focus_in". This is totally unexpected and
1766 // completely breaks wxUniv code so ignore this dummy event (we can't
1767 // be losing focus if we're about to acquire it!)
1768 if ( widget
== gs_widgetLastFocus
)
1770 gs_widgetLastFocus
= NULL
;
1775 if ( !g_activeFrameLostFocus
&& g_activeFrame
)
1777 wxASSERT_MSG( wxGetTopLevelParent(win
) == g_activeFrame
, wxT("unfocusing window that haven't gained focus properly") )
1778 g_activeFrameLostFocus
= TRUE
;
1781 // if the focus goes out of our app alltogether, OnIdle() will send
1782 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1783 // g_sendActivateEvent to -1
1784 g_sendActivateEvent
= 0;
1786 wxWindowGTK
*winFocus
= wxFindFocusedChild(win
);
1790 g_focusWindow
= (wxWindowGTK
*)NULL
;
1793 wxPrintf( "OnKillFocus from " );
1794 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
1795 wxPrintf( win
->GetClassInfo()->GetClassName() );
1805 // caret needs to be informed about focus change
1806 wxCaret
*caret
= win
->GetCaret();
1809 caret
->OnKillFocus();
1811 #endif // wxUSE_CARET
1813 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1814 event
.SetEventObject( win
);
1816 if (win
->GetEventHandler()->ProcessEvent( event
))
1818 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1825 //-----------------------------------------------------------------------------
1826 // "enter_notify_event"
1827 //-----------------------------------------------------------------------------
1829 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1834 wxapp_install_idle_handler();
1836 if (!win
->m_hasVMT
) return FALSE
;
1837 if (g_blockEventsOnDrag
) return FALSE
;
1839 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1841 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1842 event
.SetTimestamp( gdk_event
->time
);
1843 event
.SetEventObject( win
);
1847 GdkModifierType state
= (GdkModifierType
)0;
1849 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1851 InitMouseEvent(event
, gdk_event
);
1856 if (win
->GetEventHandler()->ProcessEvent( event
))
1858 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1865 //-----------------------------------------------------------------------------
1866 // "leave_notify_event"
1867 //-----------------------------------------------------------------------------
1869 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1874 wxapp_install_idle_handler();
1876 if (!win
->m_hasVMT
) return FALSE
;
1877 if (g_blockEventsOnDrag
) return FALSE
;
1879 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1881 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1882 event
.SetTimestamp( gdk_event
->time
);
1883 event
.SetEventObject( win
);
1887 GdkModifierType state
= (GdkModifierType
)0;
1889 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1891 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1892 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1893 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1894 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1895 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1896 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1897 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1902 if (win
->GetEventHandler()->ProcessEvent( event
))
1904 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1911 //-----------------------------------------------------------------------------
1912 // "value_changed" from m_vAdjust
1913 //-----------------------------------------------------------------------------
1915 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1920 wxapp_install_idle_handler();
1922 if (g_blockEventsOnDrag
) return;
1924 if (!win
->m_hasVMT
) return;
1926 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1927 if (fabs(diff
) < 0.2) return;
1929 win
->m_oldVerticalPos
= adjust
->value
;
1931 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1932 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1934 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1935 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1936 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1937 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1938 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1940 int value
= (int)(adjust
->value
+0.5);
1942 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1943 event
.SetEventObject( win
);
1944 win
->GetEventHandler()->ProcessEvent( event
);
1947 //-----------------------------------------------------------------------------
1948 // "value_changed" from m_hAdjust
1949 //-----------------------------------------------------------------------------
1951 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1956 wxapp_install_idle_handler();
1958 if (g_blockEventsOnDrag
) return;
1959 if (!win
->m_hasVMT
) return;
1961 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1962 if (fabs(diff
) < 0.2) return;
1964 win
->m_oldHorizontalPos
= adjust
->value
;
1966 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1967 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1969 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1970 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1971 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1972 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1973 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1975 int value
= (int)(adjust
->value
+0.5);
1977 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1978 event
.SetEventObject( win
);
1979 win
->GetEventHandler()->ProcessEvent( event
);
1982 //-----------------------------------------------------------------------------
1983 // "button_press_event" from scrollbar
1984 //-----------------------------------------------------------------------------
1986 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1987 GdkEventButton
*gdk_event
,
1993 wxapp_install_idle_handler();
1996 g_blockEventsOnScroll
= TRUE
;
1997 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
2002 //-----------------------------------------------------------------------------
2003 // "button_release_event" from scrollbar
2004 //-----------------------------------------------------------------------------
2006 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
2007 GdkEventButton
*WXUNUSED(gdk_event
),
2012 // don't test here as we can release the mouse while being over
2013 // a different window than the slider
2015 // if (gdk_event->window != widget->slider) return FALSE;
2017 g_blockEventsOnScroll
= FALSE
;
2019 if (win
->m_isScrolling
)
2021 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
2025 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
2026 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
2028 value
= (int)(win
->m_hAdjust
->value
+0.5);
2031 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
2033 value
= (int)(win
->m_vAdjust
->value
+0.5);
2037 wxScrollWinEvent
event( command
, value
, dir
);
2038 event
.SetEventObject( win
);
2039 win
->GetEventHandler()->ProcessEvent( event
);
2042 win
->m_isScrolling
= FALSE
;
2047 // ----------------------------------------------------------------------------
2048 // this wxWindowBase function is implemented here (in platform-specific file)
2049 // because it is static and so couldn't be made virtual
2050 // ----------------------------------------------------------------------------
2052 wxWindow
*wxWindowBase::FindFocus()
2054 // the cast is necessary when we compile in wxUniversal mode
2055 return (wxWindow
*)g_focusWindow
;
2058 //-----------------------------------------------------------------------------
2059 // "realize" from m_widget
2060 //-----------------------------------------------------------------------------
2062 /* We cannot set colours and fonts before the widget has
2063 been realized, so we do this directly after realization. */
2066 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
2071 wxapp_install_idle_handler();
2073 if (win
->m_delayedBackgroundColour
)
2074 win
->SetBackgroundColour( win
->GetBackgroundColour() );
2076 if (win
->m_delayedForegroundColour
)
2077 win
->SetForegroundColour( win
->GetForegroundColour() );
2079 wxWindowCreateEvent
event( win
);
2080 event
.SetEventObject( win
);
2081 win
->GetEventHandler()->ProcessEvent( event
);
2086 //-----------------------------------------------------------------------------
2088 //-----------------------------------------------------------------------------
2091 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
2092 GtkAllocation
*WXUNUSED(alloc
),
2096 wxapp_install_idle_handler();
2098 if (!win
->m_hasScrolling
) return;
2100 int client_width
= 0;
2101 int client_height
= 0;
2102 win
->GetClientSize( &client_width
, &client_height
);
2103 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
2106 win
->m_oldClientWidth
= client_width
;
2107 win
->m_oldClientHeight
= client_height
;
2109 if (!win
->m_nativeSizeEvent
)
2111 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
2112 event
.SetEventObject( win
);
2113 win
->GetEventHandler()->ProcessEvent( event
);
2119 #define WXUNUSED_UNLESS_XIM(param) param
2121 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2124 /* Resize XIM window */
2127 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2128 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
2129 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2132 wxapp_install_idle_handler();
2138 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
2142 gdk_window_get_size (widget
->window
, &width
, &height
);
2143 win
->m_icattr
->preedit_area
.width
= width
;
2144 win
->m_icattr
->preedit_area
.height
= height
;
2145 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2150 //-----------------------------------------------------------------------------
2151 // "realize" from m_wxwindow
2152 //-----------------------------------------------------------------------------
2154 /* Initialize XIM support */
2157 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2158 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2161 wxapp_install_idle_handler();
2164 if (win
->m_ic
) return FALSE
;
2165 if (!widget
) return FALSE
;
2166 if (!gdk_im_ready()) return FALSE
;
2168 win
->m_icattr
= gdk_ic_attr_new();
2169 if (!win
->m_icattr
) return FALSE
;
2173 GdkColormap
*colormap
;
2174 GdkICAttr
*attr
= win
->m_icattr
;
2175 unsigned attrmask
= GDK_IC_ALL_REQ
;
2177 GdkIMStyle supported_style
= (GdkIMStyle
)
2178 (GDK_IM_PREEDIT_NONE
|
2179 GDK_IM_PREEDIT_NOTHING
|
2180 GDK_IM_PREEDIT_POSITION
|
2181 GDK_IM_STATUS_NONE
|
2182 GDK_IM_STATUS_NOTHING
);
2184 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2185 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2187 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2188 attr
->client_window
= widget
->window
;
2190 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2191 gtk_widget_get_default_colormap ())
2193 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2194 attr
->preedit_colormap
= colormap
;
2197 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2198 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2199 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2200 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2202 switch (style
& GDK_IM_PREEDIT_MASK
)
2204 case GDK_IM_PREEDIT_POSITION
:
2205 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2207 g_warning ("over-the-spot style requires fontset");
2211 gdk_window_get_size (widget
->window
, &width
, &height
);
2213 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2214 attr
->spot_location
.x
= 0;
2215 attr
->spot_location
.y
= height
;
2216 attr
->preedit_area
.x
= 0;
2217 attr
->preedit_area
.y
= 0;
2218 attr
->preedit_area
.width
= width
;
2219 attr
->preedit_area
.height
= height
;
2220 attr
->preedit_fontset
= widget
->style
->font
;
2225 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2227 if (win
->m_ic
== NULL
)
2228 g_warning ("Can't create input context.");
2231 mask
= gdk_window_get_events (widget
->window
);
2232 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2233 gdk_window_set_events (widget
->window
, mask
);
2235 if (GTK_WIDGET_HAS_FOCUS(widget
))
2236 gdk_im_begin (win
->m_ic
, widget
->window
);
2243 //-----------------------------------------------------------------------------
2244 // InsertChild for wxWindowGTK.
2245 //-----------------------------------------------------------------------------
2247 /* Callback for wxWindowGTK. This very strange beast has to be used because
2248 * C++ has no virtual methods in a constructor. We have to emulate a
2249 * virtual function here as wxNotebook requires a different way to insert
2250 * a child in it. I had opted for creating a wxNotebookPage window class
2251 * which would have made this superfluous (such in the MDI window system),
2252 * but no-one was listening to me... */
2254 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child
)
2256 /* the window might have been scrolled already, do we
2257 have to adapt the position */
2258 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2259 child
->m_x
+= pizza
->xoffset
;
2260 child
->m_y
+= pizza
->yoffset
;
2262 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2263 GTK_WIDGET(child
->m_widget
),
2270 //-----------------------------------------------------------------------------
2272 //-----------------------------------------------------------------------------
2274 wxWindow
*wxGetActiveWindow()
2276 // the cast is necessary when we compile in wxUniversal mode
2277 return (wxWindow
*)g_focusWindow
;
2280 //-----------------------------------------------------------------------------
2282 //-----------------------------------------------------------------------------
2284 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
2286 #ifdef __WXUNIVERSAL__
2287 IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
)
2289 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2290 #endif // __WXUNIVERSAL__/__WXGTK__
2292 void wxWindowGTK::Init()
2298 m_widget
= (GtkWidget
*) NULL
;
2299 m_wxwindow
= (GtkWidget
*) NULL
;
2300 m_focusWidget
= (GtkWidget
*) NULL
;
2310 m_needParent
= TRUE
;
2311 m_isBeingDeleted
= FALSE
;
2314 m_nativeSizeEvent
= FALSE
;
2316 m_hasScrolling
= FALSE
;
2317 m_isScrolling
= FALSE
;
2319 m_hAdjust
= (GtkAdjustment
*) NULL
;
2320 m_vAdjust
= (GtkAdjustment
*) NULL
;
2321 m_oldHorizontalPos
= 0.0;
2322 m_oldVerticalPos
= 0.0;
2325 m_widgetStyle
= (GtkStyle
*) NULL
;
2327 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2329 m_isStaticBox
= FALSE
;
2330 m_isRadioButton
= FALSE
;
2332 m_acceptsFocus
= FALSE
;
2334 m_clipPaintRegion
= FALSE
;
2336 m_cursor
= *wxSTANDARD_CURSOR
;
2338 m_delayedForegroundColour
= FALSE
;
2339 m_delayedBackgroundColour
= FALSE
;
2342 m_ic
= (GdkIC
*) NULL
;
2343 m_icattr
= (GdkICAttr
*) NULL
;
2347 wxWindowGTK::wxWindowGTK()
2352 wxWindowGTK::wxWindowGTK( wxWindow
*parent
,
2357 const wxString
&name
)
2361 Create( parent
, id
, pos
, size
, style
, name
);
2364 bool wxWindowGTK::Create( wxWindow
*parent
,
2369 const wxString
&name
)
2371 if (!PreCreation( parent
, pos
, size
) ||
2372 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2374 wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
2378 m_insertCallback
= wxInsertChildInWindow
;
2380 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2381 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2383 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2385 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2386 scroll_class
->scrollbar_spacing
= 0;
2388 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2390 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2391 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2393 m_wxwindow
= gtk_pizza_new();
2395 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2397 #ifndef __WXUNIVERSAL__
2398 #if (GTK_MINOR_VERSION > 0)
2399 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2401 if (HasFlag(wxRAISED_BORDER
))
2403 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2405 else if (HasFlag(wxSUNKEN_BORDER
))
2407 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2409 else if (HasFlag(wxSIMPLE_BORDER
))
2411 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2415 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2417 #else // GTK_MINOR_VERSION == 0
2418 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2420 if (HasFlag(wxRAISED_BORDER
))
2422 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2424 else if (HasFlag(wxSUNKEN_BORDER
))
2426 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2430 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2432 #endif // GTK_MINOR_VERSION
2433 #endif // __WXUNIVERSAL__
2435 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2436 m_acceptsFocus
= TRUE
;
2438 #if (GTK_MINOR_VERSION == 0)
2439 // shut the viewport up
2440 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2441 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2442 #endif // GTK_MINOR_VERSION == 0
2444 // I _really_ don't want scrollbars in the beginning
2445 m_vAdjust
->lower
= 0.0;
2446 m_vAdjust
->upper
= 1.0;
2447 m_vAdjust
->value
= 0.0;
2448 m_vAdjust
->step_increment
= 1.0;
2449 m_vAdjust
->page_increment
= 1.0;
2450 m_vAdjust
->page_size
= 5.0;
2451 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2452 m_hAdjust
->lower
= 0.0;
2453 m_hAdjust
->upper
= 1.0;
2454 m_hAdjust
->value
= 0.0;
2455 m_hAdjust
->step_increment
= 1.0;
2456 m_hAdjust
->page_increment
= 1.0;
2457 m_hAdjust
->page_size
= 5.0;
2458 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2460 // these handlers block mouse events to any window during scrolling such as
2461 // motion events and prevent GTK and wxWindows from fighting over where the
2464 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2465 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2467 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2468 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2470 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2471 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2473 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2474 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2476 // these handlers get notified when screen updates are required either when
2477 // scrolling or when the window size (and therefore scrollbar configuration)
2480 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2481 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2482 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2483 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2485 gtk_widget_show( m_wxwindow
);
2488 m_parent
->DoAddChild( this );
2490 m_focusWidget
= m_wxwindow
;
2499 wxWindowGTK::~wxWindowGTK()
2501 if (g_focusWindow
== this)
2502 g_focusWindow
= NULL
;
2504 if (g_activeFrame
== this)
2505 g_activeFrame
= NULL
;
2507 m_isBeingDeleted
= TRUE
;
2516 m_parent
->RemoveChild( this );
2520 gdk_ic_destroy (m_ic
);
2522 gdk_ic_attr_destroy (m_icattr
);
2527 #if DISABLE_STYLE_IF_BROKEN_THEME
2528 // don't delete if it's a pixmap theme style
2529 if (!m_widgetStyle
->engine_data
)
2530 gtk_style_unref( m_widgetStyle
);
2532 m_widgetStyle
= (GtkStyle
*) NULL
;
2537 gtk_widget_destroy( m_wxwindow
);
2538 m_wxwindow
= (GtkWidget
*) NULL
;
2543 gtk_widget_destroy( m_widget
);
2544 m_widget
= (GtkWidget
*) NULL
;
2548 bool wxWindowGTK::PreCreation( wxWindowGTK
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2550 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2552 /* this turns -1 into 20 so that a minimal window is
2553 visible even although -1,-1 has been given as the
2554 size of the window. the same trick is used in other
2555 ports and should make debugging easier */
2556 m_width
= WidthDefault(size
.x
);
2557 m_height
= HeightDefault(size
.y
);
2562 /* some reasonable defaults */
2567 m_x
= (gdk_screen_width () - m_width
) / 2;
2568 if (m_x
< 10) m_x
= 10;
2572 m_y
= (gdk_screen_height () - m_height
) / 2;
2573 if (m_y
< 10) m_y
= 10;
2580 void wxWindowGTK::PostCreation()
2582 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2588 // these get reported to wxWindows -> wxPaintEvent
2590 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2592 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2593 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2595 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2596 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2598 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2600 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2601 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2605 // these are called when the "sunken" or "raised" borders are drawn */
2606 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2607 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2609 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2610 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2615 if (m_focusWidget
== NULL
)
2616 m_focusWidget
= m_widget
;
2619 if (GetClassInfo() && GetClassInfo()->GetClassName())
2620 wxPrintf( GetClassInfo()->GetClassName() );
2624 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event",
2625 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2627 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event",
2628 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2630 // connect to the various key and mouse handlers
2632 GtkWidget
*connect_widget
= GetConnectWidget();
2634 ConnectWidget( connect_widget
);
2636 /* We cannot set colours, fonts and cursors before the widget has
2637 been realized, so we do this directly after realization */
2638 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2639 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2643 // Catch native resize events
2644 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2645 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2647 // Initialize XIM support
2648 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2649 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2651 // And resize XIM window
2652 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2653 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2656 if (!GTK_IS_COMBO(m_widget
))
2658 // This is needed if we want to add our windows into native
2659 // GTK control, such as the toolbar. With this callback, the
2660 // toolbar gets to know the correct size (the one set by the
2661 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2662 // when moving to GTK 2.0.
2663 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2664 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2670 void wxWindowGTK::ConnectWidget( GtkWidget
*widget
)
2672 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2673 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2675 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2676 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2678 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2679 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2681 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2682 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2684 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2685 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2687 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2688 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2690 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2691 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2694 bool wxWindowGTK::Destroy()
2696 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2700 return wxWindowBase::Destroy();
2703 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
)
2705 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2708 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2710 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2711 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") );
2714 printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
2717 if (m_resizing
) return; /* I don't like recursions */
2720 int currentX
, currentY
;
2721 GetPosition(¤tX
, ¤tY
);
2726 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
2728 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2730 /* don't set the size for children of wxNotebook, just take the values. */
2738 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2740 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2742 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2743 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2744 if (width
!= -1) m_width
= width
;
2745 if (height
!= -1) m_height
= height
;
2749 m_x
= x
+ pizza
->xoffset
;
2750 m_y
= y
+ pizza
->yoffset
;
2755 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2757 if (width
== -1) m_width
= 80;
2760 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2762 if (height
== -1) m_height
= 26;
2765 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2766 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2767 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2768 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2771 int bottom_border
= 0;
2773 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2775 /* the default button has a border around it */
2780 DoMoveWindow( m_x
-border
,
2783 m_height
+border
+bottom_border
);
2788 /* Sometimes the client area changes size without the
2789 whole windows's size changing, but if the whole
2790 windows's size doesn't change, no wxSizeEvent will
2791 normally be sent. Here we add an extra test if
2792 the client test has been changed and this will
2794 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2798 wxPrintf( "OnSize sent from " );
2799 if (GetClassInfo() && GetClassInfo()->GetClassName())
2800 wxPrintf( GetClassInfo()->GetClassName() );
2801 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2804 if (!m_nativeSizeEvent
)
2806 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2807 event
.SetEventObject( this );
2808 GetEventHandler()->ProcessEvent( event
);
2814 void wxWindowGTK::OnInternalIdle()
2816 if ( g_sendActivateEvent
!= -1 )
2818 bool activate
= g_sendActivateEvent
!= 0;
2821 g_sendActivateEvent
= -1;
2823 wxTheApp
->SetActive(activate
, (wxWindow
*)g_focusWindowLast
);
2826 if ( g_activeFrameLostFocus
)
2828 if ( g_activeFrame
)
2830 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame
);
2831 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
2832 event
.SetEventObject(g_activeFrame
);
2833 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
2834 g_activeFrame
= NULL
;
2836 g_activeFrameLostFocus
= FALSE
;
2839 wxCursor cursor
= m_cursor
;
2840 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2844 /* I now set the cursor anew in every OnInternalIdle call
2845 as setting the cursor in a parent window also effects the
2846 windows above so that checking for the current cursor is
2851 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2853 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2855 if (!g_globalCursor
.Ok())
2856 cursor
= *wxSTANDARD_CURSOR
;
2858 window
= m_widget
->window
;
2859 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2860 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2866 GdkWindow
*window
= m_widget
->window
;
2867 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2868 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2876 void wxWindowGTK::DoGetSize( int *width
, int *height
) const
2878 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2880 if (width
) (*width
) = m_width
;
2881 if (height
) (*height
) = m_height
;
2884 void wxWindowGTK::DoSetClientSize( int width
, int height
)
2886 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2890 SetSize( width
, height
);
2897 #ifndef __WXUNIVERSAL__
2898 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2900 /* when using GTK 1.2 we set the shadow border size to 2 */
2904 if (HasFlag(wxSIMPLE_BORDER
))
2906 /* when using GTK 1.2 we set the simple border size to 1 */
2910 #endif // __WXUNIVERSAL__
2914 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2916 GtkRequisition vscroll_req
;
2917 vscroll_req
.width
= 2;
2918 vscroll_req
.height
= 2;
2919 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2920 (scroll_window
->vscrollbar
, &vscroll_req
);
2922 GtkRequisition hscroll_req
;
2923 hscroll_req
.width
= 2;
2924 hscroll_req
.height
= 2;
2925 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2926 (scroll_window
->hscrollbar
, &hscroll_req
);
2928 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2930 if (scroll_window
->vscrollbar_visible
)
2932 dw
+= vscroll_req
.width
;
2933 dw
+= scroll_class
->scrollbar_spacing
;
2936 if (scroll_window
->hscrollbar_visible
)
2938 dh
+= hscroll_req
.height
;
2939 dh
+= scroll_class
->scrollbar_spacing
;
2943 SetSize( width
+dw
, height
+dh
);
2947 void wxWindowGTK::DoGetClientSize( int *width
, int *height
) const
2949 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2953 if (width
) (*width
) = m_width
;
2954 if (height
) (*height
) = m_height
;
2961 #ifndef __WXUNIVERSAL__
2962 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2964 /* when using GTK 1.2 we set the shadow border size to 2 */
2968 if (HasFlag(wxSIMPLE_BORDER
))
2970 /* when using GTK 1.2 we set the simple border size to 1 */
2974 #endif // __WXUNIVERSAL__
2978 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2980 GtkRequisition vscroll_req
;
2981 vscroll_req
.width
= 2;
2982 vscroll_req
.height
= 2;
2983 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2984 (scroll_window
->vscrollbar
, &vscroll_req
);
2986 GtkRequisition hscroll_req
;
2987 hscroll_req
.width
= 2;
2988 hscroll_req
.height
= 2;
2989 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2990 (scroll_window
->hscrollbar
, &hscroll_req
);
2992 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2994 if (scroll_window
->vscrollbar_visible
)
2996 dw
+= vscroll_req
.width
;
2997 dw
+= scroll_class
->scrollbar_spacing
;
3000 if (scroll_window
->hscrollbar_visible
)
3002 dh
+= hscroll_req
.height
;
3003 dh
+= scroll_class
->scrollbar_spacing
;
3007 if (width
) (*width
) = m_width
- dw
;
3008 if (height
) (*height
) = m_height
- dh
;
3012 printf( "GetClientSize, name %s ", GetName().c_str() );
3013 if (width) printf( " width = %d", (*width) );
3014 if (height) printf( " height = %d", (*height) );
3019 void wxWindowGTK::DoGetPosition( int *x
, int *y
) const
3021 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3025 if (m_parent
&& m_parent
->m_wxwindow
)
3027 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
3028 dx
= pizza
->xoffset
;
3029 dy
= pizza
->yoffset
;
3032 if (x
) (*x
) = m_x
- dx
;
3033 if (y
) (*y
) = m_y
- dy
;
3036 void wxWindowGTK::DoClientToScreen( int *x
, int *y
) const
3038 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3040 if (!m_widget
->window
) return;
3042 GdkWindow
*source
= (GdkWindow
*) NULL
;
3044 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3046 source
= m_widget
->window
;
3050 gdk_window_get_origin( source
, &org_x
, &org_y
);
3054 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3056 org_x
+= m_widget
->allocation
.x
;
3057 org_y
+= m_widget
->allocation
.y
;
3065 void wxWindowGTK::DoScreenToClient( int *x
, int *y
) const
3067 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3069 if (!m_widget
->window
) return;
3071 GdkWindow
*source
= (GdkWindow
*) NULL
;
3073 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3075 source
= m_widget
->window
;
3079 gdk_window_get_origin( source
, &org_x
, &org_y
);
3083 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3085 org_x
+= m_widget
->allocation
.x
;
3086 org_y
+= m_widget
->allocation
.y
;
3094 bool wxWindowGTK::Show( bool show
)
3096 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3098 if (!wxWindowBase::Show(show
))
3105 gtk_widget_show( m_widget
);
3107 gtk_widget_hide( m_widget
);
3112 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
)
3114 win
->OnParentEnable(enable
);
3116 // Recurse, so that children have the opportunity to Do The Right Thing
3117 // and reset colours that have been messed up by a parent's (really ancestor's)
3119 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
3121 node
= node
->GetNext() )
3123 wxWindow
*child
= node
->GetData();
3124 if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
)))
3125 wxWindowNotifyEnable(child
, enable
);
3129 bool wxWindowGTK::Enable( bool enable
)
3131 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3133 if (!wxWindowBase::Enable(enable
))
3139 gtk_widget_set_sensitive( m_widget
, enable
);
3141 gtk_widget_set_sensitive( m_wxwindow
, enable
);
3143 wxWindowNotifyEnable(this, enable
);
3148 int wxWindowGTK::GetCharHeight() const
3150 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
3152 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
3154 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3156 return font
->ascent
+ font
->descent
;
3159 int wxWindowGTK::GetCharWidth() const
3161 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
3163 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
3165 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3167 return gdk_string_width( font
, "H" );
3170 void wxWindowGTK::GetTextExtent( const wxString
& string
,
3174 int *externalLeading
,
3175 const wxFont
*theFont
) const
3177 wxFont fontToUse
= m_font
;
3178 if (theFont
) fontToUse
= *theFont
;
3180 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
3182 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
3183 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
3184 if (y
) (*y
) = font
->ascent
+ font
->descent
;
3185 if (descent
) (*descent
) = font
->descent
;
3186 if (externalLeading
) (*externalLeading
) = 0; // ??
3189 void wxWindowGTK::SetFocus()
3191 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3195 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3197 // see comment in gtk_window_focus_out_callback()
3198 gs_widgetLastFocus
= m_wxwindow
;
3199 gtk_widget_grab_focus (m_wxwindow
);
3204 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
3206 gtk_widget_grab_focus (m_widget
);
3208 else if (GTK_IS_CONTAINER(m_widget
))
3210 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
3219 bool wxWindowGTK::AcceptsFocus() const
3221 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3224 bool wxWindowGTK::Reparent( wxWindowBase
*newParentBase
)
3226 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3228 wxWindowGTK
*oldParent
= m_parent
,
3229 *newParent
= (wxWindowGTK
*)newParentBase
;
3231 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3233 if ( !wxWindowBase::Reparent(newParent
) )
3236 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3238 /* prevent GTK from deleting the widget arbitrarily */
3239 gtk_widget_ref( m_widget
);
3243 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3246 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3250 /* insert GTK representation */
3251 (*(newParent
->m_insertCallback
))(newParent
, this);
3254 /* reverse: prevent GTK from deleting the widget arbitrarily */
3255 gtk_widget_unref( m_widget
);
3260 void wxWindowGTK::DoAddChild(wxWindowGTK
*child
)
3262 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3264 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3266 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3271 /* insert GTK representation */
3272 (*m_insertCallback
)(this, child
);
3275 void wxWindowGTK::Raise()
3277 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3279 if (!m_widget
->window
) return;
3281 gdk_window_raise( m_widget
->window
);
3284 void wxWindowGTK::Lower()
3286 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3288 if (!m_widget
->window
) return;
3290 gdk_window_lower( m_widget
->window
);
3293 bool wxWindowGTK::SetCursor( const wxCursor
&cursor
)
3295 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3297 if (cursor
== m_cursor
)
3301 wxapp_install_idle_handler();
3303 if (cursor
== wxNullCursor
)
3304 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3306 return wxWindowBase::SetCursor( cursor
);
3309 void wxWindowGTK::WarpPointer( int x
, int y
)
3311 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3313 /* we provide this function ourselves as it is
3314 missing in GDK (top of this file) */
3316 GdkWindow
*window
= (GdkWindow
*) NULL
;
3318 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3320 window
= GetConnectWidget()->window
;
3323 gdk_window_warp_pointer( window
, x
, y
);
3326 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect
*rect
)
3328 if (!m_widget
) return;
3329 if (!m_widget
->window
) return;
3331 // temporarily hide the caret to avoid nasty interactions between caret
3332 // drawing and the window contents redraw
3333 #if 0 // def wxUSE_CARET -- doesn't seem to help :-(
3334 wxCaretSuspend
cs((wxWindow
*)this);
3335 #endif // wxUSE_CARET
3337 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3341 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3343 rect
->width
, rect
->height
);
3347 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3351 /* there is no GTK equivalent of "draw only, don't clear" so we
3352 invent our own in the GtkPizza widget */
3360 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3361 gboolean old_clear = pizza->clear_on_draw;
3362 gtk_pizza_set_clear( pizza, FALSE );
3363 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3364 gtk_pizza_set_clear( pizza, old_clear );
3366 GdkEventExpose gdk_event
;
3367 gdk_event
.type
= GDK_EXPOSE
;
3368 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3369 gdk_event
.count
= 0;
3370 gdk_event
.area
.x
= 0;
3371 gdk_event
.area
.y
= 0;
3372 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3373 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3374 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, (wxWindow
*)this );
3378 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3387 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3388 gboolean old_clear = pizza->clear_on_draw;
3389 gtk_pizza_set_clear( pizza, FALSE );
3391 GdkRectangle gdk_rect;
3392 gdk_rect.x = rect->x;
3393 gdk_rect.y = rect->y;
3394 gdk_rect.width = rect->width;
3395 gdk_rect.height = rect->height;
3396 gtk_widget_draw( m_wxwindow, &gdk_rect );
3397 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3399 gtk_pizza_set_clear( pizza, old_clear );
3401 GdkEventExpose gdk_event
;
3402 gdk_event
.type
= GDK_EXPOSE
;
3403 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3404 gdk_event
.count
= 0;
3405 gdk_event
.area
.x
= rect
->x
;
3406 gdk_event
.area
.y
= rect
->y
;
3407 gdk_event
.area
.width
= rect
->width
;
3408 gdk_event
.area
.height
= rect
->height
;
3409 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, (wxWindow
*)this );
3413 GdkRectangle gdk_rect
;
3414 gdk_rect
.x
= rect
->x
;
3415 gdk_rect
.y
= rect
->y
;
3416 gdk_rect
.width
= rect
->width
;
3417 gdk_rect
.height
= rect
->height
;
3418 gtk_widget_draw( m_widget
, &gdk_rect
);
3423 void wxWindowGTK::Clear()
3425 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3427 if (!m_widget
->window
) return;
3429 if (m_wxwindow
&& m_wxwindow
->window
)
3431 // gdk_window_clear( m_wxwindow->window );
3436 void wxWindowGTK::DoSetToolTip( wxToolTip
*tip
)
3438 wxWindowBase::DoSetToolTip(tip
);
3441 m_tooltip
->Apply( (wxWindow
*)this );
3444 void wxWindowGTK::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3446 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3448 #endif // wxUSE_TOOLTIPS
3450 bool wxWindowGTK::SetBackgroundColour( const wxColour
&colour
)
3452 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3454 if (!wxWindowBase::SetBackgroundColour(colour
))
3456 // don't leave if the GTK widget has just
3458 if (!m_delayedBackgroundColour
) return FALSE
;
3461 GdkWindow
*window
= (GdkWindow
*) NULL
;
3463 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3465 window
= GetConnectWidget()->window
;
3469 // indicate that a new style has been set
3470 // but it couldn't get applied as the
3471 // widget hasn't been realized yet.
3472 m_delayedBackgroundColour
= TRUE
;
3476 (m_wxwindow
->window
) &&
3477 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3479 /* wxMSW doesn't clear the window here. I don't do that either to
3480 provide compatibility. call Clear() to do the job. */
3482 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3483 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3491 bool wxWindowGTK::SetForegroundColour( const wxColour
&colour
)
3493 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3495 if (!wxWindowBase::SetForegroundColour(colour
))
3497 // don't leave if the GTK widget has just
3499 if (!m_delayedForegroundColour
) return FALSE
;
3502 GdkWindow
*window
= (GdkWindow
*) NULL
;
3504 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3506 window
= GetConnectWidget()->window
;
3510 // indicate that a new style has been set
3511 // but it couldn't get applied as the
3512 // widget hasn't been realized yet.
3513 m_delayedForegroundColour
= TRUE
;
3521 GtkStyle
*wxWindowGTK::GetWidgetStyle()
3525 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3527 /* FIXME: is this necessary? */
3528 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3530 remake
->klass
= m_widgetStyle
->klass
;
3533 gtk_style_unref( m_widgetStyle
);
3534 m_widgetStyle
= remake
;
3538 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3541 def
= gtk_widget_get_default_style();
3543 m_widgetStyle
= gtk_style_copy( def
);
3545 /* FIXME: is this necessary? */
3546 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3548 m_widgetStyle
->klass
= def
->klass
;
3552 return m_widgetStyle
;
3555 void wxWindowGTK::SetWidgetStyle()
3557 #if DISABLE_STYLE_IF_BROKEN_THEM
3558 if (m_widget
->style
->engine_data
)
3560 static bool s_warningPrinted
= FALSE
;
3561 if (!s_warningPrinted
)
3563 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3564 s_warningPrinted
= TRUE
;
3566 m_widgetStyle
= m_widget
->style
;
3571 GtkStyle
*style
= GetWidgetStyle();
3573 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3575 gdk_font_unref( style
->font
);
3576 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3579 if (m_foregroundColour
.Ok())
3581 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3582 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3584 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3585 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3586 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3590 // Try to restore the gtk default style. This is still a little
3591 // oversimplified for what is probably really needed here for controls
3592 // other than buttons, but is better than not being able to (re)set a
3593 // control's foreground colour to *wxBLACK -- RL
3594 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3597 def
= gtk_widget_get_default_style();
3599 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3600 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3601 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3605 if (m_backgroundColour
.Ok())
3607 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3608 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3610 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3611 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3612 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3613 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3614 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3615 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3616 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3617 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3621 // Try to restore the gtk default style. This is still a little
3622 // oversimplified for what is probably really needed here for controls
3623 // other than buttons, but is better than not being able to (re)set a
3624 // control's background colour to default grey and means resetting a
3625 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3627 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3630 def
= gtk_widget_get_default_style();
3632 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3633 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3634 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3635 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3636 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3637 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3638 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3639 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3644 void wxWindowGTK::ApplyWidgetStyle()
3648 //-----------------------------------------------------------------------------
3649 // Pop-up menu stuff
3650 //-----------------------------------------------------------------------------
3652 #if wxUSE_MENUS_NATIVE
3654 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3656 *is_waiting
= FALSE
;
3659 static void SetInvokingWindow( wxMenu
*menu
, wxWindowGTK
*win
)
3661 menu
->SetInvokingWindow( win
);
3662 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3665 wxMenuItem
*menuitem
= node
->GetData();
3666 if (menuitem
->IsSubMenu())
3668 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3671 node
= node
->GetNext();
3675 static gint gs_pop_x
= 0;
3676 static gint gs_pop_y
= 0;
3678 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3682 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3687 bool wxWindowGTK::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3689 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3691 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3693 SetInvokingWindow( menu
, this );
3700 bool is_waiting
= TRUE
;
3702 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3703 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3706 GTK_MENU(menu
->m_menu
),
3707 (GtkWidget
*) NULL
, // parent menu shell
3708 (GtkWidget
*) NULL
, // parent menu item
3709 (GtkMenuPositionFunc
) pop_pos_callback
,
3710 (gpointer
) this, // client data
3711 0, // button used to activate it
3712 gs_timeLastClick
// the time of activation
3717 while (gtk_events_pending())
3718 gtk_main_iteration();
3724 #endif // wxUSE_MENUS_NATIVE
3726 #if wxUSE_DRAG_AND_DROP
3728 void wxWindowGTK::SetDropTarget( wxDropTarget
*dropTarget
)
3730 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3732 GtkWidget
*dnd_widget
= GetConnectWidget();
3734 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3736 if (m_dropTarget
) delete m_dropTarget
;
3737 m_dropTarget
= dropTarget
;
3739 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3742 #endif // wxUSE_DRAG_AND_DROP
3744 GtkWidget
* wxWindowGTK::GetConnectWidget()
3746 GtkWidget
*connect_widget
= m_widget
;
3747 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3749 return connect_widget
;
3752 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow
*window
)
3755 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3757 return (window
== m_widget
->window
);
3760 bool wxWindowGTK::SetFont( const wxFont
&font
)
3762 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3764 if (!wxWindowBase::SetFont(font
))
3769 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3770 if ( sysbg
== m_backgroundColour
)
3772 m_backgroundColour
= wxNullColour
;
3774 m_backgroundColour
= sysbg
;
3784 void wxWindowGTK::CaptureMouse()
3786 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3788 GdkWindow
*window
= (GdkWindow
*) NULL
;
3790 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3792 window
= GetConnectWidget()->window
;
3794 wxCHECK_RET( window
, _T("CaptureMouse() failed") );
3796 wxCursor
* cursor
= & m_cursor
;
3798 cursor
= wxSTANDARD_CURSOR
;
3800 gdk_pointer_grab( window
, FALSE
,
3802 (GDK_BUTTON_PRESS_MASK
|
3803 GDK_BUTTON_RELEASE_MASK
|
3804 GDK_POINTER_MOTION_HINT_MASK
|
3805 GDK_POINTER_MOTION_MASK
),
3807 cursor
->GetCursor(),
3808 (guint32
)GDK_CURRENT_TIME
);
3809 g_captureWindow
= this;
3810 g_captureWindowHasMouse
= TRUE
;
3813 void wxWindowGTK::ReleaseMouse()
3815 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3817 wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") );
3819 GdkWindow
*window
= (GdkWindow
*) NULL
;
3821 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3823 window
= GetConnectWidget()->window
;
3828 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3829 g_captureWindow
= (wxWindowGTK
*) NULL
;
3833 wxWindow
*wxWindowBase::GetCapture()
3835 return (wxWindow
*)g_captureWindow
;
3838 bool wxWindowGTK::IsRetained() const
3843 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3844 int range
, bool refresh
)
3846 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3848 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3850 m_hasScrolling
= TRUE
;
3852 if (orient
== wxHORIZONTAL
)
3854 float fpos
= (float)pos
;
3855 float frange
= (float)range
;
3856 float fthumb
= (float)thumbVisible
;
3857 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3858 if (fpos
< 0.0) fpos
= 0.0;
3860 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3861 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3863 SetScrollPos( orient
, pos
, refresh
);
3867 m_oldHorizontalPos
= fpos
;
3869 m_hAdjust
->lower
= 0.0;
3870 m_hAdjust
->upper
= frange
;
3871 m_hAdjust
->value
= fpos
;
3872 m_hAdjust
->step_increment
= 1.0;
3873 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3874 m_hAdjust
->page_size
= fthumb
;
3878 float fpos
= (float)pos
;
3879 float frange
= (float)range
;
3880 float fthumb
= (float)thumbVisible
;
3881 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3882 if (fpos
< 0.0) fpos
= 0.0;
3884 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3885 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3887 SetScrollPos( orient
, pos
, refresh
);
3891 m_oldVerticalPos
= fpos
;
3893 m_vAdjust
->lower
= 0.0;
3894 m_vAdjust
->upper
= frange
;
3895 m_vAdjust
->value
= fpos
;
3896 m_vAdjust
->step_increment
= 1.0;
3897 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3898 m_vAdjust
->page_size
= fthumb
;
3901 if (orient
== wxHORIZONTAL
)
3902 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3904 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3907 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3909 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3911 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3913 if (orient
== wxHORIZONTAL
)
3915 float fpos
= (float)pos
;
3916 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3917 if (fpos
< 0.0) fpos
= 0.0;
3918 m_oldHorizontalPos
= fpos
;
3920 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3921 m_hAdjust
->value
= fpos
;
3925 float fpos
= (float)pos
;
3926 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3927 if (fpos
< 0.0) fpos
= 0.0;
3928 m_oldVerticalPos
= fpos
;
3930 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3931 m_vAdjust
->value
= fpos
;
3934 if (m_wxwindow
->window
)
3936 if (orient
== wxHORIZONTAL
)
3938 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3939 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3941 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3943 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3944 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3948 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3949 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3951 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3953 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3954 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3959 int wxWindowGTK::GetScrollThumb( int orient
) const
3961 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3963 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3965 if (orient
== wxHORIZONTAL
)
3966 return (int)(m_hAdjust
->page_size
+0.5);
3968 return (int)(m_vAdjust
->page_size
+0.5);
3971 int wxWindowGTK::GetScrollPos( int orient
) const
3973 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3975 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3977 if (orient
== wxHORIZONTAL
)
3978 return (int)(m_hAdjust
->value
+0.5);
3980 return (int)(m_vAdjust
->value
+0.5);
3983 int wxWindowGTK::GetScrollRange( int orient
) const
3985 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3987 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3989 if (orient
== wxHORIZONTAL
)
3990 return (int)(m_hAdjust
->upper
+0.5);
3992 return (int)(m_vAdjust
->upper
+0.5);
3995 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3997 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3999 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4001 if ((dx
== 0) && (dy
== 0)) return;
4003 m_clipPaintRegion
= TRUE
;
4004 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
4005 m_clipPaintRegion
= FALSE
;
4008 if (m_children.GetCount() > 0)
4010 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
4014 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
4016 pizza->xoffset -= dx;
4017 pizza->yoffset -= dy;
4019 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
4020 gdk_gc_set_exposures( m_scrollGC, TRUE );
4024 GetClientSize( &cw, &ch );
4025 int w = cw - abs(dx);
4026 int h = ch - abs(dy);
4028 if ((h < 0) || (w < 0))
4036 if (dx < 0) s_x = -dx;
4037 if (dy < 0) s_y = -dy;
4040 if (dx > 0) d_x = dx;
4041 if (dy > 0) d_y = dy;
4043 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
4044 pizza->bin_window, s_x, s_y, w, h );
4047 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
4048 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
4049 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
4050 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
4052 Refresh( TRUE, &rect );
4055 gdk_gc_unref( m_scrollGC );
4060 // Find the wxWindow at the current mouse position, also returning the mouse
4062 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
4064 pt
= wxGetMousePosition();
4065 wxWindow
* found
= wxFindWindowAtPoint(pt
);
4069 // Get the current mouse position.
4070 wxPoint
wxGetMousePosition()
4072 /* This crashes when used within wxHelpContext,
4073 so we have to use the X-specific implementation below.
4075 GdkModifierType *mask;
4076 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
4078 return wxPoint(x, y);
4082 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
4084 return wxPoint(-999, -999);
4086 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
4087 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
4088 Window rootReturn
, childReturn
;
4089 int rootX
, rootY
, winX
, winY
;
4090 unsigned int maskReturn
;
4092 XQueryPointer (display
,
4096 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
4097 return wxPoint(rootX
, rootY
);