1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/window.cpp
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #define XWarpPointer XWARPPOINTER
20 #include "wx/window.h"
21 #include "wx/dcclient.h"
24 #include "wx/layout.h"
26 #include "wx/dialog.h"
27 #include "wx/msgdlg.h"
29 #if wxUSE_DRAG_AND_DROP
34 #include "wx/tooltip.h"
42 #include "wx/textctrl.h"
46 #include "wx/statusbr.h"
48 #include "wx/settings.h"
52 #include "wx/thread.h"
59 #include <gdk/gdkprivate.h>
60 #include <gdk/gdkkeysyms.h>
64 #include <gtk/gtkprivate.h>
66 #include "wx/gtk/win_gtk.h"
68 //-----------------------------------------------------------------------------
69 // documentation on internals
70 //-----------------------------------------------------------------------------
73 I have been asked several times about writing some documentation about
74 the GTK port of wxWindows, especially its internal structures. Obviously,
75 you cannot understand wxGTK without knowing a little about the GTK, but
76 some more information about what the wxWindow, which is the base class
77 for all other window classes, does seems required as well.
81 What does wxWindow do? It contains the common interface for the following
82 jobs of its descendants:
84 1) Define the rudimentary behaviour common to all window classes, such as
85 resizing, intercepting user input (so as to make it possible to use these
86 events for special purposes in a derived class), window names etc.
88 2) Provide the possibility to contain and manage children, if the derived
89 class is allowed to contain children, which holds true for those window
90 classes which do not display a native GTK widget. To name them, these
91 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
92 work classes are a special case and are handled a bit differently from
93 the rest. The same holds true for the wxNotebook class.
95 3) Provide the possibility to draw into a client area of a window. This,
96 too, only holds true for classes that do not display a native GTK widget
99 4) Provide the entire mechanism for scrolling widgets. This actual inter-
100 face for this is usually in wxScrolledWindow, but the GTK implementation
103 5) A multitude of helper or extra methods for special purposes, such as
104 Drag'n'Drop, managing validators etc.
106 6) Display a border (sunken, raised, simple or none).
108 Normally one might expect, that one wxWindows window would always correspond
109 to one GTK widget. Under GTK, there is no such allround widget that has all
110 the functionality. Moreover, the GTK defines a client area as a different
111 widget from the actual widget you are handling. Last but not least some
112 special classes (e.g. wxFrame) handle different categories of widgets and
113 still have the possibility to draw something in the client area.
114 It was therefore required to write a special purpose GTK widget, that would
115 represent a client area in the sense of wxWindows capable to do the jobs
116 2), 3) and 4). I have written this class and it resides in win_gtk.c of
119 All windows must have a widget, with which they interact with other under-
120 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
121 thw wxWindow class has a member variable called m_widget which holds a
122 pointer to this widget. When the window class represents a GTK native widget,
123 this is (in most cases) the only GTK widget the class manages. E.g. the
124 wxStatitText class handles only a GtkLabel widget a pointer to which you
125 can find in m_widget (defined in wxWindow)
127 When the class has a client area for drawing into and for containing children
128 it has to handle the client area widget (of the type GtkPizza, defined in
129 win_gtk.c), but there could be any number of widgets, handled by a class
130 The common rule for all windows is only, that the widget that interacts with
131 the rest of GTK must be referenced in m_widget and all other widgets must be
132 children of this widget on the GTK level. The top-most widget, which also
133 represents the client area, must be in the m_wxwindow field and must be of
136 As I said, the window classes that display a GTK native widget only have
137 one widget, so in the case of e.g. the wxButton class m_widget holds a
138 pointer to a GtkButton widget. But windows with client areas (for drawing
139 and children) have a m_widget field that is a pointer to a GtkScrolled-
140 Window and a m_wxwindow field that is pointer to a GtkPizza and this
141 one is (in the GTK sense) a child of the GtkScrolledWindow.
143 If the m_wxwindow field is set, then all input to this widget is inter-
144 cepted and sent to the wxWindows class. If not, all input to the widget
145 that gets pointed to by m_widget gets intercepted and sent to the class.
149 The design of scrolling in wxWindows is markedly different from that offered
150 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
151 clicking on a scrollbar belonging to scrolled window will inevitably move
152 the window. In wxWindows, the scrollbar will only emit an event, send this
153 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
154 which actually moves the window and its subchildren. Note that GtkPizza
155 memorizes how much it has been scrolled but that wxWindows forgets this
156 so that the two coordinates systems have to be kept in synch. This is done
157 in various places using the pizza->xoffset and pizza->yoffset values.
161 Singularily the most broken code in GTK is the code that is supposes to
162 inform subwindows (child windows) about new positions. Very often, duplicate
163 events are sent without changes in size or position, equally often no
164 events are sent at all (All this is due to a bug in the GtkContainer code
165 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
166 GTK's own system and it simply waits for size events for toplevel windows
167 and then iterates down the respective size events to all window. This has
168 the disadvantage, that windows might get size events before the GTK widget
169 actually has the reported size. This doesn't normally pose any problem, but
170 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
171 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
172 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
173 window that is used for OpenGl output really has that size (as reported by
178 If someone at some point of time feels the immense desire to have a look at,
179 change or attempt to optimse the Refresh() logic, this person will need an
180 intimate understanding of what a "draw" and what an "expose" events are and
181 what there are used for, in particular when used in connection with GTK's
182 own windowless widgets. Beware.
186 Cursors, too, have been a constant source of pleasure. The main difficulty
187 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
188 for the parent. To prevent this from doing too much harm, I use idle time
189 to set the cursor over and over again, starting from the toplevel windows
190 and ending with the youngest generation (speaking of parent and child windows).
191 Also don't forget that cursors (like much else) are connected to GdkWindows,
192 not GtkWidgets and that the "window" field of a GtkWidget might very well
193 point to the GdkWindow of the parent widget (-> "window less widget") and
194 that the two obviously have very different meanings.
198 //-----------------------------------------------------------------------------
200 //-----------------------------------------------------------------------------
202 extern wxList wxPendingDelete
;
203 extern bool g_blockEventsOnDrag
;
204 extern bool g_blockEventsOnScroll
;
205 extern wxCursor g_globalCursor
;
207 // mouse capture state: the window which has it and if the mouse is currently
209 static wxWindowGTK
*g_captureWindow
= (wxWindowGTK
*) NULL
;
210 static bool g_captureWindowHasMouse
= FALSE
;
212 /* extern */ wxWindowGTK
*g_focusWindow
= (wxWindowGTK
*) NULL
;
214 // the last window which had the focus - this is normally never NULL (except
215 // if we never had focus at all) as even when g_focusWindow is NULL it still
216 // keeps its previous value
217 static wxWindowGTK
*g_focusWindowLast
= (wxWindowGTK
*)NULL
;
219 // the frame that is currently active (i.e. its child has focus). It is
220 // used to generate wxActivateEvents
221 static wxWindowGTK
*g_activeFrame
= (wxWindowGTK
*)NULL
;
222 static bool g_activeFrameLostFocus
= FALSE
;
224 // if we detect that the app has got/lost the focus, we set this variable to
225 // either TRUE or FALSE and an activate event will be sent during the next
226 // OnIdle() call and it is reset to -1: this value means that we shouldn't
227 // send any activate events at all
228 static int g_sendActivateEvent
= -1;
230 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
231 the last click here */
232 static guint32 gs_timeLastClick
= 0;
234 extern bool g_mainThreadLocked
;
236 //-----------------------------------------------------------------------------
238 //-----------------------------------------------------------------------------
241 #define DISABLE_STYLE_IF_BROKEN_THEME 1
247 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
249 # define DEBUG_MAIN_THREAD
252 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
253 GdkEvent
*WXUNUSED(event
),
254 const wxChar
*WXUNUSED(name
) )
257 static bool s_done = FALSE;
260 wxLog::AddTraceMask("focus");
263 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
269 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
271 // suppress warnings about gtk_debug_focus_in_callback being unused with
276 tmp
+= wxT(" FROM ");
279 wxChar
*s
= new wxChar
[tmp
.Length()+1];
283 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
284 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
289 #define DEBUG_MAIN_THREAD
292 //-----------------------------------------------------------------------------
293 // missing gdk functions
294 //-----------------------------------------------------------------------------
297 gdk_window_warp_pointer (GdkWindow
*window
,
302 GdkWindowPrivate
*priv
;
306 window
= GDK_ROOT_PARENT();
309 if (!GDK_WINDOW_DESTROYED(window
))
311 XWarpPointer (GDK_WINDOW_XDISPLAY(window
),
312 None
, /* not source window -> move from anywhere */
313 GDK_WINDOW_XID(window
), /* dest window */
314 0, 0, 0, 0, /* not source window -> move from anywhere */
318 priv
= (GdkWindowPrivate
*) window
;
320 if (!priv
->destroyed
)
322 XWarpPointer (priv
->xdisplay
,
323 None
, /* not source window -> move from anywhere */
324 priv
->xwindow
, /* dest window */
325 0, 0, 0, 0, /* not source window -> move from anywhere */
331 //-----------------------------------------------------------------------------
333 //-----------------------------------------------------------------------------
335 extern void wxapp_install_idle_handler();
336 extern bool g_isIdle
;
338 //-----------------------------------------------------------------------------
339 // local code (see below)
340 //-----------------------------------------------------------------------------
342 // returns the child of win which currently has focus or NULL if not found
344 // Note: can't be static, needed by textctrl.cpp.
345 wxWindow
*wxFindFocusedChild(wxWindowGTK
*win
)
347 wxWindow
*winFocus
= wxWindowGTK::FindFocus();
349 return (wxWindow
*)NULL
;
351 if ( winFocus
== win
)
352 return (wxWindow
*)win
;
354 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
356 node
= node
->GetNext() )
358 wxWindow
*child
= wxFindFocusedChild(node
->GetData());
363 return (wxWindow
*)NULL
;
366 // Returns toplevel grandparent of given window:
367 static wxWindowGTK
* wxGetTopLevelParent(wxWindowGTK
*win
)
369 wxWindowGTK
*p
= win
;
370 while (p
&& !p
->IsTopLevel())
376 static void draw_frame( GtkWidget
*widget
, wxWindowGTK
*win
)
378 // wxUniversal widgets draw the borders and scrollbars themselves
379 #ifndef __WXUNIVERSAL__
386 if (win
->m_hasScrolling
)
388 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
390 GtkRequisition vscroll_req
;
391 vscroll_req
.width
= 2;
392 vscroll_req
.height
= 2;
393 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
394 (scroll_window
->vscrollbar
, &vscroll_req
);
396 GtkRequisition hscroll_req
;
397 hscroll_req
.width
= 2;
398 hscroll_req
.height
= 2;
399 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
400 (scroll_window
->hscrollbar
, &hscroll_req
);
402 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) );
404 if (scroll_window
->vscrollbar_visible
)
406 dw
+= vscroll_req
.width
;
407 dw
+= scroll_class
->scrollbar_spacing
;
410 if (scroll_window
->hscrollbar_visible
)
412 dh
+= hscroll_req
.height
;
413 dh
+= scroll_class
->scrollbar_spacing
;
419 if (GTK_WIDGET_NO_WINDOW (widget
))
421 dx
+= widget
->allocation
.x
;
422 dy
+= widget
->allocation
.y
;
425 if (win
->HasFlag(wxRAISED_BORDER
))
427 gtk_draw_shadow( widget
->style
,
432 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
436 if (win
->HasFlag(wxSUNKEN_BORDER
))
438 gtk_draw_shadow( widget
->style
,
443 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
447 if (win
->HasFlag(wxSIMPLE_BORDER
))
450 gc
= gdk_gc_new( widget
->window
);
451 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
452 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
454 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
458 #endif // __WXUNIVERSAL__
461 //-----------------------------------------------------------------------------
462 // "expose_event" of m_widget
463 //-----------------------------------------------------------------------------
465 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindowGTK
*win
)
467 if (gdk_event
->count
> 0) return FALSE
;
469 draw_frame( widget
, win
);
474 //-----------------------------------------------------------------------------
475 // "draw" of m_widget
476 //-----------------------------------------------------------------------------
478 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindowGTK
*win
)
480 draw_frame( widget
, win
);
483 //-----------------------------------------------------------------------------
484 // key code mapping routines
485 //-----------------------------------------------------------------------------
487 static long map_to_unmodified_wx_keysym( GdkEventKey
*event
)
489 KeySym keysym
= event
->keyval
;
495 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
497 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
503 case GDK_Super_R
: key_code
= WXK_ALT
; break;
504 case GDK_Menu
: key_code
= WXK_MENU
; break;
505 case GDK_Help
: key_code
= WXK_HELP
; break;
506 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
507 case GDK_ISO_Left_Tab
:
508 case GDK_Tab
: key_code
= WXK_TAB
; break;
509 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
510 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
511 case GDK_Return
: key_code
= WXK_RETURN
; break;
512 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
513 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
514 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
515 case GDK_Delete
: key_code
= WXK_DELETE
; break;
516 case GDK_Home
: key_code
= WXK_HOME
; break;
517 case GDK_Left
: key_code
= WXK_LEFT
; break;
518 case GDK_Up
: key_code
= WXK_UP
; break;
519 case GDK_Right
: key_code
= WXK_RIGHT
; break;
520 case GDK_Down
: key_code
= WXK_DOWN
; break;
521 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
522 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
523 case GDK_Next
: key_code
= WXK_NEXT
; break;
524 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
525 case GDK_End
: key_code
= WXK_END
; break;
526 case GDK_Begin
: key_code
= WXK_HOME
; break;
527 case GDK_Select
: key_code
= WXK_SELECT
; break;
528 case GDK_Print
: key_code
= WXK_PRINT
; break;
529 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
530 case GDK_Insert
: key_code
= WXK_INSERT
; break;
531 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
533 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
534 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
535 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
536 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
537 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
538 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
539 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
540 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
541 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
542 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
543 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
544 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
545 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
546 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
547 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
548 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
549 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
550 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
551 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
552 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
553 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
554 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
555 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
556 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
557 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
558 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
559 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
560 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
561 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
562 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
563 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
564 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
565 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
566 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
567 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
568 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
569 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
571 case GDK_F1
: key_code
= WXK_F1
; break;
572 case GDK_F2
: key_code
= WXK_F2
; break;
573 case GDK_F3
: key_code
= WXK_F3
; break;
574 case GDK_F4
: key_code
= WXK_F4
; break;
575 case GDK_F5
: key_code
= WXK_F5
; break;
576 case GDK_F6
: key_code
= WXK_F6
; break;
577 case GDK_F7
: key_code
= WXK_F7
; break;
578 case GDK_F8
: key_code
= WXK_F8
; break;
579 case GDK_F9
: key_code
= WXK_F9
; break;
580 case GDK_F10
: key_code
= WXK_F10
; break;
581 case GDK_F11
: key_code
= WXK_F11
; break;
582 case GDK_F12
: key_code
= WXK_F12
; break;
584 if ( (keysym
& 0xFF) == keysym
)
586 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
587 key_code
= upper
? upper
: keysym
;
599 static long map_to_wx_keysym( GdkEventKey
*event
)
601 KeySym keysym
= event
->keyval
;
606 case GDK_Menu
: key_code
= WXK_MENU
; break;
607 case GDK_Help
: key_code
= WXK_HELP
; break;
608 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
609 case GDK_ISO_Left_Tab
:
610 case GDK_Tab
: key_code
= WXK_TAB
; break;
611 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
612 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
613 case GDK_Return
: key_code
= WXK_RETURN
; break;
614 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
615 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
616 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
617 case GDK_Delete
: key_code
= WXK_DELETE
; break;
618 case GDK_Home
: key_code
= WXK_HOME
; break;
619 case GDK_Left
: key_code
= WXK_LEFT
; break;
620 case GDK_Up
: key_code
= WXK_UP
; break;
621 case GDK_Right
: key_code
= WXK_RIGHT
; break;
622 case GDK_Down
: key_code
= WXK_DOWN
; break;
623 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
624 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
625 case GDK_Next
: key_code
= WXK_NEXT
; break;
626 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
627 case GDK_End
: key_code
= WXK_END
; break;
628 case GDK_Begin
: key_code
= WXK_HOME
; break;
629 case GDK_Select
: key_code
= WXK_SELECT
; break;
630 case GDK_Print
: key_code
= WXK_PRINT
; break;
631 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
632 case GDK_Insert
: key_code
= WXK_INSERT
; break;
633 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
635 case GDK_KP_0
: key_code
= '0'; break;
636 case GDK_KP_1
: key_code
= '1'; break;
637 case GDK_KP_2
: key_code
= '2'; break;
638 case GDK_KP_3
: key_code
= '3'; break;
639 case GDK_KP_4
: key_code
= '4'; break;
640 case GDK_KP_5
: key_code
= '5'; break;
641 case GDK_KP_6
: key_code
= '6'; break;
642 case GDK_KP_7
: key_code
= '7'; break;
643 case GDK_KP_8
: key_code
= '8'; break;
644 case GDK_KP_9
: key_code
= '9'; break;
645 case GDK_KP_Space
: key_code
= ' '; break;
646 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
647 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
648 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
649 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
650 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
651 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
652 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
653 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
654 case GDK_KP_Up
: key_code
= WXK_UP
; break;
655 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
656 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
657 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
658 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
659 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
660 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
661 case GDK_KP_End
: key_code
= WXK_END
; break;
662 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
663 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
664 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
665 case GDK_KP_Equal
: key_code
= '='; break;
666 case GDK_KP_Multiply
: key_code
= '*'; break;
667 case GDK_KP_Add
: key_code
= '+'; break;
668 case GDK_KP_Separator
: key_code
= ','; break;
669 case GDK_KP_Subtract
: key_code
= '-'; break;
670 case GDK_KP_Decimal
: key_code
= '.'; break;
671 case GDK_KP_Divide
: key_code
= '/'; break;
673 case GDK_F1
: key_code
= WXK_F1
; break;
674 case GDK_F2
: key_code
= WXK_F2
; break;
675 case GDK_F3
: key_code
= WXK_F3
; break;
676 case GDK_F4
: key_code
= WXK_F4
; break;
677 case GDK_F5
: key_code
= WXK_F5
; break;
678 case GDK_F6
: key_code
= WXK_F6
; break;
679 case GDK_F7
: key_code
= WXK_F7
; break;
680 case GDK_F8
: key_code
= WXK_F8
; break;
681 case GDK_F9
: key_code
= WXK_F9
; break;
682 case GDK_F10
: key_code
= WXK_F10
; break;
683 case GDK_F11
: key_code
= WXK_F11
; break;
684 case GDK_F12
: key_code
= WXK_F12
; break;
687 if (event
->length
== 1)
689 if (event
->length
== 1)
691 key_code
= (unsigned char)*event
->string
;
693 else if ((keysym
& 0xFF) == keysym
)
695 key_code
= (guint
)keysym
;
704 //-----------------------------------------------------------------------------
705 // "size_request" of m_widget
706 //-----------------------------------------------------------------------------
708 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
711 win
->GetSize( &w
, &h
);
715 requisition
->height
= h
;
716 requisition
->width
= w
;
719 //-----------------------------------------------------------------------------
720 // "expose_event" of m_wxwindow
721 //-----------------------------------------------------------------------------
723 static int gtk_window_expose_callback( GtkWidget
*widget
,
724 GdkEventExpose
*gdk_event
,
730 wxapp_install_idle_handler();
733 if (win->GetName() == wxT("panel"))
735 wxPrintf( wxT("OnExpose from ") );
736 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
737 wxPrintf( win->GetClassInfo()->GetClassName() );
738 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
739 (int)gdk_event->area.y,
740 (int)gdk_event->area.width,
741 (int)gdk_event->area.height );
745 GtkPizza
*pizza
= GTK_PIZZA (widget
);
747 if (win
->GetThemeEnabled())
749 wxWindow
*parent
= win
->GetParent();
750 while (parent
&& !parent
->IsTopLevel())
751 parent
= parent
->GetParent();
755 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
756 GTK_SHADOW_NONE
, &gdk_event
->area
, parent
->m_widget
, "base", 0, 0, -1, -1);
759 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
761 gdk_event
->area
.width
,
762 gdk_event
->area
.height
);
764 if (gdk_event
->count
== 0)
766 win
->m_clipPaintRegion
= TRUE
;
769 dc
.SetClippingRegion(win
->GetUpdateRegion());
770 wxEraseEvent
eevent( win
->GetId(), &dc
);
771 eevent
.SetEventObject( win
);
773 (void)win
->GetEventHandler()->ProcessEvent(eevent
);
775 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
777 wxClientDC
dc( win
);
778 dc
.SetBrush( wxBrush( win
->GetBackgroundColour(), wxSOLID
) );
779 dc
.SetPen( *wxTRANSPARENT_PEN
);
781 wxRegionIterator
upd( win
->GetUpdateRegion() );
784 dc
.DrawRectangle( upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
790 wxNcPaintEvent
eventNc( win
->GetId() );
791 eventNc
.SetEventObject( win
);
792 win
->GetEventHandler()->ProcessEvent( eventNc
);
794 wxPaintEvent
event( win
->GetId() );
795 event
.SetEventObject( win
);
796 win
->GetEventHandler()->ProcessEvent( event
);
798 win
->GetUpdateRegion().Clear();
800 win
->m_clipPaintRegion
= FALSE
;
803 /* The following code will result in all window-less widgets
804 being redrawn if the wxWindows class is given a chance to
805 paint *anything* because it will then be allowed to paint
806 over the window-less widgets */
807 GList
*children
= pizza
->children
;
810 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
811 children
= children
->next
;
813 GdkEventExpose child_event
= *gdk_event
;
815 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
816 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
817 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
819 child_event
.area
.x
= child
->widget
->allocation
.x
;
820 child_event
.area
.y
= child
->widget
->allocation
.y
;
821 child_event
.area
.width
= child
->widget
->allocation
.width
;
822 child_event
.area
.height
= child
->widget
->allocation
.height
;
823 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
830 //-----------------------------------------------------------------------------
831 // "event" of m_wxwindow
832 //-----------------------------------------------------------------------------
834 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
835 expose events. We need them, of course, so we override the main event
836 procedure in GtkWidget by giving our own handler for all system events.
837 There, we look for expose events ourselves whereas all other events are
840 gint
gtk_window_event_event_callback( GtkWidget
*widget
,
841 GdkEventExpose
*event
,
844 if (event
->type
== GDK_EXPOSE
)
846 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
853 //-----------------------------------------------------------------------------
854 // "draw" of m_wxwindow
855 //-----------------------------------------------------------------------------
857 /* This callback is a complete replacement of the gtk_pizza_draw() function,
860 static void gtk_window_draw_callback( GtkWidget
*widget
,
867 wxapp_install_idle_handler();
869 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
870 (win
->GetChildren().GetCount() == 0))
876 if (win->GetName() == wxT("panel"))
878 wxPrintf( wxT("OnDraw from ") );
879 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
880 wxPrintf( win->GetClassInfo()->GetClassName() );
881 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
888 GtkPizza
*pizza
= GTK_PIZZA (widget
);
890 if (win
->GetThemeEnabled())
892 wxWindow
*parent
= win
->GetParent();
893 while (parent
&& !parent
->IsTopLevel())
894 parent
= parent
->GetParent();
898 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
899 GTK_SHADOW_NONE
, rect
, parent
->m_widget
, "base", 0, 0, -1, -1);
903 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
904 (pizza
->clear_on_draw
))
906 gdk_window_clear_area( pizza
->bin_window
,
907 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
910 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
912 win
->m_clipPaintRegion
= TRUE
;
915 dc
.SetClippingRegion(win
->GetUpdateRegion());
916 wxEraseEvent
eevent( win
->GetId(), &dc
);
917 eevent
.SetEventObject( win
);
920 (void)win
->GetEventHandler()->ProcessEvent(eevent
);
922 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
924 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
926 wxClientDC
dc( win
);
927 dc
.SetBrush( wxBrush( win
->GetBackgroundColour(), wxSOLID
) );
928 dc
.SetPen( *wxTRANSPARENT_PEN
);
930 wxRegionIterator
upd( win
->GetUpdateRegion() );
933 dc
.DrawRectangle( upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
940 wxNcPaintEvent
eventNc( win
->GetId() );
941 eventNc
.SetEventObject( win
);
942 win
->GetEventHandler()->ProcessEvent( eventNc
);
944 wxPaintEvent
event( win
->GetId() );
945 event
.SetEventObject( win
);
946 win
->GetEventHandler()->ProcessEvent( event
);
948 win
->GetUpdateRegion().Clear();
950 win
->m_clipPaintRegion
= FALSE
;
953 GList
*children
= pizza
->children
;
956 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
957 children
= children
->next
;
959 GdkRectangle child_area
;
960 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
962 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
967 //-----------------------------------------------------------------------------
968 // "key_press_event" from any window
969 //-----------------------------------------------------------------------------
971 // turn on to see the key event codes on the console
972 #undef DEBUG_KEY_EVENTS
974 static gint
gtk_window_key_press_callback( GtkWidget
*widget
,
975 GdkEventKey
*gdk_event
,
981 wxapp_install_idle_handler();
983 if (!win
->m_hasVMT
) return FALSE
;
984 if (g_blockEventsOnDrag
) return FALSE
;
989 GdkModifierType state
;
990 if (gdk_event
->window
)
991 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
995 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
997 #ifdef DEBUG_KEY_EVENTS
998 wxPrintf(_T("Key press event: %d => %ld\n"), gdk_event
->keyval
, key_code
);
999 #endif // DEBUG_KEY_EVENTS
1001 /* sending unknown key events doesn't really make sense */
1005 wxKeyEvent
event( wxEVT_KEY_DOWN
);
1006 event
.SetTimestamp( gdk_event
->time
);
1007 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1008 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1009 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1010 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1011 event
.m_keyCode
= key_code
;
1012 event
.m_scanCode
= gdk_event
->keyval
;
1015 event
.SetEventObject( win
);
1016 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1021 wxWindowGTK
*ancestor
= win
;
1024 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
1027 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
1028 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
1031 if (ancestor
->IsTopLevel())
1033 ancestor
= ancestor
->GetParent();
1036 #endif // wxUSE_ACCEL
1038 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
1039 will only be sent if it is not in an accelerator table. */
1042 key_code
= map_to_wx_keysym( gdk_event
);
1046 #ifdef DEBUG_KEY_EVENTS
1047 wxPrintf(_T("Char event: %ld\n"), key_code
);
1048 #endif // DEBUG_KEY_EVENTS
1050 // reuse the ame event object, just change its type and use the
1051 // translated keycode instead of the raw one
1052 event
.SetEventType(wxEVT_CHAR
);
1053 event
.m_keyCode
= key_code
;
1055 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1059 /* win is a control: tab can be propagated up */
1061 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
1062 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
1063 // have this style, yet choose not to process this particular TAB in which
1064 // case TAB must still work as a navigational character
1066 !win
->HasFlag(wxTE_PROCESS_TAB
) &&
1068 win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
1070 wxNavigationKeyEvent new_event
;
1071 new_event
.SetEventObject( win
->GetParent() );
1072 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
1073 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
1074 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1075 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
1076 new_event
.SetCurrentFocus( win
);
1077 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
1080 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
1082 (gdk_event
->keyval
== GDK_Escape
) )
1084 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
1085 new_event
.SetEventObject( win
);
1086 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
1090 #if 0 // (GTK_MINOR_VERSION > 0)
1091 /* Pressing F10 will activate the menu bar of the top frame. */
1093 (gdk_event
->keyval
== GDK_F10
) )
1095 wxWindowGTK
*ancestor
= win
;
1098 if (wxIsKindOf(ancestor
,wxFrame
))
1100 wxFrame
*frame
= (wxFrame
*) ancestor
;
1101 wxMenuBar
*menubar
= frame
->GetMenuBar();
1104 wxNode
*node
= menubar
->GetMenus().First();
1107 wxMenu
*firstMenu
= (wxMenu
*) node
->Data();
1108 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu
->m_owner
) );
1114 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
;
1142 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
1144 #ifdef DEBUG_KEY_EVENTS
1145 wxPrintf(_T("Key release event: %d => %ld\n"), gdk_event
->keyval
, key_code
);
1146 #endif // DEBUG_KEY_EVENTS
1148 /* sending unknown key events doesn't really make sense */
1149 if (key_code
== 0) return FALSE
;
1153 GdkModifierType state
;
1154 if (gdk_event
->window
)
1155 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1157 wxKeyEvent
event( wxEVT_KEY_UP
);
1158 event
.SetTimestamp( gdk_event
->time
);
1159 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1160 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1161 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1162 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1163 event
.m_keyCode
= key_code
;
1164 event
.m_scanCode
= gdk_event
->keyval
;
1167 event
.SetEventObject( win
);
1169 if (win
->GetEventHandler()->ProcessEvent( event
))
1171 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1178 // ----------------------------------------------------------------------------
1179 // mouse event processing helper
1180 // ----------------------------------------------------------------------------
1182 static void AdjustEventButtonState(wxMouseEvent
& event
)
1184 // GDK reports the old state of the button for a button press event, but
1185 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1186 // for a LEFT_DOWN event, not FALSE, so we will invert
1187 // left/right/middleDown for the corresponding click events
1189 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1190 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1191 (event
.GetEventType() == wxEVT_LEFT_UP
))
1193 event
.m_leftDown
= !event
.m_leftDown
;
1197 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1198 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1199 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1201 event
.m_middleDown
= !event
.m_middleDown
;
1205 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1206 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1207 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1209 event
.m_rightDown
= !event
.m_rightDown
;
1214 //-----------------------------------------------------------------------------
1215 // "button_press_event"
1216 //-----------------------------------------------------------------------------
1218 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1223 wxapp_install_idle_handler();
1226 wxPrintf( wxT("1) OnButtonPress from ") );
1227 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1228 wxPrintf( win->GetClassInfo()->GetClassName() );
1229 wxPrintf( wxT(".\n") );
1231 if (!win
->m_hasVMT
) return FALSE
;
1232 if (g_blockEventsOnDrag
) return TRUE
;
1233 if (g_blockEventsOnScroll
) return TRUE
;
1235 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1237 if (win
->m_wxwindow
)
1239 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1241 gtk_widget_grab_focus (win
->m_wxwindow
);
1244 wxPrintf( wxT("GrabFocus from ") );
1245 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1246 wxPrintf( win->GetClassInfo()->GetClassName() );
1247 wxPrintf( wxT(".\n") );
1253 wxEventType event_type
= wxEVT_NULL
;
1255 if (gdk_event
->button
== 1)
1257 switch (gdk_event
->type
)
1259 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1260 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1264 else if (gdk_event
->button
== 2)
1266 switch (gdk_event
->type
)
1268 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1269 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1273 else if (gdk_event
->button
== 3)
1275 switch (gdk_event
->type
)
1277 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1278 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1283 if ( event_type
== wxEVT_NULL
)
1285 // unknown mouse button or click type
1289 wxMouseEvent
event( event_type
);
1290 event
.SetTimestamp( gdk_event
->time
);
1291 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1292 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1293 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1294 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1295 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1296 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1297 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1299 event
.m_x
= (wxCoord
)gdk_event
->x
;
1300 event
.m_y
= (wxCoord
)gdk_event
->y
;
1302 AdjustEventButtonState(event
);
1304 // Some control don't have their own X window and thus cannot get
1307 if (!g_captureWindow
)
1309 wxCoord x
= event
.m_x
;
1310 wxCoord y
= event
.m_y
;
1311 if (win
->m_wxwindow
)
1313 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1314 x
+= pizza
->xoffset
;
1315 y
+= pizza
->yoffset
;
1318 wxNode
*node
= win
->GetChildren().First();
1321 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1323 node
= node
->Next();
1324 if (!child
->IsShown())
1327 if (child
->m_isStaticBox
)
1329 // wxStaticBox is transparent in the box itself
1330 int xx1
= child
->m_x
;
1331 int yy1
= child
->m_y
;
1332 int xx2
= child
->m_x
+ child
->m_width
;
1333 int yy2
= child
->m_x
+ child
->m_height
;
1336 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1338 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1340 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1342 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1345 event
.m_x
-= child
->m_x
;
1346 event
.m_y
-= child
->m_y
;
1353 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1354 (child
->m_x
<= x
) &&
1355 (child
->m_y
<= y
) &&
1356 (child
->m_x
+child
->m_width
>= x
) &&
1357 (child
->m_y
+child
->m_height
>= y
))
1360 event
.m_x
-= child
->m_x
;
1361 event
.m_y
-= child
->m_y
;
1368 event
.SetEventObject( win
);
1370 gs_timeLastClick
= gdk_event
->time
;
1373 wxPrintf( wxT("2) OnButtonPress from ") );
1374 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1375 wxPrintf( win->GetClassInfo()->GetClassName() );
1376 wxPrintf( wxT(".\n") );
1379 if (win
->GetEventHandler()->ProcessEvent( event
))
1381 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1388 //-----------------------------------------------------------------------------
1389 // "button_release_event"
1390 //-----------------------------------------------------------------------------
1392 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1397 wxapp_install_idle_handler();
1399 if (!win
->m_hasVMT
) return FALSE
;
1400 if (g_blockEventsOnDrag
) return FALSE
;
1401 if (g_blockEventsOnScroll
) return FALSE
;
1403 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1406 printf( "OnButtonRelease from " );
1407 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1408 printf( win->GetClassInfo()->GetClassName() );
1412 wxEventType event_type
= wxEVT_NULL
;
1414 switch (gdk_event
->button
)
1416 case 1: event_type
= wxEVT_LEFT_UP
; break;
1417 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1418 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1419 default: return FALSE
;
1422 wxMouseEvent
event( event_type
);
1423 event
.SetTimestamp( gdk_event
->time
);
1424 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1425 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1426 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1427 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1428 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1429 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1430 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1431 event
.m_x
= (wxCoord
)gdk_event
->x
;
1432 event
.m_y
= (wxCoord
)gdk_event
->y
;
1434 AdjustEventButtonState(event
);
1436 // Some control don't have their own X window and thus cannot get
1439 if (!g_captureWindow
)
1441 wxCoord x
= event
.m_x
;
1442 wxCoord y
= event
.m_y
;
1443 if (win
->m_wxwindow
)
1445 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1446 x
+= pizza
->xoffset
;
1447 y
+= pizza
->yoffset
;
1450 wxNode
*node
= win
->GetChildren().First();
1453 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1455 node
= node
->Next();
1456 if (!child
->IsShown())
1459 if (child
->m_isStaticBox
)
1461 // wxStaticBox is transparent in the box itself
1462 int xx1
= child
->m_x
;
1463 int yy1
= child
->m_y
;
1464 int xx2
= child
->m_x
+ child
->m_width
;
1465 int yy2
= child
->m_x
+ child
->m_height
;
1468 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1470 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1472 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1474 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1477 event
.m_x
-= child
->m_x
;
1478 event
.m_y
-= child
->m_y
;
1485 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1486 (child
->m_x
<= x
) &&
1487 (child
->m_y
<= y
) &&
1488 (child
->m_x
+child
->m_width
>= x
) &&
1489 (child
->m_y
+child
->m_height
>= y
))
1492 event
.m_x
-= child
->m_x
;
1493 event
.m_y
-= child
->m_y
;
1500 event
.SetEventObject( win
);
1502 if (win
->GetEventHandler()->ProcessEvent( event
))
1504 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1511 // ============================================================================
1513 // ============================================================================
1515 // init wxMouseEvent with the info from gdk_event
1516 #define InitMouseEvent(event, gdk_event) \
1517 event.SetTimestamp( gdk_event->time ); \
1518 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
1519 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
1520 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
1521 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
1522 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
1523 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
1524 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
1526 event.m_x = (wxCoord)gdk_event->x; \
1527 event.m_y = (wxCoord)gdk_event->y \
1529 //-----------------------------------------------------------------------------
1530 // "motion_notify_event"
1531 //-----------------------------------------------------------------------------
1533 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
,
1534 GdkEventMotion
*gdk_event
,
1540 wxapp_install_idle_handler();
1542 if (!win
->m_hasVMT
) return FALSE
;
1543 if (g_blockEventsOnDrag
) return FALSE
;
1544 if (g_blockEventsOnScroll
) return FALSE
;
1546 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1548 if (gdk_event
->is_hint
)
1552 GdkModifierType state
;
1553 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1559 printf( "OnMotion from " );
1560 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1561 printf( win->GetClassInfo()->GetClassName() );
1565 wxMouseEvent
event( wxEVT_MOTION
);
1566 InitMouseEvent(event
, gdk_event
);
1568 if ( g_captureWindow
)
1570 // synthetize a mouse enter or leave event if needed
1571 GdkWindow
*winUnderMouse
= gdk_window_at_pointer(NULL
, NULL
);
1572 bool hasMouse
= winUnderMouse
== gdk_event
->window
;
1573 if ( hasMouse
!= g_captureWindowHasMouse
)
1575 // the mouse changed window
1576 g_captureWindowHasMouse
= hasMouse
;
1578 wxMouseEvent
event(g_captureWindowHasMouse
? wxEVT_ENTER_WINDOW
1579 : wxEVT_LEAVE_WINDOW
);
1580 InitMouseEvent(event
, gdk_event
);
1581 event
.SetEventObject(win
);
1582 win
->GetEventHandler()->ProcessEvent(event
);
1587 // Some control don't have their own X window and thus cannot get
1590 wxCoord x
= event
.m_x
;
1591 wxCoord y
= event
.m_y
;
1592 if (win
->m_wxwindow
)
1594 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1595 x
+= pizza
->xoffset
;
1596 y
+= pizza
->yoffset
;
1599 wxNode
*node
= win
->GetChildren().First();
1602 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1604 node
= node
->Next();
1605 if (!child
->IsShown())
1608 if (child
->m_isStaticBox
)
1610 // wxStaticBox is transparent in the box itself
1611 int xx1
= child
->m_x
;
1612 int yy1
= child
->m_y
;
1613 int xx2
= child
->m_x
+ child
->m_width
;
1614 int yy2
= child
->m_x
+ child
->m_height
;
1617 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1619 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1621 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1623 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1626 event
.m_x
-= child
->m_x
;
1627 event
.m_y
-= child
->m_y
;
1634 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1635 (child
->m_x
<= x
) &&
1636 (child
->m_y
<= y
) &&
1637 (child
->m_x
+child
->m_width
>= x
) &&
1638 (child
->m_y
+child
->m_height
>= y
))
1641 event
.m_x
-= child
->m_x
;
1642 event
.m_y
-= child
->m_y
;
1649 event
.SetEventObject( win
);
1651 if (win
->GetEventHandler()->ProcessEvent( event
))
1653 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1660 //-----------------------------------------------------------------------------
1662 //-----------------------------------------------------------------------------
1664 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
,
1665 GdkEvent
*WXUNUSED(event
),
1671 wxapp_install_idle_handler();
1673 if (!win
->m_hasVMT
) return FALSE
;
1674 if (g_blockEventsOnDrag
) return FALSE
;
1676 switch ( g_sendActivateEvent
)
1679 // we've got focus from outside, synthetize wxActivateEvent
1680 g_sendActivateEvent
= 1;
1684 // another our window just lost focus, it was already ours before
1685 // - don't send any wxActivateEvent
1686 g_sendActivateEvent
= -1;
1691 g_focusWindow
= win
;
1694 wxPrintf( "OnSetFocus from " );
1695 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
1696 wxPrintf( win
->GetClassInfo()->GetClassName() );
1700 // notify the parent keeping track of focus for the kbd navigation
1701 // purposes that we got it
1702 wxChildFocusEvent
eventFocus(win
);
1703 (void)win
->GetEventHandler()->ProcessEvent(eventFocus
);
1707 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1711 // caret needs to be informed about focus change
1712 wxCaret
*caret
= win
->GetCaret();
1715 caret
->OnSetFocus();
1717 #endif // wxUSE_CARET
1719 wxWindowGTK
*active
= wxGetTopLevelParent(win
);
1720 if ( active
!= g_activeFrame
)
1722 if ( g_activeFrame
)
1724 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame
);
1725 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
1726 event
.SetEventObject(g_activeFrame
);
1727 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1730 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active
);
1731 g_activeFrame
= active
;
1732 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId());
1733 event
.SetEventObject(g_activeFrame
);
1734 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1736 g_activeFrameLostFocus
= FALSE
;
1739 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1740 event
.SetEventObject( win
);
1742 if (win
->GetEventHandler()->ProcessEvent( event
))
1744 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1752 //-----------------------------------------------------------------------------
1753 // "focus_out_event"
1754 //-----------------------------------------------------------------------------
1756 static GtkWidget
*gs_widgetLastFocus
= NULL
;
1758 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindowGTK
*win
)
1763 wxapp_install_idle_handler();
1765 if (!win
->m_hasVMT
) return FALSE
;
1766 if (g_blockEventsOnDrag
) return FALSE
;
1768 // VZ: this is really weird but GTK+ seems to call us from inside
1769 // gtk_widget_grab_focus(), i.e. it first sends "focus_out" signal to
1770 // this widget and then "focus_in". This is totally unexpected and
1771 // completely breaks wxUniv code so ignore this dummy event (we can't
1772 // be losing focus if we're about to acquire it!)
1773 if ( widget
== gs_widgetLastFocus
)
1775 gs_widgetLastFocus
= NULL
;
1780 if ( !g_activeFrameLostFocus
&& g_activeFrame
)
1782 wxASSERT_MSG( wxGetTopLevelParent(win
) == g_activeFrame
, wxT("unfocusing window that haven't gained focus properly") )
1783 g_activeFrameLostFocus
= TRUE
;
1786 // if the focus goes out of our app alltogether, OnIdle() will send
1787 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1788 // g_sendActivateEvent to -1
1789 g_sendActivateEvent
= 0;
1791 wxWindowGTK
*winFocus
= wxFindFocusedChild(win
);
1795 g_focusWindow
= (wxWindowGTK
*)NULL
;
1798 wxPrintf( "OnKillFocus from " );
1799 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
1800 wxPrintf( win
->GetClassInfo()->GetClassName() );
1810 // caret needs to be informed about focus change
1811 wxCaret
*caret
= win
->GetCaret();
1814 caret
->OnKillFocus();
1816 #endif // wxUSE_CARET
1818 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1819 event
.SetEventObject( win
);
1821 if (win
->GetEventHandler()->ProcessEvent( event
))
1823 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1830 //-----------------------------------------------------------------------------
1831 // "enter_notify_event"
1832 //-----------------------------------------------------------------------------
1834 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1839 wxapp_install_idle_handler();
1841 if (!win
->m_hasVMT
) return FALSE
;
1842 if (g_blockEventsOnDrag
) return FALSE
;
1844 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1846 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1847 event
.SetTimestamp( gdk_event
->time
);
1848 event
.SetEventObject( win
);
1852 GdkModifierType state
= (GdkModifierType
)0;
1854 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1856 InitMouseEvent(event
, gdk_event
);
1861 if (win
->GetEventHandler()->ProcessEvent( event
))
1863 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1870 //-----------------------------------------------------------------------------
1871 // "leave_notify_event"
1872 //-----------------------------------------------------------------------------
1874 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1879 wxapp_install_idle_handler();
1881 if (!win
->m_hasVMT
) return FALSE
;
1882 if (g_blockEventsOnDrag
) return FALSE
;
1884 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1886 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1887 event
.SetTimestamp( gdk_event
->time
);
1888 event
.SetEventObject( win
);
1892 GdkModifierType state
= (GdkModifierType
)0;
1894 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1896 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1897 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1898 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1899 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1900 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1901 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1902 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1907 if (win
->GetEventHandler()->ProcessEvent( event
))
1909 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1916 //-----------------------------------------------------------------------------
1917 // "value_changed" from m_vAdjust
1918 //-----------------------------------------------------------------------------
1920 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1925 wxapp_install_idle_handler();
1927 if (g_blockEventsOnDrag
) return;
1929 if (!win
->m_hasVMT
) return;
1931 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1932 if (fabs(diff
) < 0.2) return;
1934 win
->m_oldVerticalPos
= adjust
->value
;
1936 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1937 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1939 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1940 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1941 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1942 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1943 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1945 int value
= (int)(adjust
->value
+0.5);
1947 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1948 event
.SetEventObject( win
);
1949 win
->GetEventHandler()->ProcessEvent( event
);
1952 //-----------------------------------------------------------------------------
1953 // "value_changed" from m_hAdjust
1954 //-----------------------------------------------------------------------------
1956 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1961 wxapp_install_idle_handler();
1963 if (g_blockEventsOnDrag
) return;
1964 if (!win
->m_hasVMT
) return;
1966 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1967 if (fabs(diff
) < 0.2) return;
1969 win
->m_oldHorizontalPos
= adjust
->value
;
1971 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1972 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1974 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1975 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1976 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1977 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1978 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1980 int value
= (int)(adjust
->value
+0.5);
1982 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1983 event
.SetEventObject( win
);
1984 win
->GetEventHandler()->ProcessEvent( event
);
1987 //-----------------------------------------------------------------------------
1988 // "button_press_event" from scrollbar
1989 //-----------------------------------------------------------------------------
1991 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1992 GdkEventButton
*gdk_event
,
1998 wxapp_install_idle_handler();
2001 g_blockEventsOnScroll
= TRUE
;
2002 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
2007 //-----------------------------------------------------------------------------
2008 // "button_release_event" from scrollbar
2009 //-----------------------------------------------------------------------------
2011 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
2012 GdkEventButton
*WXUNUSED(gdk_event
),
2017 // don't test here as we can release the mouse while being over
2018 // a different window than the slider
2020 // if (gdk_event->window != widget->slider) return FALSE;
2022 g_blockEventsOnScroll
= FALSE
;
2024 if (win
->m_isScrolling
)
2026 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
2030 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
2031 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
2033 value
= (int)(win
->m_hAdjust
->value
+0.5);
2036 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
2038 value
= (int)(win
->m_vAdjust
->value
+0.5);
2042 wxScrollWinEvent
event( command
, value
, dir
);
2043 event
.SetEventObject( win
);
2044 win
->GetEventHandler()->ProcessEvent( event
);
2047 win
->m_isScrolling
= FALSE
;
2052 // ----------------------------------------------------------------------------
2053 // this wxWindowBase function is implemented here (in platform-specific file)
2054 // because it is static and so couldn't be made virtual
2055 // ----------------------------------------------------------------------------
2057 wxWindow
*wxWindowBase::FindFocus()
2059 // the cast is necessary when we compile in wxUniversal mode
2060 return (wxWindow
*)g_focusWindow
;
2063 //-----------------------------------------------------------------------------
2064 // "realize" from m_widget
2065 //-----------------------------------------------------------------------------
2067 /* We cannot set colours and fonts before the widget has
2068 been realized, so we do this directly after realization. */
2071 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
2076 wxapp_install_idle_handler();
2078 if (win
->m_delayedBackgroundColour
)
2079 win
->SetBackgroundColour( win
->GetBackgroundColour() );
2081 if (win
->m_delayedForegroundColour
)
2082 win
->SetForegroundColour( win
->GetForegroundColour() );
2084 wxWindowCreateEvent
event( win
);
2085 event
.SetEventObject( win
);
2086 win
->GetEventHandler()->ProcessEvent( event
);
2091 //-----------------------------------------------------------------------------
2093 //-----------------------------------------------------------------------------
2096 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
2097 GtkAllocation
*WXUNUSED(alloc
),
2101 wxapp_install_idle_handler();
2103 if (!win
->m_hasScrolling
) return;
2105 int client_width
= 0;
2106 int client_height
= 0;
2107 win
->GetClientSize( &client_width
, &client_height
);
2108 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
2111 win
->m_oldClientWidth
= client_width
;
2112 win
->m_oldClientHeight
= client_height
;
2114 if (!win
->m_nativeSizeEvent
)
2116 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
2117 event
.SetEventObject( win
);
2118 win
->GetEventHandler()->ProcessEvent( event
);
2124 #define WXUNUSED_UNLESS_XIM(param) param
2126 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2129 /* Resize XIM window */
2132 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2133 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
2134 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2137 wxapp_install_idle_handler();
2143 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
2147 gdk_window_get_size (widget
->window
, &width
, &height
);
2148 win
->m_icattr
->preedit_area
.width
= width
;
2149 win
->m_icattr
->preedit_area
.height
= height
;
2150 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2155 //-----------------------------------------------------------------------------
2156 // "realize" from m_wxwindow
2157 //-----------------------------------------------------------------------------
2159 /* Initialize XIM support */
2162 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2163 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2166 wxapp_install_idle_handler();
2169 if (win
->m_ic
) return FALSE
;
2170 if (!widget
) return FALSE
;
2171 if (!gdk_im_ready()) return FALSE
;
2173 win
->m_icattr
= gdk_ic_attr_new();
2174 if (!win
->m_icattr
) return FALSE
;
2178 GdkColormap
*colormap
;
2179 GdkICAttr
*attr
= win
->m_icattr
;
2180 unsigned attrmask
= GDK_IC_ALL_REQ
;
2182 GdkIMStyle supported_style
= (GdkIMStyle
)
2183 (GDK_IM_PREEDIT_NONE
|
2184 GDK_IM_PREEDIT_NOTHING
|
2185 GDK_IM_PREEDIT_POSITION
|
2186 GDK_IM_STATUS_NONE
|
2187 GDK_IM_STATUS_NOTHING
);
2189 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2190 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2192 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2193 attr
->client_window
= widget
->window
;
2195 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2196 gtk_widget_get_default_colormap ())
2198 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2199 attr
->preedit_colormap
= colormap
;
2202 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2203 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2204 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2205 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2207 switch (style
& GDK_IM_PREEDIT_MASK
)
2209 case GDK_IM_PREEDIT_POSITION
:
2210 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2212 g_warning ("over-the-spot style requires fontset");
2216 gdk_window_get_size (widget
->window
, &width
, &height
);
2218 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2219 attr
->spot_location
.x
= 0;
2220 attr
->spot_location
.y
= height
;
2221 attr
->preedit_area
.x
= 0;
2222 attr
->preedit_area
.y
= 0;
2223 attr
->preedit_area
.width
= width
;
2224 attr
->preedit_area
.height
= height
;
2225 attr
->preedit_fontset
= widget
->style
->font
;
2230 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2232 if (win
->m_ic
== NULL
)
2233 g_warning ("Can't create input context.");
2236 mask
= gdk_window_get_events (widget
->window
);
2237 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2238 gdk_window_set_events (widget
->window
, mask
);
2240 if (GTK_WIDGET_HAS_FOCUS(widget
))
2241 gdk_im_begin (win
->m_ic
, widget
->window
);
2248 //-----------------------------------------------------------------------------
2249 // InsertChild for wxWindowGTK.
2250 //-----------------------------------------------------------------------------
2252 /* Callback for wxWindowGTK. This very strange beast has to be used because
2253 * C++ has no virtual methods in a constructor. We have to emulate a
2254 * virtual function here as wxNotebook requires a different way to insert
2255 * a child in it. I had opted for creating a wxNotebookPage window class
2256 * which would have made this superfluous (such in the MDI window system),
2257 * but no-one was listening to me... */
2259 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child
)
2261 /* the window might have been scrolled already, do we
2262 have to adapt the position */
2263 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2264 child
->m_x
+= pizza
->xoffset
;
2265 child
->m_y
+= pizza
->yoffset
;
2267 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2268 GTK_WIDGET(child
->m_widget
),
2275 //-----------------------------------------------------------------------------
2277 //-----------------------------------------------------------------------------
2279 wxWindow
*wxGetActiveWindow()
2281 // the cast is necessary when we compile in wxUniversal mode
2282 return (wxWindow
*)g_focusWindow
;
2285 //-----------------------------------------------------------------------------
2287 //-----------------------------------------------------------------------------
2289 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
2291 #ifdef __WXUNIVERSAL__
2292 IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
)
2294 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2295 #endif // __WXUNIVERSAL__/__WXGTK__
2297 void wxWindowGTK::Init()
2303 m_widget
= (GtkWidget
*) NULL
;
2304 m_wxwindow
= (GtkWidget
*) NULL
;
2305 m_focusWidget
= (GtkWidget
*) NULL
;
2315 m_needParent
= TRUE
;
2316 m_isBeingDeleted
= FALSE
;
2319 m_nativeSizeEvent
= FALSE
;
2321 m_hasScrolling
= FALSE
;
2322 m_isScrolling
= FALSE
;
2324 m_hAdjust
= (GtkAdjustment
*) NULL
;
2325 m_vAdjust
= (GtkAdjustment
*) NULL
;
2326 m_oldHorizontalPos
= 0.0;
2327 m_oldVerticalPos
= 0.0;
2330 m_widgetStyle
= (GtkStyle
*) NULL
;
2332 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2334 m_isStaticBox
= FALSE
;
2335 m_isRadioButton
= FALSE
;
2337 m_acceptsFocus
= FALSE
;
2339 m_clipPaintRegion
= FALSE
;
2341 m_cursor
= *wxSTANDARD_CURSOR
;
2343 m_delayedForegroundColour
= FALSE
;
2344 m_delayedBackgroundColour
= FALSE
;
2347 m_ic
= (GdkIC
*) NULL
;
2348 m_icattr
= (GdkICAttr
*) NULL
;
2352 wxWindowGTK::wxWindowGTK()
2357 wxWindowGTK::wxWindowGTK( wxWindow
*parent
,
2362 const wxString
&name
)
2366 Create( parent
, id
, pos
, size
, style
, name
);
2369 bool wxWindowGTK::Create( wxWindow
*parent
,
2374 const wxString
&name
)
2376 if (!PreCreation( parent
, pos
, size
) ||
2377 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2379 wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
2383 m_insertCallback
= wxInsertChildInWindow
;
2385 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2386 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2388 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2390 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2391 scroll_class
->scrollbar_spacing
= 0;
2393 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2395 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2396 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2398 m_wxwindow
= gtk_pizza_new();
2400 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2402 #ifndef __WXUNIVERSAL__
2403 #if (GTK_MINOR_VERSION > 0)
2404 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2406 if (HasFlag(wxRAISED_BORDER
))
2408 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2410 else if (HasFlag(wxSUNKEN_BORDER
))
2412 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2414 else if (HasFlag(wxSIMPLE_BORDER
))
2416 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2420 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2422 #else // GTK_MINOR_VERSION == 0
2423 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2425 if (HasFlag(wxRAISED_BORDER
))
2427 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2429 else if (HasFlag(wxSUNKEN_BORDER
))
2431 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2435 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2437 #endif // GTK_MINOR_VERSION
2438 #endif // __WXUNIVERSAL__
2440 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2441 m_acceptsFocus
= TRUE
;
2443 #if (GTK_MINOR_VERSION == 0)
2444 // shut the viewport up
2445 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2446 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2447 #endif // GTK_MINOR_VERSION == 0
2449 // I _really_ don't want scrollbars in the beginning
2450 m_vAdjust
->lower
= 0.0;
2451 m_vAdjust
->upper
= 1.0;
2452 m_vAdjust
->value
= 0.0;
2453 m_vAdjust
->step_increment
= 1.0;
2454 m_vAdjust
->page_increment
= 1.0;
2455 m_vAdjust
->page_size
= 5.0;
2456 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2457 m_hAdjust
->lower
= 0.0;
2458 m_hAdjust
->upper
= 1.0;
2459 m_hAdjust
->value
= 0.0;
2460 m_hAdjust
->step_increment
= 1.0;
2461 m_hAdjust
->page_increment
= 1.0;
2462 m_hAdjust
->page_size
= 5.0;
2463 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2465 // these handlers block mouse events to any window during scrolling such as
2466 // motion events and prevent GTK and wxWindows from fighting over where the
2469 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2470 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2472 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2473 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2475 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2476 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2478 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2479 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2481 // these handlers get notified when screen updates are required either when
2482 // scrolling or when the window size (and therefore scrollbar configuration)
2485 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2486 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2487 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2488 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2490 gtk_widget_show( m_wxwindow
);
2493 m_parent
->DoAddChild( this );
2495 m_focusWidget
= m_wxwindow
;
2504 wxWindowGTK::~wxWindowGTK()
2506 if (g_focusWindow
== this)
2507 g_focusWindow
= NULL
;
2509 if (g_activeFrame
== this)
2510 g_activeFrame
= NULL
;
2512 m_isBeingDeleted
= TRUE
;
2521 m_parent
->RemoveChild( this );
2525 gdk_ic_destroy (m_ic
);
2527 gdk_ic_attr_destroy (m_icattr
);
2532 #if DISABLE_STYLE_IF_BROKEN_THEME
2533 // don't delete if it's a pixmap theme style
2534 if (!m_widgetStyle
->engine_data
)
2535 gtk_style_unref( m_widgetStyle
);
2537 m_widgetStyle
= (GtkStyle
*) NULL
;
2542 gtk_widget_destroy( m_wxwindow
);
2543 m_wxwindow
= (GtkWidget
*) NULL
;
2548 gtk_widget_destroy( m_widget
);
2549 m_widget
= (GtkWidget
*) NULL
;
2553 bool wxWindowGTK::PreCreation( wxWindowGTK
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2555 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2557 /* this turns -1 into 20 so that a minimal window is
2558 visible even although -1,-1 has been given as the
2559 size of the window. the same trick is used in other
2560 ports and should make debugging easier */
2561 m_width
= WidthDefault(size
.x
);
2562 m_height
= HeightDefault(size
.y
);
2567 /* some reasonable defaults */
2572 m_x
= (gdk_screen_width () - m_width
) / 2;
2573 if (m_x
< 10) m_x
= 10;
2577 m_y
= (gdk_screen_height () - m_height
) / 2;
2578 if (m_y
< 10) m_y
= 10;
2585 void wxWindowGTK::PostCreation()
2587 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2593 // these get reported to wxWindows -> wxPaintEvent
2595 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2597 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2598 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2600 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2601 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2603 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2605 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2606 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2610 // these are called when the "sunken" or "raised" borders are drawn */
2611 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2612 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2614 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2615 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2620 if (m_focusWidget
== NULL
)
2621 m_focusWidget
= m_widget
;
2624 if (GetClassInfo() && GetClassInfo()->GetClassName())
2625 wxPrintf( GetClassInfo()->GetClassName() );
2629 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event",
2630 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2632 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event",
2633 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2635 // connect to the various key and mouse handlers
2637 GtkWidget
*connect_widget
= GetConnectWidget();
2639 ConnectWidget( connect_widget
);
2641 /* We cannot set colours, fonts and cursors before the widget has
2642 been realized, so we do this directly after realization */
2643 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2644 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2648 // Catch native resize events
2649 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2650 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2652 // Initialize XIM support
2653 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2654 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2656 // And resize XIM window
2657 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2658 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2661 if (!GTK_IS_COMBO(m_widget
))
2663 // This is needed if we want to add our windows into native
2664 // GTK control, such as the toolbar. With this callback, the
2665 // toolbar gets to know the correct size (the one set by the
2666 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2667 // when moving to GTK 2.0.
2668 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2669 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2675 void wxWindowGTK::ConnectWidget( GtkWidget
*widget
)
2677 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2678 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2680 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2681 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2683 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2684 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2686 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2687 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2689 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2690 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2692 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2693 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2695 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2696 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2699 bool wxWindowGTK::Destroy()
2701 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2705 return wxWindowBase::Destroy();
2708 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
)
2710 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2713 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2715 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2716 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") );
2719 printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
2722 if (m_resizing
) return; /* I don't like recursions */
2725 int currentX
, currentY
;
2726 GetPosition(¤tX
, ¤tY
);
2731 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
2733 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2735 /* don't set the size for children of wxNotebook, just take the values. */
2743 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2745 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2747 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2748 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2749 if (width
!= -1) m_width
= width
;
2750 if (height
!= -1) m_height
= height
;
2754 m_x
= x
+ pizza
->xoffset
;
2755 m_y
= y
+ pizza
->yoffset
;
2760 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2762 if (width
== -1) m_width
= 80;
2765 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2767 if (height
== -1) m_height
= 26;
2770 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2771 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2772 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2773 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2776 int bottom_border
= 0;
2778 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2780 /* the default button has a border around it */
2785 DoMoveWindow( m_x
-border
,
2788 m_height
+border
+bottom_border
);
2793 /* Sometimes the client area changes size without the
2794 whole windows's size changing, but if the whole
2795 windows's size doesn't change, no wxSizeEvent will
2796 normally be sent. Here we add an extra test if
2797 the client test has been changed and this will
2799 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2803 wxPrintf( "OnSize sent from " );
2804 if (GetClassInfo() && GetClassInfo()->GetClassName())
2805 wxPrintf( GetClassInfo()->GetClassName() );
2806 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2809 if (!m_nativeSizeEvent
)
2811 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2812 event
.SetEventObject( this );
2813 GetEventHandler()->ProcessEvent( event
);
2819 void wxWindowGTK::OnInternalIdle()
2821 if ( g_sendActivateEvent
!= -1 )
2823 bool activate
= g_sendActivateEvent
!= 0;
2826 g_sendActivateEvent
= -1;
2828 wxTheApp
->SetActive(activate
, (wxWindow
*)g_focusWindowLast
);
2831 if ( g_activeFrameLostFocus
)
2833 if ( g_activeFrame
)
2835 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame
);
2836 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
2837 event
.SetEventObject(g_activeFrame
);
2838 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
2839 g_activeFrame
= NULL
;
2841 g_activeFrameLostFocus
= FALSE
;
2844 wxCursor cursor
= m_cursor
;
2845 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2849 /* I now set the cursor anew in every OnInternalIdle call
2850 as setting the cursor in a parent window also effects the
2851 windows above so that checking for the current cursor is
2856 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2858 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2860 if (!g_globalCursor
.Ok())
2861 cursor
= *wxSTANDARD_CURSOR
;
2863 window
= m_widget
->window
;
2864 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2865 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2871 GdkWindow
*window
= m_widget
->window
;
2872 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2873 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2881 void wxWindowGTK::DoGetSize( int *width
, int *height
) const
2883 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2885 if (width
) (*width
) = m_width
;
2886 if (height
) (*height
) = m_height
;
2889 void wxWindowGTK::DoSetClientSize( int width
, int height
)
2891 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2895 SetSize( width
, height
);
2902 #ifndef __WXUNIVERSAL__
2903 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2905 /* when using GTK 1.2 we set the shadow border size to 2 */
2909 if (HasFlag(wxSIMPLE_BORDER
))
2911 /* when using GTK 1.2 we set the simple border size to 1 */
2915 #endif // __WXUNIVERSAL__
2919 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2921 GtkRequisition vscroll_req
;
2922 vscroll_req
.width
= 2;
2923 vscroll_req
.height
= 2;
2924 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2925 (scroll_window
->vscrollbar
, &vscroll_req
);
2927 GtkRequisition hscroll_req
;
2928 hscroll_req
.width
= 2;
2929 hscroll_req
.height
= 2;
2930 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2931 (scroll_window
->hscrollbar
, &hscroll_req
);
2933 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2935 if (scroll_window
->vscrollbar_visible
)
2937 dw
+= vscroll_req
.width
;
2938 dw
+= scroll_class
->scrollbar_spacing
;
2941 if (scroll_window
->hscrollbar_visible
)
2943 dh
+= hscroll_req
.height
;
2944 dh
+= scroll_class
->scrollbar_spacing
;
2948 SetSize( width
+dw
, height
+dh
);
2952 void wxWindowGTK::DoGetClientSize( int *width
, int *height
) const
2954 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2958 if (width
) (*width
) = m_width
;
2959 if (height
) (*height
) = m_height
;
2966 #ifndef __WXUNIVERSAL__
2967 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2969 /* when using GTK 1.2 we set the shadow border size to 2 */
2973 if (HasFlag(wxSIMPLE_BORDER
))
2975 /* when using GTK 1.2 we set the simple border size to 1 */
2979 #endif // __WXUNIVERSAL__
2983 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2985 GtkRequisition vscroll_req
;
2986 vscroll_req
.width
= 2;
2987 vscroll_req
.height
= 2;
2988 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2989 (scroll_window
->vscrollbar
, &vscroll_req
);
2991 GtkRequisition hscroll_req
;
2992 hscroll_req
.width
= 2;
2993 hscroll_req
.height
= 2;
2994 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2995 (scroll_window
->hscrollbar
, &hscroll_req
);
2997 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2999 if (scroll_window
->vscrollbar_visible
)
3001 dw
+= vscroll_req
.width
;
3002 dw
+= scroll_class
->scrollbar_spacing
;
3005 if (scroll_window
->hscrollbar_visible
)
3007 dh
+= hscroll_req
.height
;
3008 dh
+= scroll_class
->scrollbar_spacing
;
3012 if (width
) (*width
) = m_width
- dw
;
3013 if (height
) (*height
) = m_height
- dh
;
3017 printf( "GetClientSize, name %s ", GetName().c_str() );
3018 if (width) printf( " width = %d", (*width) );
3019 if (height) printf( " height = %d", (*height) );
3024 void wxWindowGTK::DoGetPosition( int *x
, int *y
) const
3026 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3030 if (m_parent
&& m_parent
->m_wxwindow
)
3032 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
3033 dx
= pizza
->xoffset
;
3034 dy
= pizza
->yoffset
;
3037 if (x
) (*x
) = m_x
- dx
;
3038 if (y
) (*y
) = m_y
- dy
;
3041 void wxWindowGTK::DoClientToScreen( int *x
, int *y
) const
3043 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3045 if (!m_widget
->window
) return;
3047 GdkWindow
*source
= (GdkWindow
*) NULL
;
3049 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3051 source
= m_widget
->window
;
3055 gdk_window_get_origin( source
, &org_x
, &org_y
);
3059 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3061 org_x
+= m_widget
->allocation
.x
;
3062 org_y
+= m_widget
->allocation
.y
;
3070 void wxWindowGTK::DoScreenToClient( int *x
, int *y
) const
3072 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3074 if (!m_widget
->window
) return;
3076 GdkWindow
*source
= (GdkWindow
*) NULL
;
3078 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3080 source
= m_widget
->window
;
3084 gdk_window_get_origin( source
, &org_x
, &org_y
);
3088 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3090 org_x
+= m_widget
->allocation
.x
;
3091 org_y
+= m_widget
->allocation
.y
;
3099 bool wxWindowGTK::Show( bool show
)
3101 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3103 if (!wxWindowBase::Show(show
))
3110 gtk_widget_show( m_widget
);
3112 gtk_widget_hide( m_widget
);
3117 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
)
3119 win
->OnParentEnable(enable
);
3121 // Recurse, so that children have the opportunity to Do The Right Thing
3122 // and reset colours that have been messed up by a parent's (really ancestor's)
3124 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
3126 node
= node
->GetNext() )
3128 wxWindow
*child
= node
->GetData();
3129 if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
)))
3130 wxWindowNotifyEnable(child
, enable
);
3134 bool wxWindowGTK::Enable( bool enable
)
3136 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3138 if (!wxWindowBase::Enable(enable
))
3144 gtk_widget_set_sensitive( m_widget
, enable
);
3146 gtk_widget_set_sensitive( m_wxwindow
, enable
);
3148 wxWindowNotifyEnable(this, enable
);
3153 int wxWindowGTK::GetCharHeight() const
3155 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
3157 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
3159 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3161 return font
->ascent
+ font
->descent
;
3164 int wxWindowGTK::GetCharWidth() const
3166 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
3168 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
3170 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3172 return gdk_string_width( font
, "H" );
3175 void wxWindowGTK::GetTextExtent( const wxString
& string
,
3179 int *externalLeading
,
3180 const wxFont
*theFont
) const
3182 wxFont fontToUse
= m_font
;
3183 if (theFont
) fontToUse
= *theFont
;
3185 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
3187 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
3188 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
3189 if (y
) (*y
) = font
->ascent
+ font
->descent
;
3190 if (descent
) (*descent
) = font
->descent
;
3191 if (externalLeading
) (*externalLeading
) = 0; // ??
3194 void wxWindowGTK::SetFocus()
3196 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3200 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3202 // see comment in gtk_window_focus_out_callback()
3203 gs_widgetLastFocus
= m_wxwindow
;
3204 gtk_widget_grab_focus (m_wxwindow
);
3209 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
3211 gtk_widget_grab_focus (m_widget
);
3213 else if (GTK_IS_CONTAINER(m_widget
))
3215 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
3224 bool wxWindowGTK::AcceptsFocus() const
3226 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3229 bool wxWindowGTK::Reparent( wxWindowBase
*newParentBase
)
3231 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3233 wxWindowGTK
*oldParent
= m_parent
,
3234 *newParent
= (wxWindowGTK
*)newParentBase
;
3236 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3238 if ( !wxWindowBase::Reparent(newParent
) )
3241 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3243 /* prevent GTK from deleting the widget arbitrarily */
3244 gtk_widget_ref( m_widget
);
3248 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3251 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3255 /* insert GTK representation */
3256 (*(newParent
->m_insertCallback
))(newParent
, this);
3259 /* reverse: prevent GTK from deleting the widget arbitrarily */
3260 gtk_widget_unref( m_widget
);
3265 void wxWindowGTK::DoAddChild(wxWindowGTK
*child
)
3267 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3269 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3271 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3276 /* insert GTK representation */
3277 (*m_insertCallback
)(this, child
);
3280 void wxWindowGTK::Raise()
3282 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3284 if (!m_widget
->window
) return;
3286 gdk_window_raise( m_widget
->window
);
3289 void wxWindowGTK::Lower()
3291 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3293 if (!m_widget
->window
) return;
3295 gdk_window_lower( m_widget
->window
);
3298 bool wxWindowGTK::SetCursor( const wxCursor
&cursor
)
3300 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3302 if (cursor
== m_cursor
)
3306 wxapp_install_idle_handler();
3308 if (cursor
== wxNullCursor
)
3309 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3311 return wxWindowBase::SetCursor( cursor
);
3314 void wxWindowGTK::WarpPointer( int x
, int y
)
3316 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3318 /* we provide this function ourselves as it is
3319 missing in GDK (top of this file) */
3321 GdkWindow
*window
= (GdkWindow
*) NULL
;
3323 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3325 window
= GetConnectWidget()->window
;
3328 gdk_window_warp_pointer( window
, x
, y
);
3331 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect
*rect
)
3333 if (!m_widget
) return;
3334 if (!m_widget
->window
) return;
3336 // temporarily hide the caret to avoid nasty interactions between caret
3337 // drawing and the window contents redraw
3338 #if 0 // def wxUSE_CARET -- doesn't seem to help :-(
3339 wxCaretSuspend
cs((wxWindow
*)this);
3340 #endif // wxUSE_CARET
3342 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3346 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3348 rect
->width
, rect
->height
);
3352 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3356 /* there is no GTK equivalent of "draw only, don't clear" so we
3357 invent our own in the GtkPizza widget */
3365 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3366 gboolean old_clear = pizza->clear_on_draw;
3367 gtk_pizza_set_clear( pizza, FALSE );
3368 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3369 gtk_pizza_set_clear( pizza, old_clear );
3371 GdkEventExpose gdk_event
;
3372 gdk_event
.type
= GDK_EXPOSE
;
3373 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3374 gdk_event
.count
= 0;
3375 gdk_event
.area
.x
= 0;
3376 gdk_event
.area
.y
= 0;
3377 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3378 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3379 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, (wxWindow
*)this );
3383 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3392 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3393 gboolean old_clear = pizza->clear_on_draw;
3394 gtk_pizza_set_clear( pizza, FALSE );
3396 GdkRectangle gdk_rect;
3397 gdk_rect.x = rect->x;
3398 gdk_rect.y = rect->y;
3399 gdk_rect.width = rect->width;
3400 gdk_rect.height = rect->height;
3401 gtk_widget_draw( m_wxwindow, &gdk_rect );
3402 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3404 gtk_pizza_set_clear( pizza, old_clear );
3406 GdkEventExpose gdk_event
;
3407 gdk_event
.type
= GDK_EXPOSE
;
3408 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3409 gdk_event
.count
= 0;
3410 gdk_event
.area
.x
= rect
->x
;
3411 gdk_event
.area
.y
= rect
->y
;
3412 gdk_event
.area
.width
= rect
->width
;
3413 gdk_event
.area
.height
= rect
->height
;
3414 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, (wxWindow
*)this );
3418 GdkRectangle gdk_rect
;
3419 gdk_rect
.x
= rect
->x
;
3420 gdk_rect
.y
= rect
->y
;
3421 gdk_rect
.width
= rect
->width
;
3422 gdk_rect
.height
= rect
->height
;
3423 gtk_widget_draw( m_widget
, &gdk_rect
);
3428 void wxWindowGTK::Clear()
3430 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3432 if (!m_widget
->window
) return;
3434 if (m_wxwindow
&& m_wxwindow
->window
)
3436 // gdk_window_clear( m_wxwindow->window );
3441 void wxWindowGTK::DoSetToolTip( wxToolTip
*tip
)
3443 wxWindowBase::DoSetToolTip(tip
);
3446 m_tooltip
->Apply( (wxWindow
*)this );
3449 void wxWindowGTK::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3451 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3453 #endif // wxUSE_TOOLTIPS
3455 bool wxWindowGTK::SetBackgroundColour( const wxColour
&colour
)
3457 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3459 if (!wxWindowBase::SetBackgroundColour(colour
))
3461 // don't leave if the GTK widget has just
3463 if (!m_delayedBackgroundColour
) return FALSE
;
3466 GdkWindow
*window
= (GdkWindow
*) NULL
;
3468 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3470 window
= GetConnectWidget()->window
;
3474 // indicate that a new style has been set
3475 // but it couldn't get applied as the
3476 // widget hasn't been realized yet.
3477 m_delayedBackgroundColour
= TRUE
;
3481 (m_wxwindow
->window
) &&
3482 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3484 /* wxMSW doesn't clear the window here. I don't do that either to
3485 provide compatibility. call Clear() to do the job. */
3487 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3488 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3496 bool wxWindowGTK::SetForegroundColour( const wxColour
&colour
)
3498 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3500 if (!wxWindowBase::SetForegroundColour(colour
))
3502 // don't leave if the GTK widget has just
3504 if (!m_delayedForegroundColour
) return FALSE
;
3507 GdkWindow
*window
= (GdkWindow
*) NULL
;
3509 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3511 window
= GetConnectWidget()->window
;
3515 // indicate that a new style has been set
3516 // but it couldn't get applied as the
3517 // widget hasn't been realized yet.
3518 m_delayedForegroundColour
= TRUE
;
3526 GtkStyle
*wxWindowGTK::GetWidgetStyle()
3530 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3532 /* FIXME: is this necessary? */
3533 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3535 remake
->klass
= m_widgetStyle
->klass
;
3538 gtk_style_unref( m_widgetStyle
);
3539 m_widgetStyle
= remake
;
3543 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3546 def
= gtk_widget_get_default_style();
3548 m_widgetStyle
= gtk_style_copy( def
);
3550 /* FIXME: is this necessary? */
3551 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3553 m_widgetStyle
->klass
= def
->klass
;
3557 return m_widgetStyle
;
3560 void wxWindowGTK::SetWidgetStyle()
3562 #if DISABLE_STYLE_IF_BROKEN_THEM
3563 if (m_widget
->style
->engine_data
)
3565 static bool s_warningPrinted
= FALSE
;
3566 if (!s_warningPrinted
)
3568 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3569 s_warningPrinted
= TRUE
;
3571 m_widgetStyle
= m_widget
->style
;
3576 GtkStyle
*style
= GetWidgetStyle();
3578 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3580 gdk_font_unref( style
->font
);
3581 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3584 if (m_foregroundColour
.Ok())
3586 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3587 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3589 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3590 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3591 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3595 // Try to restore the gtk default style. This is still a little
3596 // oversimplified for what is probably really needed here for controls
3597 // other than buttons, but is better than not being able to (re)set a
3598 // control's foreground colour to *wxBLACK -- RL
3599 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3602 def
= gtk_widget_get_default_style();
3604 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3605 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3606 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3610 if (m_backgroundColour
.Ok())
3612 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3613 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3615 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3616 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3617 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3618 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3619 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3620 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3621 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3622 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3626 // Try to restore the gtk default style. This is still a little
3627 // oversimplified for what is probably really needed here for controls
3628 // other than buttons, but is better than not being able to (re)set a
3629 // control's background colour to default grey and means resetting a
3630 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3632 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3635 def
= gtk_widget_get_default_style();
3637 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3638 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3639 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3640 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3641 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3642 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3643 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3644 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3649 void wxWindowGTK::ApplyWidgetStyle()
3653 //-----------------------------------------------------------------------------
3654 // Pop-up menu stuff
3655 //-----------------------------------------------------------------------------
3657 #if wxUSE_MENUS_NATIVE
3659 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3661 *is_waiting
= FALSE
;
3664 static void SetInvokingWindow( wxMenu
*menu
, wxWindowGTK
*win
)
3666 menu
->SetInvokingWindow( win
);
3667 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3670 wxMenuItem
*menuitem
= node
->GetData();
3671 if (menuitem
->IsSubMenu())
3673 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3676 node
= node
->GetNext();
3680 static gint gs_pop_x
= 0;
3681 static gint gs_pop_y
= 0;
3683 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3687 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3692 bool wxWindowGTK::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3694 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3696 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3698 SetInvokingWindow( menu
, this );
3705 bool is_waiting
= TRUE
;
3707 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3708 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3711 GTK_MENU(menu
->m_menu
),
3712 (GtkWidget
*) NULL
, // parent menu shell
3713 (GtkWidget
*) NULL
, // parent menu item
3714 (GtkMenuPositionFunc
) pop_pos_callback
,
3715 (gpointer
) this, // client data
3716 0, // button used to activate it
3717 gs_timeLastClick
// the time of activation
3722 while (gtk_events_pending())
3723 gtk_main_iteration();
3729 #endif // wxUSE_MENUS_NATIVE
3731 #if wxUSE_DRAG_AND_DROP
3733 void wxWindowGTK::SetDropTarget( wxDropTarget
*dropTarget
)
3735 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3737 GtkWidget
*dnd_widget
= GetConnectWidget();
3739 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3741 if (m_dropTarget
) delete m_dropTarget
;
3742 m_dropTarget
= dropTarget
;
3744 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3747 #endif // wxUSE_DRAG_AND_DROP
3749 GtkWidget
* wxWindowGTK::GetConnectWidget()
3751 GtkWidget
*connect_widget
= m_widget
;
3752 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3754 return connect_widget
;
3757 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow
*window
)
3760 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3762 return (window
== m_widget
->window
);
3765 bool wxWindowGTK::SetFont( const wxFont
&font
)
3767 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3769 if (!wxWindowBase::SetFont(font
))
3774 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3775 if ( sysbg
== m_backgroundColour
)
3777 m_backgroundColour
= wxNullColour
;
3779 m_backgroundColour
= sysbg
;
3789 void wxWindowGTK::CaptureMouse()
3791 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3793 GdkWindow
*window
= (GdkWindow
*) NULL
;
3795 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3797 window
= GetConnectWidget()->window
;
3799 wxCHECK_RET( window
, _T("CaptureMouse() failed") );
3801 wxCursor
* cursor
= & m_cursor
;
3803 cursor
= wxSTANDARD_CURSOR
;
3805 gdk_pointer_grab( window
, FALSE
,
3807 (GDK_BUTTON_PRESS_MASK
|
3808 GDK_BUTTON_RELEASE_MASK
|
3809 GDK_POINTER_MOTION_HINT_MASK
|
3810 GDK_POINTER_MOTION_MASK
),
3812 cursor
->GetCursor(),
3813 (guint32
)GDK_CURRENT_TIME
);
3814 g_captureWindow
= this;
3815 g_captureWindowHasMouse
= TRUE
;
3818 void wxWindowGTK::ReleaseMouse()
3820 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3822 wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") );
3824 GdkWindow
*window
= (GdkWindow
*) NULL
;
3826 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3828 window
= GetConnectWidget()->window
;
3833 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3834 g_captureWindow
= (wxWindowGTK
*) NULL
;
3838 wxWindow
*wxWindowBase::GetCapture()
3840 return (wxWindow
*)g_captureWindow
;
3843 bool wxWindowGTK::IsRetained() const
3848 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3849 int range
, bool refresh
)
3851 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3853 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3855 m_hasScrolling
= TRUE
;
3857 if (orient
== wxHORIZONTAL
)
3859 float fpos
= (float)pos
;
3860 float frange
= (float)range
;
3861 float fthumb
= (float)thumbVisible
;
3862 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3863 if (fpos
< 0.0) fpos
= 0.0;
3865 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3866 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3868 SetScrollPos( orient
, pos
, refresh
);
3872 m_oldHorizontalPos
= fpos
;
3874 m_hAdjust
->lower
= 0.0;
3875 m_hAdjust
->upper
= frange
;
3876 m_hAdjust
->value
= fpos
;
3877 m_hAdjust
->step_increment
= 1.0;
3878 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3879 m_hAdjust
->page_size
= fthumb
;
3883 float fpos
= (float)pos
;
3884 float frange
= (float)range
;
3885 float fthumb
= (float)thumbVisible
;
3886 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3887 if (fpos
< 0.0) fpos
= 0.0;
3889 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3890 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3892 SetScrollPos( orient
, pos
, refresh
);
3896 m_oldVerticalPos
= fpos
;
3898 m_vAdjust
->lower
= 0.0;
3899 m_vAdjust
->upper
= frange
;
3900 m_vAdjust
->value
= fpos
;
3901 m_vAdjust
->step_increment
= 1.0;
3902 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3903 m_vAdjust
->page_size
= fthumb
;
3906 if (orient
== wxHORIZONTAL
)
3907 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3909 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3912 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3914 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3916 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3918 if (orient
== wxHORIZONTAL
)
3920 float fpos
= (float)pos
;
3921 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3922 if (fpos
< 0.0) fpos
= 0.0;
3923 m_oldHorizontalPos
= fpos
;
3925 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3926 m_hAdjust
->value
= fpos
;
3930 float fpos
= (float)pos
;
3931 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3932 if (fpos
< 0.0) fpos
= 0.0;
3933 m_oldVerticalPos
= fpos
;
3935 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3936 m_vAdjust
->value
= fpos
;
3939 if (m_wxwindow
->window
)
3941 if (orient
== wxHORIZONTAL
)
3943 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3944 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3946 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3948 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3949 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3953 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3954 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3956 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3958 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3959 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3964 int wxWindowGTK::GetScrollThumb( int orient
) const
3966 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3968 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3970 if (orient
== wxHORIZONTAL
)
3971 return (int)(m_hAdjust
->page_size
+0.5);
3973 return (int)(m_vAdjust
->page_size
+0.5);
3976 int wxWindowGTK::GetScrollPos( int orient
) const
3978 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3980 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3982 if (orient
== wxHORIZONTAL
)
3983 return (int)(m_hAdjust
->value
+0.5);
3985 return (int)(m_vAdjust
->value
+0.5);
3988 int wxWindowGTK::GetScrollRange( int orient
) const
3990 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3992 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3994 if (orient
== wxHORIZONTAL
)
3995 return (int)(m_hAdjust
->upper
+0.5);
3997 return (int)(m_vAdjust
->upper
+0.5);
4000 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
4002 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4004 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4006 if ((dx
== 0) && (dy
== 0)) return;
4008 m_clipPaintRegion
= TRUE
;
4009 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
4010 m_clipPaintRegion
= FALSE
;
4013 if (m_children.GetCount() > 0)
4015 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
4019 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
4021 pizza->xoffset -= dx;
4022 pizza->yoffset -= dy;
4024 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
4025 gdk_gc_set_exposures( m_scrollGC, TRUE );
4029 GetClientSize( &cw, &ch );
4030 int w = cw - abs(dx);
4031 int h = ch - abs(dy);
4033 if ((h < 0) || (w < 0))
4041 if (dx < 0) s_x = -dx;
4042 if (dy < 0) s_y = -dy;
4045 if (dx > 0) d_x = dx;
4046 if (dy > 0) d_y = dy;
4048 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
4049 pizza->bin_window, s_x, s_y, w, h );
4052 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
4053 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
4054 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
4055 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
4057 Refresh( TRUE, &rect );
4060 gdk_gc_unref( m_scrollGC );
4065 // Find the wxWindow at the current mouse position, also returning the mouse
4067 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
4069 pt
= wxGetMousePosition();
4070 wxWindow
* found
= wxFindWindowAtPoint(pt
);
4074 // Get the current mouse position.
4075 wxPoint
wxGetMousePosition()
4077 /* This crashes when used within wxHelpContext,
4078 so we have to use the X-specific implementation below.
4080 GdkModifierType *mask;
4081 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
4083 return wxPoint(x, y);
4087 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
4089 return wxPoint(-999, -999);
4091 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
4092 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
4093 Window rootReturn
, childReturn
;
4094 int rootX
, rootY
, winX
, winY
;
4095 unsigned int maskReturn
;
4097 XQueryPointer (display
,
4101 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
4102 return wxPoint(rootX
, rootY
);