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;
585 if (event
->length
== 1)
587 key_code
= toupper( (unsigned char)*event
->string
);
589 else if ((keysym
& 0xFF) == keysym
)
591 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
592 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
593 key_code
= (guint
)keysym
;
601 static long map_to_wx_keysym( GdkEventKey
*event
)
603 KeySym keysym
= event
->keyval
;
608 case GDK_Menu
: key_code
= WXK_MENU
; break;
609 case GDK_Help
: key_code
= WXK_HELP
; break;
610 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
611 case GDK_ISO_Left_Tab
:
612 case GDK_Tab
: key_code
= WXK_TAB
; break;
613 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
614 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
615 case GDK_Return
: key_code
= WXK_RETURN
; break;
616 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
617 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
618 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
619 case GDK_Delete
: key_code
= WXK_DELETE
; break;
620 case GDK_Home
: key_code
= WXK_HOME
; break;
621 case GDK_Left
: key_code
= WXK_LEFT
; break;
622 case GDK_Up
: key_code
= WXK_UP
; break;
623 case GDK_Right
: key_code
= WXK_RIGHT
; break;
624 case GDK_Down
: key_code
= WXK_DOWN
; break;
625 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
626 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
627 case GDK_Next
: key_code
= WXK_NEXT
; break;
628 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
629 case GDK_End
: key_code
= WXK_END
; break;
630 case GDK_Begin
: key_code
= WXK_HOME
; break;
631 case GDK_Select
: key_code
= WXK_SELECT
; break;
632 case GDK_Print
: key_code
= WXK_PRINT
; break;
633 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
634 case GDK_Insert
: key_code
= WXK_INSERT
; break;
635 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
637 case GDK_KP_0
: key_code
= '0'; break;
638 case GDK_KP_1
: key_code
= '1'; break;
639 case GDK_KP_2
: key_code
= '2'; break;
640 case GDK_KP_3
: key_code
= '3'; break;
641 case GDK_KP_4
: key_code
= '4'; break;
642 case GDK_KP_5
: key_code
= '5'; break;
643 case GDK_KP_6
: key_code
= '6'; break;
644 case GDK_KP_7
: key_code
= '7'; break;
645 case GDK_KP_8
: key_code
= '8'; break;
646 case GDK_KP_9
: key_code
= '9'; break;
647 case GDK_KP_Space
: key_code
= ' '; break;
648 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
649 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
650 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
651 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
652 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
653 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
654 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
655 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
656 case GDK_KP_Up
: key_code
= WXK_UP
; break;
657 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
658 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
659 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
660 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
661 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
662 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
663 case GDK_KP_End
: key_code
= WXK_END
; break;
664 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
665 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
666 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
667 case GDK_KP_Equal
: key_code
= '='; break;
668 case GDK_KP_Multiply
: key_code
= '*'; break;
669 case GDK_KP_Add
: key_code
= '+'; break;
670 case GDK_KP_Separator
: key_code
= ','; break;
671 case GDK_KP_Subtract
: key_code
= '-'; break;
672 case GDK_KP_Decimal
: key_code
= '.'; break;
673 case GDK_KP_Divide
: key_code
= '/'; break;
675 case GDK_F1
: key_code
= WXK_F1
; break;
676 case GDK_F2
: key_code
= WXK_F2
; break;
677 case GDK_F3
: key_code
= WXK_F3
; break;
678 case GDK_F4
: key_code
= WXK_F4
; break;
679 case GDK_F5
: key_code
= WXK_F5
; break;
680 case GDK_F6
: key_code
= WXK_F6
; break;
681 case GDK_F7
: key_code
= WXK_F7
; break;
682 case GDK_F8
: key_code
= WXK_F8
; break;
683 case GDK_F9
: key_code
= WXK_F9
; break;
684 case GDK_F10
: key_code
= WXK_F10
; break;
685 case GDK_F11
: key_code
= WXK_F11
; break;
686 case GDK_F12
: key_code
= WXK_F12
; break;
689 if (event
->length
== 1)
691 key_code
= (unsigned char)*event
->string
;
693 else if ((keysym
& 0xFF) == keysym
)
695 key_code
= (guint
)keysym
;
703 //-----------------------------------------------------------------------------
704 // "size_request" of m_widget
705 //-----------------------------------------------------------------------------
707 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
710 win
->GetSize( &w
, &h
);
714 requisition
->height
= h
;
715 requisition
->width
= w
;
718 //-----------------------------------------------------------------------------
719 // "expose_event" of m_wxwindow
720 //-----------------------------------------------------------------------------
722 static int gtk_window_expose_callback( GtkWidget
*widget
,
723 GdkEventExpose
*gdk_event
,
729 wxapp_install_idle_handler();
732 if (win->GetName() == wxT("panel"))
734 wxPrintf( wxT("OnExpose from ") );
735 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
736 wxPrintf( win->GetClassInfo()->GetClassName() );
737 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
738 (int)gdk_event->area.y,
739 (int)gdk_event->area.width,
740 (int)gdk_event->area.height );
744 GtkPizza
*pizza
= GTK_PIZZA (widget
);
746 if (win
->GetThemeEnabled())
748 wxWindow
*parent
= win
->GetParent();
749 while (parent
&& !parent
->IsTopLevel())
750 parent
= parent
->GetParent();
754 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
755 GTK_SHADOW_NONE
, &gdk_event
->area
, parent
->m_widget
, "base", 0, 0, -1, -1);
758 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
760 gdk_event
->area
.width
,
761 gdk_event
->area
.height
);
763 if (gdk_event
->count
== 0)
765 win
->m_clipPaintRegion
= TRUE
;
768 dc
.SetClippingRegion(win
->GetUpdateRegion());
769 wxEraseEvent
eevent( win
->GetId(), &dc
);
770 eevent
.SetEventObject( win
);
772 (void)win
->GetEventHandler()->ProcessEvent(eevent
);
774 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
776 wxClientDC
dc( win
);
777 dc
.SetBrush( wxBrush( win
->GetBackgroundColour(), wxSOLID
) );
778 dc
.SetPen( *wxTRANSPARENT_PEN
);
780 wxRegionIterator
upd( win
->GetUpdateRegion() );
783 dc
.DrawRectangle( upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
789 wxNcPaintEvent
eventNc( win
->GetId() );
790 eventNc
.SetEventObject( win
);
791 win
->GetEventHandler()->ProcessEvent( eventNc
);
793 wxPaintEvent
event( win
->GetId() );
794 event
.SetEventObject( win
);
795 win
->GetEventHandler()->ProcessEvent( event
);
797 win
->GetUpdateRegion().Clear();
799 win
->m_clipPaintRegion
= FALSE
;
802 /* The following code will result in all window-less widgets
803 being redrawn if the wxWindows class is given a chance to
804 paint *anything* because it will then be allowed to paint
805 over the window-less widgets */
806 GList
*children
= pizza
->children
;
809 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
810 children
= children
->next
;
812 GdkEventExpose child_event
= *gdk_event
;
814 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
815 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
816 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
818 child_event
.area
.x
= child
->widget
->allocation
.x
;
819 child_event
.area
.y
= child
->widget
->allocation
.y
;
820 child_event
.area
.width
= child
->widget
->allocation
.width
;
821 child_event
.area
.height
= child
->widget
->allocation
.height
;
822 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
829 //-----------------------------------------------------------------------------
830 // "event" of m_wxwindow
831 //-----------------------------------------------------------------------------
833 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
834 expose events. We need them, of course, so we override the main event
835 procedure in GtkWidget by giving our own handler for all system events.
836 There, we look for expose events ourselves whereas all other events are
839 gint
gtk_window_event_event_callback( GtkWidget
*widget
,
840 GdkEventExpose
*event
,
843 if (event
->type
== GDK_EXPOSE
)
845 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
852 //-----------------------------------------------------------------------------
853 // "draw" of m_wxwindow
854 //-----------------------------------------------------------------------------
856 /* This callback is a complete replacement of the gtk_pizza_draw() function,
859 static void gtk_window_draw_callback( GtkWidget
*widget
,
866 wxapp_install_idle_handler();
868 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
869 (win
->GetChildren().GetCount() == 0))
875 if (win->GetName() == wxT("panel"))
877 wxPrintf( wxT("OnDraw from ") );
878 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
879 wxPrintf( win->GetClassInfo()->GetClassName() );
880 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
887 GtkPizza
*pizza
= GTK_PIZZA (widget
);
889 if (win
->GetThemeEnabled())
891 wxWindow
*parent
= win
->GetParent();
892 while (parent
&& !parent
->IsTopLevel())
893 parent
= parent
->GetParent();
897 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
898 GTK_SHADOW_NONE
, rect
, parent
->m_widget
, "base", 0, 0, -1, -1);
902 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
903 (pizza
->clear_on_draw
))
905 gdk_window_clear_area( pizza
->bin_window
,
906 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
909 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
911 win
->m_clipPaintRegion
= TRUE
;
914 dc
.SetClippingRegion(win
->GetUpdateRegion());
915 wxEraseEvent
eevent( win
->GetId(), &dc
);
916 eevent
.SetEventObject( win
);
919 (void)win
->GetEventHandler()->ProcessEvent(eevent
);
921 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
923 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
925 wxClientDC
dc( win
);
926 dc
.SetBrush( wxBrush( win
->GetBackgroundColour(), wxSOLID
) );
927 dc
.SetPen( *wxTRANSPARENT_PEN
);
929 wxRegionIterator
upd( win
->GetUpdateRegion() );
932 dc
.DrawRectangle( upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
939 wxNcPaintEvent
eventNc( win
->GetId() );
940 eventNc
.SetEventObject( win
);
941 win
->GetEventHandler()->ProcessEvent( eventNc
);
943 wxPaintEvent
event( win
->GetId() );
944 event
.SetEventObject( win
);
945 win
->GetEventHandler()->ProcessEvent( event
);
947 win
->GetUpdateRegion().Clear();
949 win
->m_clipPaintRegion
= FALSE
;
952 GList
*children
= pizza
->children
;
955 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
956 children
= children
->next
;
958 GdkRectangle child_area
;
959 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
961 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
966 //-----------------------------------------------------------------------------
967 // "key_press_event" from any window
968 //-----------------------------------------------------------------------------
970 static gint
gtk_window_key_press_callback( GtkWidget
*widget
,
971 GdkEventKey
*gdk_event
,
977 wxapp_install_idle_handler();
979 if (!win
->m_hasVMT
) return FALSE
;
980 if (g_blockEventsOnDrag
) return FALSE
;
985 tmp += (char)gdk_event->keyval;
986 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
987 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
992 GdkModifierType state
;
993 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
997 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
998 /* sending unknown key events doesn't really make sense */
999 if (key_code
== 0) return FALSE
;
1001 wxKeyEvent
event( wxEVT_KEY_DOWN
);
1002 event
.SetTimestamp( gdk_event
->time
);
1003 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1004 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1005 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1006 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1007 event
.m_keyCode
= key_code
;
1008 event
.m_scanCode
= gdk_event
->keyval
;
1011 event
.SetEventObject( win
);
1012 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1017 wxWindowGTK
*ancestor
= win
;
1020 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
1023 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
1024 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
1027 if (ancestor
->IsTopLevel())
1029 ancestor
= ancestor
->GetParent();
1032 #endif // wxUSE_ACCEL
1034 /* wxMSW doesn't send char events with Alt pressed */
1035 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
1036 will only be sent if it is not in an accelerator table. */
1037 key_code
= map_to_wx_keysym( gdk_event
);
1042 wxKeyEvent
event2( wxEVT_CHAR
);
1043 event2
.SetTimestamp( gdk_event
->time
);
1044 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1045 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1046 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1047 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1048 event2
.m_keyCode
= key_code
;
1049 event2
.m_scanCode
= gdk_event
->keyval
;
1052 event2
.SetEventObject( win
);
1053 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
1056 /* win is a control: tab can be propagated up */
1058 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
1059 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
1060 // have this style, yet choose not to process this particular TAB in which
1061 // case TAB must still work as a navigational character
1063 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
1065 (win
->GetParent()) &&
1066 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
1068 wxNavigationKeyEvent new_event
;
1069 new_event
.SetEventObject( win
->GetParent() );
1070 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
1071 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
1072 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1073 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
1074 new_event
.SetCurrentFocus( win
);
1075 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
1078 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
1080 (gdk_event
->keyval
== GDK_Escape
) )
1082 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
1083 new_event
.SetEventObject( win
);
1084 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
1087 #if (GTK_MINOR_VERSION > 0)
1088 /* Pressing F10 will activate the menu bar of the top frame. */
1092 (gdk_event->keyval == GDK_F10) )
1094 wxWindowGTK *ancestor = win;
1097 if (wxIsKindOf(ancestor,wxFrame))
1099 wxFrame *frame = (wxFrame*) ancestor;
1100 wxMenuBar *menubar = frame->GetMenuBar();
1103 wxNode *node = menubar->GetMenus().First();
1106 wxMenu *firstMenu = (wxMenu*) node->Data();
1107 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
1113 ancestor = ancestor->GetParent();
1121 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1128 //-----------------------------------------------------------------------------
1129 // "key_release_event" from any window
1130 //-----------------------------------------------------------------------------
1132 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindowGTK
*win
)
1137 wxapp_install_idle_handler();
1139 if (!win
->m_hasVMT
) return FALSE
;
1140 if (g_blockEventsOnDrag
) return FALSE
;
1143 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
1144 if (gdk_event->state & GDK_SHIFT_MASK)
1145 printf( "ShiftDown.\n" );
1147 printf( "ShiftUp.\n" );
1148 if (gdk_event->state & GDK_CONTROL_MASK)
1149 printf( "ControlDown.\n" );
1151 printf( "ControlUp.\n" );
1155 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
1157 /* sending unknown key events doesn't really make sense */
1158 if (key_code
== 0) return FALSE
;
1162 GdkModifierType state
;
1163 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1165 wxKeyEvent
event( wxEVT_KEY_UP
);
1166 event
.SetTimestamp( gdk_event
->time
);
1167 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1168 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1169 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1170 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1171 event
.m_keyCode
= key_code
;
1172 event
.m_scanCode
= gdk_event
->keyval
;
1175 event
.SetEventObject( win
);
1177 if (win
->GetEventHandler()->ProcessEvent( event
))
1179 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1186 // ----------------------------------------------------------------------------
1187 // mouse event processing helper
1188 // ----------------------------------------------------------------------------
1190 static void AdjustEventButtonState(wxMouseEvent
& event
)
1192 // GDK reports the old state of the button for a button press event, but
1193 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1194 // for a LEFT_DOWN event, not FALSE, so we will invert
1195 // left/right/middleDown for the corresponding click events
1197 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1198 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1199 (event
.GetEventType() == wxEVT_LEFT_UP
))
1201 event
.m_leftDown
= !event
.m_leftDown
;
1205 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1206 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1207 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1209 event
.m_middleDown
= !event
.m_middleDown
;
1213 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1214 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1215 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1217 event
.m_rightDown
= !event
.m_rightDown
;
1222 //-----------------------------------------------------------------------------
1223 // "button_press_event"
1224 //-----------------------------------------------------------------------------
1226 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1231 wxapp_install_idle_handler();
1234 wxPrintf( wxT("1) OnButtonPress from ") );
1235 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1236 wxPrintf( win->GetClassInfo()->GetClassName() );
1237 wxPrintf( wxT(".\n") );
1239 if (!win
->m_hasVMT
) return FALSE
;
1240 if (g_blockEventsOnDrag
) return TRUE
;
1241 if (g_blockEventsOnScroll
) return TRUE
;
1243 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1245 if (win
->m_wxwindow
)
1247 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1249 gtk_widget_grab_focus (win
->m_wxwindow
);
1252 wxPrintf( wxT("GrabFocus from ") );
1253 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1254 wxPrintf( win->GetClassInfo()->GetClassName() );
1255 wxPrintf( wxT(".\n") );
1261 wxEventType event_type
= wxEVT_NULL
;
1263 if (gdk_event
->button
== 1)
1265 switch (gdk_event
->type
)
1267 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1268 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1272 else if (gdk_event
->button
== 2)
1274 switch (gdk_event
->type
)
1276 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1277 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1281 else if (gdk_event
->button
== 3)
1283 switch (gdk_event
->type
)
1285 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1286 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1291 if ( event_type
== wxEVT_NULL
)
1293 // unknown mouse button or click type
1297 wxMouseEvent
event( event_type
);
1298 event
.SetTimestamp( gdk_event
->time
);
1299 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1300 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1301 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1302 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1303 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1304 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1305 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1307 event
.m_x
= (wxCoord
)gdk_event
->x
;
1308 event
.m_y
= (wxCoord
)gdk_event
->y
;
1310 AdjustEventButtonState(event
);
1312 // Some control don't have their own X window and thus cannot get
1315 if (!g_captureWindow
)
1317 wxCoord x
= event
.m_x
;
1318 wxCoord y
= event
.m_y
;
1319 if (win
->m_wxwindow
)
1321 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1322 x
+= pizza
->xoffset
;
1323 y
+= pizza
->yoffset
;
1326 wxNode
*node
= win
->GetChildren().First();
1329 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1331 node
= node
->Next();
1332 if (!child
->IsShown())
1335 if (child
->m_isStaticBox
)
1337 // wxStaticBox is transparent in the box itself
1338 int xx1
= child
->m_x
;
1339 int yy1
= child
->m_y
;
1340 int xx2
= child
->m_x
+ child
->m_width
;
1341 int yy2
= child
->m_x
+ child
->m_height
;
1344 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1346 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1348 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1350 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1353 event
.m_x
-= child
->m_x
;
1354 event
.m_y
-= child
->m_y
;
1361 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1362 (child
->m_x
<= x
) &&
1363 (child
->m_y
<= y
) &&
1364 (child
->m_x
+child
->m_width
>= x
) &&
1365 (child
->m_y
+child
->m_height
>= y
))
1368 event
.m_x
-= child
->m_x
;
1369 event
.m_y
-= child
->m_y
;
1376 event
.SetEventObject( win
);
1378 gs_timeLastClick
= gdk_event
->time
;
1381 wxPrintf( wxT("2) OnButtonPress from ") );
1382 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1383 wxPrintf( win->GetClassInfo()->GetClassName() );
1384 wxPrintf( wxT(".\n") );
1387 if (win
->GetEventHandler()->ProcessEvent( event
))
1389 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1396 //-----------------------------------------------------------------------------
1397 // "button_release_event"
1398 //-----------------------------------------------------------------------------
1400 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1405 wxapp_install_idle_handler();
1407 if (!win
->m_hasVMT
) return FALSE
;
1408 if (g_blockEventsOnDrag
) return FALSE
;
1409 if (g_blockEventsOnScroll
) return FALSE
;
1411 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1414 printf( "OnButtonRelease from " );
1415 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1416 printf( win->GetClassInfo()->GetClassName() );
1420 wxEventType event_type
= wxEVT_NULL
;
1422 switch (gdk_event
->button
)
1424 case 1: event_type
= wxEVT_LEFT_UP
; break;
1425 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1426 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1427 default: return FALSE
;
1430 wxMouseEvent
event( event_type
);
1431 event
.SetTimestamp( gdk_event
->time
);
1432 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1433 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1434 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1435 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1436 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1437 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1438 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1439 event
.m_x
= (wxCoord
)gdk_event
->x
;
1440 event
.m_y
= (wxCoord
)gdk_event
->y
;
1442 AdjustEventButtonState(event
);
1444 // Some control don't have their own X window and thus cannot get
1447 if (!g_captureWindow
)
1449 wxCoord x
= event
.m_x
;
1450 wxCoord y
= event
.m_y
;
1451 if (win
->m_wxwindow
)
1453 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1454 x
+= pizza
->xoffset
;
1455 y
+= pizza
->yoffset
;
1458 wxNode
*node
= win
->GetChildren().First();
1461 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1463 node
= node
->Next();
1464 if (!child
->IsShown())
1467 if (child
->m_isStaticBox
)
1469 // wxStaticBox is transparent in the box itself
1470 int xx1
= child
->m_x
;
1471 int yy1
= child
->m_y
;
1472 int xx2
= child
->m_x
+ child
->m_width
;
1473 int yy2
= child
->m_x
+ child
->m_height
;
1476 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1478 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1480 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1482 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1485 event
.m_x
-= child
->m_x
;
1486 event
.m_y
-= child
->m_y
;
1493 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1494 (child
->m_x
<= x
) &&
1495 (child
->m_y
<= y
) &&
1496 (child
->m_x
+child
->m_width
>= x
) &&
1497 (child
->m_y
+child
->m_height
>= y
))
1500 event
.m_x
-= child
->m_x
;
1501 event
.m_y
-= child
->m_y
;
1508 event
.SetEventObject( win
);
1510 if (win
->GetEventHandler()->ProcessEvent( event
))
1512 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1519 // ============================================================================
1521 // ============================================================================
1523 // init wxMouseEvent with the info from gdk_event
1524 #define InitMouseEvent(event, gdk_event) \
1525 event.SetTimestamp( gdk_event->time ); \
1526 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
1527 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
1528 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
1529 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
1530 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
1531 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
1532 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
1534 event.m_x = (wxCoord)gdk_event->x; \
1535 event.m_y = (wxCoord)gdk_event->y \
1537 //-----------------------------------------------------------------------------
1538 // "motion_notify_event"
1539 //-----------------------------------------------------------------------------
1541 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
,
1542 GdkEventMotion
*gdk_event
,
1548 wxapp_install_idle_handler();
1550 if (!win
->m_hasVMT
) return FALSE
;
1551 if (g_blockEventsOnDrag
) return FALSE
;
1552 if (g_blockEventsOnScroll
) return FALSE
;
1554 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1556 if (gdk_event
->is_hint
)
1560 GdkModifierType state
;
1561 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1567 printf( "OnMotion from " );
1568 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1569 printf( win->GetClassInfo()->GetClassName() );
1573 wxMouseEvent
event( wxEVT_MOTION
);
1574 InitMouseEvent(event
, gdk_event
);
1576 if ( g_captureWindow
)
1578 // synthetize a mouse enter or leave event if needed
1579 GdkWindow
*winUnderMouse
= gdk_window_at_pointer(NULL
, NULL
);
1580 bool hasMouse
= winUnderMouse
== gdk_event
->window
;
1581 if ( hasMouse
!= g_captureWindowHasMouse
)
1583 // the mouse changed window
1584 g_captureWindowHasMouse
= hasMouse
;
1586 wxMouseEvent
event(g_captureWindowHasMouse
? wxEVT_ENTER_WINDOW
1587 : wxEVT_LEAVE_WINDOW
);
1588 InitMouseEvent(event
, gdk_event
);
1589 event
.SetEventObject(win
);
1590 win
->GetEventHandler()->ProcessEvent(event
);
1595 // Some control don't have their own X window and thus cannot get
1598 wxCoord x
= event
.m_x
;
1599 wxCoord y
= event
.m_y
;
1600 if (win
->m_wxwindow
)
1602 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1603 x
+= pizza
->xoffset
;
1604 y
+= pizza
->yoffset
;
1607 wxNode
*node
= win
->GetChildren().First();
1610 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1612 node
= node
->Next();
1613 if (!child
->IsShown())
1616 if (child
->m_isStaticBox
)
1618 // wxStaticBox is transparent in the box itself
1619 int xx1
= child
->m_x
;
1620 int yy1
= child
->m_y
;
1621 int xx2
= child
->m_x
+ child
->m_width
;
1622 int yy2
= child
->m_x
+ child
->m_height
;
1625 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1627 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1629 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1631 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1634 event
.m_x
-= child
->m_x
;
1635 event
.m_y
-= child
->m_y
;
1642 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1643 (child
->m_x
<= x
) &&
1644 (child
->m_y
<= y
) &&
1645 (child
->m_x
+child
->m_width
>= x
) &&
1646 (child
->m_y
+child
->m_height
>= y
))
1649 event
.m_x
-= child
->m_x
;
1650 event
.m_y
-= child
->m_y
;
1657 event
.SetEventObject( win
);
1659 if (win
->GetEventHandler()->ProcessEvent( event
))
1661 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1668 //-----------------------------------------------------------------------------
1670 //-----------------------------------------------------------------------------
1672 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
,
1673 GdkEvent
*WXUNUSED(event
),
1679 wxapp_install_idle_handler();
1681 if (!win
->m_hasVMT
) return FALSE
;
1682 if (g_blockEventsOnDrag
) return FALSE
;
1684 switch ( g_sendActivateEvent
)
1687 // we've got focus from outside, synthetize wxActivateEvent
1688 g_sendActivateEvent
= 1;
1692 // another our window just lost focus, it was already ours before
1693 // - don't send any wxActivateEvent
1694 g_sendActivateEvent
= -1;
1699 g_focusWindow
= win
;
1702 wxPrintf( "OnSetFocus from " );
1703 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
1704 wxPrintf( win
->GetClassInfo()->GetClassName() );
1708 // notify the parent keeping track of focus for the kbd navigation
1709 // purposes that we got it
1710 wxChildFocusEvent
eventFocus(win
);
1711 (void)win
->GetEventHandler()->ProcessEvent(eventFocus
);
1715 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1719 // caret needs to be informed about focus change
1720 wxCaret
*caret
= win
->GetCaret();
1723 caret
->OnSetFocus();
1725 #endif // wxUSE_CARET
1728 wxWindowGTK
*active
= wxGetTopLevelParent(win
);
1729 if ( active
!= g_activeFrame
)
1731 if ( g_activeFrame
)
1733 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
1734 event
.SetEventObject(g_activeFrame
);
1735 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1738 g_activeFrame
= active
;
1739 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId());
1740 event
.SetEventObject(g_activeFrame
);
1741 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1743 g_activeFrameLostFocus
= FALSE
;
1746 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1747 event
.SetEventObject( win
);
1749 if (win
->GetEventHandler()->ProcessEvent( event
))
1751 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1759 //-----------------------------------------------------------------------------
1760 // "focus_out_event"
1761 //-----------------------------------------------------------------------------
1763 static GtkWidget
*gs_widgetLastFocus
= NULL
;
1765 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindowGTK
*win
)
1770 wxapp_install_idle_handler();
1772 if (!win
->m_hasVMT
) return FALSE
;
1773 if (g_blockEventsOnDrag
) return FALSE
;
1775 // VZ: this is really weird but GTK+ seems to call us from inside
1776 // gtk_widget_grab_focus(), i.e. it first sends "focus_out" signal to
1777 // this widget and then "focus_in". This is totally unexpected and
1778 // completely breaks wxUniv code so ignore this dummy event (we can't
1779 // be losing focus if we're about to acquire it!)
1780 if ( widget
== gs_widgetLastFocus
)
1782 gs_widgetLastFocus
= NULL
;
1787 // if the focus goes out of our app alltogether, OnIdle() will send
1788 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1789 // g_sendActivateEvent to -1
1790 g_sendActivateEvent
= 0;
1792 wxWindowGTK
*winFocus
= wxFindFocusedChild(win
);
1796 g_focusWindow
= (wxWindowGTK
*)NULL
;
1799 wxPrintf( "OnKillFocus from " );
1800 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
1801 wxPrintf( win
->GetClassInfo()->GetClassName() );
1811 // caret needs to be informed about focus change
1812 wxCaret
*caret
= win
->GetCaret();
1815 caret
->OnKillFocus();
1817 #endif // wxUSE_CARET
1819 wxASSERT_MSG( wxGetTopLevelParent(win
) == g_activeFrame
, wxT("unfocusing window that haven't gained focus properly") )
1820 g_activeFrameLostFocus
= TRUE
;
1822 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1823 event
.SetEventObject( win
);
1825 if (win
->GetEventHandler()->ProcessEvent( event
))
1827 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1834 //-----------------------------------------------------------------------------
1835 // "enter_notify_event"
1836 //-----------------------------------------------------------------------------
1838 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1843 wxapp_install_idle_handler();
1845 if (!win
->m_hasVMT
) return FALSE
;
1846 if (g_blockEventsOnDrag
) return FALSE
;
1848 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1850 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1851 event
.SetTimestamp( gdk_event
->time
);
1852 event
.SetEventObject( win
);
1856 GdkModifierType state
= (GdkModifierType
)0;
1858 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1860 InitMouseEvent(event
, gdk_event
);
1865 if (win
->GetEventHandler()->ProcessEvent( event
))
1867 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1874 //-----------------------------------------------------------------------------
1875 // "leave_notify_event"
1876 //-----------------------------------------------------------------------------
1878 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1883 wxapp_install_idle_handler();
1885 if (!win
->m_hasVMT
) return FALSE
;
1886 if (g_blockEventsOnDrag
) return FALSE
;
1888 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1890 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1891 event
.SetTimestamp( gdk_event
->time
);
1892 event
.SetEventObject( win
);
1896 GdkModifierType state
= (GdkModifierType
)0;
1898 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1900 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1901 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1902 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1903 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1904 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1905 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1906 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1911 if (win
->GetEventHandler()->ProcessEvent( event
))
1913 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1920 //-----------------------------------------------------------------------------
1921 // "value_changed" from m_vAdjust
1922 //-----------------------------------------------------------------------------
1924 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1929 wxapp_install_idle_handler();
1931 if (g_blockEventsOnDrag
) return;
1933 if (!win
->m_hasVMT
) return;
1935 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1936 if (fabs(diff
) < 0.2) return;
1938 win
->m_oldVerticalPos
= adjust
->value
;
1940 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1941 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1943 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1944 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1945 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1946 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1947 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1949 int value
= (int)(adjust
->value
+0.5);
1951 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1952 event
.SetEventObject( win
);
1953 win
->GetEventHandler()->ProcessEvent( event
);
1956 //-----------------------------------------------------------------------------
1957 // "value_changed" from m_hAdjust
1958 //-----------------------------------------------------------------------------
1960 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1965 wxapp_install_idle_handler();
1967 if (g_blockEventsOnDrag
) return;
1968 if (!win
->m_hasVMT
) return;
1970 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1971 if (fabs(diff
) < 0.2) return;
1973 win
->m_oldHorizontalPos
= adjust
->value
;
1975 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1976 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1978 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1979 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1980 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1981 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1982 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1984 int value
= (int)(adjust
->value
+0.5);
1986 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1987 event
.SetEventObject( win
);
1988 win
->GetEventHandler()->ProcessEvent( event
);
1991 //-----------------------------------------------------------------------------
1992 // "button_press_event" from scrollbar
1993 //-----------------------------------------------------------------------------
1995 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1996 GdkEventButton
*gdk_event
,
2002 wxapp_install_idle_handler();
2005 g_blockEventsOnScroll
= TRUE
;
2006 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
2011 //-----------------------------------------------------------------------------
2012 // "button_release_event" from scrollbar
2013 //-----------------------------------------------------------------------------
2015 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
2016 GdkEventButton
*WXUNUSED(gdk_event
),
2021 // don't test here as we can release the mouse while being over
2022 // a different window than the slider
2024 // if (gdk_event->window != widget->slider) return FALSE;
2026 g_blockEventsOnScroll
= FALSE
;
2028 if (win
->m_isScrolling
)
2030 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
2034 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
2035 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
2037 value
= (int)(win
->m_hAdjust
->value
+0.5);
2040 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
2042 value
= (int)(win
->m_vAdjust
->value
+0.5);
2046 wxScrollWinEvent
event( command
, value
, dir
);
2047 event
.SetEventObject( win
);
2048 win
->GetEventHandler()->ProcessEvent( event
);
2051 win
->m_isScrolling
= FALSE
;
2056 // ----------------------------------------------------------------------------
2057 // this wxWindowBase function is implemented here (in platform-specific file)
2058 // because it is static and so couldn't be made virtual
2059 // ----------------------------------------------------------------------------
2061 wxWindow
*wxWindowBase::FindFocus()
2063 // the cast is necessary when we compile in wxUniversal mode
2064 return (wxWindow
*)g_focusWindow
;
2067 //-----------------------------------------------------------------------------
2068 // "realize" from m_widget
2069 //-----------------------------------------------------------------------------
2071 /* We cannot set colours and fonts before the widget has
2072 been realized, so we do this directly after realization. */
2075 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
2080 wxapp_install_idle_handler();
2082 if (win
->m_delayedBackgroundColour
)
2083 win
->SetBackgroundColour( win
->GetBackgroundColour() );
2085 if (win
->m_delayedForegroundColour
)
2086 win
->SetForegroundColour( win
->GetForegroundColour() );
2088 wxWindowCreateEvent
event( win
);
2089 event
.SetEventObject( win
);
2090 win
->GetEventHandler()->ProcessEvent( event
);
2095 //-----------------------------------------------------------------------------
2097 //-----------------------------------------------------------------------------
2100 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
2101 GtkAllocation
*WXUNUSED(alloc
),
2105 wxapp_install_idle_handler();
2107 if (!win
->m_hasScrolling
) return;
2109 int client_width
= 0;
2110 int client_height
= 0;
2111 win
->GetClientSize( &client_width
, &client_height
);
2112 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
2115 win
->m_oldClientWidth
= client_width
;
2116 win
->m_oldClientHeight
= client_height
;
2118 if (!win
->m_nativeSizeEvent
)
2120 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
2121 event
.SetEventObject( win
);
2122 win
->GetEventHandler()->ProcessEvent( event
);
2128 #define WXUNUSED_UNLESS_XIM(param) param
2130 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2133 /* Resize XIM window */
2136 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2137 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
2138 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2141 wxapp_install_idle_handler();
2147 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
2151 gdk_window_get_size (widget
->window
, &width
, &height
);
2152 win
->m_icattr
->preedit_area
.width
= width
;
2153 win
->m_icattr
->preedit_area
.height
= height
;
2154 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2159 //-----------------------------------------------------------------------------
2160 // "realize" from m_wxwindow
2161 //-----------------------------------------------------------------------------
2163 /* Initialize XIM support */
2166 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2167 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2170 wxapp_install_idle_handler();
2173 if (win
->m_ic
) return FALSE
;
2174 if (!widget
) return FALSE
;
2175 if (!gdk_im_ready()) return FALSE
;
2177 win
->m_icattr
= gdk_ic_attr_new();
2178 if (!win
->m_icattr
) return FALSE
;
2182 GdkColormap
*colormap
;
2183 GdkICAttr
*attr
= win
->m_icattr
;
2184 unsigned attrmask
= GDK_IC_ALL_REQ
;
2186 GdkIMStyle supported_style
= (GdkIMStyle
)
2187 (GDK_IM_PREEDIT_NONE
|
2188 GDK_IM_PREEDIT_NOTHING
|
2189 GDK_IM_PREEDIT_POSITION
|
2190 GDK_IM_STATUS_NONE
|
2191 GDK_IM_STATUS_NOTHING
);
2193 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2194 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2196 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2197 attr
->client_window
= widget
->window
;
2199 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2200 gtk_widget_get_default_colormap ())
2202 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2203 attr
->preedit_colormap
= colormap
;
2206 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2207 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2208 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2209 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2211 switch (style
& GDK_IM_PREEDIT_MASK
)
2213 case GDK_IM_PREEDIT_POSITION
:
2214 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2216 g_warning ("over-the-spot style requires fontset");
2220 gdk_window_get_size (widget
->window
, &width
, &height
);
2222 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2223 attr
->spot_location
.x
= 0;
2224 attr
->spot_location
.y
= height
;
2225 attr
->preedit_area
.x
= 0;
2226 attr
->preedit_area
.y
= 0;
2227 attr
->preedit_area
.width
= width
;
2228 attr
->preedit_area
.height
= height
;
2229 attr
->preedit_fontset
= widget
->style
->font
;
2234 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2236 if (win
->m_ic
== NULL
)
2237 g_warning ("Can't create input context.");
2240 mask
= gdk_window_get_events (widget
->window
);
2241 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2242 gdk_window_set_events (widget
->window
, mask
);
2244 if (GTK_WIDGET_HAS_FOCUS(widget
))
2245 gdk_im_begin (win
->m_ic
, widget
->window
);
2252 //-----------------------------------------------------------------------------
2253 // InsertChild for wxWindowGTK.
2254 //-----------------------------------------------------------------------------
2256 /* Callback for wxWindowGTK. This very strange beast has to be used because
2257 * C++ has no virtual methods in a constructor. We have to emulate a
2258 * virtual function here as wxNotebook requires a different way to insert
2259 * a child in it. I had opted for creating a wxNotebookPage window class
2260 * which would have made this superfluous (such in the MDI window system),
2261 * but no-one was listening to me... */
2263 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child
)
2265 /* the window might have been scrolled already, do we
2266 have to adapt the position */
2267 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2268 child
->m_x
+= pizza
->xoffset
;
2269 child
->m_y
+= pizza
->yoffset
;
2271 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2272 GTK_WIDGET(child
->m_widget
),
2279 //-----------------------------------------------------------------------------
2281 //-----------------------------------------------------------------------------
2283 wxWindow
*wxGetActiveWindow()
2285 // the cast is necessary when we compile in wxUniversal mode
2286 return (wxWindow
*)g_focusWindow
;
2289 //-----------------------------------------------------------------------------
2291 //-----------------------------------------------------------------------------
2293 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
2295 #ifdef __WXUNIVERSAL__
2296 IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
)
2298 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2299 #endif // __WXUNIVERSAL__/__WXGTK__
2301 void wxWindowGTK::Init()
2307 m_widget
= (GtkWidget
*) NULL
;
2308 m_wxwindow
= (GtkWidget
*) NULL
;
2309 m_focusWidget
= (GtkWidget
*) NULL
;
2319 m_needParent
= TRUE
;
2320 m_isBeingDeleted
= FALSE
;
2323 m_nativeSizeEvent
= FALSE
;
2325 m_hasScrolling
= FALSE
;
2326 m_isScrolling
= FALSE
;
2328 m_hAdjust
= (GtkAdjustment
*) NULL
;
2329 m_vAdjust
= (GtkAdjustment
*) NULL
;
2330 m_oldHorizontalPos
= 0.0;
2331 m_oldVerticalPos
= 0.0;
2334 m_widgetStyle
= (GtkStyle
*) NULL
;
2336 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2338 m_isStaticBox
= FALSE
;
2339 m_isRadioButton
= FALSE
;
2341 m_acceptsFocus
= FALSE
;
2343 m_clipPaintRegion
= FALSE
;
2345 m_cursor
= *wxSTANDARD_CURSOR
;
2347 m_delayedForegroundColour
= FALSE
;
2348 m_delayedBackgroundColour
= FALSE
;
2351 m_ic
= (GdkIC
*) NULL
;
2352 m_icattr
= (GdkICAttr
*) NULL
;
2356 wxWindowGTK::wxWindowGTK()
2361 wxWindowGTK::wxWindowGTK( wxWindow
*parent
,
2366 const wxString
&name
)
2370 Create( parent
, id
, pos
, size
, style
, name
);
2373 bool wxWindowGTK::Create( wxWindow
*parent
,
2378 const wxString
&name
)
2380 if (!PreCreation( parent
, pos
, size
) ||
2381 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2383 wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
2387 m_insertCallback
= wxInsertChildInWindow
;
2389 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2390 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2392 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2394 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2395 scroll_class
->scrollbar_spacing
= 0;
2397 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2399 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2400 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2402 m_wxwindow
= gtk_pizza_new();
2404 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2406 #ifndef __WXUNIVERSAL__
2407 #if (GTK_MINOR_VERSION > 0)
2408 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2410 if (HasFlag(wxRAISED_BORDER
))
2412 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2414 else if (HasFlag(wxSUNKEN_BORDER
))
2416 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2418 else if (HasFlag(wxSIMPLE_BORDER
))
2420 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2424 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2426 #else // GTK_MINOR_VERSION == 0
2427 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2429 if (HasFlag(wxRAISED_BORDER
))
2431 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2433 else if (HasFlag(wxSUNKEN_BORDER
))
2435 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2439 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2441 #endif // GTK_MINOR_VERSION
2442 #endif // __WXUNIVERSAL__
2444 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2445 m_acceptsFocus
= TRUE
;
2447 #if (GTK_MINOR_VERSION == 0)
2448 // shut the viewport up
2449 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2450 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2451 #endif // GTK_MINOR_VERSION == 0
2453 // I _really_ don't want scrollbars in the beginning
2454 m_vAdjust
->lower
= 0.0;
2455 m_vAdjust
->upper
= 1.0;
2456 m_vAdjust
->value
= 0.0;
2457 m_vAdjust
->step_increment
= 1.0;
2458 m_vAdjust
->page_increment
= 1.0;
2459 m_vAdjust
->page_size
= 5.0;
2460 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2461 m_hAdjust
->lower
= 0.0;
2462 m_hAdjust
->upper
= 1.0;
2463 m_hAdjust
->value
= 0.0;
2464 m_hAdjust
->step_increment
= 1.0;
2465 m_hAdjust
->page_increment
= 1.0;
2466 m_hAdjust
->page_size
= 5.0;
2467 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2469 // these handlers block mouse events to any window during scrolling such as
2470 // motion events and prevent GTK and wxWindows from fighting over where the
2473 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2474 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2476 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2477 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2479 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2480 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2482 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2483 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2485 // these handlers get notified when screen updates are required either when
2486 // scrolling or when the window size (and therefore scrollbar configuration)
2489 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2490 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2491 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2492 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2494 gtk_widget_show( m_wxwindow
);
2497 m_parent
->DoAddChild( this );
2499 m_focusWidget
= m_wxwindow
;
2508 wxWindowGTK::~wxWindowGTK()
2510 if (g_focusWindow
== this)
2511 g_focusWindow
= NULL
;
2513 if (g_activeFrame
== this)
2514 g_activeFrame
= NULL
;
2516 m_isBeingDeleted
= TRUE
;
2525 m_parent
->RemoveChild( this );
2529 gdk_ic_destroy (m_ic
);
2531 gdk_ic_attr_destroy (m_icattr
);
2536 #if DISABLE_STYLE_IF_BROKEN_THEME
2537 // don't delete if it's a pixmap theme style
2538 if (!m_widgetStyle
->engine_data
)
2539 gtk_style_unref( m_widgetStyle
);
2541 m_widgetStyle
= (GtkStyle
*) NULL
;
2546 gtk_widget_destroy( m_wxwindow
);
2547 m_wxwindow
= (GtkWidget
*) NULL
;
2552 gtk_widget_destroy( m_widget
);
2553 m_widget
= (GtkWidget
*) NULL
;
2557 bool wxWindowGTK::PreCreation( wxWindowGTK
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2559 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2561 /* this turns -1 into 20 so that a minimal window is
2562 visible even although -1,-1 has been given as the
2563 size of the window. the same trick is used in other
2564 ports and should make debugging easier */
2565 m_width
= WidthDefault(size
.x
);
2566 m_height
= HeightDefault(size
.y
);
2571 /* some reasonable defaults */
2576 m_x
= (gdk_screen_width () - m_width
) / 2;
2577 if (m_x
< 10) m_x
= 10;
2581 m_y
= (gdk_screen_height () - m_height
) / 2;
2582 if (m_y
< 10) m_y
= 10;
2589 void wxWindowGTK::PostCreation()
2591 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2597 // these get reported to wxWindows -> wxPaintEvent
2599 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2601 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2602 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2604 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2605 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2607 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2609 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2610 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2614 // these are called when the "sunken" or "raised" borders are drawn */
2615 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2616 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2618 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2619 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2624 if (m_focusWidget
== NULL
)
2625 m_focusWidget
= m_widget
;
2628 if (GetClassInfo() && GetClassInfo()->GetClassName())
2629 wxPrintf( GetClassInfo()->GetClassName() );
2633 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event",
2634 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2636 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event",
2637 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2639 // connect to the various key and mouse handlers
2641 GtkWidget
*connect_widget
= GetConnectWidget();
2643 ConnectWidget( connect_widget
);
2645 /* We cannot set colours, fonts and cursors before the widget has
2646 been realized, so we do this directly after realization */
2647 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2648 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2652 // Catch native resize events
2653 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2654 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2656 // Initialize XIM support
2657 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2658 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2660 // And resize XIM window
2661 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2662 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2665 if (!GTK_IS_COMBO(m_widget
))
2667 // This is needed if we want to add our windows into native
2668 // GTK control, such as the toolbar. With this callback, the
2669 // toolbar gets to know the correct size (the one set by the
2670 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2671 // when moving to GTK 2.0.
2672 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2673 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2679 void wxWindowGTK::ConnectWidget( GtkWidget
*widget
)
2681 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2682 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2684 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2685 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2687 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2688 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2690 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2691 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2693 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2694 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2696 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2697 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2699 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2700 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2703 bool wxWindowGTK::Destroy()
2705 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2709 return wxWindowBase::Destroy();
2712 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
)
2714 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2717 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2719 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2720 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") );
2723 printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
2726 if (m_resizing
) return; /* I don't like recursions */
2729 int currentX
, currentY
;
2730 GetPosition(¤tX
, ¤tY
);
2735 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
2737 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2739 /* don't set the size for children of wxNotebook, just take the values. */
2747 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2749 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2751 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2752 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2753 if (width
!= -1) m_width
= width
;
2754 if (height
!= -1) m_height
= height
;
2758 m_x
= x
+ pizza
->xoffset
;
2759 m_y
= y
+ pizza
->yoffset
;
2764 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2766 if (width
== -1) m_width
= 80;
2769 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2771 if (height
== -1) m_height
= 26;
2774 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2775 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2776 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2777 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2780 int bottom_border
= 0;
2782 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2784 /* the default button has a border around it */
2789 DoMoveWindow( m_x
-border
,
2792 m_height
+border
+bottom_border
);
2797 /* Sometimes the client area changes size without the
2798 whole windows's size changing, but if the whole
2799 windows's size doesn't change, no wxSizeEvent will
2800 normally be sent. Here we add an extra test if
2801 the client test has been changed and this will
2803 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2807 wxPrintf( "OnSize sent from " );
2808 if (GetClassInfo() && GetClassInfo()->GetClassName())
2809 wxPrintf( GetClassInfo()->GetClassName() );
2810 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2813 if (!m_nativeSizeEvent
)
2815 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2816 event
.SetEventObject( this );
2817 GetEventHandler()->ProcessEvent( event
);
2823 void wxWindowGTK::OnInternalIdle()
2825 if ( g_sendActivateEvent
!= -1 )
2827 bool activate
= g_sendActivateEvent
!= 0;
2830 g_sendActivateEvent
= -1;
2832 wxTheApp
->SetActive(activate
, (wxWindow
*)g_focusWindowLast
);
2835 if ( g_activeFrameLostFocus
)
2837 if ( g_activeFrame
)
2839 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
2840 event
.SetEventObject(g_activeFrame
);
2841 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
2842 g_activeFrame
= NULL
;
2844 g_activeFrameLostFocus
= FALSE
;
2847 wxCursor cursor
= m_cursor
;
2848 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2852 /* I now set the cursor anew in every OnInternalIdle call
2853 as setting the cursor in a parent window also effects the
2854 windows above so that checking for the current cursor is
2859 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2861 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2863 if (!g_globalCursor
.Ok())
2864 cursor
= *wxSTANDARD_CURSOR
;
2866 window
= m_widget
->window
;
2867 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2868 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2874 GdkWindow
*window
= m_widget
->window
;
2875 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2876 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2884 void wxWindowGTK::DoGetSize( int *width
, int *height
) const
2886 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2888 if (width
) (*width
) = m_width
;
2889 if (height
) (*height
) = m_height
;
2892 void wxWindowGTK::DoSetClientSize( int width
, int height
)
2894 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2898 SetSize( width
, height
);
2905 #ifndef __WXUNIVERSAL__
2906 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2908 /* when using GTK 1.2 we set the shadow border size to 2 */
2912 if (HasFlag(wxSIMPLE_BORDER
))
2914 /* when using GTK 1.2 we set the simple border size to 1 */
2918 #endif // __WXUNIVERSAL__
2922 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2924 GtkRequisition vscroll_req
;
2925 vscroll_req
.width
= 2;
2926 vscroll_req
.height
= 2;
2927 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2928 (scroll_window
->vscrollbar
, &vscroll_req
);
2930 GtkRequisition hscroll_req
;
2931 hscroll_req
.width
= 2;
2932 hscroll_req
.height
= 2;
2933 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2934 (scroll_window
->hscrollbar
, &hscroll_req
);
2936 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2938 if (scroll_window
->vscrollbar_visible
)
2940 dw
+= vscroll_req
.width
;
2941 dw
+= scroll_class
->scrollbar_spacing
;
2944 if (scroll_window
->hscrollbar_visible
)
2946 dh
+= hscroll_req
.height
;
2947 dh
+= scroll_class
->scrollbar_spacing
;
2951 SetSize( width
+dw
, height
+dh
);
2955 void wxWindowGTK::DoGetClientSize( int *width
, int *height
) const
2957 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2961 if (width
) (*width
) = m_width
;
2962 if (height
) (*height
) = m_height
;
2969 #ifndef __WXUNIVERSAL__
2970 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2972 /* when using GTK 1.2 we set the shadow border size to 2 */
2976 if (HasFlag(wxSIMPLE_BORDER
))
2978 /* when using GTK 1.2 we set the simple border size to 1 */
2982 #endif // __WXUNIVERSAL__
2986 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2988 GtkRequisition vscroll_req
;
2989 vscroll_req
.width
= 2;
2990 vscroll_req
.height
= 2;
2991 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2992 (scroll_window
->vscrollbar
, &vscroll_req
);
2994 GtkRequisition hscroll_req
;
2995 hscroll_req
.width
= 2;
2996 hscroll_req
.height
= 2;
2997 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2998 (scroll_window
->hscrollbar
, &hscroll_req
);
3000 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
3002 if (scroll_window
->vscrollbar_visible
)
3004 dw
+= vscroll_req
.width
;
3005 dw
+= scroll_class
->scrollbar_spacing
;
3008 if (scroll_window
->hscrollbar_visible
)
3010 dh
+= hscroll_req
.height
;
3011 dh
+= scroll_class
->scrollbar_spacing
;
3015 if (width
) (*width
) = m_width
- dw
;
3016 if (height
) (*height
) = m_height
- dh
;
3020 printf( "GetClientSize, name %s ", GetName().c_str() );
3021 if (width) printf( " width = %d", (*width) );
3022 if (height) printf( " height = %d", (*height) );
3027 void wxWindowGTK::DoGetPosition( int *x
, int *y
) const
3029 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3033 if (m_parent
&& m_parent
->m_wxwindow
)
3035 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
3036 dx
= pizza
->xoffset
;
3037 dy
= pizza
->yoffset
;
3040 if (x
) (*x
) = m_x
- dx
;
3041 if (y
) (*y
) = m_y
- dy
;
3044 void wxWindowGTK::DoClientToScreen( int *x
, int *y
) const
3046 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3048 if (!m_widget
->window
) return;
3050 GdkWindow
*source
= (GdkWindow
*) NULL
;
3052 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3054 source
= m_widget
->window
;
3058 gdk_window_get_origin( source
, &org_x
, &org_y
);
3062 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3064 org_x
+= m_widget
->allocation
.x
;
3065 org_y
+= m_widget
->allocation
.y
;
3073 void wxWindowGTK::DoScreenToClient( int *x
, int *y
) const
3075 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3077 if (!m_widget
->window
) return;
3079 GdkWindow
*source
= (GdkWindow
*) NULL
;
3081 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3083 source
= m_widget
->window
;
3087 gdk_window_get_origin( source
, &org_x
, &org_y
);
3091 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3093 org_x
+= m_widget
->allocation
.x
;
3094 org_y
+= m_widget
->allocation
.y
;
3102 bool wxWindowGTK::Show( bool show
)
3104 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3106 if (!wxWindowBase::Show(show
))
3113 gtk_widget_show( m_widget
);
3115 gtk_widget_hide( m_widget
);
3120 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
)
3122 win
->OnParentEnable(enable
);
3124 // Recurse, so that children have the opportunity to Do The Right Thing
3125 // and reset colours that have been messed up by a parent's (really ancestor's)
3127 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
3129 node
= node
->GetNext() )
3131 wxWindow
*child
= node
->GetData();
3132 if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
)))
3133 wxWindowNotifyEnable(child
, enable
);
3137 bool wxWindowGTK::Enable( bool enable
)
3139 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3141 if (!wxWindowBase::Enable(enable
))
3147 gtk_widget_set_sensitive( m_widget
, enable
);
3149 gtk_widget_set_sensitive( m_wxwindow
, enable
);
3151 wxWindowNotifyEnable(this, enable
);
3156 int wxWindowGTK::GetCharHeight() const
3158 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
3160 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
3162 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3164 return font
->ascent
+ font
->descent
;
3167 int wxWindowGTK::GetCharWidth() const
3169 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
3171 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
3173 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3175 return gdk_string_width( font
, "H" );
3178 void wxWindowGTK::GetTextExtent( const wxString
& string
,
3182 int *externalLeading
,
3183 const wxFont
*theFont
) const
3185 wxFont fontToUse
= m_font
;
3186 if (theFont
) fontToUse
= *theFont
;
3188 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
3190 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
3191 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
3192 if (y
) (*y
) = font
->ascent
+ font
->descent
;
3193 if (descent
) (*descent
) = font
->descent
;
3194 if (externalLeading
) (*externalLeading
) = 0; // ??
3197 void wxWindowGTK::SetFocus()
3199 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3203 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3205 // see comment in gtk_window_focus_out_callback()
3206 gs_widgetLastFocus
= m_wxwindow
;
3207 gtk_widget_grab_focus (m_wxwindow
);
3212 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
3214 gtk_widget_grab_focus (m_widget
);
3216 else if (GTK_IS_CONTAINER(m_widget
))
3218 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
3227 bool wxWindowGTK::AcceptsFocus() const
3229 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3232 bool wxWindowGTK::Reparent( wxWindowBase
*newParentBase
)
3234 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3236 wxWindowGTK
*oldParent
= m_parent
,
3237 *newParent
= (wxWindowGTK
*)newParentBase
;
3239 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3241 if ( !wxWindowBase::Reparent(newParent
) )
3244 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3246 /* prevent GTK from deleting the widget arbitrarily */
3247 gtk_widget_ref( m_widget
);
3251 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3254 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3258 /* insert GTK representation */
3259 (*(newParent
->m_insertCallback
))(newParent
, this);
3262 /* reverse: prevent GTK from deleting the widget arbitrarily */
3263 gtk_widget_unref( m_widget
);
3268 void wxWindowGTK::DoAddChild(wxWindowGTK
*child
)
3270 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3272 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3274 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3279 /* insert GTK representation */
3280 (*m_insertCallback
)(this, child
);
3283 void wxWindowGTK::Raise()
3285 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3287 if (!m_widget
->window
) return;
3289 gdk_window_raise( m_widget
->window
);
3292 void wxWindowGTK::Lower()
3294 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3296 if (!m_widget
->window
) return;
3298 gdk_window_lower( m_widget
->window
);
3301 bool wxWindowGTK::SetCursor( const wxCursor
&cursor
)
3303 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3305 if (cursor
== m_cursor
)
3309 wxapp_install_idle_handler();
3311 if (cursor
== wxNullCursor
)
3312 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3314 return wxWindowBase::SetCursor( cursor
);
3317 void wxWindowGTK::WarpPointer( int x
, int y
)
3319 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3321 /* we provide this function ourselves as it is
3322 missing in GDK (top of this file) */
3324 GdkWindow
*window
= (GdkWindow
*) NULL
;
3326 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3328 window
= GetConnectWidget()->window
;
3331 gdk_window_warp_pointer( window
, x
, y
);
3334 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect
*rect
)
3336 if (!m_widget
) return;
3337 if (!m_widget
->window
) return;
3339 // temporarily hide the caret to avoid nasty interactions between caret
3340 // drawing and the window contents redraw
3341 #if 0 // def wxUSE_CARET -- doesn't seem to help :-(
3342 wxCaretSuspend
cs((wxWindow
*)this);
3343 #endif // wxUSE_CARET
3345 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3349 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3351 rect
->width
, rect
->height
);
3355 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3359 /* there is no GTK equivalent of "draw only, don't clear" so we
3360 invent our own in the GtkPizza widget */
3368 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3369 gboolean old_clear = pizza->clear_on_draw;
3370 gtk_pizza_set_clear( pizza, FALSE );
3371 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3372 gtk_pizza_set_clear( pizza, old_clear );
3374 GdkEventExpose gdk_event
;
3375 gdk_event
.type
= GDK_EXPOSE
;
3376 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3377 gdk_event
.count
= 0;
3378 gdk_event
.area
.x
= 0;
3379 gdk_event
.area
.y
= 0;
3380 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3381 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3382 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, (wxWindow
*)this );
3386 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3395 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3396 gboolean old_clear = pizza->clear_on_draw;
3397 gtk_pizza_set_clear( pizza, FALSE );
3399 GdkRectangle gdk_rect;
3400 gdk_rect.x = rect->x;
3401 gdk_rect.y = rect->y;
3402 gdk_rect.width = rect->width;
3403 gdk_rect.height = rect->height;
3404 gtk_widget_draw( m_wxwindow, &gdk_rect );
3405 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3407 gtk_pizza_set_clear( pizza, old_clear );
3409 GdkEventExpose gdk_event
;
3410 gdk_event
.type
= GDK_EXPOSE
;
3411 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3412 gdk_event
.count
= 0;
3413 gdk_event
.area
.x
= rect
->x
;
3414 gdk_event
.area
.y
= rect
->y
;
3415 gdk_event
.area
.width
= rect
->width
;
3416 gdk_event
.area
.height
= rect
->height
;
3417 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, (wxWindow
*)this );
3421 GdkRectangle gdk_rect
;
3422 gdk_rect
.x
= rect
->x
;
3423 gdk_rect
.y
= rect
->y
;
3424 gdk_rect
.width
= rect
->width
;
3425 gdk_rect
.height
= rect
->height
;
3426 gtk_widget_draw( m_widget
, &gdk_rect
);
3431 void wxWindowGTK::Clear()
3433 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3435 if (!m_widget
->window
) return;
3437 if (m_wxwindow
&& m_wxwindow
->window
)
3439 // gdk_window_clear( m_wxwindow->window );
3444 void wxWindowGTK::DoSetToolTip( wxToolTip
*tip
)
3446 wxWindowBase::DoSetToolTip(tip
);
3449 m_tooltip
->Apply( (wxWindow
*)this );
3452 void wxWindowGTK::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3454 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3456 #endif // wxUSE_TOOLTIPS
3458 bool wxWindowGTK::SetBackgroundColour( const wxColour
&colour
)
3460 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3462 if (!wxWindowBase::SetBackgroundColour(colour
))
3464 // don't leave if the GTK widget has just
3466 if (!m_delayedBackgroundColour
) return FALSE
;
3469 GdkWindow
*window
= (GdkWindow
*) NULL
;
3471 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3473 window
= GetConnectWidget()->window
;
3477 // indicate that a new style has been set
3478 // but it couldn't get applied as the
3479 // widget hasn't been realized yet.
3480 m_delayedBackgroundColour
= TRUE
;
3484 (m_wxwindow
->window
) &&
3485 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3487 /* wxMSW doesn't clear the window here. I don't do that either to
3488 provide compatibility. call Clear() to do the job. */
3490 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3491 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3499 bool wxWindowGTK::SetForegroundColour( const wxColour
&colour
)
3501 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3503 if (!wxWindowBase::SetForegroundColour(colour
))
3505 // don't leave if the GTK widget has just
3507 if (!m_delayedForegroundColour
) return FALSE
;
3510 GdkWindow
*window
= (GdkWindow
*) NULL
;
3512 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3514 window
= GetConnectWidget()->window
;
3518 // indicate that a new style has been set
3519 // but it couldn't get applied as the
3520 // widget hasn't been realized yet.
3521 m_delayedForegroundColour
= TRUE
;
3529 GtkStyle
*wxWindowGTK::GetWidgetStyle()
3533 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3535 /* FIXME: is this necessary? */
3536 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3538 remake
->klass
= m_widgetStyle
->klass
;
3541 gtk_style_unref( m_widgetStyle
);
3542 m_widgetStyle
= remake
;
3546 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3549 def
= gtk_widget_get_default_style();
3551 m_widgetStyle
= gtk_style_copy( def
);
3553 /* FIXME: is this necessary? */
3554 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3556 m_widgetStyle
->klass
= def
->klass
;
3560 return m_widgetStyle
;
3563 void wxWindowGTK::SetWidgetStyle()
3565 #if DISABLE_STYLE_IF_BROKEN_THEM
3566 if (m_widget
->style
->engine_data
)
3568 static bool s_warningPrinted
= FALSE
;
3569 if (!s_warningPrinted
)
3571 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3572 s_warningPrinted
= TRUE
;
3574 m_widgetStyle
= m_widget
->style
;
3579 GtkStyle
*style
= GetWidgetStyle();
3581 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3583 gdk_font_unref( style
->font
);
3584 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3587 if (m_foregroundColour
.Ok())
3589 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3590 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3592 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3593 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3594 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3598 // Try to restore the gtk default style. This is still a little
3599 // oversimplified for what is probably really needed here for controls
3600 // other than buttons, but is better than not being able to (re)set a
3601 // control's foreground colour to *wxBLACK -- RL
3602 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3605 def
= gtk_widget_get_default_style();
3607 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3608 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3609 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3613 if (m_backgroundColour
.Ok())
3615 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3616 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3618 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3619 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3620 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3621 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3622 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3623 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3624 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3625 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3629 // Try to restore the gtk default style. This is still a little
3630 // oversimplified for what is probably really needed here for controls
3631 // other than buttons, but is better than not being able to (re)set a
3632 // control's background colour to default grey and means resetting a
3633 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3635 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3638 def
= gtk_widget_get_default_style();
3640 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3641 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3642 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3643 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3644 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3645 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3646 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3647 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3652 void wxWindowGTK::ApplyWidgetStyle()
3656 //-----------------------------------------------------------------------------
3657 // Pop-up menu stuff
3658 //-----------------------------------------------------------------------------
3660 #if wxUSE_MENUS_NATIVE
3662 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3664 *is_waiting
= FALSE
;
3667 static void SetInvokingWindow( wxMenu
*menu
, wxWindowGTK
*win
)
3669 menu
->SetInvokingWindow( win
);
3670 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3673 wxMenuItem
*menuitem
= node
->GetData();
3674 if (menuitem
->IsSubMenu())
3676 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3679 node
= node
->GetNext();
3683 static gint gs_pop_x
= 0;
3684 static gint gs_pop_y
= 0;
3686 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3690 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3695 bool wxWindowGTK::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3697 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3699 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3701 SetInvokingWindow( menu
, this );
3708 bool is_waiting
= TRUE
;
3710 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3711 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3714 GTK_MENU(menu
->m_menu
),
3715 (GtkWidget
*) NULL
, // parent menu shell
3716 (GtkWidget
*) NULL
, // parent menu item
3717 (GtkMenuPositionFunc
) pop_pos_callback
,
3718 (gpointer
) this, // client data
3719 0, // button used to activate it
3720 gs_timeLastClick
// the time of activation
3725 while (gtk_events_pending())
3726 gtk_main_iteration();
3732 #endif // wxUSE_MENUS_NATIVE
3734 #if wxUSE_DRAG_AND_DROP
3736 void wxWindowGTK::SetDropTarget( wxDropTarget
*dropTarget
)
3738 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3740 GtkWidget
*dnd_widget
= GetConnectWidget();
3742 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3744 if (m_dropTarget
) delete m_dropTarget
;
3745 m_dropTarget
= dropTarget
;
3747 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3750 #endif // wxUSE_DRAG_AND_DROP
3752 GtkWidget
* wxWindowGTK::GetConnectWidget()
3754 GtkWidget
*connect_widget
= m_widget
;
3755 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3757 return connect_widget
;
3760 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow
*window
)
3763 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3765 return (window
== m_widget
->window
);
3768 bool wxWindowGTK::SetFont( const wxFont
&font
)
3770 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3772 if (!wxWindowBase::SetFont(font
))
3777 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3778 if ( sysbg
== m_backgroundColour
)
3780 m_backgroundColour
= wxNullColour
;
3782 m_backgroundColour
= sysbg
;
3792 void wxWindowGTK::CaptureMouse()
3794 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3796 GdkWindow
*window
= (GdkWindow
*) NULL
;
3798 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3800 window
= GetConnectWidget()->window
;
3802 wxCHECK_RET( window
, _T("CaptureMouse() failed") );
3804 wxCursor
* cursor
= & m_cursor
;
3806 cursor
= wxSTANDARD_CURSOR
;
3808 gdk_pointer_grab( window
, FALSE
,
3810 (GDK_BUTTON_PRESS_MASK
|
3811 GDK_BUTTON_RELEASE_MASK
|
3812 GDK_POINTER_MOTION_HINT_MASK
|
3813 GDK_POINTER_MOTION_MASK
),
3815 cursor
->GetCursor(),
3816 (guint32
)GDK_CURRENT_TIME
);
3817 g_captureWindow
= this;
3818 g_captureWindowHasMouse
= TRUE
;
3821 void wxWindowGTK::ReleaseMouse()
3823 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3825 wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") );
3827 GdkWindow
*window
= (GdkWindow
*) NULL
;
3829 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3831 window
= GetConnectWidget()->window
;
3836 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3837 g_captureWindow
= (wxWindowGTK
*) NULL
;
3841 wxWindow
*wxWindowBase::GetCapture()
3843 return (wxWindow
*)g_captureWindow
;
3846 bool wxWindowGTK::IsRetained() const
3851 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3852 int range
, bool refresh
)
3854 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3856 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3858 m_hasScrolling
= TRUE
;
3860 if (orient
== wxHORIZONTAL
)
3862 float fpos
= (float)pos
;
3863 float frange
= (float)range
;
3864 float fthumb
= (float)thumbVisible
;
3865 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3866 if (fpos
< 0.0) fpos
= 0.0;
3868 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3869 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3871 SetScrollPos( orient
, pos
, refresh
);
3875 m_oldHorizontalPos
= fpos
;
3877 m_hAdjust
->lower
= 0.0;
3878 m_hAdjust
->upper
= frange
;
3879 m_hAdjust
->value
= fpos
;
3880 m_hAdjust
->step_increment
= 1.0;
3881 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3882 m_hAdjust
->page_size
= fthumb
;
3886 float fpos
= (float)pos
;
3887 float frange
= (float)range
;
3888 float fthumb
= (float)thumbVisible
;
3889 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3890 if (fpos
< 0.0) fpos
= 0.0;
3892 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3893 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3895 SetScrollPos( orient
, pos
, refresh
);
3899 m_oldVerticalPos
= fpos
;
3901 m_vAdjust
->lower
= 0.0;
3902 m_vAdjust
->upper
= frange
;
3903 m_vAdjust
->value
= fpos
;
3904 m_vAdjust
->step_increment
= 1.0;
3905 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3906 m_vAdjust
->page_size
= fthumb
;
3909 if (orient
== wxHORIZONTAL
)
3910 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3912 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3915 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3917 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3919 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3921 if (orient
== wxHORIZONTAL
)
3923 float fpos
= (float)pos
;
3924 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3925 if (fpos
< 0.0) fpos
= 0.0;
3926 m_oldHorizontalPos
= fpos
;
3928 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3929 m_hAdjust
->value
= fpos
;
3933 float fpos
= (float)pos
;
3934 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3935 if (fpos
< 0.0) fpos
= 0.0;
3936 m_oldVerticalPos
= fpos
;
3938 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3939 m_vAdjust
->value
= fpos
;
3942 if (m_wxwindow
->window
)
3944 if (orient
== wxHORIZONTAL
)
3946 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3947 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3949 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3951 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3952 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3956 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3957 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3959 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3961 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3962 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3967 int wxWindowGTK::GetScrollThumb( int orient
) const
3969 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3971 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3973 if (orient
== wxHORIZONTAL
)
3974 return (int)(m_hAdjust
->page_size
+0.5);
3976 return (int)(m_vAdjust
->page_size
+0.5);
3979 int wxWindowGTK::GetScrollPos( int orient
) const
3981 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3983 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3985 if (orient
== wxHORIZONTAL
)
3986 return (int)(m_hAdjust
->value
+0.5);
3988 return (int)(m_vAdjust
->value
+0.5);
3991 int wxWindowGTK::GetScrollRange( int orient
) const
3993 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3995 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3997 if (orient
== wxHORIZONTAL
)
3998 return (int)(m_hAdjust
->upper
+0.5);
4000 return (int)(m_vAdjust
->upper
+0.5);
4003 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
4005 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4007 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4009 if ((dx
== 0) && (dy
== 0)) return;
4011 m_clipPaintRegion
= TRUE
;
4012 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
4013 m_clipPaintRegion
= FALSE
;
4016 if (m_children.GetCount() > 0)
4018 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
4022 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
4024 pizza->xoffset -= dx;
4025 pizza->yoffset -= dy;
4027 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
4028 gdk_gc_set_exposures( m_scrollGC, TRUE );
4032 GetClientSize( &cw, &ch );
4033 int w = cw - abs(dx);
4034 int h = ch - abs(dy);
4036 if ((h < 0) || (w < 0))
4044 if (dx < 0) s_x = -dx;
4045 if (dy < 0) s_y = -dy;
4048 if (dx > 0) d_x = dx;
4049 if (dy > 0) d_y = dy;
4051 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
4052 pizza->bin_window, s_x, s_y, w, h );
4055 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
4056 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
4057 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
4058 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
4060 Refresh( TRUE, &rect );
4063 gdk_gc_unref( m_scrollGC );
4068 // Find the wxWindow at the current mouse position, also returning the mouse
4070 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
4072 pt
= wxGetMousePosition();
4073 wxWindow
* found
= wxFindWindowAtPoint(pt
);
4077 // Get the current mouse position.
4078 wxPoint
wxGetMousePosition()
4080 /* This crashes when used within wxHelpContext,
4081 so we have to use the X-specific implementation below.
4083 GdkModifierType *mask;
4084 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
4086 return wxPoint(x, y);
4090 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
4092 return wxPoint(-999, -999);
4094 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
4095 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
4096 Window rootReturn
, childReturn
;
4097 int rootX
, rootY
, winX
, winY
;
4098 unsigned int maskReturn
;
4100 XQueryPointer (display
,
4104 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
4105 return wxPoint(rootX
, rootY
);