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
;
703 //-----------------------------------------------------------------------------
704 // "size_request" of m_widget
705 //-----------------------------------------------------------------------------
707 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
710 win
->GetSize( &w
, &h
);
714 requisition
->height
= h
;
715 requisition
->width
= w
;
718 //-----------------------------------------------------------------------------
719 // "expose_event" of m_wxwindow
720 //-----------------------------------------------------------------------------
722 static int gtk_window_expose_callback( GtkWidget
*widget
,
723 GdkEventExpose
*gdk_event
,
729 wxapp_install_idle_handler();
732 if (win->GetName() == wxT("panel"))
734 wxPrintf( wxT("OnExpose from ") );
735 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
736 wxPrintf( win->GetClassInfo()->GetClassName() );
737 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
738 (int)gdk_event->area.y,
739 (int)gdk_event->area.width,
740 (int)gdk_event->area.height );
744 GtkPizza
*pizza
= GTK_PIZZA (widget
);
746 if (win
->GetThemeEnabled())
748 wxWindow
*parent
= win
->GetParent();
749 while (parent
&& !parent
->IsTopLevel())
750 parent
= parent
->GetParent();
754 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
755 GTK_SHADOW_NONE
, &gdk_event
->area
, parent
->m_widget
, "base", 0, 0, -1, -1);
758 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
760 gdk_event
->area
.width
,
761 gdk_event
->area
.height
);
763 if (gdk_event
->count
== 0)
765 win
->m_clipPaintRegion
= TRUE
;
768 dc
.SetClippingRegion(win
->GetUpdateRegion());
769 wxEraseEvent
eevent( win
->GetId(), &dc
);
770 eevent
.SetEventObject( win
);
772 (void)win
->GetEventHandler()->ProcessEvent(eevent
);
774 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
776 wxClientDC
dc( win
);
777 dc
.SetBrush( wxBrush( win
->GetBackgroundColour(), wxSOLID
) );
778 dc
.SetPen( *wxTRANSPARENT_PEN
);
780 wxRegionIterator
upd( win
->GetUpdateRegion() );
783 dc
.DrawRectangle( upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
789 wxNcPaintEvent
eventNc( win
->GetId() );
790 eventNc
.SetEventObject( win
);
791 win
->GetEventHandler()->ProcessEvent( eventNc
);
793 wxPaintEvent
event( win
->GetId() );
794 event
.SetEventObject( win
);
795 win
->GetEventHandler()->ProcessEvent( event
);
797 win
->GetUpdateRegion().Clear();
799 win
->m_clipPaintRegion
= FALSE
;
802 /* The following code will result in all window-less widgets
803 being redrawn if the wxWindows class is given a chance to
804 paint *anything* because it will then be allowed to paint
805 over the window-less widgets */
806 GList
*children
= pizza
->children
;
809 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
810 children
= children
->next
;
812 GdkEventExpose child_event
= *gdk_event
;
814 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
815 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
816 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
818 child_event
.area
.x
= child
->widget
->allocation
.x
;
819 child_event
.area
.y
= child
->widget
->allocation
.y
;
820 child_event
.area
.width
= child
->widget
->allocation
.width
;
821 child_event
.area
.height
= child
->widget
->allocation
.height
;
822 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
829 //-----------------------------------------------------------------------------
830 // "event" of m_wxwindow
831 //-----------------------------------------------------------------------------
833 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
834 expose events. We need them, of course, so we override the main event
835 procedure in GtkWidget by giving our own handler for all system events.
836 There, we look for expose events ourselves whereas all other events are
839 gint
gtk_window_event_event_callback( GtkWidget
*widget
,
840 GdkEventExpose
*event
,
843 if (event
->type
== GDK_EXPOSE
)
845 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
852 //-----------------------------------------------------------------------------
853 // "draw" of m_wxwindow
854 //-----------------------------------------------------------------------------
856 /* This callback is a complete replacement of the gtk_pizza_draw() function,
859 static void gtk_window_draw_callback( GtkWidget
*widget
,
866 wxapp_install_idle_handler();
868 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
869 (win
->GetChildren().GetCount() == 0))
875 if (win->GetName() == wxT("panel"))
877 wxPrintf( wxT("OnDraw from ") );
878 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
879 wxPrintf( win->GetClassInfo()->GetClassName() );
880 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
887 GtkPizza
*pizza
= GTK_PIZZA (widget
);
889 if (win
->GetThemeEnabled())
891 wxWindow
*parent
= win
->GetParent();
892 while (parent
&& !parent
->IsTopLevel())
893 parent
= parent
->GetParent();
897 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
898 GTK_SHADOW_NONE
, rect
, parent
->m_widget
, "base", 0, 0, -1, -1);
902 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
903 (pizza
->clear_on_draw
))
905 gdk_window_clear_area( pizza
->bin_window
,
906 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
909 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
911 win
->m_clipPaintRegion
= TRUE
;
914 dc
.SetClippingRegion(win
->GetUpdateRegion());
915 wxEraseEvent
eevent( win
->GetId(), &dc
);
916 eevent
.SetEventObject( win
);
919 (void)win
->GetEventHandler()->ProcessEvent(eevent
);
921 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
923 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
925 wxClientDC
dc( win
);
926 dc
.SetBrush( wxBrush( win
->GetBackgroundColour(), wxSOLID
) );
927 dc
.SetPen( *wxTRANSPARENT_PEN
);
929 wxRegionIterator
upd( win
->GetUpdateRegion() );
932 dc
.DrawRectangle( upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
939 wxNcPaintEvent
eventNc( win
->GetId() );
940 eventNc
.SetEventObject( win
);
941 win
->GetEventHandler()->ProcessEvent( eventNc
);
943 wxPaintEvent
event( win
->GetId() );
944 event
.SetEventObject( win
);
945 win
->GetEventHandler()->ProcessEvent( event
);
947 win
->GetUpdateRegion().Clear();
949 win
->m_clipPaintRegion
= FALSE
;
952 GList
*children
= pizza
->children
;
955 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
956 children
= children
->next
;
958 GdkRectangle child_area
;
959 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
961 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
966 //-----------------------------------------------------------------------------
967 // "key_press_event" from any window
968 //-----------------------------------------------------------------------------
970 // turn on to see the key event codes on the console
971 #undef DEBUG_KEY_EVENTS
973 static gint
gtk_window_key_press_callback( GtkWidget
*widget
,
974 GdkEventKey
*gdk_event
,
980 wxapp_install_idle_handler();
982 if (!win
->m_hasVMT
) return FALSE
;
983 if (g_blockEventsOnDrag
) return FALSE
;
988 GdkModifierType state
;
989 if (gdk_event
->window
)
990 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
994 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
996 #ifdef DEBUG_KEY_EVENTS
997 wxPrintf(_T("Key press event: %d => %ld\n"), gdk_event
->keyval
, key_code
);
998 #endif // DEBUG_KEY_EVENTS
1000 /* sending unknown key events doesn't really make sense */
1004 wxKeyEvent
event( wxEVT_KEY_DOWN
);
1005 event
.SetTimestamp( gdk_event
->time
);
1006 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1007 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1008 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1009 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1010 event
.m_keyCode
= key_code
;
1011 event
.m_scanCode
= gdk_event
->keyval
;
1014 event
.SetEventObject( win
);
1015 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1020 wxWindowGTK
*ancestor
= win
;
1023 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
1026 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
1027 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
1030 if (ancestor
->IsTopLevel())
1032 ancestor
= ancestor
->GetParent();
1035 #endif // wxUSE_ACCEL
1037 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
1038 will only be sent if it is not in an accelerator table. */
1041 key_code
= map_to_wx_keysym( gdk_event
);
1045 #ifdef DEBUG_KEY_EVENTS
1046 wxPrintf(_T("Char event: %ld\n"), key_code
);
1047 #endif // DEBUG_KEY_EVENTS
1049 // reuse the ame event object, just change its type and use the
1050 // translated keycode instead of the raw one
1051 event
.SetEventType(wxEVT_CHAR
);
1052 event
.m_keyCode
= key_code
;
1054 ret
= win
->GetEventHandler()->ProcessEvent( event
);
1058 /* win is a control: tab can be propagated up */
1060 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
1061 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
1062 // have this style, yet choose not to process this particular TAB in which
1063 // case TAB must still work as a navigational character
1065 !win
->HasFlag(wxTE_PROCESS_TAB
) &&
1067 win
->GetParent() && (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
1069 wxNavigationKeyEvent new_event
;
1070 new_event
.SetEventObject( win
->GetParent() );
1071 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
1072 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
1073 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1074 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
1075 new_event
.SetCurrentFocus( win
);
1076 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
1079 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
1081 (gdk_event
->keyval
== GDK_Escape
) )
1083 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
1084 new_event
.SetEventObject( win
);
1085 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
1089 #if 0 // (GTK_MINOR_VERSION > 0)
1090 /* Pressing F10 will activate the menu bar of the top frame. */
1092 (gdk_event
->keyval
== GDK_F10
) )
1094 wxWindowGTK
*ancestor
= win
;
1097 if (wxIsKindOf(ancestor
,wxFrame
))
1099 wxFrame
*frame
= (wxFrame
*) ancestor
;
1100 wxMenuBar
*menubar
= frame
->GetMenuBar();
1103 wxNode
*node
= menubar
->GetMenus().First();
1106 wxMenu
*firstMenu
= (wxMenu
*) node
->Data();
1107 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu
->m_owner
) );
1113 ancestor
= ancestor
->GetParent();
1120 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1127 //-----------------------------------------------------------------------------
1128 // "key_release_event" from any window
1129 //-----------------------------------------------------------------------------
1131 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindowGTK
*win
)
1136 wxapp_install_idle_handler();
1138 if (!win
->m_hasVMT
) return FALSE
;
1139 if (g_blockEventsOnDrag
) return FALSE
;
1141 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
1143 #ifdef DEBUG_KEY_EVENTS
1144 wxPrintf(_T("Key release event: %d => %ld\n"), gdk_event
->keyval
, key_code
);
1145 #endif // DEBUG_KEY_EVENTS
1147 /* sending unknown key events doesn't really make sense */
1148 if (key_code
== 0) return FALSE
;
1152 GdkModifierType state
;
1153 if (gdk_event
->window
)
1154 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1156 wxKeyEvent
event( wxEVT_KEY_UP
);
1157 event
.SetTimestamp( gdk_event
->time
);
1158 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1159 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1160 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1161 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1162 event
.m_keyCode
= key_code
;
1163 event
.m_scanCode
= gdk_event
->keyval
;
1166 event
.SetEventObject( win
);
1168 if (win
->GetEventHandler()->ProcessEvent( event
))
1170 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1177 // ----------------------------------------------------------------------------
1178 // mouse event processing helper
1179 // ----------------------------------------------------------------------------
1181 static void AdjustEventButtonState(wxMouseEvent
& event
)
1183 // GDK reports the old state of the button for a button press event, but
1184 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1185 // for a LEFT_DOWN event, not FALSE, so we will invert
1186 // left/right/middleDown for the corresponding click events
1188 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1189 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1190 (event
.GetEventType() == wxEVT_LEFT_UP
))
1192 event
.m_leftDown
= !event
.m_leftDown
;
1196 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1197 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1198 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1200 event
.m_middleDown
= !event
.m_middleDown
;
1204 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1205 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1206 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1208 event
.m_rightDown
= !event
.m_rightDown
;
1213 //-----------------------------------------------------------------------------
1214 // "button_press_event"
1215 //-----------------------------------------------------------------------------
1217 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1222 wxapp_install_idle_handler();
1225 wxPrintf( wxT("1) OnButtonPress from ") );
1226 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1227 wxPrintf( win->GetClassInfo()->GetClassName() );
1228 wxPrintf( wxT(".\n") );
1230 if (!win
->m_hasVMT
) return FALSE
;
1231 if (g_blockEventsOnDrag
) return TRUE
;
1232 if (g_blockEventsOnScroll
) return TRUE
;
1234 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1236 if (win
->m_wxwindow
)
1238 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1240 gtk_widget_grab_focus (win
->m_wxwindow
);
1243 wxPrintf( wxT("GrabFocus from ") );
1244 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1245 wxPrintf( win->GetClassInfo()->GetClassName() );
1246 wxPrintf( wxT(".\n") );
1252 wxEventType event_type
= wxEVT_NULL
;
1254 if (gdk_event
->button
== 1)
1256 switch (gdk_event
->type
)
1258 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1259 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1263 else if (gdk_event
->button
== 2)
1265 switch (gdk_event
->type
)
1267 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1268 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1272 else if (gdk_event
->button
== 3)
1274 switch (gdk_event
->type
)
1276 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1277 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1282 if ( event_type
== wxEVT_NULL
)
1284 // unknown mouse button or click type
1288 wxMouseEvent
event( event_type
);
1289 event
.SetTimestamp( gdk_event
->time
);
1290 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1291 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1292 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1293 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1294 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1295 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1296 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1298 event
.m_x
= (wxCoord
)gdk_event
->x
;
1299 event
.m_y
= (wxCoord
)gdk_event
->y
;
1301 AdjustEventButtonState(event
);
1303 // Some control don't have their own X window and thus cannot get
1306 if (!g_captureWindow
)
1308 wxCoord x
= event
.m_x
;
1309 wxCoord y
= event
.m_y
;
1310 if (win
->m_wxwindow
)
1312 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1313 x
+= pizza
->xoffset
;
1314 y
+= pizza
->yoffset
;
1317 wxNode
*node
= win
->GetChildren().First();
1320 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1322 node
= node
->Next();
1323 if (!child
->IsShown())
1326 if (child
->m_isStaticBox
)
1328 // wxStaticBox is transparent in the box itself
1329 int xx1
= child
->m_x
;
1330 int yy1
= child
->m_y
;
1331 int xx2
= child
->m_x
+ child
->m_width
;
1332 int yy2
= child
->m_x
+ child
->m_height
;
1335 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1337 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1339 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1341 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1344 event
.m_x
-= child
->m_x
;
1345 event
.m_y
-= child
->m_y
;
1352 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1353 (child
->m_x
<= x
) &&
1354 (child
->m_y
<= y
) &&
1355 (child
->m_x
+child
->m_width
>= x
) &&
1356 (child
->m_y
+child
->m_height
>= y
))
1359 event
.m_x
-= child
->m_x
;
1360 event
.m_y
-= child
->m_y
;
1367 event
.SetEventObject( win
);
1369 gs_timeLastClick
= gdk_event
->time
;
1372 wxPrintf( wxT("2) OnButtonPress from ") );
1373 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1374 wxPrintf( win->GetClassInfo()->GetClassName() );
1375 wxPrintf( wxT(".\n") );
1378 if (win
->GetEventHandler()->ProcessEvent( event
))
1380 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1387 //-----------------------------------------------------------------------------
1388 // "button_release_event"
1389 //-----------------------------------------------------------------------------
1391 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1396 wxapp_install_idle_handler();
1398 if (!win
->m_hasVMT
) return FALSE
;
1399 if (g_blockEventsOnDrag
) return FALSE
;
1400 if (g_blockEventsOnScroll
) return FALSE
;
1402 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1405 printf( "OnButtonRelease from " );
1406 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1407 printf( win->GetClassInfo()->GetClassName() );
1411 wxEventType event_type
= wxEVT_NULL
;
1413 switch (gdk_event
->button
)
1415 case 1: event_type
= wxEVT_LEFT_UP
; break;
1416 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1417 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1418 default: return FALSE
;
1421 wxMouseEvent
event( event_type
);
1422 event
.SetTimestamp( gdk_event
->time
);
1423 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1424 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1425 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1426 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1427 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1428 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1429 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1430 event
.m_x
= (wxCoord
)gdk_event
->x
;
1431 event
.m_y
= (wxCoord
)gdk_event
->y
;
1433 AdjustEventButtonState(event
);
1435 // Some control don't have their own X window and thus cannot get
1438 if (!g_captureWindow
)
1440 wxCoord x
= event
.m_x
;
1441 wxCoord y
= event
.m_y
;
1442 if (win
->m_wxwindow
)
1444 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1445 x
+= pizza
->xoffset
;
1446 y
+= pizza
->yoffset
;
1449 wxNode
*node
= win
->GetChildren().First();
1452 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1454 node
= node
->Next();
1455 if (!child
->IsShown())
1458 if (child
->m_isStaticBox
)
1460 // wxStaticBox is transparent in the box itself
1461 int xx1
= child
->m_x
;
1462 int yy1
= child
->m_y
;
1463 int xx2
= child
->m_x
+ child
->m_width
;
1464 int yy2
= child
->m_x
+ child
->m_height
;
1467 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1469 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1471 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1473 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1476 event
.m_x
-= child
->m_x
;
1477 event
.m_y
-= child
->m_y
;
1484 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1485 (child
->m_x
<= x
) &&
1486 (child
->m_y
<= y
) &&
1487 (child
->m_x
+child
->m_width
>= x
) &&
1488 (child
->m_y
+child
->m_height
>= y
))
1491 event
.m_x
-= child
->m_x
;
1492 event
.m_y
-= child
->m_y
;
1499 event
.SetEventObject( win
);
1501 if (win
->GetEventHandler()->ProcessEvent( event
))
1503 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1510 // ============================================================================
1512 // ============================================================================
1514 // init wxMouseEvent with the info from gdk_event
1515 #define InitMouseEvent(event, gdk_event) \
1516 event.SetTimestamp( gdk_event->time ); \
1517 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
1518 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
1519 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
1520 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
1521 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
1522 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
1523 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
1525 event.m_x = (wxCoord)gdk_event->x; \
1526 event.m_y = (wxCoord)gdk_event->y \
1528 //-----------------------------------------------------------------------------
1529 // "motion_notify_event"
1530 //-----------------------------------------------------------------------------
1532 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
,
1533 GdkEventMotion
*gdk_event
,
1539 wxapp_install_idle_handler();
1541 if (!win
->m_hasVMT
) return FALSE
;
1542 if (g_blockEventsOnDrag
) return FALSE
;
1543 if (g_blockEventsOnScroll
) return FALSE
;
1545 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1547 if (gdk_event
->is_hint
)
1551 GdkModifierType state
;
1552 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1558 printf( "OnMotion from " );
1559 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1560 printf( win->GetClassInfo()->GetClassName() );
1564 wxMouseEvent
event( wxEVT_MOTION
);
1565 InitMouseEvent(event
, gdk_event
);
1567 if ( g_captureWindow
)
1569 // synthetize a mouse enter or leave event if needed
1570 GdkWindow
*winUnderMouse
= gdk_window_at_pointer(NULL
, NULL
);
1571 bool hasMouse
= winUnderMouse
== gdk_event
->window
;
1572 if ( hasMouse
!= g_captureWindowHasMouse
)
1574 // the mouse changed window
1575 g_captureWindowHasMouse
= hasMouse
;
1577 wxMouseEvent
event(g_captureWindowHasMouse
? wxEVT_ENTER_WINDOW
1578 : wxEVT_LEAVE_WINDOW
);
1579 InitMouseEvent(event
, gdk_event
);
1580 event
.SetEventObject(win
);
1581 win
->GetEventHandler()->ProcessEvent(event
);
1586 // Some control don't have their own X window and thus cannot get
1589 wxCoord x
= event
.m_x
;
1590 wxCoord y
= event
.m_y
;
1591 if (win
->m_wxwindow
)
1593 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1594 x
+= pizza
->xoffset
;
1595 y
+= pizza
->yoffset
;
1598 wxNode
*node
= win
->GetChildren().First();
1601 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1603 node
= node
->Next();
1604 if (!child
->IsShown())
1607 if (child
->m_isStaticBox
)
1609 // wxStaticBox is transparent in the box itself
1610 int xx1
= child
->m_x
;
1611 int yy1
= child
->m_y
;
1612 int xx2
= child
->m_x
+ child
->m_width
;
1613 int yy2
= child
->m_x
+ child
->m_height
;
1616 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1618 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1620 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1622 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1625 event
.m_x
-= child
->m_x
;
1626 event
.m_y
-= child
->m_y
;
1633 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1634 (child
->m_x
<= x
) &&
1635 (child
->m_y
<= y
) &&
1636 (child
->m_x
+child
->m_width
>= x
) &&
1637 (child
->m_y
+child
->m_height
>= y
))
1640 event
.m_x
-= child
->m_x
;
1641 event
.m_y
-= child
->m_y
;
1648 event
.SetEventObject( win
);
1650 if (win
->GetEventHandler()->ProcessEvent( event
))
1652 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1659 //-----------------------------------------------------------------------------
1661 //-----------------------------------------------------------------------------
1663 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
,
1664 GdkEvent
*WXUNUSED(event
),
1670 wxapp_install_idle_handler();
1672 if (!win
->m_hasVMT
) return FALSE
;
1673 if (g_blockEventsOnDrag
) return FALSE
;
1675 switch ( g_sendActivateEvent
)
1678 // we've got focus from outside, synthetize wxActivateEvent
1679 g_sendActivateEvent
= 1;
1683 // another our window just lost focus, it was already ours before
1684 // - don't send any wxActivateEvent
1685 g_sendActivateEvent
= -1;
1690 g_focusWindow
= win
;
1693 wxPrintf( "OnSetFocus from " );
1694 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
1695 wxPrintf( win
->GetClassInfo()->GetClassName() );
1699 // notify the parent keeping track of focus for the kbd navigation
1700 // purposes that we got it
1701 wxChildFocusEvent
eventFocus(win
);
1702 (void)win
->GetEventHandler()->ProcessEvent(eventFocus
);
1706 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1710 // caret needs to be informed about focus change
1711 wxCaret
*caret
= win
->GetCaret();
1714 caret
->OnSetFocus();
1716 #endif // wxUSE_CARET
1718 wxWindowGTK
*active
= wxGetTopLevelParent(win
);
1719 if ( active
!= g_activeFrame
)
1721 if ( g_activeFrame
)
1723 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from focus_in)"), g_activeFrame
);
1724 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
1725 event
.SetEventObject(g_activeFrame
);
1726 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1729 wxLogTrace(wxT("activate"), wxT("Activating frame %p (from focus_in)"), active
);
1730 g_activeFrame
= active
;
1731 wxActivateEvent
event(wxEVT_ACTIVATE
, TRUE
, g_activeFrame
->GetId());
1732 event
.SetEventObject(g_activeFrame
);
1733 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
1735 g_activeFrameLostFocus
= FALSE
;
1738 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1739 event
.SetEventObject( win
);
1741 if (win
->GetEventHandler()->ProcessEvent( event
))
1743 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1751 //-----------------------------------------------------------------------------
1752 // "focus_out_event"
1753 //-----------------------------------------------------------------------------
1755 static GtkWidget
*gs_widgetLastFocus
= NULL
;
1757 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindowGTK
*win
)
1762 wxapp_install_idle_handler();
1764 if (!win
->m_hasVMT
) return FALSE
;
1765 if (g_blockEventsOnDrag
) return FALSE
;
1767 // VZ: this is really weird but GTK+ seems to call us from inside
1768 // gtk_widget_grab_focus(), i.e. it first sends "focus_out" signal to
1769 // this widget and then "focus_in". This is totally unexpected and
1770 // completely breaks wxUniv code so ignore this dummy event (we can't
1771 // be losing focus if we're about to acquire it!)
1772 if ( widget
== gs_widgetLastFocus
)
1774 gs_widgetLastFocus
= NULL
;
1779 if ( !g_activeFrameLostFocus
&& g_activeFrame
)
1781 wxASSERT_MSG( wxGetTopLevelParent(win
) == g_activeFrame
, wxT("unfocusing window that haven't gained focus properly") )
1782 g_activeFrameLostFocus
= TRUE
;
1785 // if the focus goes out of our app alltogether, OnIdle() will send
1786 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1787 // g_sendActivateEvent to -1
1788 g_sendActivateEvent
= 0;
1790 wxWindowGTK
*winFocus
= wxFindFocusedChild(win
);
1794 g_focusWindow
= (wxWindowGTK
*)NULL
;
1797 wxPrintf( "OnKillFocus from " );
1798 if (win
->GetClassInfo() && win
->GetClassInfo()->GetClassName())
1799 wxPrintf( win
->GetClassInfo()->GetClassName() );
1809 // caret needs to be informed about focus change
1810 wxCaret
*caret
= win
->GetCaret();
1813 caret
->OnKillFocus();
1815 #endif // wxUSE_CARET
1817 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1818 event
.SetEventObject( win
);
1820 if (win
->GetEventHandler()->ProcessEvent( event
))
1822 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1829 //-----------------------------------------------------------------------------
1830 // "enter_notify_event"
1831 //-----------------------------------------------------------------------------
1833 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1838 wxapp_install_idle_handler();
1840 if (!win
->m_hasVMT
) return FALSE
;
1841 if (g_blockEventsOnDrag
) return FALSE
;
1843 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1845 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1846 event
.SetTimestamp( gdk_event
->time
);
1847 event
.SetEventObject( win
);
1851 GdkModifierType state
= (GdkModifierType
)0;
1853 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1855 InitMouseEvent(event
, gdk_event
);
1860 if (win
->GetEventHandler()->ProcessEvent( event
))
1862 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1869 //-----------------------------------------------------------------------------
1870 // "leave_notify_event"
1871 //-----------------------------------------------------------------------------
1873 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1878 wxapp_install_idle_handler();
1880 if (!win
->m_hasVMT
) return FALSE
;
1881 if (g_blockEventsOnDrag
) return FALSE
;
1883 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1885 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1886 event
.SetTimestamp( gdk_event
->time
);
1887 event
.SetEventObject( win
);
1891 GdkModifierType state
= (GdkModifierType
)0;
1893 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1895 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1896 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1897 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1898 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1899 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1900 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1901 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1906 if (win
->GetEventHandler()->ProcessEvent( event
))
1908 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1915 //-----------------------------------------------------------------------------
1916 // "value_changed" from m_vAdjust
1917 //-----------------------------------------------------------------------------
1919 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1924 wxapp_install_idle_handler();
1926 if (g_blockEventsOnDrag
) return;
1928 if (!win
->m_hasVMT
) return;
1930 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1931 if (fabs(diff
) < 0.2) return;
1933 win
->m_oldVerticalPos
= adjust
->value
;
1935 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1936 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1938 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1939 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1940 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1941 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1942 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1944 int value
= (int)(adjust
->value
+0.5);
1946 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1947 event
.SetEventObject( win
);
1948 win
->GetEventHandler()->ProcessEvent( event
);
1951 //-----------------------------------------------------------------------------
1952 // "value_changed" from m_hAdjust
1953 //-----------------------------------------------------------------------------
1955 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1960 wxapp_install_idle_handler();
1962 if (g_blockEventsOnDrag
) return;
1963 if (!win
->m_hasVMT
) return;
1965 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1966 if (fabs(diff
) < 0.2) return;
1968 win
->m_oldHorizontalPos
= adjust
->value
;
1970 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1971 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1973 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1974 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1975 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1976 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1977 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1979 int value
= (int)(adjust
->value
+0.5);
1981 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1982 event
.SetEventObject( win
);
1983 win
->GetEventHandler()->ProcessEvent( event
);
1986 //-----------------------------------------------------------------------------
1987 // "button_press_event" from scrollbar
1988 //-----------------------------------------------------------------------------
1990 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1991 GdkEventButton
*gdk_event
,
1997 wxapp_install_idle_handler();
2000 g_blockEventsOnScroll
= TRUE
;
2001 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
2006 //-----------------------------------------------------------------------------
2007 // "button_release_event" from scrollbar
2008 //-----------------------------------------------------------------------------
2010 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
2011 GdkEventButton
*WXUNUSED(gdk_event
),
2016 // don't test here as we can release the mouse while being over
2017 // a different window than the slider
2019 // if (gdk_event->window != widget->slider) return FALSE;
2021 g_blockEventsOnScroll
= FALSE
;
2023 if (win
->m_isScrolling
)
2025 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
2029 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
2030 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
2032 value
= (int)(win
->m_hAdjust
->value
+0.5);
2035 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
2037 value
= (int)(win
->m_vAdjust
->value
+0.5);
2041 wxScrollWinEvent
event( command
, value
, dir
);
2042 event
.SetEventObject( win
);
2043 win
->GetEventHandler()->ProcessEvent( event
);
2046 win
->m_isScrolling
= FALSE
;
2051 // ----------------------------------------------------------------------------
2052 // this wxWindowBase function is implemented here (in platform-specific file)
2053 // because it is static and so couldn't be made virtual
2054 // ----------------------------------------------------------------------------
2056 wxWindow
*wxWindowBase::FindFocus()
2058 // the cast is necessary when we compile in wxUniversal mode
2059 return (wxWindow
*)g_focusWindow
;
2062 //-----------------------------------------------------------------------------
2063 // "realize" from m_widget
2064 //-----------------------------------------------------------------------------
2066 /* We cannot set colours and fonts before the widget has
2067 been realized, so we do this directly after realization. */
2070 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
2075 wxapp_install_idle_handler();
2077 if (win
->m_delayedBackgroundColour
)
2078 win
->SetBackgroundColour( win
->GetBackgroundColour() );
2080 if (win
->m_delayedForegroundColour
)
2081 win
->SetForegroundColour( win
->GetForegroundColour() );
2083 wxWindowCreateEvent
event( win
);
2084 event
.SetEventObject( win
);
2085 win
->GetEventHandler()->ProcessEvent( event
);
2090 //-----------------------------------------------------------------------------
2092 //-----------------------------------------------------------------------------
2095 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
2096 GtkAllocation
*WXUNUSED(alloc
),
2100 wxapp_install_idle_handler();
2102 if (!win
->m_hasScrolling
) return;
2104 int client_width
= 0;
2105 int client_height
= 0;
2106 win
->GetClientSize( &client_width
, &client_height
);
2107 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
2110 win
->m_oldClientWidth
= client_width
;
2111 win
->m_oldClientHeight
= client_height
;
2113 if (!win
->m_nativeSizeEvent
)
2115 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
2116 event
.SetEventObject( win
);
2117 win
->GetEventHandler()->ProcessEvent( event
);
2123 #define WXUNUSED_UNLESS_XIM(param) param
2125 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2128 /* Resize XIM window */
2131 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2132 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
2133 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2136 wxapp_install_idle_handler();
2142 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
2146 gdk_window_get_size (widget
->window
, &width
, &height
);
2147 win
->m_icattr
->preedit_area
.width
= width
;
2148 win
->m_icattr
->preedit_area
.height
= height
;
2149 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2154 //-----------------------------------------------------------------------------
2155 // "realize" from m_wxwindow
2156 //-----------------------------------------------------------------------------
2158 /* Initialize XIM support */
2161 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2162 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2165 wxapp_install_idle_handler();
2168 if (win
->m_ic
) return FALSE
;
2169 if (!widget
) return FALSE
;
2170 if (!gdk_im_ready()) return FALSE
;
2172 win
->m_icattr
= gdk_ic_attr_new();
2173 if (!win
->m_icattr
) return FALSE
;
2177 GdkColormap
*colormap
;
2178 GdkICAttr
*attr
= win
->m_icattr
;
2179 unsigned attrmask
= GDK_IC_ALL_REQ
;
2181 GdkIMStyle supported_style
= (GdkIMStyle
)
2182 (GDK_IM_PREEDIT_NONE
|
2183 GDK_IM_PREEDIT_NOTHING
|
2184 GDK_IM_PREEDIT_POSITION
|
2185 GDK_IM_STATUS_NONE
|
2186 GDK_IM_STATUS_NOTHING
);
2188 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2189 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2191 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2192 attr
->client_window
= widget
->window
;
2194 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2195 gtk_widget_get_default_colormap ())
2197 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2198 attr
->preedit_colormap
= colormap
;
2201 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2202 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2203 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2204 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2206 switch (style
& GDK_IM_PREEDIT_MASK
)
2208 case GDK_IM_PREEDIT_POSITION
:
2209 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2211 g_warning ("over-the-spot style requires fontset");
2215 gdk_window_get_size (widget
->window
, &width
, &height
);
2217 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2218 attr
->spot_location
.x
= 0;
2219 attr
->spot_location
.y
= height
;
2220 attr
->preedit_area
.x
= 0;
2221 attr
->preedit_area
.y
= 0;
2222 attr
->preedit_area
.width
= width
;
2223 attr
->preedit_area
.height
= height
;
2224 attr
->preedit_fontset
= widget
->style
->font
;
2229 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2231 if (win
->m_ic
== NULL
)
2232 g_warning ("Can't create input context.");
2235 mask
= gdk_window_get_events (widget
->window
);
2236 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2237 gdk_window_set_events (widget
->window
, mask
);
2239 if (GTK_WIDGET_HAS_FOCUS(widget
))
2240 gdk_im_begin (win
->m_ic
, widget
->window
);
2247 //-----------------------------------------------------------------------------
2248 // InsertChild for wxWindowGTK.
2249 //-----------------------------------------------------------------------------
2251 /* Callback for wxWindowGTK. This very strange beast has to be used because
2252 * C++ has no virtual methods in a constructor. We have to emulate a
2253 * virtual function here as wxNotebook requires a different way to insert
2254 * a child in it. I had opted for creating a wxNotebookPage window class
2255 * which would have made this superfluous (such in the MDI window system),
2256 * but no-one was listening to me... */
2258 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child
)
2260 /* the window might have been scrolled already, do we
2261 have to adapt the position */
2262 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2263 child
->m_x
+= pizza
->xoffset
;
2264 child
->m_y
+= pizza
->yoffset
;
2266 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2267 GTK_WIDGET(child
->m_widget
),
2274 //-----------------------------------------------------------------------------
2276 //-----------------------------------------------------------------------------
2278 wxWindow
*wxGetActiveWindow()
2280 // the cast is necessary when we compile in wxUniversal mode
2281 return (wxWindow
*)g_focusWindow
;
2284 //-----------------------------------------------------------------------------
2286 //-----------------------------------------------------------------------------
2288 // in wxUniv/MSW this class is abstract because it doesn't have DoPopupMenu()
2290 #ifdef __WXUNIVERSAL__
2291 IMPLEMENT_ABSTRACT_CLASS(wxWindowGTK
, wxWindowBase
)
2293 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2294 #endif // __WXUNIVERSAL__/__WXGTK__
2296 void wxWindowGTK::Init()
2302 m_widget
= (GtkWidget
*) NULL
;
2303 m_wxwindow
= (GtkWidget
*) NULL
;
2304 m_focusWidget
= (GtkWidget
*) NULL
;
2314 m_needParent
= TRUE
;
2315 m_isBeingDeleted
= FALSE
;
2318 m_nativeSizeEvent
= FALSE
;
2320 m_hasScrolling
= FALSE
;
2321 m_isScrolling
= FALSE
;
2323 m_hAdjust
= (GtkAdjustment
*) NULL
;
2324 m_vAdjust
= (GtkAdjustment
*) NULL
;
2325 m_oldHorizontalPos
= 0.0;
2326 m_oldVerticalPos
= 0.0;
2329 m_widgetStyle
= (GtkStyle
*) NULL
;
2331 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2333 m_isStaticBox
= FALSE
;
2334 m_isRadioButton
= FALSE
;
2336 m_acceptsFocus
= FALSE
;
2338 m_clipPaintRegion
= FALSE
;
2340 m_cursor
= *wxSTANDARD_CURSOR
;
2342 m_delayedForegroundColour
= FALSE
;
2343 m_delayedBackgroundColour
= FALSE
;
2346 m_ic
= (GdkIC
*) NULL
;
2347 m_icattr
= (GdkICAttr
*) NULL
;
2351 wxWindowGTK::wxWindowGTK()
2356 wxWindowGTK::wxWindowGTK( wxWindow
*parent
,
2361 const wxString
&name
)
2365 Create( parent
, id
, pos
, size
, style
, name
);
2368 bool wxWindowGTK::Create( wxWindow
*parent
,
2373 const wxString
&name
)
2375 if (!PreCreation( parent
, pos
, size
) ||
2376 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2378 wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
2382 m_insertCallback
= wxInsertChildInWindow
;
2384 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2385 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2387 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2389 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2390 scroll_class
->scrollbar_spacing
= 0;
2392 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2394 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2395 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2397 m_wxwindow
= gtk_pizza_new();
2399 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2401 #ifndef __WXUNIVERSAL__
2402 #if (GTK_MINOR_VERSION > 0)
2403 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2405 if (HasFlag(wxRAISED_BORDER
))
2407 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2409 else if (HasFlag(wxSUNKEN_BORDER
))
2411 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2413 else if (HasFlag(wxSIMPLE_BORDER
))
2415 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2419 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2421 #else // GTK_MINOR_VERSION == 0
2422 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2424 if (HasFlag(wxRAISED_BORDER
))
2426 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2428 else if (HasFlag(wxSUNKEN_BORDER
))
2430 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2434 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2436 #endif // GTK_MINOR_VERSION
2437 #endif // __WXUNIVERSAL__
2439 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2440 m_acceptsFocus
= TRUE
;
2442 #if (GTK_MINOR_VERSION == 0)
2443 // shut the viewport up
2444 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2445 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2446 #endif // GTK_MINOR_VERSION == 0
2448 // I _really_ don't want scrollbars in the beginning
2449 m_vAdjust
->lower
= 0.0;
2450 m_vAdjust
->upper
= 1.0;
2451 m_vAdjust
->value
= 0.0;
2452 m_vAdjust
->step_increment
= 1.0;
2453 m_vAdjust
->page_increment
= 1.0;
2454 m_vAdjust
->page_size
= 5.0;
2455 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2456 m_hAdjust
->lower
= 0.0;
2457 m_hAdjust
->upper
= 1.0;
2458 m_hAdjust
->value
= 0.0;
2459 m_hAdjust
->step_increment
= 1.0;
2460 m_hAdjust
->page_increment
= 1.0;
2461 m_hAdjust
->page_size
= 5.0;
2462 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2464 // these handlers block mouse events to any window during scrolling such as
2465 // motion events and prevent GTK and wxWindows from fighting over where the
2468 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2469 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2471 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2472 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2474 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2475 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2477 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2478 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2480 // these handlers get notified when screen updates are required either when
2481 // scrolling or when the window size (and therefore scrollbar configuration)
2484 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2485 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2486 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2487 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2489 gtk_widget_show( m_wxwindow
);
2492 m_parent
->DoAddChild( this );
2494 m_focusWidget
= m_wxwindow
;
2503 wxWindowGTK::~wxWindowGTK()
2505 if (g_focusWindow
== this)
2506 g_focusWindow
= NULL
;
2508 if (g_activeFrame
== this)
2509 g_activeFrame
= NULL
;
2511 m_isBeingDeleted
= TRUE
;
2520 m_parent
->RemoveChild( this );
2524 gdk_ic_destroy (m_ic
);
2526 gdk_ic_attr_destroy (m_icattr
);
2531 #if DISABLE_STYLE_IF_BROKEN_THEME
2532 // don't delete if it's a pixmap theme style
2533 if (!m_widgetStyle
->engine_data
)
2534 gtk_style_unref( m_widgetStyle
);
2536 m_widgetStyle
= (GtkStyle
*) NULL
;
2541 gtk_widget_destroy( m_wxwindow
);
2542 m_wxwindow
= (GtkWidget
*) NULL
;
2547 gtk_widget_destroy( m_widget
);
2548 m_widget
= (GtkWidget
*) NULL
;
2552 bool wxWindowGTK::PreCreation( wxWindowGTK
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2554 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2556 /* this turns -1 into 20 so that a minimal window is
2557 visible even although -1,-1 has been given as the
2558 size of the window. the same trick is used in other
2559 ports and should make debugging easier */
2560 m_width
= WidthDefault(size
.x
);
2561 m_height
= HeightDefault(size
.y
);
2566 /* some reasonable defaults */
2571 m_x
= (gdk_screen_width () - m_width
) / 2;
2572 if (m_x
< 10) m_x
= 10;
2576 m_y
= (gdk_screen_height () - m_height
) / 2;
2577 if (m_y
< 10) m_y
= 10;
2584 void wxWindowGTK::PostCreation()
2586 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2592 // these get reported to wxWindows -> wxPaintEvent
2594 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2596 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2597 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2599 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2600 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2602 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2604 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2605 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2609 // these are called when the "sunken" or "raised" borders are drawn */
2610 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2611 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2613 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2614 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2619 if (m_focusWidget
== NULL
)
2620 m_focusWidget
= m_widget
;
2623 if (GetClassInfo() && GetClassInfo()->GetClassName())
2624 wxPrintf( GetClassInfo()->GetClassName() );
2628 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_in_event",
2629 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2631 gtk_signal_connect( GTK_OBJECT(m_focusWidget
), "focus_out_event",
2632 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2634 // connect to the various key and mouse handlers
2636 GtkWidget
*connect_widget
= GetConnectWidget();
2638 ConnectWidget( connect_widget
);
2640 /* We cannot set colours, fonts and cursors before the widget has
2641 been realized, so we do this directly after realization */
2642 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2643 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2647 // Catch native resize events
2648 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2649 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2651 // Initialize XIM support
2652 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2653 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2655 // And resize XIM window
2656 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2657 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2660 if (!GTK_IS_COMBO(m_widget
))
2662 // This is needed if we want to add our windows into native
2663 // GTK control, such as the toolbar. With this callback, the
2664 // toolbar gets to know the correct size (the one set by the
2665 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2666 // when moving to GTK 2.0.
2667 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2668 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2674 void wxWindowGTK::ConnectWidget( GtkWidget
*widget
)
2676 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2677 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2679 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2680 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2682 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2683 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2685 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2686 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2688 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2689 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2691 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2692 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2694 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2695 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2698 bool wxWindowGTK::Destroy()
2700 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2704 return wxWindowBase::Destroy();
2707 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
)
2709 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2712 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2714 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2715 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") );
2718 printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
2721 if (m_resizing
) return; /* I don't like recursions */
2724 int currentX
, currentY
;
2725 GetPosition(¤tX
, ¤tY
);
2730 AdjustForParentClientOrigin(x
, y
, sizeFlags
);
2732 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2734 /* don't set the size for children of wxNotebook, just take the values. */
2742 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2744 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2746 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2747 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2748 if (width
!= -1) m_width
= width
;
2749 if (height
!= -1) m_height
= height
;
2753 m_x
= x
+ pizza
->xoffset
;
2754 m_y
= y
+ pizza
->yoffset
;
2759 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2761 if (width
== -1) m_width
= 80;
2764 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2766 if (height
== -1) m_height
= 26;
2769 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2770 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2771 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2772 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2775 int bottom_border
= 0;
2777 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2779 /* the default button has a border around it */
2784 DoMoveWindow( m_x
-border
,
2787 m_height
+border
+bottom_border
);
2792 /* Sometimes the client area changes size without the
2793 whole windows's size changing, but if the whole
2794 windows's size doesn't change, no wxSizeEvent will
2795 normally be sent. Here we add an extra test if
2796 the client test has been changed and this will
2798 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2802 wxPrintf( "OnSize sent from " );
2803 if (GetClassInfo() && GetClassInfo()->GetClassName())
2804 wxPrintf( GetClassInfo()->GetClassName() );
2805 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2808 if (!m_nativeSizeEvent
)
2810 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2811 event
.SetEventObject( this );
2812 GetEventHandler()->ProcessEvent( event
);
2818 void wxWindowGTK::OnInternalIdle()
2820 if ( g_sendActivateEvent
!= -1 )
2822 bool activate
= g_sendActivateEvent
!= 0;
2825 g_sendActivateEvent
= -1;
2827 wxTheApp
->SetActive(activate
, (wxWindow
*)g_focusWindowLast
);
2830 if ( g_activeFrameLostFocus
)
2832 if ( g_activeFrame
)
2834 wxLogTrace(wxT("activate"), wxT("Deactivating frame %p (from idle)"), g_activeFrame
);
2835 wxActivateEvent
event(wxEVT_ACTIVATE
, FALSE
, g_activeFrame
->GetId());
2836 event
.SetEventObject(g_activeFrame
);
2837 g_activeFrame
->GetEventHandler()->ProcessEvent(event
);
2838 g_activeFrame
= NULL
;
2840 g_activeFrameLostFocus
= FALSE
;
2843 wxCursor cursor
= m_cursor
;
2844 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2848 /* I now set the cursor anew in every OnInternalIdle call
2849 as setting the cursor in a parent window also effects the
2850 windows above so that checking for the current cursor is
2855 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2857 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2859 if (!g_globalCursor
.Ok())
2860 cursor
= *wxSTANDARD_CURSOR
;
2862 window
= m_widget
->window
;
2863 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2864 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2870 GdkWindow
*window
= m_widget
->window
;
2871 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2872 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2880 void wxWindowGTK::DoGetSize( int *width
, int *height
) const
2882 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2884 if (width
) (*width
) = m_width
;
2885 if (height
) (*height
) = m_height
;
2888 void wxWindowGTK::DoSetClientSize( int width
, int height
)
2890 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2894 SetSize( width
, height
);
2901 #ifndef __WXUNIVERSAL__
2902 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2904 /* when using GTK 1.2 we set the shadow border size to 2 */
2908 if (HasFlag(wxSIMPLE_BORDER
))
2910 /* when using GTK 1.2 we set the simple border size to 1 */
2914 #endif // __WXUNIVERSAL__
2918 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2920 GtkRequisition vscroll_req
;
2921 vscroll_req
.width
= 2;
2922 vscroll_req
.height
= 2;
2923 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2924 (scroll_window
->vscrollbar
, &vscroll_req
);
2926 GtkRequisition hscroll_req
;
2927 hscroll_req
.width
= 2;
2928 hscroll_req
.height
= 2;
2929 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2930 (scroll_window
->hscrollbar
, &hscroll_req
);
2932 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2934 if (scroll_window
->vscrollbar_visible
)
2936 dw
+= vscroll_req
.width
;
2937 dw
+= scroll_class
->scrollbar_spacing
;
2940 if (scroll_window
->hscrollbar_visible
)
2942 dh
+= hscroll_req
.height
;
2943 dh
+= scroll_class
->scrollbar_spacing
;
2947 SetSize( width
+dw
, height
+dh
);
2951 void wxWindowGTK::DoGetClientSize( int *width
, int *height
) const
2953 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2957 if (width
) (*width
) = m_width
;
2958 if (height
) (*height
) = m_height
;
2965 #ifndef __WXUNIVERSAL__
2966 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2968 /* when using GTK 1.2 we set the shadow border size to 2 */
2972 if (HasFlag(wxSIMPLE_BORDER
))
2974 /* when using GTK 1.2 we set the simple border size to 1 */
2978 #endif // __WXUNIVERSAL__
2982 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2984 GtkRequisition vscroll_req
;
2985 vscroll_req
.width
= 2;
2986 vscroll_req
.height
= 2;
2987 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2988 (scroll_window
->vscrollbar
, &vscroll_req
);
2990 GtkRequisition hscroll_req
;
2991 hscroll_req
.width
= 2;
2992 hscroll_req
.height
= 2;
2993 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2994 (scroll_window
->hscrollbar
, &hscroll_req
);
2996 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2998 if (scroll_window
->vscrollbar_visible
)
3000 dw
+= vscroll_req
.width
;
3001 dw
+= scroll_class
->scrollbar_spacing
;
3004 if (scroll_window
->hscrollbar_visible
)
3006 dh
+= hscroll_req
.height
;
3007 dh
+= scroll_class
->scrollbar_spacing
;
3011 if (width
) (*width
) = m_width
- dw
;
3012 if (height
) (*height
) = m_height
- dh
;
3016 printf( "GetClientSize, name %s ", GetName().c_str() );
3017 if (width) printf( " width = %d", (*width) );
3018 if (height) printf( " height = %d", (*height) );
3023 void wxWindowGTK::DoGetPosition( int *x
, int *y
) const
3025 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3029 if (m_parent
&& m_parent
->m_wxwindow
)
3031 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
3032 dx
= pizza
->xoffset
;
3033 dy
= pizza
->yoffset
;
3036 if (x
) (*x
) = m_x
- dx
;
3037 if (y
) (*y
) = m_y
- dy
;
3040 void wxWindowGTK::DoClientToScreen( int *x
, int *y
) const
3042 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3044 if (!m_widget
->window
) return;
3046 GdkWindow
*source
= (GdkWindow
*) NULL
;
3048 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3050 source
= m_widget
->window
;
3054 gdk_window_get_origin( source
, &org_x
, &org_y
);
3058 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3060 org_x
+= m_widget
->allocation
.x
;
3061 org_y
+= m_widget
->allocation
.y
;
3069 void wxWindowGTK::DoScreenToClient( int *x
, int *y
) const
3071 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3073 if (!m_widget
->window
) return;
3075 GdkWindow
*source
= (GdkWindow
*) NULL
;
3077 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3079 source
= m_widget
->window
;
3083 gdk_window_get_origin( source
, &org_x
, &org_y
);
3087 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3089 org_x
+= m_widget
->allocation
.x
;
3090 org_y
+= m_widget
->allocation
.y
;
3098 bool wxWindowGTK::Show( bool show
)
3100 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3102 if (!wxWindowBase::Show(show
))
3109 gtk_widget_show( m_widget
);
3111 gtk_widget_hide( m_widget
);
3116 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
)
3118 win
->OnParentEnable(enable
);
3120 // Recurse, so that children have the opportunity to Do The Right Thing
3121 // and reset colours that have been messed up by a parent's (really ancestor's)
3123 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
3125 node
= node
->GetNext() )
3127 wxWindow
*child
= node
->GetData();
3128 if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
)))
3129 wxWindowNotifyEnable(child
, enable
);
3133 bool wxWindowGTK::Enable( bool enable
)
3135 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3137 if (!wxWindowBase::Enable(enable
))
3143 gtk_widget_set_sensitive( m_widget
, enable
);
3145 gtk_widget_set_sensitive( m_wxwindow
, enable
);
3147 wxWindowNotifyEnable(this, enable
);
3152 int wxWindowGTK::GetCharHeight() const
3154 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
3156 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
3158 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3160 return font
->ascent
+ font
->descent
;
3163 int wxWindowGTK::GetCharWidth() const
3165 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
3167 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
3169 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3171 return gdk_string_width( font
, "H" );
3174 void wxWindowGTK::GetTextExtent( const wxString
& string
,
3178 int *externalLeading
,
3179 const wxFont
*theFont
) const
3181 wxFont fontToUse
= m_font
;
3182 if (theFont
) fontToUse
= *theFont
;
3184 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
3186 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
3187 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
3188 if (y
) (*y
) = font
->ascent
+ font
->descent
;
3189 if (descent
) (*descent
) = font
->descent
;
3190 if (externalLeading
) (*externalLeading
) = 0; // ??
3193 void wxWindowGTK::SetFocus()
3195 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3199 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3201 // see comment in gtk_window_focus_out_callback()
3202 gs_widgetLastFocus
= m_wxwindow
;
3203 gtk_widget_grab_focus (m_wxwindow
);
3208 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
3210 gtk_widget_grab_focus (m_widget
);
3212 else if (GTK_IS_CONTAINER(m_widget
))
3214 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
3223 bool wxWindowGTK::AcceptsFocus() const
3225 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3228 bool wxWindowGTK::Reparent( wxWindowBase
*newParentBase
)
3230 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3232 wxWindowGTK
*oldParent
= m_parent
,
3233 *newParent
= (wxWindowGTK
*)newParentBase
;
3235 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3237 if ( !wxWindowBase::Reparent(newParent
) )
3240 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3242 /* prevent GTK from deleting the widget arbitrarily */
3243 gtk_widget_ref( m_widget
);
3247 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3250 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3254 /* insert GTK representation */
3255 (*(newParent
->m_insertCallback
))(newParent
, this);
3258 /* reverse: prevent GTK from deleting the widget arbitrarily */
3259 gtk_widget_unref( m_widget
);
3264 void wxWindowGTK::DoAddChild(wxWindowGTK
*child
)
3266 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3268 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3270 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3275 /* insert GTK representation */
3276 (*m_insertCallback
)(this, child
);
3279 void wxWindowGTK::Raise()
3281 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3283 if (!m_widget
->window
) return;
3285 gdk_window_raise( m_widget
->window
);
3288 void wxWindowGTK::Lower()
3290 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3292 if (!m_widget
->window
) return;
3294 gdk_window_lower( m_widget
->window
);
3297 bool wxWindowGTK::SetCursor( const wxCursor
&cursor
)
3299 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3301 if (cursor
== m_cursor
)
3305 wxapp_install_idle_handler();
3307 if (cursor
== wxNullCursor
)
3308 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3310 return wxWindowBase::SetCursor( cursor
);
3313 void wxWindowGTK::WarpPointer( int x
, int y
)
3315 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3317 /* we provide this function ourselves as it is
3318 missing in GDK (top of this file) */
3320 GdkWindow
*window
= (GdkWindow
*) NULL
;
3322 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3324 window
= GetConnectWidget()->window
;
3327 gdk_window_warp_pointer( window
, x
, y
);
3330 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect
*rect
)
3332 if (!m_widget
) return;
3333 if (!m_widget
->window
) return;
3335 // temporarily hide the caret to avoid nasty interactions between caret
3336 // drawing and the window contents redraw
3337 #if 0 // def wxUSE_CARET -- doesn't seem to help :-(
3338 wxCaretSuspend
cs((wxWindow
*)this);
3339 #endif // wxUSE_CARET
3341 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3345 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3347 rect
->width
, rect
->height
);
3351 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3355 /* there is no GTK equivalent of "draw only, don't clear" so we
3356 invent our own in the GtkPizza widget */
3364 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3365 gboolean old_clear = pizza->clear_on_draw;
3366 gtk_pizza_set_clear( pizza, FALSE );
3367 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3368 gtk_pizza_set_clear( pizza, old_clear );
3370 GdkEventExpose gdk_event
;
3371 gdk_event
.type
= GDK_EXPOSE
;
3372 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3373 gdk_event
.count
= 0;
3374 gdk_event
.area
.x
= 0;
3375 gdk_event
.area
.y
= 0;
3376 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3377 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3378 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, (wxWindow
*)this );
3382 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3391 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3392 gboolean old_clear = pizza->clear_on_draw;
3393 gtk_pizza_set_clear( pizza, FALSE );
3395 GdkRectangle gdk_rect;
3396 gdk_rect.x = rect->x;
3397 gdk_rect.y = rect->y;
3398 gdk_rect.width = rect->width;
3399 gdk_rect.height = rect->height;
3400 gtk_widget_draw( m_wxwindow, &gdk_rect );
3401 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3403 gtk_pizza_set_clear( pizza, old_clear );
3405 GdkEventExpose gdk_event
;
3406 gdk_event
.type
= GDK_EXPOSE
;
3407 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3408 gdk_event
.count
= 0;
3409 gdk_event
.area
.x
= rect
->x
;
3410 gdk_event
.area
.y
= rect
->y
;
3411 gdk_event
.area
.width
= rect
->width
;
3412 gdk_event
.area
.height
= rect
->height
;
3413 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, (wxWindow
*)this );
3417 GdkRectangle gdk_rect
;
3418 gdk_rect
.x
= rect
->x
;
3419 gdk_rect
.y
= rect
->y
;
3420 gdk_rect
.width
= rect
->width
;
3421 gdk_rect
.height
= rect
->height
;
3422 gtk_widget_draw( m_widget
, &gdk_rect
);
3427 void wxWindowGTK::Clear()
3429 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3431 if (!m_widget
->window
) return;
3433 if (m_wxwindow
&& m_wxwindow
->window
)
3435 // gdk_window_clear( m_wxwindow->window );
3440 void wxWindowGTK::DoSetToolTip( wxToolTip
*tip
)
3442 wxWindowBase::DoSetToolTip(tip
);
3445 m_tooltip
->Apply( (wxWindow
*)this );
3448 void wxWindowGTK::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3450 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3452 #endif // wxUSE_TOOLTIPS
3454 bool wxWindowGTK::SetBackgroundColour( const wxColour
&colour
)
3456 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3458 if (!wxWindowBase::SetBackgroundColour(colour
))
3460 // don't leave if the GTK widget has just
3462 if (!m_delayedBackgroundColour
) return FALSE
;
3465 GdkWindow
*window
= (GdkWindow
*) NULL
;
3467 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3469 window
= GetConnectWidget()->window
;
3473 // indicate that a new style has been set
3474 // but it couldn't get applied as the
3475 // widget hasn't been realized yet.
3476 m_delayedBackgroundColour
= TRUE
;
3480 (m_wxwindow
->window
) &&
3481 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3483 /* wxMSW doesn't clear the window here. I don't do that either to
3484 provide compatibility. call Clear() to do the job. */
3486 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3487 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3495 bool wxWindowGTK::SetForegroundColour( const wxColour
&colour
)
3497 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3499 if (!wxWindowBase::SetForegroundColour(colour
))
3501 // don't leave if the GTK widget has just
3503 if (!m_delayedForegroundColour
) return FALSE
;
3506 GdkWindow
*window
= (GdkWindow
*) NULL
;
3508 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3510 window
= GetConnectWidget()->window
;
3514 // indicate that a new style has been set
3515 // but it couldn't get applied as the
3516 // widget hasn't been realized yet.
3517 m_delayedForegroundColour
= TRUE
;
3525 GtkStyle
*wxWindowGTK::GetWidgetStyle()
3529 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3531 /* FIXME: is this necessary? */
3532 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3534 remake
->klass
= m_widgetStyle
->klass
;
3537 gtk_style_unref( m_widgetStyle
);
3538 m_widgetStyle
= remake
;
3542 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3545 def
= gtk_widget_get_default_style();
3547 m_widgetStyle
= gtk_style_copy( def
);
3549 /* FIXME: is this necessary? */
3550 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3552 m_widgetStyle
->klass
= def
->klass
;
3556 return m_widgetStyle
;
3559 void wxWindowGTK::SetWidgetStyle()
3561 #if DISABLE_STYLE_IF_BROKEN_THEM
3562 if (m_widget
->style
->engine_data
)
3564 static bool s_warningPrinted
= FALSE
;
3565 if (!s_warningPrinted
)
3567 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3568 s_warningPrinted
= TRUE
;
3570 m_widgetStyle
= m_widget
->style
;
3575 GtkStyle
*style
= GetWidgetStyle();
3577 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3579 gdk_font_unref( style
->font
);
3580 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3583 if (m_foregroundColour
.Ok())
3585 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3586 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3588 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3589 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3590 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3594 // Try to restore the gtk default style. This is still a little
3595 // oversimplified for what is probably really needed here for controls
3596 // other than buttons, but is better than not being able to (re)set a
3597 // control's foreground colour to *wxBLACK -- RL
3598 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3601 def
= gtk_widget_get_default_style();
3603 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3604 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3605 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3609 if (m_backgroundColour
.Ok())
3611 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3612 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3614 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3615 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3616 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3617 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3618 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3619 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3620 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3621 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3625 // Try to restore the gtk default style. This is still a little
3626 // oversimplified for what is probably really needed here for controls
3627 // other than buttons, but is better than not being able to (re)set a
3628 // control's background colour to default grey and means resetting a
3629 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3631 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3634 def
= gtk_widget_get_default_style();
3636 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3637 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3638 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3639 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3640 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3641 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3642 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3643 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3648 void wxWindowGTK::ApplyWidgetStyle()
3652 //-----------------------------------------------------------------------------
3653 // Pop-up menu stuff
3654 //-----------------------------------------------------------------------------
3656 #if wxUSE_MENUS_NATIVE
3658 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3660 *is_waiting
= FALSE
;
3663 static void SetInvokingWindow( wxMenu
*menu
, wxWindowGTK
*win
)
3665 menu
->SetInvokingWindow( win
);
3666 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3669 wxMenuItem
*menuitem
= node
->GetData();
3670 if (menuitem
->IsSubMenu())
3672 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3675 node
= node
->GetNext();
3679 static gint gs_pop_x
= 0;
3680 static gint gs_pop_y
= 0;
3682 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3686 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3691 bool wxWindowGTK::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3693 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3695 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3697 SetInvokingWindow( menu
, this );
3704 bool is_waiting
= TRUE
;
3706 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3707 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3710 GTK_MENU(menu
->m_menu
),
3711 (GtkWidget
*) NULL
, // parent menu shell
3712 (GtkWidget
*) NULL
, // parent menu item
3713 (GtkMenuPositionFunc
) pop_pos_callback
,
3714 (gpointer
) this, // client data
3715 0, // button used to activate it
3716 gs_timeLastClick
// the time of activation
3721 while (gtk_events_pending())
3722 gtk_main_iteration();
3728 #endif // wxUSE_MENUS_NATIVE
3730 #if wxUSE_DRAG_AND_DROP
3732 void wxWindowGTK::SetDropTarget( wxDropTarget
*dropTarget
)
3734 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3736 GtkWidget
*dnd_widget
= GetConnectWidget();
3738 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3740 if (m_dropTarget
) delete m_dropTarget
;
3741 m_dropTarget
= dropTarget
;
3743 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3746 #endif // wxUSE_DRAG_AND_DROP
3748 GtkWidget
* wxWindowGTK::GetConnectWidget()
3750 GtkWidget
*connect_widget
= m_widget
;
3751 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3753 return connect_widget
;
3756 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow
*window
)
3759 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3761 return (window
== m_widget
->window
);
3764 bool wxWindowGTK::SetFont( const wxFont
&font
)
3766 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3768 if (!wxWindowBase::SetFont(font
))
3773 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3774 if ( sysbg
== m_backgroundColour
)
3776 m_backgroundColour
= wxNullColour
;
3778 m_backgroundColour
= sysbg
;
3788 void wxWindowGTK::CaptureMouse()
3790 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3792 GdkWindow
*window
= (GdkWindow
*) NULL
;
3794 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3796 window
= GetConnectWidget()->window
;
3798 wxCHECK_RET( window
, _T("CaptureMouse() failed") );
3800 wxCursor
* cursor
= & m_cursor
;
3802 cursor
= wxSTANDARD_CURSOR
;
3804 gdk_pointer_grab( window
, FALSE
,
3806 (GDK_BUTTON_PRESS_MASK
|
3807 GDK_BUTTON_RELEASE_MASK
|
3808 GDK_POINTER_MOTION_HINT_MASK
|
3809 GDK_POINTER_MOTION_MASK
),
3811 cursor
->GetCursor(),
3812 (guint32
)GDK_CURRENT_TIME
);
3813 g_captureWindow
= this;
3814 g_captureWindowHasMouse
= TRUE
;
3817 void wxWindowGTK::ReleaseMouse()
3819 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3821 wxCHECK_RET( g_captureWindow
, wxT("can't release mouse - not captured") );
3823 GdkWindow
*window
= (GdkWindow
*) NULL
;
3825 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3827 window
= GetConnectWidget()->window
;
3832 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3833 g_captureWindow
= (wxWindowGTK
*) NULL
;
3837 wxWindow
*wxWindowBase::GetCapture()
3839 return (wxWindow
*)g_captureWindow
;
3842 bool wxWindowGTK::IsRetained() const
3847 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3848 int range
, bool refresh
)
3850 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3852 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3854 m_hasScrolling
= TRUE
;
3856 if (orient
== wxHORIZONTAL
)
3858 float fpos
= (float)pos
;
3859 float frange
= (float)range
;
3860 float fthumb
= (float)thumbVisible
;
3861 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3862 if (fpos
< 0.0) fpos
= 0.0;
3864 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3865 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3867 SetScrollPos( orient
, pos
, refresh
);
3871 m_oldHorizontalPos
= fpos
;
3873 m_hAdjust
->lower
= 0.0;
3874 m_hAdjust
->upper
= frange
;
3875 m_hAdjust
->value
= fpos
;
3876 m_hAdjust
->step_increment
= 1.0;
3877 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3878 m_hAdjust
->page_size
= fthumb
;
3882 float fpos
= (float)pos
;
3883 float frange
= (float)range
;
3884 float fthumb
= (float)thumbVisible
;
3885 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3886 if (fpos
< 0.0) fpos
= 0.0;
3888 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3889 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3891 SetScrollPos( orient
, pos
, refresh
);
3895 m_oldVerticalPos
= fpos
;
3897 m_vAdjust
->lower
= 0.0;
3898 m_vAdjust
->upper
= frange
;
3899 m_vAdjust
->value
= fpos
;
3900 m_vAdjust
->step_increment
= 1.0;
3901 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3902 m_vAdjust
->page_size
= fthumb
;
3905 if (orient
== wxHORIZONTAL
)
3906 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3908 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3911 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3913 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3915 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3917 if (orient
== wxHORIZONTAL
)
3919 float fpos
= (float)pos
;
3920 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3921 if (fpos
< 0.0) fpos
= 0.0;
3922 m_oldHorizontalPos
= fpos
;
3924 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3925 m_hAdjust
->value
= fpos
;
3929 float fpos
= (float)pos
;
3930 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3931 if (fpos
< 0.0) fpos
= 0.0;
3932 m_oldVerticalPos
= fpos
;
3934 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3935 m_vAdjust
->value
= fpos
;
3938 if (m_wxwindow
->window
)
3940 if (orient
== wxHORIZONTAL
)
3942 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3943 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3945 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3947 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3948 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3952 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3953 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3955 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3957 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3958 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3963 int wxWindowGTK::GetScrollThumb( int orient
) const
3965 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3967 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3969 if (orient
== wxHORIZONTAL
)
3970 return (int)(m_hAdjust
->page_size
+0.5);
3972 return (int)(m_vAdjust
->page_size
+0.5);
3975 int wxWindowGTK::GetScrollPos( int orient
) const
3977 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3979 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3981 if (orient
== wxHORIZONTAL
)
3982 return (int)(m_hAdjust
->value
+0.5);
3984 return (int)(m_vAdjust
->value
+0.5);
3987 int wxWindowGTK::GetScrollRange( int orient
) const
3989 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3991 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3993 if (orient
== wxHORIZONTAL
)
3994 return (int)(m_hAdjust
->upper
+0.5);
3996 return (int)(m_vAdjust
->upper
+0.5);
3999 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
4001 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
4003 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
4005 if ((dx
== 0) && (dy
== 0)) return;
4007 m_clipPaintRegion
= TRUE
;
4008 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
4009 m_clipPaintRegion
= FALSE
;
4012 if (m_children.GetCount() > 0)
4014 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
4018 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
4020 pizza->xoffset -= dx;
4021 pizza->yoffset -= dy;
4023 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
4024 gdk_gc_set_exposures( m_scrollGC, TRUE );
4028 GetClientSize( &cw, &ch );
4029 int w = cw - abs(dx);
4030 int h = ch - abs(dy);
4032 if ((h < 0) || (w < 0))
4040 if (dx < 0) s_x = -dx;
4041 if (dy < 0) s_y = -dy;
4044 if (dx > 0) d_x = dx;
4045 if (dy > 0) d_y = dy;
4047 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
4048 pizza->bin_window, s_x, s_y, w, h );
4051 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
4052 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
4053 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
4054 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
4056 Refresh( TRUE, &rect );
4059 gdk_gc_unref( m_scrollGC );
4064 // Find the wxWindow at the current mouse position, also returning the mouse
4066 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
4068 pt
= wxGetMousePosition();
4069 wxWindow
* found
= wxFindWindowAtPoint(pt
);
4073 // Get the current mouse position.
4074 wxPoint
wxGetMousePosition()
4076 /* This crashes when used within wxHelpContext,
4077 so we have to use the X-specific implementation below.
4079 GdkModifierType *mask;
4080 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
4082 return wxPoint(x, y);
4086 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
4088 return wxPoint(-999, -999);
4090 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
4091 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
4092 Window rootReturn
, childReturn
;
4093 int rootX
, rootY
, winX
, winY
;
4094 unsigned int maskReturn
;
4096 XQueryPointer (display
,
4100 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
4101 return wxPoint(rootX
, rootY
);