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/statusbr.h"
44 #include "wx/settings.h"
48 #include "wx/thread.h"
55 #include <gdk/gdkprivate.h>
56 #include <gdk/gdkkeysyms.h>
60 #include <gtk/gtkprivate.h>
62 #include "wx/gtk/win_gtk.h"
64 //-----------------------------------------------------------------------------
65 // documentation on internals
66 //-----------------------------------------------------------------------------
69 I have been asked several times about writing some documentation about
70 the GTK port of wxWindows, especially its internal structures. Obviously,
71 you cannot understand wxGTK without knowing a little about the GTK, but
72 some more information about what the wxWindow, which is the base class
73 for all other window classes, does seems required as well.
77 What does wxWindow do? It contains the common interface for the following
78 jobs of its descendants:
80 1) Define the rudimentary behaviour common to all window classes, such as
81 resizing, intercepting user input (so as to make it possible to use these
82 events for special purposes in a derived class), window names etc.
84 2) Provide the possibility to contain and manage children, if the derived
85 class is allowed to contain children, which holds true for those window
86 classes which do not display a native GTK widget. To name them, these
87 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
88 work classes are a special case and are handled a bit differently from
89 the rest. The same holds true for the wxNotebook class.
91 3) Provide the possibility to draw into a client area of a window. This,
92 too, only holds true for classes that do not display a native GTK widget
95 4) Provide the entire mechanism for scrolling widgets. This actual inter-
96 face for this is usually in wxScrolledWindow, but the GTK implementation
99 5) A multitude of helper or extra methods for special purposes, such as
100 Drag'n'Drop, managing validators etc.
102 6) Display a border (sunken, raised, simple or none).
104 Normally one might expect, that one wxWindows window would always correspond
105 to one GTK widget. Under GTK, there is no such allround widget that has all
106 the functionality. Moreover, the GTK defines a client area as a different
107 widget from the actual widget you are handling. Last but not least some
108 special classes (e.g. wxFrame) handle different categories of widgets and
109 still have the possibility to draw something in the client area.
110 It was therefore required to write a special purpose GTK widget, that would
111 represent a client area in the sense of wxWindows capable to do the jobs
112 2), 3) and 4). I have written this class and it resides in win_gtk.c of
115 All windows must have a widget, with which they interact with other under-
116 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
117 thw wxWindow class has a member variable called m_widget which holds a
118 pointer to this widget. When the window class represents a GTK native widget,
119 this is (in most cases) the only GTK widget the class manages. E.g. the
120 wxStatitText class handles only a GtkLabel widget a pointer to which you
121 can find in m_widget (defined in wxWindow)
123 When the class has a client area for drawing into and for containing children
124 it has to handle the client area widget (of the type GtkPizza, defined in
125 win_gtk.c), but there could be any number of widgets, handled by a class
126 The common rule for all windows is only, that the widget that interacts with
127 the rest of GTK must be referenced in m_widget and all other widgets must be
128 children of this widget on the GTK level. The top-most widget, which also
129 represents the client area, must be in the m_wxwindow field and must be of
132 As I said, the window classes that display a GTK native widget only have
133 one widget, so in the case of e.g. the wxButton class m_widget holds a
134 pointer to a GtkButton widget. But windows with client areas (for drawing
135 and children) have a m_widget field that is a pointer to a GtkScrolled-
136 Window and a m_wxwindow field that is pointer to a GtkPizza and this
137 one is (in the GTK sense) a child of the GtkScrolledWindow.
139 If the m_wxwindow field is set, then all input to this widget is inter-
140 cepted and sent to the wxWindows class. If not, all input to the widget
141 that gets pointed to by m_widget gets intercepted and sent to the class.
145 The design of scrolling in wxWindows is markedly different from that offered
146 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
147 clicking on a scrollbar belonging to scrolled window will inevitably move
148 the window. In wxWindows, the scrollbar will only emit an event, send this
149 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
150 which actually moves the window and its subchildren. Note that GtkPizza
151 memorizes how much it has been scrolled but that wxWindows forgets this
152 so that the two coordinates systems have to be kept in synch. This is done
153 in various places using the pizza->xoffset and pizza->yoffset values.
157 Singularily the most broken code in GTK is the code that is supposes to
158 inform subwindows (child windows) about new positions. Very often, duplicate
159 events are sent without changes in size or position, equally often no
160 events are sent at all (All this is due to a bug in the GtkContainer code
161 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
162 GTK's own system and it simply waits for size events for toplevel windows
163 and then iterates down the respective size events to all window. This has
164 the disadvantage, that windows might get size events before the GTK widget
165 actually has the reported size. This doesn't normally pose any problem, but
166 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
167 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
168 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
169 window that is used for OpenGl output really has that size (as reported by
174 If someone at some point of time feels the immense desire to have a look at,
175 change or attempt to optimse the Refresh() logic, this person will need an
176 intimate understanding of what a "draw" and what an "expose" events are and
177 what there are used for, in particular when used in connection with GTK's
178 own windowless widgets. Beware.
182 Cursors, too, have been a constant source of pleasure. The main difficulty
183 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
184 for the parent. To prevent this from doing too much harm, I use idle time
185 to set the cursor over and over again, starting from the toplevel windows
186 and ending with the youngest generation (speaking of parent and child windows).
187 Also don't forget that cursors (like much else) are connected to GdkWindows,
188 not GtkWidgets and that the "window" field of a GtkWidget might very well
189 point to the GdkWindow of the parent widget (-> "window less widget") and
190 that the two obviously have very different meanings.
194 //-----------------------------------------------------------------------------
196 //-----------------------------------------------------------------------------
198 extern wxList wxPendingDelete
;
199 extern bool g_blockEventsOnDrag
;
200 extern bool g_blockEventsOnScroll
;
201 extern wxCursor g_globalCursor
;
203 // mouse capture state: the window which has it and if the mouse is currently
205 static wxWindowGTK
*g_captureWindow
= (wxWindowGTK
*) NULL
;
206 static bool g_captureWindowHasMouse
= FALSE
;
208 /* extern */ wxWindowGTK
*g_focusWindow
= (wxWindowGTK
*) NULL
;
210 // the last window which had the focus - this is normally never NULL (except
211 // if we never had focus at all) as even when g_focusWindow is NULL it still
212 // keeps its previous value
213 static wxWindowGTK
*g_focusWindowLast
= (wxWindowGTK
*)NULL
;
215 // if we detect that the app has got/lost the focus, we set this variable to
216 // either TRUE or FALSE and an activate event will be sent during the next
217 // OnIdle() call and it is reset to -1: this value means that we shouldn't
218 // send any activate events at all
219 static int g_sendActivateEvent
= -1;
221 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
222 the last click here */
223 static guint32 gs_timeLastClick
= 0;
225 extern bool g_mainThreadLocked
;
227 //-----------------------------------------------------------------------------
229 //-----------------------------------------------------------------------------
232 #define DISABLE_STYLE_IF_BROKEN_THEME 1
238 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
240 # define DEBUG_MAIN_THREAD
243 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
244 GdkEvent
*WXUNUSED(event
),
245 const wxChar
*WXUNUSED(name
) )
248 static bool s_done = FALSE;
251 wxLog::AddTraceMask("focus");
254 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
260 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
262 // suppress warnings about gtk_debug_focus_in_callback being unused with
267 tmp
+= wxT(" FROM ");
270 wxChar
*s
= new wxChar
[tmp
.Length()+1];
274 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
275 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
280 #define DEBUG_MAIN_THREAD
283 //-----------------------------------------------------------------------------
284 // missing gdk functions
285 //-----------------------------------------------------------------------------
288 gdk_window_warp_pointer (GdkWindow
*window
,
293 GdkWindowPrivate
*priv
;
297 window
= GDK_ROOT_PARENT();
300 if (!GDK_WINDOW_DESTROYED(window
))
302 XWarpPointer (GDK_WINDOW_XDISPLAY(window
),
303 None
, /* not source window -> move from anywhere */
304 GDK_WINDOW_XID(window
), /* dest window */
305 0, 0, 0, 0, /* not source window -> move from anywhere */
309 priv
= (GdkWindowPrivate
*) window
;
311 if (!priv
->destroyed
)
313 XWarpPointer (priv
->xdisplay
,
314 None
, /* not source window -> move from anywhere */
315 priv
->xwindow
, /* dest window */
316 0, 0, 0, 0, /* not source window -> move from anywhere */
322 //-----------------------------------------------------------------------------
324 //-----------------------------------------------------------------------------
326 extern void wxapp_install_idle_handler();
327 extern bool g_isIdle
;
329 //-----------------------------------------------------------------------------
330 // local code (see below)
331 //-----------------------------------------------------------------------------
333 // returns the child of win which currently has focus or NULL if not found
335 // Note: can't be static, needed by textctrl.cpp.
336 wxWindow
*wxFindFocusedChild(wxWindowGTK
*win
)
338 wxWindow
*winFocus
= wxWindowGTK::FindFocus();
340 return (wxWindow
*)NULL
;
342 if ( winFocus
== win
)
343 return (wxWindow
*)win
;
345 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
347 node
= node
->GetNext() )
349 wxWindow
*child
= wxFindFocusedChild(node
->GetData());
354 return (wxWindow
*)NULL
;
357 static void draw_frame( GtkWidget
*widget
, wxWindowGTK
*win
)
359 // wxUniversal widgets draw the borders and scrollbars themselves
360 #ifndef __WXUNIVERSAL__
367 if (win
->m_hasScrolling
)
369 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
371 GtkRequisition vscroll_req
;
372 vscroll_req
.width
= 2;
373 vscroll_req
.height
= 2;
374 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
375 (scroll_window
->vscrollbar
, &vscroll_req
);
377 GtkRequisition hscroll_req
;
378 hscroll_req
.width
= 2;
379 hscroll_req
.height
= 2;
380 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
381 (scroll_window
->hscrollbar
, &hscroll_req
);
383 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) );
385 if (scroll_window
->vscrollbar_visible
)
387 dw
+= vscroll_req
.width
;
388 dw
+= scroll_class
->scrollbar_spacing
;
391 if (scroll_window
->hscrollbar_visible
)
393 dh
+= hscroll_req
.height
;
394 dh
+= scroll_class
->scrollbar_spacing
;
400 if (GTK_WIDGET_NO_WINDOW (widget
))
402 dx
+= widget
->allocation
.x
;
403 dy
+= widget
->allocation
.y
;
406 if (win
->HasFlag(wxRAISED_BORDER
))
408 gtk_draw_shadow( widget
->style
,
413 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
417 if (win
->HasFlag(wxSUNKEN_BORDER
))
419 gtk_draw_shadow( widget
->style
,
424 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
428 if (win
->HasFlag(wxSIMPLE_BORDER
))
431 gc
= gdk_gc_new( widget
->window
);
432 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
433 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
435 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
439 #endif // __WXUNIVERSAL__
442 //-----------------------------------------------------------------------------
443 // "expose_event" of m_widget
444 //-----------------------------------------------------------------------------
446 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindowGTK
*win
)
448 if (gdk_event
->count
> 0) return FALSE
;
450 draw_frame( widget
, win
);
455 //-----------------------------------------------------------------------------
456 // "draw" of m_widget
457 //-----------------------------------------------------------------------------
459 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindowGTK
*win
)
461 draw_frame( widget
, win
);
464 //-----------------------------------------------------------------------------
465 // key code mapping routines
466 //-----------------------------------------------------------------------------
468 static long map_to_unmodified_wx_keysym( GdkEventKey
*event
)
470 KeySym keysym
= event
->keyval
;
476 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
478 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
484 case GDK_Super_R
: key_code
= WXK_ALT
; break;
485 case GDK_Menu
: key_code
= WXK_MENU
; break;
486 case GDK_Help
: key_code
= WXK_HELP
; break;
487 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
488 case GDK_ISO_Left_Tab
:
489 case GDK_Tab
: key_code
= WXK_TAB
; break;
490 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
491 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
492 case GDK_Return
: key_code
= WXK_RETURN
; break;
493 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
494 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
495 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
496 case GDK_Delete
: key_code
= WXK_DELETE
; break;
497 case GDK_Home
: key_code
= WXK_HOME
; break;
498 case GDK_Left
: key_code
= WXK_LEFT
; break;
499 case GDK_Up
: key_code
= WXK_UP
; break;
500 case GDK_Right
: key_code
= WXK_RIGHT
; break;
501 case GDK_Down
: key_code
= WXK_DOWN
; break;
502 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
503 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
504 case GDK_Next
: key_code
= WXK_NEXT
; break;
505 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
506 case GDK_End
: key_code
= WXK_END
; break;
507 case GDK_Begin
: key_code
= WXK_HOME
; break;
508 case GDK_Select
: key_code
= WXK_SELECT
; break;
509 case GDK_Print
: key_code
= WXK_PRINT
; break;
510 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
511 case GDK_Insert
: key_code
= WXK_INSERT
; break;
512 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
514 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
515 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
516 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
517 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
518 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
519 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
520 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
521 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
522 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
523 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
524 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
525 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
526 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
527 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
528 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
529 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
530 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
531 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
532 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
533 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
534 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
535 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
536 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
537 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
538 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
539 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
540 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
541 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
542 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
543 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
544 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
545 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
546 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
547 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
548 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
549 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
550 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
552 case GDK_F1
: key_code
= WXK_F1
; break;
553 case GDK_F2
: key_code
= WXK_F2
; break;
554 case GDK_F3
: key_code
= WXK_F3
; break;
555 case GDK_F4
: key_code
= WXK_F4
; break;
556 case GDK_F5
: key_code
= WXK_F5
; break;
557 case GDK_F6
: key_code
= WXK_F6
; break;
558 case GDK_F7
: key_code
= WXK_F7
; break;
559 case GDK_F8
: key_code
= WXK_F8
; break;
560 case GDK_F9
: key_code
= WXK_F9
; break;
561 case GDK_F10
: key_code
= WXK_F10
; break;
562 case GDK_F11
: key_code
= WXK_F11
; break;
563 case GDK_F12
: key_code
= WXK_F12
; break;
566 if (event
->length
== 1)
568 key_code
= toupper( (unsigned char)*event
->string
);
570 else if ((keysym
& 0xFF) == keysym
)
572 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
573 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
574 key_code
= (guint
)keysym
;
582 static long map_to_wx_keysym( GdkEventKey
*event
)
584 KeySym keysym
= event
->keyval
;
589 case GDK_Menu
: key_code
= WXK_MENU
; break;
590 case GDK_Help
: key_code
= WXK_HELP
; break;
591 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
592 case GDK_ISO_Left_Tab
:
593 case GDK_Tab
: key_code
= WXK_TAB
; break;
594 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
595 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
596 case GDK_Return
: key_code
= WXK_RETURN
; break;
597 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
598 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
599 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
600 case GDK_Delete
: key_code
= WXK_DELETE
; break;
601 case GDK_Home
: key_code
= WXK_HOME
; break;
602 case GDK_Left
: key_code
= WXK_LEFT
; break;
603 case GDK_Up
: key_code
= WXK_UP
; break;
604 case GDK_Right
: key_code
= WXK_RIGHT
; break;
605 case GDK_Down
: key_code
= WXK_DOWN
; break;
606 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
607 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
608 case GDK_Next
: key_code
= WXK_NEXT
; break;
609 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
610 case GDK_End
: key_code
= WXK_END
; break;
611 case GDK_Begin
: key_code
= WXK_HOME
; break;
612 case GDK_Select
: key_code
= WXK_SELECT
; break;
613 case GDK_Print
: key_code
= WXK_PRINT
; break;
614 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
615 case GDK_Insert
: key_code
= WXK_INSERT
; break;
616 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
618 case GDK_KP_0
: key_code
= '0'; break;
619 case GDK_KP_1
: key_code
= '1'; break;
620 case GDK_KP_2
: key_code
= '2'; break;
621 case GDK_KP_3
: key_code
= '3'; break;
622 case GDK_KP_4
: key_code
= '4'; break;
623 case GDK_KP_5
: key_code
= '5'; break;
624 case GDK_KP_6
: key_code
= '6'; break;
625 case GDK_KP_7
: key_code
= '7'; break;
626 case GDK_KP_8
: key_code
= '8'; break;
627 case GDK_KP_9
: key_code
= '9'; break;
628 case GDK_KP_Space
: key_code
= ' '; break;
629 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
630 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
631 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
632 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
633 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
634 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
635 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
636 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
637 case GDK_KP_Up
: key_code
= WXK_UP
; break;
638 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
639 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
640 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
641 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
642 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
643 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
644 case GDK_KP_End
: key_code
= WXK_END
; break;
645 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
646 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
647 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
648 case GDK_KP_Equal
: key_code
= '='; break;
649 case GDK_KP_Multiply
: key_code
= '*'; break;
650 case GDK_KP_Add
: key_code
= '+'; break;
651 case GDK_KP_Separator
: key_code
= ','; break;
652 case GDK_KP_Subtract
: key_code
= '-'; break;
653 case GDK_KP_Decimal
: key_code
= '.'; break;
654 case GDK_KP_Divide
: key_code
= '/'; break;
656 case GDK_F1
: key_code
= WXK_F1
; break;
657 case GDK_F2
: key_code
= WXK_F2
; break;
658 case GDK_F3
: key_code
= WXK_F3
; break;
659 case GDK_F4
: key_code
= WXK_F4
; break;
660 case GDK_F5
: key_code
= WXK_F5
; break;
661 case GDK_F6
: key_code
= WXK_F6
; break;
662 case GDK_F7
: key_code
= WXK_F7
; break;
663 case GDK_F8
: key_code
= WXK_F8
; break;
664 case GDK_F9
: key_code
= WXK_F9
; break;
665 case GDK_F10
: key_code
= WXK_F10
; break;
666 case GDK_F11
: key_code
= WXK_F11
; break;
667 case GDK_F12
: key_code
= WXK_F12
; break;
670 if (event
->length
== 1)
672 key_code
= (unsigned char)*event
->string
;
674 else if ((keysym
& 0xFF) == keysym
)
676 key_code
= (guint
)keysym
;
684 //-----------------------------------------------------------------------------
685 // "size_request" of m_widget
686 //-----------------------------------------------------------------------------
688 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
691 win
->GetSize( &w
, &h
);
695 requisition
->height
= h
;
696 requisition
->width
= w
;
699 //-----------------------------------------------------------------------------
700 // "expose_event" of m_wxwindow
701 //-----------------------------------------------------------------------------
703 static int gtk_window_expose_callback( GtkWidget
*widget
,
704 GdkEventExpose
*gdk_event
,
710 wxapp_install_idle_handler();
713 if (win->GetName() == wxT("panel"))
715 wxPrintf( wxT("OnExpose from ") );
716 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
717 wxPrintf( win->GetClassInfo()->GetClassName() );
718 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
719 (int)gdk_event->area.y,
720 (int)gdk_event->area.width,
721 (int)gdk_event->area.height );
725 GtkPizza
*pizza
= GTK_PIZZA (widget
);
727 if (win
->GetThemeEnabled())
729 wxWindow
*parent
= win
->GetParent();
730 while (parent
&& !parent
->IsTopLevel())
731 parent
= parent
->GetParent();
735 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
736 GTK_SHADOW_NONE
, &gdk_event
->area
, parent
->m_widget
, "base", 0, 0, -1, -1);
739 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
741 gdk_event
->area
.width
,
742 gdk_event
->area
.height
);
744 if (gdk_event
->count
== 0)
746 win
->m_clipPaintRegion
= TRUE
;
749 dc
.SetClippingRegion(win
->GetUpdateRegion());
750 wxEraseEvent
eevent( win
->GetId(), &dc
);
751 eevent
.SetEventObject( win
);
753 (void)win
->GetEventHandler()->ProcessEvent(eevent
);
755 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
757 wxClientDC
dc( win
);
758 dc
.SetBrush( wxBrush( win
->GetBackgroundColour(), wxSOLID
) );
759 dc
.SetPen( *wxTRANSPARENT_PEN
);
761 wxRegionIterator
upd( win
->GetUpdateRegion() );
764 dc
.DrawRectangle( upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
770 wxNcPaintEvent
eventNc( win
->GetId() );
771 eventNc
.SetEventObject( win
);
772 win
->GetEventHandler()->ProcessEvent( eventNc
);
774 wxPaintEvent
event( win
->GetId() );
775 event
.SetEventObject( win
);
776 win
->GetEventHandler()->ProcessEvent( event
);
778 win
->GetUpdateRegion().Clear();
780 win
->m_clipPaintRegion
= FALSE
;
783 /* The following code will result in all window-less widgets
784 being redrawn if the wxWindows class is given a chance to
785 paint *anything* because it will then be allowed to paint
786 over the window-less widgets */
787 GList
*children
= pizza
->children
;
790 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
791 children
= children
->next
;
793 GdkEventExpose child_event
= *gdk_event
;
795 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
796 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
797 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
799 child_event
.area
.x
= child
->widget
->allocation
.x
;
800 child_event
.area
.y
= child
->widget
->allocation
.y
;
801 child_event
.area
.width
= child
->widget
->allocation
.width
;
802 child_event
.area
.height
= child
->widget
->allocation
.height
;
803 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
810 //-----------------------------------------------------------------------------
811 // "event" of m_wxwindow
812 //-----------------------------------------------------------------------------
814 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
815 expose events. We need them, of course, so we override the main event
816 procedure in GtkWidget by giving our own handler for all system events.
817 There, we look for expose events ourselves whereas all other events are
820 gint
gtk_window_event_event_callback( GtkWidget
*widget
,
821 GdkEventExpose
*event
,
824 if (event
->type
== GDK_EXPOSE
)
826 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
833 //-----------------------------------------------------------------------------
834 // "draw" of m_wxwindow
835 //-----------------------------------------------------------------------------
837 /* This callback is a complete replacement of the gtk_pizza_draw() function,
840 static void gtk_window_draw_callback( GtkWidget
*widget
,
847 wxapp_install_idle_handler();
849 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
850 (win
->GetChildren().GetCount() == 0))
856 if (win->GetName() == wxT("panel"))
858 wxPrintf( wxT("OnDraw from ") );
859 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
860 wxPrintf( win->GetClassInfo()->GetClassName() );
861 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
868 GtkPizza
*pizza
= GTK_PIZZA (widget
);
870 if (win
->GetThemeEnabled())
872 wxWindow
*parent
= win
->GetParent();
873 while (parent
&& !parent
->IsTopLevel())
874 parent
= parent
->GetParent();
878 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
879 GTK_SHADOW_NONE
, rect
, parent
->m_widget
, "base", 0, 0, -1, -1);
883 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
884 (pizza
->clear_on_draw
))
886 gdk_window_clear_area( pizza
->bin_window
,
887 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
890 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
892 win
->m_clipPaintRegion
= TRUE
;
895 dc
.SetClippingRegion(win
->GetUpdateRegion());
896 wxEraseEvent
eevent( win
->GetId(), &dc
);
897 eevent
.SetEventObject( win
);
900 (void)win
->GetEventHandler()->ProcessEvent(eevent
);
902 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
904 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
906 wxClientDC
dc( win
);
907 dc
.SetBrush( wxBrush( win
->GetBackgroundColour(), wxSOLID
) );
908 dc
.SetPen( *wxTRANSPARENT_PEN
);
910 wxRegionIterator
upd( win
->GetUpdateRegion() );
913 dc
.DrawRectangle( upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
920 wxNcPaintEvent
eventNc( win
->GetId() );
921 eventNc
.SetEventObject( win
);
922 win
->GetEventHandler()->ProcessEvent( eventNc
);
924 wxPaintEvent
event( win
->GetId() );
925 event
.SetEventObject( win
);
926 win
->GetEventHandler()->ProcessEvent( event
);
928 win
->GetUpdateRegion().Clear();
930 win
->m_clipPaintRegion
= FALSE
;
933 GList
*children
= pizza
->children
;
936 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
937 children
= children
->next
;
939 GdkRectangle child_area
;
940 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
942 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
947 //-----------------------------------------------------------------------------
948 // "key_press_event" from any window
949 //-----------------------------------------------------------------------------
951 static gint
gtk_window_key_press_callback( GtkWidget
*widget
,
952 GdkEventKey
*gdk_event
,
958 wxapp_install_idle_handler();
960 if (!win
->m_hasVMT
) return FALSE
;
961 if (g_blockEventsOnDrag
) return FALSE
;
966 tmp += (char)gdk_event->keyval;
967 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
968 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
973 GdkModifierType state
;
974 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
978 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
979 /* sending unknown key events doesn't really make sense */
980 if (key_code
== 0) return FALSE
;
982 wxKeyEvent
event( wxEVT_KEY_DOWN
);
983 event
.SetTimestamp( gdk_event
->time
);
984 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
985 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
986 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
987 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
988 event
.m_keyCode
= key_code
;
989 event
.m_scanCode
= gdk_event
->keyval
;
992 event
.SetEventObject( win
);
993 ret
= win
->GetEventHandler()->ProcessEvent( event
);
998 wxWindowGTK
*ancestor
= win
;
1001 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
1004 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
1005 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
1008 if (ancestor
->IsTopLevel())
1010 ancestor
= ancestor
->GetParent();
1013 #endif // wxUSE_ACCEL
1015 /* wxMSW doesn't send char events with Alt pressed */
1016 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
1017 will only be sent if it is not in an accelerator table. */
1018 key_code
= map_to_wx_keysym( gdk_event
);
1023 wxKeyEvent
event2( wxEVT_CHAR
);
1024 event2
.SetTimestamp( gdk_event
->time
);
1025 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1026 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1027 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1028 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1029 event2
.m_keyCode
= key_code
;
1030 event2
.m_scanCode
= gdk_event
->keyval
;
1033 event2
.SetEventObject( win
);
1034 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
1037 /* win is a control: tab can be propagated up */
1039 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
1040 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
1041 // have this style, yet choose not to process this particular TAB in which
1042 // case TAB must still work as a navigational character
1044 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
1046 (win
->GetParent()) &&
1047 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
1049 wxNavigationKeyEvent new_event
;
1050 new_event
.SetEventObject( win
->GetParent() );
1051 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
1052 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
1053 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1054 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
1055 new_event
.SetCurrentFocus( win
);
1056 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
1059 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
1061 (gdk_event
->keyval
== GDK_Escape
) )
1063 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
1064 new_event
.SetEventObject( win
);
1065 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
1068 #if (GTK_MINOR_VERSION > 0)
1069 /* Pressing F10 will activate the menu bar of the top frame. */
1073 (gdk_event->keyval == GDK_F10) )
1075 wxWindowGTK *ancestor = win;
1078 if (wxIsKindOf(ancestor,wxFrame))
1080 wxFrame *frame = (wxFrame*) ancestor;
1081 wxMenuBar *menubar = frame->GetMenuBar();
1084 wxNode *node = menubar->GetMenus().First();
1087 wxMenu *firstMenu = (wxMenu*) node->Data();
1088 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
1094 ancestor = ancestor->GetParent();
1102 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1109 //-----------------------------------------------------------------------------
1110 // "key_release_event" from any window
1111 //-----------------------------------------------------------------------------
1113 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindowGTK
*win
)
1118 wxapp_install_idle_handler();
1120 if (!win
->m_hasVMT
) return FALSE
;
1121 if (g_blockEventsOnDrag
) return FALSE
;
1124 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
1125 if (gdk_event->state & GDK_SHIFT_MASK)
1126 printf( "ShiftDown.\n" );
1128 printf( "ShiftUp.\n" );
1129 if (gdk_event->state & GDK_CONTROL_MASK)
1130 printf( "ControlDown.\n" );
1132 printf( "ControlUp.\n" );
1136 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
1138 /* sending unknown key events doesn't really make sense */
1139 if (key_code
== 0) return FALSE
;
1143 GdkModifierType state
;
1144 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1146 wxKeyEvent
event( wxEVT_KEY_UP
);
1147 event
.SetTimestamp( gdk_event
->time
);
1148 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1149 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1150 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1151 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1152 event
.m_keyCode
= key_code
;
1153 event
.m_scanCode
= gdk_event
->keyval
;
1156 event
.SetEventObject( win
);
1158 if (win
->GetEventHandler()->ProcessEvent( event
))
1160 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1167 // ----------------------------------------------------------------------------
1168 // mouse event processing helper
1169 // ----------------------------------------------------------------------------
1171 static void AdjustEventButtonState(wxMouseEvent
& event
)
1173 // GDK reports the old state of the button for a button press event, but
1174 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1175 // for a LEFT_DOWN event, not FALSE, so we will invert
1176 // left/right/middleDown for the corresponding click events
1178 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1179 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1180 (event
.GetEventType() == wxEVT_LEFT_UP
))
1182 event
.m_leftDown
= !event
.m_leftDown
;
1186 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1187 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1188 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1190 event
.m_middleDown
= !event
.m_middleDown
;
1194 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1195 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1196 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1198 event
.m_rightDown
= !event
.m_rightDown
;
1203 //-----------------------------------------------------------------------------
1204 // "button_press_event"
1205 //-----------------------------------------------------------------------------
1207 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1212 wxapp_install_idle_handler();
1215 wxPrintf( wxT("1) OnButtonPress from ") );
1216 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1217 wxPrintf( win->GetClassInfo()->GetClassName() );
1218 wxPrintf( wxT(".\n") );
1220 if (!win
->m_hasVMT
) return FALSE
;
1221 if (g_blockEventsOnDrag
) return TRUE
;
1222 if (g_blockEventsOnScroll
) return TRUE
;
1224 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1226 if (win
->m_wxwindow
)
1228 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1230 gtk_widget_grab_focus (win
->m_wxwindow
);
1233 wxPrintf( wxT("GrabFocus from ") );
1234 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1235 wxPrintf( win->GetClassInfo()->GetClassName() );
1236 wxPrintf( wxT(".\n") );
1242 wxEventType event_type
= wxEVT_NULL
;
1244 if (gdk_event
->button
== 1)
1246 switch (gdk_event
->type
)
1248 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1249 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1253 else if (gdk_event
->button
== 2)
1255 switch (gdk_event
->type
)
1257 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1258 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1262 else if (gdk_event
->button
== 3)
1264 switch (gdk_event
->type
)
1266 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1267 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1272 if ( event_type
== wxEVT_NULL
)
1274 // unknown mouse button or click type
1278 wxMouseEvent
event( event_type
);
1279 event
.SetTimestamp( gdk_event
->time
);
1280 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1281 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1282 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1283 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1284 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1285 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1286 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1288 event
.m_x
= (wxCoord
)gdk_event
->x
;
1289 event
.m_y
= (wxCoord
)gdk_event
->y
;
1291 AdjustEventButtonState(event
);
1293 // Some control don't have their own X window and thus cannot get
1296 if (!g_captureWindow
)
1298 wxCoord x
= event
.m_x
;
1299 wxCoord y
= event
.m_y
;
1300 if (win
->m_wxwindow
)
1302 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1303 x
+= pizza
->xoffset
;
1304 y
+= pizza
->yoffset
;
1307 wxNode
*node
= win
->GetChildren().First();
1310 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1312 node
= node
->Next();
1313 if (!child
->IsShown())
1316 if (child
->m_isStaticBox
)
1318 // wxStaticBox is transparent in the box itself
1319 int xx1
= child
->m_x
;
1320 int yy1
= child
->m_y
;
1321 int xx2
= child
->m_x
+ child
->m_width
;
1322 int yy2
= child
->m_x
+ child
->m_height
;
1325 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1327 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1329 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1331 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1334 event
.m_x
-= child
->m_x
;
1335 event
.m_y
-= child
->m_y
;
1342 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1343 (child
->m_x
<= x
) &&
1344 (child
->m_y
<= y
) &&
1345 (child
->m_x
+child
->m_width
>= x
) &&
1346 (child
->m_y
+child
->m_height
>= y
))
1349 event
.m_x
-= child
->m_x
;
1350 event
.m_y
-= child
->m_y
;
1357 event
.SetEventObject( win
);
1359 gs_timeLastClick
= gdk_event
->time
;
1362 wxPrintf( wxT("2) OnButtonPress from ") );
1363 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1364 wxPrintf( win->GetClassInfo()->GetClassName() );
1365 wxPrintf( wxT(".\n") );
1368 if (win
->GetEventHandler()->ProcessEvent( event
))
1370 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1377 //-----------------------------------------------------------------------------
1378 // "button_release_event"
1379 //-----------------------------------------------------------------------------
1381 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindowGTK
*win
)
1386 wxapp_install_idle_handler();
1388 if (!win
->m_hasVMT
) return FALSE
;
1389 if (g_blockEventsOnDrag
) return FALSE
;
1390 if (g_blockEventsOnScroll
) return FALSE
;
1392 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1395 printf( "OnButtonRelease from " );
1396 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1397 printf( win->GetClassInfo()->GetClassName() );
1401 wxEventType event_type
= wxEVT_NULL
;
1403 switch (gdk_event
->button
)
1405 case 1: event_type
= wxEVT_LEFT_UP
; break;
1406 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1407 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1408 default: return FALSE
;
1411 wxMouseEvent
event( event_type
);
1412 event
.SetTimestamp( gdk_event
->time
);
1413 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1414 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1415 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1416 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1417 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1418 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1419 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1420 event
.m_x
= (wxCoord
)gdk_event
->x
;
1421 event
.m_y
= (wxCoord
)gdk_event
->y
;
1423 AdjustEventButtonState(event
);
1425 // Some control don't have their own X window and thus cannot get
1428 if (!g_captureWindow
)
1430 wxCoord x
= event
.m_x
;
1431 wxCoord y
= event
.m_y
;
1432 if (win
->m_wxwindow
)
1434 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1435 x
+= pizza
->xoffset
;
1436 y
+= pizza
->yoffset
;
1439 wxNode
*node
= win
->GetChildren().First();
1442 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1444 node
= node
->Next();
1445 if (!child
->IsShown())
1448 if (child
->m_isStaticBox
)
1450 // wxStaticBox is transparent in the box itself
1451 int xx1
= child
->m_x
;
1452 int yy1
= child
->m_y
;
1453 int xx2
= child
->m_x
+ child
->m_width
;
1454 int yy2
= child
->m_x
+ child
->m_height
;
1457 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1459 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1461 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1463 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1466 event
.m_x
-= child
->m_x
;
1467 event
.m_y
-= child
->m_y
;
1474 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1475 (child
->m_x
<= x
) &&
1476 (child
->m_y
<= y
) &&
1477 (child
->m_x
+child
->m_width
>= x
) &&
1478 (child
->m_y
+child
->m_height
>= y
))
1481 event
.m_x
-= child
->m_x
;
1482 event
.m_y
-= child
->m_y
;
1489 event
.SetEventObject( win
);
1491 if (win
->GetEventHandler()->ProcessEvent( event
))
1493 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1500 // ============================================================================
1502 // ============================================================================
1504 // init wxMouseEvent with the info from gdk_event
1505 #define InitMouseEvent(event, gdk_event) \
1506 event.SetTimestamp( gdk_event->time ); \
1507 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK); \
1508 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK); \
1509 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK); \
1510 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK); \
1511 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK); \
1512 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK); \
1513 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK); \
1515 event.m_x = (wxCoord)gdk_event->x; \
1516 event.m_y = (wxCoord)gdk_event->y \
1518 //-----------------------------------------------------------------------------
1519 // "motion_notify_event"
1520 //-----------------------------------------------------------------------------
1522 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
,
1523 GdkEventMotion
*gdk_event
,
1529 wxapp_install_idle_handler();
1531 if (!win
->m_hasVMT
) return FALSE
;
1532 if (g_blockEventsOnDrag
) return FALSE
;
1533 if (g_blockEventsOnScroll
) return FALSE
;
1535 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1537 if (gdk_event
->is_hint
)
1541 GdkModifierType state
;
1542 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1548 printf( "OnMotion from " );
1549 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1550 printf( win->GetClassInfo()->GetClassName() );
1554 wxMouseEvent
event( wxEVT_MOTION
);
1555 InitMouseEvent(event
, gdk_event
);
1557 if ( g_captureWindow
)
1559 // synthetize a mouse enter or leave event if needed
1560 GdkWindow
*winUnderMouse
= gdk_window_at_pointer(NULL
, NULL
);
1561 bool hasMouse
= winUnderMouse
== gdk_event
->window
;
1562 if ( hasMouse
!= g_captureWindowHasMouse
)
1564 // the mouse changed window
1565 g_captureWindowHasMouse
= hasMouse
;
1567 wxMouseEvent
event(g_captureWindowHasMouse
? wxEVT_ENTER_WINDOW
1568 : wxEVT_LEAVE_WINDOW
);
1569 InitMouseEvent(event
, gdk_event
);
1570 event
.SetEventObject(win
);
1571 win
->GetEventHandler()->ProcessEvent(event
);
1576 // Some control don't have their own X window and thus cannot get
1579 wxCoord x
= event
.m_x
;
1580 wxCoord y
= event
.m_y
;
1581 if (win
->m_wxwindow
)
1583 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1584 x
+= pizza
->xoffset
;
1585 y
+= pizza
->yoffset
;
1588 wxNode
*node
= win
->GetChildren().First();
1591 wxWindowGTK
*child
= (wxWindowGTK
*)node
->Data();
1593 node
= node
->Next();
1594 if (!child
->IsShown())
1597 if (child
->m_isStaticBox
)
1599 // wxStaticBox is transparent in the box itself
1600 int xx1
= child
->m_x
;
1601 int yy1
= child
->m_y
;
1602 int xx2
= child
->m_x
+ child
->m_width
;
1603 int yy2
= child
->m_x
+ child
->m_height
;
1606 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1608 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1610 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1612 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1615 event
.m_x
-= child
->m_x
;
1616 event
.m_y
-= child
->m_y
;
1623 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1624 (child
->m_x
<= x
) &&
1625 (child
->m_y
<= y
) &&
1626 (child
->m_x
+child
->m_width
>= x
) &&
1627 (child
->m_y
+child
->m_height
>= y
))
1630 event
.m_x
-= child
->m_x
;
1631 event
.m_y
-= child
->m_y
;
1638 event
.SetEventObject( win
);
1640 if (win
->GetEventHandler()->ProcessEvent( event
))
1642 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1649 //-----------------------------------------------------------------------------
1651 //-----------------------------------------------------------------------------
1653 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
,
1654 GdkEvent
*WXUNUSED(event
),
1660 wxapp_install_idle_handler();
1662 if (!win
->m_hasVMT
) return FALSE
;
1663 if (g_blockEventsOnDrag
) return FALSE
;
1665 switch ( g_sendActivateEvent
)
1668 // we've got focus from outside, synthtize wxActivateEvent
1669 g_sendActivateEvent
= 1;
1673 // another our window just lost focus, it was already ours before
1674 // - don't send any wxActivateEvent
1675 g_sendActivateEvent
= -1;
1680 g_focusWindow
= win
;
1683 printf( "OnSetFocus from " );
1684 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1685 printf( win->GetClassInfo()->GetClassName() );
1687 printf( WXSTRINGCAST win->GetLabel() );
1691 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1694 panel
->SetLastFocus(win
);
1699 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1703 // caret needs to be informed about focus change
1704 wxCaret
*caret
= win
->GetCaret();
1707 caret
->OnSetFocus();
1709 #endif // wxUSE_CARET
1711 if (win
->IsTopLevel())
1713 wxActivateEvent
event( wxEVT_ACTIVATE
, TRUE
, win
->GetId() );
1714 event
.SetEventObject( win
);
1716 // ignore return value
1717 win
->GetEventHandler()->ProcessEvent( event
);
1720 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1721 event
.SetEventObject( win
);
1723 if (win
->GetEventHandler()->ProcessEvent( event
))
1725 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1733 //-----------------------------------------------------------------------------
1734 // "focus_out_event"
1735 //-----------------------------------------------------------------------------
1737 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindowGTK
*win
)
1742 wxapp_install_idle_handler();
1744 if (!win
->m_hasVMT
) return FALSE
;
1745 if (g_blockEventsOnDrag
) return FALSE
;
1747 // if the focus goes out of our app alltogether, OnIdle() will send
1748 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1749 // g_sendActivateEvent to -1
1750 g_sendActivateEvent
= 0;
1752 wxWindowGTK
*winFocus
= wxFindFocusedChild(win
);
1756 g_focusWindow
= (wxWindowGTK
*)NULL
;
1759 printf( "OnKillFocus from " );
1760 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1761 printf( win->GetClassInfo()->GetClassName() );
1771 // caret needs to be informed about focus change
1772 wxCaret
*caret
= win
->GetCaret();
1775 caret
->OnKillFocus();
1777 #endif // wxUSE_CARET
1779 if (win
->IsTopLevel())
1781 wxActivateEvent
event( wxEVT_ACTIVATE
, FALSE
, win
->GetId() );
1782 event
.SetEventObject( win
);
1784 // ignore return value
1785 win
->GetEventHandler()->ProcessEvent( event
);
1788 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1789 event
.SetEventObject( win
);
1791 if (win
->GetEventHandler()->ProcessEvent( event
))
1793 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1800 //-----------------------------------------------------------------------------
1801 // "enter_notify_event"
1802 //-----------------------------------------------------------------------------
1804 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1809 wxapp_install_idle_handler();
1811 if (!win
->m_hasVMT
) return FALSE
;
1812 if (g_blockEventsOnDrag
) return FALSE
;
1814 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1816 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1817 #if (GTK_MINOR_VERSION > 0)
1818 event
.SetTimestamp( gdk_event
->time
);
1820 event
.SetEventObject( win
);
1824 GdkModifierType state
= (GdkModifierType
)0;
1826 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1828 InitMouseEvent(event
, gdk_event
);
1833 if (win
->GetEventHandler()->ProcessEvent( event
))
1835 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1842 //-----------------------------------------------------------------------------
1843 // "leave_notify_event"
1844 //-----------------------------------------------------------------------------
1846 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindowGTK
*win
)
1851 wxapp_install_idle_handler();
1853 if (!win
->m_hasVMT
) return FALSE
;
1854 if (g_blockEventsOnDrag
) return FALSE
;
1856 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1858 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1859 #if (GTK_MINOR_VERSION > 0)
1860 event
.SetTimestamp( gdk_event
->time
);
1862 event
.SetEventObject( win
);
1866 GdkModifierType state
= (GdkModifierType
)0;
1868 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1870 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1871 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1872 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1873 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1874 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1875 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1876 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1881 if (win
->GetEventHandler()->ProcessEvent( event
))
1883 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1890 //-----------------------------------------------------------------------------
1891 // "value_changed" from m_vAdjust
1892 //-----------------------------------------------------------------------------
1894 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1899 wxapp_install_idle_handler();
1901 if (g_blockEventsOnDrag
) return;
1903 if (!win
->m_hasVMT
) return;
1905 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1906 if (fabs(diff
) < 0.2) return;
1908 win
->m_oldVerticalPos
= adjust
->value
;
1910 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1911 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1913 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1914 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1915 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1916 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1917 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1919 int value
= (int)(adjust
->value
+0.5);
1921 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1922 event
.SetEventObject( win
);
1923 win
->GetEventHandler()->ProcessEvent( event
);
1926 //-----------------------------------------------------------------------------
1927 // "value_changed" from m_hAdjust
1928 //-----------------------------------------------------------------------------
1930 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindowGTK
*win
)
1935 wxapp_install_idle_handler();
1937 if (g_blockEventsOnDrag
) return;
1938 if (!win
->m_hasVMT
) return;
1940 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1941 if (fabs(diff
) < 0.2) return;
1943 win
->m_oldHorizontalPos
= adjust
->value
;
1945 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1946 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1948 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1949 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1950 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1951 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1952 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1954 int value
= (int)(adjust
->value
+0.5);
1956 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1957 event
.SetEventObject( win
);
1958 win
->GetEventHandler()->ProcessEvent( event
);
1961 //-----------------------------------------------------------------------------
1962 // "button_press_event" from scrollbar
1963 //-----------------------------------------------------------------------------
1965 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1966 GdkEventButton
*gdk_event
,
1972 wxapp_install_idle_handler();
1975 g_blockEventsOnScroll
= TRUE
;
1976 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1981 //-----------------------------------------------------------------------------
1982 // "button_release_event" from scrollbar
1983 //-----------------------------------------------------------------------------
1985 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1986 GdkEventButton
*WXUNUSED(gdk_event
),
1991 // don't test here as we can release the mouse while being over
1992 // a different window than the slider
1994 // if (gdk_event->window != widget->slider) return FALSE;
1996 g_blockEventsOnScroll
= FALSE
;
1998 if (win
->m_isScrolling
)
2000 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
2004 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
2005 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
2007 value
= (int)(win
->m_hAdjust
->value
+0.5);
2010 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
2012 value
= (int)(win
->m_vAdjust
->value
+0.5);
2016 wxScrollWinEvent
event( command
, value
, dir
);
2017 event
.SetEventObject( win
);
2018 win
->GetEventHandler()->ProcessEvent( event
);
2021 win
->m_isScrolling
= FALSE
;
2026 // ----------------------------------------------------------------------------
2027 // this wxWindowBase function is implemented here (in platform-specific file)
2028 // because it is static and so couldn't be made virtual
2029 // ----------------------------------------------------------------------------
2031 wxWindow
*wxWindowBase::FindFocus()
2033 // the cast is necessary when we compile in wxUniversal mode
2034 return (wxWindow
*)g_focusWindow
;
2037 //-----------------------------------------------------------------------------
2038 // "realize" from m_widget
2039 //-----------------------------------------------------------------------------
2041 /* We cannot set colours and fonts before the widget has
2042 been realized, so we do this directly after realization. */
2045 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
2050 wxapp_install_idle_handler();
2052 if (win
->m_delayedBackgroundColour
)
2053 win
->SetBackgroundColour( win
->GetBackgroundColour() );
2055 if (win
->m_delayedForegroundColour
)
2056 win
->SetForegroundColour( win
->GetForegroundColour() );
2058 wxWindowCreateEvent
event( win
);
2059 event
.SetEventObject( win
);
2060 win
->GetEventHandler()->ProcessEvent( event
);
2065 //-----------------------------------------------------------------------------
2067 //-----------------------------------------------------------------------------
2070 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
2071 GtkAllocation
*WXUNUSED(alloc
),
2075 wxapp_install_idle_handler();
2077 if (!win
->m_hasScrolling
) return;
2079 int client_width
= 0;
2080 int client_height
= 0;
2081 win
->GetClientSize( &client_width
, &client_height
);
2082 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
2085 win
->m_oldClientWidth
= client_width
;
2086 win
->m_oldClientHeight
= client_height
;
2088 if (!win
->m_nativeSizeEvent
)
2090 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
2091 event
.SetEventObject( win
);
2092 win
->GetEventHandler()->ProcessEvent( event
);
2098 #define WXUNUSED_UNLESS_XIM(param) param
2100 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2103 /* Resize XIM window */
2106 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2107 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
2108 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2111 wxapp_install_idle_handler();
2117 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
2121 gdk_window_get_size (widget
->window
, &width
, &height
);
2122 win
->m_icattr
->preedit_area
.width
= width
;
2123 win
->m_icattr
->preedit_area
.height
= height
;
2124 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2129 //-----------------------------------------------------------------------------
2130 // "realize" from m_wxwindow
2131 //-----------------------------------------------------------------------------
2133 /* Initialize XIM support */
2136 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2137 wxWindowGTK
* WXUNUSED_UNLESS_XIM(win
) )
2140 wxapp_install_idle_handler();
2143 if (win
->m_ic
) return FALSE
;
2144 if (!widget
) return FALSE
;
2145 if (!gdk_im_ready()) return FALSE
;
2147 win
->m_icattr
= gdk_ic_attr_new();
2148 if (!win
->m_icattr
) return FALSE
;
2152 GdkColormap
*colormap
;
2153 GdkICAttr
*attr
= win
->m_icattr
;
2154 unsigned attrmask
= GDK_IC_ALL_REQ
;
2156 GdkIMStyle supported_style
= (GdkIMStyle
)
2157 (GDK_IM_PREEDIT_NONE
|
2158 GDK_IM_PREEDIT_NOTHING
|
2159 GDK_IM_PREEDIT_POSITION
|
2160 GDK_IM_STATUS_NONE
|
2161 GDK_IM_STATUS_NOTHING
);
2163 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2164 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2166 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2167 attr
->client_window
= widget
->window
;
2169 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2170 gtk_widget_get_default_colormap ())
2172 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2173 attr
->preedit_colormap
= colormap
;
2176 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2177 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2178 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2179 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2181 switch (style
& GDK_IM_PREEDIT_MASK
)
2183 case GDK_IM_PREEDIT_POSITION
:
2184 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2186 g_warning ("over-the-spot style requires fontset");
2190 gdk_window_get_size (widget
->window
, &width
, &height
);
2192 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2193 attr
->spot_location
.x
= 0;
2194 attr
->spot_location
.y
= height
;
2195 attr
->preedit_area
.x
= 0;
2196 attr
->preedit_area
.y
= 0;
2197 attr
->preedit_area
.width
= width
;
2198 attr
->preedit_area
.height
= height
;
2199 attr
->preedit_fontset
= widget
->style
->font
;
2204 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2206 if (win
->m_ic
== NULL
)
2207 g_warning ("Can't create input context.");
2210 mask
= gdk_window_get_events (widget
->window
);
2211 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2212 gdk_window_set_events (widget
->window
, mask
);
2214 if (GTK_WIDGET_HAS_FOCUS(widget
))
2215 gdk_im_begin (win
->m_ic
, widget
->window
);
2222 //-----------------------------------------------------------------------------
2223 // InsertChild for wxWindowGTK.
2224 //-----------------------------------------------------------------------------
2226 /* Callback for wxWindowGTK. This very strange beast has to be used because
2227 * C++ has no virtual methods in a constructor. We have to emulate a
2228 * virtual function here as wxNotebook requires a different way to insert
2229 * a child in it. I had opted for creating a wxNotebookPage window class
2230 * which would have made this superfluous (such in the MDI window system),
2231 * but no-one was listening to me... */
2233 static void wxInsertChildInWindow( wxWindowGTK
* parent
, wxWindowGTK
* child
)
2235 /* the window might have been scrolled already, do we
2236 have to adapt the position */
2237 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2238 child
->m_x
+= pizza
->xoffset
;
2239 child
->m_y
+= pizza
->yoffset
;
2241 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2242 GTK_WIDGET(child
->m_widget
),
2249 //-----------------------------------------------------------------------------
2251 //-----------------------------------------------------------------------------
2253 wxWindow
*wxGetActiveWindow()
2255 // the cast is necessary when we compile in wxUniversal mode
2256 return (wxWindow
*)g_focusWindow
;
2259 //-----------------------------------------------------------------------------
2261 //-----------------------------------------------------------------------------
2263 #ifdef __WXUNIVERSAL__
2264 IMPLEMENT_DYNAMIC_CLASS(wxWindowGTK
, wxWindowBase
)
2266 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2269 void wxWindowGTK::Init()
2275 m_widget
= (GtkWidget
*) NULL
;
2276 m_wxwindow
= (GtkWidget
*) NULL
;
2286 m_needParent
= TRUE
;
2287 m_isBeingDeleted
= FALSE
;
2290 m_nativeSizeEvent
= FALSE
;
2292 m_hasScrolling
= FALSE
;
2293 m_isScrolling
= FALSE
;
2295 m_hAdjust
= (GtkAdjustment
*) NULL
;
2296 m_vAdjust
= (GtkAdjustment
*) NULL
;
2297 m_oldHorizontalPos
= 0.0;
2298 m_oldVerticalPos
= 0.0;
2301 m_widgetStyle
= (GtkStyle
*) NULL
;
2303 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2305 m_isStaticBox
= FALSE
;
2306 m_isRadioButton
= FALSE
;
2308 m_acceptsFocus
= FALSE
;
2310 m_clipPaintRegion
= FALSE
;
2312 m_cursor
= *wxSTANDARD_CURSOR
;
2314 m_delayedForegroundColour
= FALSE
;
2315 m_delayedBackgroundColour
= FALSE
;
2318 m_ic
= (GdkIC
*) NULL
;
2319 m_icattr
= (GdkICAttr
*) NULL
;
2323 wxWindowGTK::wxWindowGTK()
2328 wxWindowGTK::wxWindowGTK( wxWindow
*parent
,
2333 const wxString
&name
)
2337 Create( parent
, id
, pos
, size
, style
, name
);
2340 bool wxWindowGTK::Create( wxWindow
*parent
,
2345 const wxString
&name
)
2347 if (!PreCreation( parent
, pos
, size
) ||
2348 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2350 wxFAIL_MSG( wxT("wxWindowGTK creation failed") );
2354 m_insertCallback
= wxInsertChildInWindow
;
2356 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2357 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2359 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2361 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2362 scroll_class
->scrollbar_spacing
= 0;
2364 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2366 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2367 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2369 m_wxwindow
= gtk_pizza_new();
2371 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2373 #ifndef __WXUNIVERSAL__
2374 #if (GTK_MINOR_VERSION > 0)
2375 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2377 if (HasFlag(wxRAISED_BORDER
))
2379 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2381 else if (HasFlag(wxSUNKEN_BORDER
))
2383 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2385 else if (HasFlag(wxSIMPLE_BORDER
))
2387 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2391 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2393 #else // GTK_MINOR_VERSION == 0
2394 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2396 if (HasFlag(wxRAISED_BORDER
))
2398 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2400 else if (HasFlag(wxSUNKEN_BORDER
))
2402 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2406 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2408 #endif // GTK_MINOR_VERSION
2409 #endif // __WXUNIVERSAL__
2411 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2412 m_acceptsFocus
= TRUE
;
2414 #if (GTK_MINOR_VERSION == 0)
2415 // shut the viewport up
2416 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2417 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2418 #endif // GTK_MINOR_VERSION == 0
2420 // I _really_ don't want scrollbars in the beginning
2421 m_vAdjust
->lower
= 0.0;
2422 m_vAdjust
->upper
= 1.0;
2423 m_vAdjust
->value
= 0.0;
2424 m_vAdjust
->step_increment
= 1.0;
2425 m_vAdjust
->page_increment
= 1.0;
2426 m_vAdjust
->page_size
= 5.0;
2427 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2428 m_hAdjust
->lower
= 0.0;
2429 m_hAdjust
->upper
= 1.0;
2430 m_hAdjust
->value
= 0.0;
2431 m_hAdjust
->step_increment
= 1.0;
2432 m_hAdjust
->page_increment
= 1.0;
2433 m_hAdjust
->page_size
= 5.0;
2434 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2436 // these handlers block mouse events to any window during scrolling such as
2437 // motion events and prevent GTK and wxWindows from fighting over where the
2440 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2441 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2443 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2444 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2446 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2447 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2449 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2450 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2452 // these handlers get notified when screen updates are required either when
2453 // scrolling or when the window size (and therefore scrollbar configuration)
2456 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2457 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2458 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2459 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2461 gtk_widget_show( m_wxwindow
);
2464 m_parent
->DoAddChild( this );
2473 wxWindowGTK::~wxWindowGTK()
2475 if (g_focusWindow
== this)
2476 g_focusWindow
= NULL
;
2478 m_isBeingDeleted
= TRUE
;
2487 m_parent
->RemoveChild( this );
2491 gdk_ic_destroy (m_ic
);
2493 gdk_ic_attr_destroy (m_icattr
);
2498 #if DISABLE_STYLE_IF_BROKEN_THEME
2499 // don't delete if it's a pixmap theme style
2500 if (!m_widgetStyle
->engine_data
)
2501 gtk_style_unref( m_widgetStyle
);
2503 m_widgetStyle
= (GtkStyle
*) NULL
;
2508 gtk_widget_destroy( m_wxwindow
);
2509 m_wxwindow
= (GtkWidget
*) NULL
;
2514 gtk_widget_destroy( m_widget
);
2515 m_widget
= (GtkWidget
*) NULL
;
2519 bool wxWindowGTK::PreCreation( wxWindowGTK
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2521 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2523 /* this turns -1 into 20 so that a minimal window is
2524 visible even although -1,-1 has been given as the
2525 size of the window. the same trick is used in other
2526 ports and should make debugging easier */
2527 m_width
= WidthDefault(size
.x
);
2528 m_height
= HeightDefault(size
.y
);
2533 /* some reasonable defaults */
2538 m_x
= (gdk_screen_width () - m_width
) / 2;
2539 if (m_x
< 10) m_x
= 10;
2543 m_y
= (gdk_screen_height () - m_height
) / 2;
2544 if (m_y
< 10) m_y
= 10;
2551 void wxWindowGTK::PostCreation()
2553 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2559 /* these get reported to wxWindows -> wxPaintEvent */
2561 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2563 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2564 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2566 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2567 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2569 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2571 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2572 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2576 #if (GTK_MINOR_VERSION > 0)
2577 /* these are called when the "sunken" or "raised" borders are drawn */
2578 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2579 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2581 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2582 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2586 if (m_wxwindow
&& m_needParent
)
2588 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2589 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2591 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2592 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2596 // For dialogs and frames, we are interested mainly in
2597 // m_widget's focus.
2599 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2600 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2602 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2603 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2606 GtkWidget
*connect_widget
= GetConnectWidget();
2608 ConnectWidget( connect_widget
);
2610 /* We cannot set colours, fonts and cursors before the widget has
2611 been realized, so we do this directly after realization */
2612 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2613 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2617 // Catch native resize events
2618 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2619 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2621 // Initialize XIM support
2622 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2623 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2625 // And resize XIM window
2626 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2627 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2630 if (!GTK_IS_COMBO(m_widget
))
2632 // This is needed if we want to add our windows into native
2633 // GTK control, such as the toolbar. With this callback, the
2634 // toolbar gets to know the correct size (the one set by the
2635 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2636 // when moving to GTK 2.0.
2637 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2638 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2644 void wxWindowGTK::ConnectWidget( GtkWidget
*widget
)
2646 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2647 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2649 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2650 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2652 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2653 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2655 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2656 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2658 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2659 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2661 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2662 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2664 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2665 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2668 bool wxWindowGTK::Destroy()
2670 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2674 return wxWindowBase::Destroy();
2677 void wxWindowGTK::DoMoveWindow(int x
, int y
, int width
, int height
)
2679 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2682 void wxWindowGTK::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2684 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2685 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindowGTK::SetSize requires parent.\n") );
2688 printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
2691 if (m_resizing
) return; /* I don't like recursions */
2694 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2696 /* don't set the size for children of wxNotebook, just take the values. */
2704 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2706 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2708 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2709 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2710 if (width
!= -1) m_width
= width
;
2711 if (height
!= -1) m_height
= height
;
2715 m_x
= x
+ pizza
->xoffset
;
2716 m_y
= y
+ pizza
->yoffset
;
2721 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2723 if (width
== -1) m_width
= 80;
2726 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2728 if (height
== -1) m_height
= 26;
2731 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2732 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2733 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2734 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2737 int bottom_border
= 0;
2739 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2741 /* the default button has a border around it */
2746 DoMoveWindow( m_x
-border
,
2749 m_height
+border
+bottom_border
);
2754 /* Sometimes the client area changes size without the
2755 whole windows's size changing, but if the whole
2756 windows's size doesn't change, no wxSizeEvent will
2757 normally be sent. Here we add an extra test if
2758 the client test has been changed and this will
2760 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2764 wxPrintf( "OnSize sent from " );
2765 if (GetClassInfo() && GetClassInfo()->GetClassName())
2766 wxPrintf( GetClassInfo()->GetClassName() );
2767 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2770 if (!m_nativeSizeEvent
)
2772 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2773 event
.SetEventObject( this );
2774 GetEventHandler()->ProcessEvent( event
);
2780 void wxWindowGTK::OnInternalIdle()
2782 if ( g_sendActivateEvent
!= -1 )
2784 bool activate
= g_sendActivateEvent
!= 0;
2787 g_sendActivateEvent
= -1;
2789 wxTheApp
->SetActive(activate
, (wxWindow
*)g_focusWindowLast
);
2791 wxActivateEvent
event(wxEVT_ACTIVATE_APP
, activate
, GetId());
2792 event
.SetEventObject(this);
2794 (void)GetEventHandler()->ProcessEvent(event
);
2797 wxCursor cursor
= m_cursor
;
2798 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2802 /* I now set the cursor anew in every OnInternalIdle call
2803 as setting the cursor in a parent window also effects the
2804 windows above so that checking for the current cursor is
2809 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2811 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2813 if (!g_globalCursor
.Ok())
2814 cursor
= *wxSTANDARD_CURSOR
;
2816 window
= m_widget
->window
;
2817 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2818 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2824 GdkWindow
*window
= m_widget
->window
;
2825 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2826 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2834 void wxWindowGTK::DoGetSize( int *width
, int *height
) const
2836 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2838 if (width
) (*width
) = m_width
;
2839 if (height
) (*height
) = m_height
;
2842 void wxWindowGTK::DoSetClientSize( int width
, int height
)
2844 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2848 SetSize( width
, height
);
2855 #ifndef __WXUNIVERSAL__
2856 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2858 /* when using GTK 1.2 we set the shadow border size to 2 */
2862 if (HasFlag(wxSIMPLE_BORDER
))
2864 /* when using GTK 1.2 we set the simple border size to 1 */
2868 #endif // __WXUNIVERSAL__
2872 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2874 GtkRequisition vscroll_req
;
2875 vscroll_req
.width
= 2;
2876 vscroll_req
.height
= 2;
2877 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2878 (scroll_window
->vscrollbar
, &vscroll_req
);
2880 GtkRequisition hscroll_req
;
2881 hscroll_req
.width
= 2;
2882 hscroll_req
.height
= 2;
2883 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2884 (scroll_window
->hscrollbar
, &hscroll_req
);
2886 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2888 if (scroll_window
->vscrollbar_visible
)
2890 dw
+= vscroll_req
.width
;
2891 dw
+= scroll_class
->scrollbar_spacing
;
2894 if (scroll_window
->hscrollbar_visible
)
2896 dh
+= hscroll_req
.height
;
2897 dh
+= scroll_class
->scrollbar_spacing
;
2901 SetSize( width
+dw
, height
+dh
);
2905 void wxWindowGTK::DoGetClientSize( int *width
, int *height
) const
2907 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2911 if (width
) (*width
) = m_width
;
2912 if (height
) (*height
) = m_height
;
2919 #ifndef __WXUNIVERSAL__
2920 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2922 /* when using GTK 1.2 we set the shadow border size to 2 */
2926 if (HasFlag(wxSIMPLE_BORDER
))
2928 /* when using GTK 1.2 we set the simple border size to 1 */
2932 #endif // __WXUNIVERSAL__
2936 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2938 GtkRequisition vscroll_req
;
2939 vscroll_req
.width
= 2;
2940 vscroll_req
.height
= 2;
2941 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2942 (scroll_window
->vscrollbar
, &vscroll_req
);
2944 GtkRequisition hscroll_req
;
2945 hscroll_req
.width
= 2;
2946 hscroll_req
.height
= 2;
2947 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2948 (scroll_window
->hscrollbar
, &hscroll_req
);
2950 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2952 if (scroll_window
->vscrollbar_visible
)
2954 dw
+= vscroll_req
.width
;
2955 dw
+= scroll_class
->scrollbar_spacing
;
2958 if (scroll_window
->hscrollbar_visible
)
2960 dh
+= hscroll_req
.height
;
2961 dh
+= scroll_class
->scrollbar_spacing
;
2965 if (width
) (*width
) = m_width
- dw
;
2966 if (height
) (*height
) = m_height
- dh
;
2970 printf( "GetClientSize, name %s ", GetName().c_str() );
2971 if (width) printf( " width = %d", (*width) );
2972 if (height) printf( " height = %d", (*height) );
2977 void wxWindowGTK::DoGetPosition( int *x
, int *y
) const
2979 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2983 if (m_parent
&& m_parent
->m_wxwindow
)
2985 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2986 dx
= pizza
->xoffset
;
2987 dy
= pizza
->yoffset
;
2990 if (x
) (*x
) = m_x
- dx
;
2991 if (y
) (*y
) = m_y
- dy
;
2994 void wxWindowGTK::DoClientToScreen( int *x
, int *y
) const
2996 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2998 if (!m_widget
->window
) return;
3000 GdkWindow
*source
= (GdkWindow
*) NULL
;
3002 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3004 source
= m_widget
->window
;
3008 gdk_window_get_origin( source
, &org_x
, &org_y
);
3012 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3014 org_x
+= m_widget
->allocation
.x
;
3015 org_y
+= m_widget
->allocation
.y
;
3023 void wxWindowGTK::DoScreenToClient( int *x
, int *y
) const
3025 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3027 if (!m_widget
->window
) return;
3029 GdkWindow
*source
= (GdkWindow
*) NULL
;
3031 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3033 source
= m_widget
->window
;
3037 gdk_window_get_origin( source
, &org_x
, &org_y
);
3041 if (GTK_WIDGET_NO_WINDOW (m_widget
))
3043 org_x
+= m_widget
->allocation
.x
;
3044 org_y
+= m_widget
->allocation
.y
;
3052 bool wxWindowGTK::Show( bool show
)
3054 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3056 if (!wxWindowBase::Show(show
))
3063 gtk_widget_show( m_widget
);
3065 gtk_widget_hide( m_widget
);
3070 static void wxWindowNotifyEnable(wxWindowGTK
* win
, bool enable
)
3072 win
->OnParentEnable(enable
);
3074 // Recurse, so that children have the opportunity to Do The Right Thing
3075 // and reset colours that have been messed up by a parent's (really ancestor's)
3077 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
3079 node
= node
->GetNext() )
3081 wxWindow
*child
= node
->GetData();
3082 if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
)))
3083 wxWindowNotifyEnable(child
, enable
);
3087 bool wxWindowGTK::Enable( bool enable
)
3089 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3091 if (!wxWindowBase::Enable(enable
))
3097 gtk_widget_set_sensitive( m_widget
, enable
);
3099 gtk_widget_set_sensitive( m_wxwindow
, enable
);
3101 wxWindowNotifyEnable(this, enable
);
3106 int wxWindowGTK::GetCharHeight() const
3108 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
3110 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
3112 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3114 return font
->ascent
+ font
->descent
;
3117 int wxWindowGTK::GetCharWidth() const
3119 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
3121 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
3123 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3125 return gdk_string_width( font
, "H" );
3128 void wxWindowGTK::GetTextExtent( const wxString
& string
,
3132 int *externalLeading
,
3133 const wxFont
*theFont
) const
3135 wxFont fontToUse
= m_font
;
3136 if (theFont
) fontToUse
= *theFont
;
3138 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
3140 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
3141 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
3142 if (y
) (*y
) = font
->ascent
+ font
->descent
;
3143 if (descent
) (*descent
) = font
->descent
;
3144 if (externalLeading
) (*externalLeading
) = 0; // ??
3147 void wxWindowGTK::SetFocus()
3149 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3153 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3154 gtk_widget_grab_focus (m_wxwindow
);
3160 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
3162 gtk_widget_grab_focus (m_widget
);
3164 else if (GTK_IS_CONTAINER(m_widget
))
3166 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
3175 bool wxWindowGTK::AcceptsFocus() const
3177 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3180 bool wxWindowGTK::Reparent( wxWindowBase
*newParentBase
)
3182 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3184 wxWindowGTK
*oldParent
= m_parent
,
3185 *newParent
= (wxWindowGTK
*)newParentBase
;
3187 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3189 if ( !wxWindowBase::Reparent(newParent
) )
3192 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3194 /* prevent GTK from deleting the widget arbitrarily */
3195 gtk_widget_ref( m_widget
);
3199 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3202 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3206 /* insert GTK representation */
3207 (*(newParent
->m_insertCallback
))(newParent
, this);
3210 /* reverse: prevent GTK from deleting the widget arbitrarily */
3211 gtk_widget_unref( m_widget
);
3216 void wxWindowGTK::DoAddChild(wxWindowGTK
*child
)
3218 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3220 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3222 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3227 /* insert GTK representation */
3228 (*m_insertCallback
)(this, child
);
3231 void wxWindowGTK::Raise()
3233 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3235 if (!m_widget
->window
) return;
3237 gdk_window_raise( m_widget
->window
);
3240 void wxWindowGTK::Lower()
3242 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3244 if (!m_widget
->window
) return;
3246 gdk_window_lower( m_widget
->window
);
3249 bool wxWindowGTK::SetCursor( const wxCursor
&cursor
)
3251 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3253 if (cursor
== m_cursor
)
3257 wxapp_install_idle_handler();
3259 if (cursor
== wxNullCursor
)
3260 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3262 return wxWindowBase::SetCursor( cursor
);
3265 void wxWindowGTK::WarpPointer( int x
, int y
)
3267 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3269 /* we provide this function ourselves as it is
3270 missing in GDK (top of this file) */
3272 GdkWindow
*window
= (GdkWindow
*) NULL
;
3274 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3276 window
= GetConnectWidget()->window
;
3279 gdk_window_warp_pointer( window
, x
, y
);
3282 void wxWindowGTK::Refresh( bool eraseBackground
, const wxRect
*rect
)
3284 if (!m_widget
) return;
3285 if (!m_widget
->window
) return;
3287 // temporarily hide the caret to avoid nasty interactions between caret
3288 // drawing and the window contents redraw
3289 #if 0 // def wxUSE_CARET -- doesn't seem to help :-(
3290 wxCaretSuspend
cs((wxWindow
*)this);
3291 #endif // wxUSE_CARET
3293 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3297 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3299 rect
->width
, rect
->height
);
3303 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3307 /* there is no GTK equivalent of "draw only, don't clear" so we
3308 invent our own in the GtkPizza widget */
3316 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3317 gboolean old_clear = pizza->clear_on_draw;
3318 gtk_pizza_set_clear( pizza, FALSE );
3319 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3320 gtk_pizza_set_clear( pizza, old_clear );
3322 GdkEventExpose gdk_event
;
3323 gdk_event
.type
= GDK_EXPOSE
;
3324 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3325 gdk_event
.count
= 0;
3326 gdk_event
.area
.x
= 0;
3327 gdk_event
.area
.y
= 0;
3328 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3329 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3330 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, (wxWindow
*)this );
3334 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3343 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3344 gboolean old_clear = pizza->clear_on_draw;
3345 gtk_pizza_set_clear( pizza, FALSE );
3347 GdkRectangle gdk_rect;
3348 gdk_rect.x = rect->x;
3349 gdk_rect.y = rect->y;
3350 gdk_rect.width = rect->width;
3351 gdk_rect.height = rect->height;
3352 gtk_widget_draw( m_wxwindow, &gdk_rect );
3353 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3355 gtk_pizza_set_clear( pizza, old_clear );
3357 GdkEventExpose gdk_event
;
3358 gdk_event
.type
= GDK_EXPOSE
;
3359 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3360 gdk_event
.count
= 0;
3361 gdk_event
.area
.x
= rect
->x
;
3362 gdk_event
.area
.y
= rect
->y
;
3363 gdk_event
.area
.width
= rect
->width
;
3364 gdk_event
.area
.height
= rect
->height
;
3365 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, (wxWindow
*)this );
3369 GdkRectangle gdk_rect
;
3370 gdk_rect
.x
= rect
->x
;
3371 gdk_rect
.y
= rect
->y
;
3372 gdk_rect
.width
= rect
->width
;
3373 gdk_rect
.height
= rect
->height
;
3374 gtk_widget_draw( m_widget
, &gdk_rect
);
3379 void wxWindowGTK::Clear()
3381 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3383 if (!m_widget
->window
) return;
3385 if (m_wxwindow
&& m_wxwindow
->window
)
3387 // gdk_window_clear( m_wxwindow->window );
3392 void wxWindowGTK::DoSetToolTip( wxToolTip
*tip
)
3394 wxWindowBase::DoSetToolTip(tip
);
3397 m_tooltip
->Apply( (wxWindow
*)this );
3400 void wxWindowGTK::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3402 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3404 #endif // wxUSE_TOOLTIPS
3406 bool wxWindowGTK::SetBackgroundColour( const wxColour
&colour
)
3408 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3410 if (!wxWindowBase::SetBackgroundColour(colour
))
3412 // don't leave if the GTK widget has just
3414 if (!m_delayedBackgroundColour
) return FALSE
;
3417 GdkWindow
*window
= (GdkWindow
*) NULL
;
3419 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3421 window
= GetConnectWidget()->window
;
3425 // indicate that a new style has been set
3426 // but it couldn't get applied as the
3427 // widget hasn't been realized yet.
3428 m_delayedBackgroundColour
= TRUE
;
3432 (m_wxwindow
->window
) &&
3433 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3435 /* wxMSW doesn't clear the window here. I don't do that either to
3436 provide compatibility. call Clear() to do the job. */
3438 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3439 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3447 bool wxWindowGTK::SetForegroundColour( const wxColour
&colour
)
3449 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3451 if (!wxWindowBase::SetForegroundColour(colour
))
3453 // don't leave if the GTK widget has just
3455 if (!m_delayedForegroundColour
) return FALSE
;
3458 GdkWindow
*window
= (GdkWindow
*) NULL
;
3460 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3462 window
= GetConnectWidget()->window
;
3466 // indicate that a new style has been set
3467 // but it couldn't get applied as the
3468 // widget hasn't been realized yet.
3469 m_delayedForegroundColour
= TRUE
;
3477 GtkStyle
*wxWindowGTK::GetWidgetStyle()
3481 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3483 /* FIXME: is this necessary? */
3484 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3486 remake
->klass
= m_widgetStyle
->klass
;
3489 gtk_style_unref( m_widgetStyle
);
3490 m_widgetStyle
= remake
;
3494 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3497 def
= gtk_widget_get_default_style();
3499 m_widgetStyle
= gtk_style_copy( def
);
3501 /* FIXME: is this necessary? */
3502 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3504 m_widgetStyle
->klass
= def
->klass
;
3508 return m_widgetStyle
;
3511 void wxWindowGTK::SetWidgetStyle()
3513 #if DISABLE_STYLE_IF_BROKEN_THEM
3514 if (m_widget
->style
->engine_data
)
3516 static bool s_warningPrinted
= FALSE
;
3517 if (!s_warningPrinted
)
3519 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3520 s_warningPrinted
= TRUE
;
3522 m_widgetStyle
= m_widget
->style
;
3527 GtkStyle
*style
= GetWidgetStyle();
3529 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3531 gdk_font_unref( style
->font
);
3532 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3535 if (m_foregroundColour
.Ok())
3537 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3538 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3540 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3541 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3542 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3546 // Try to restore the gtk default style. This is still a little
3547 // oversimplified for what is probably really needed here for controls
3548 // other than buttons, but is better than not being able to (re)set a
3549 // control's foreground colour to *wxBLACK -- RL
3550 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3553 def
= gtk_widget_get_default_style();
3555 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3556 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3557 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3561 if (m_backgroundColour
.Ok())
3563 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3564 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3566 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3567 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3568 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3569 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3570 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3571 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3572 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3573 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3577 // Try to restore the gtk default style. This is still a little
3578 // oversimplified for what is probably really needed here for controls
3579 // other than buttons, but is better than not being able to (re)set a
3580 // control's background colour to default grey and means resetting a
3581 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3583 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3586 def
= gtk_widget_get_default_style();
3588 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3589 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3590 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3591 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3592 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3593 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3594 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3595 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3600 void wxWindowGTK::ApplyWidgetStyle()
3604 //-----------------------------------------------------------------------------
3605 // Pop-up menu stuff
3606 //-----------------------------------------------------------------------------
3610 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3612 *is_waiting
= FALSE
;
3615 static void SetInvokingWindow( wxMenu
*menu
, wxWindowGTK
*win
)
3617 menu
->SetInvokingWindow( win
);
3618 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3621 wxMenuItem
*menuitem
= node
->GetData();
3622 if (menuitem
->IsSubMenu())
3624 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3627 node
= node
->GetNext();
3631 static gint gs_pop_x
= 0;
3632 static gint gs_pop_y
= 0;
3634 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3638 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3643 bool wxWindowGTK::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3645 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3647 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3649 SetInvokingWindow( menu
, this );
3656 bool is_waiting
= TRUE
;
3658 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3659 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3662 GTK_MENU(menu
->m_menu
),
3663 (GtkWidget
*) NULL
, // parent menu shell
3664 (GtkWidget
*) NULL
, // parent menu item
3665 (GtkMenuPositionFunc
) pop_pos_callback
,
3666 (gpointer
) this, // client data
3667 0, // button used to activate it
3668 gs_timeLastClick
// the time of activation
3673 while (gtk_events_pending())
3674 gtk_main_iteration();
3680 #endif // wxUSE_MENUS
3682 #if wxUSE_DRAG_AND_DROP
3684 void wxWindowGTK::SetDropTarget( wxDropTarget
*dropTarget
)
3686 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3688 GtkWidget
*dnd_widget
= GetConnectWidget();
3690 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3692 if (m_dropTarget
) delete m_dropTarget
;
3693 m_dropTarget
= dropTarget
;
3695 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3698 #endif // wxUSE_DRAG_AND_DROP
3700 GtkWidget
* wxWindowGTK::GetConnectWidget()
3702 GtkWidget
*connect_widget
= m_widget
;
3703 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3705 return connect_widget
;
3708 bool wxWindowGTK::IsOwnGtkWindow( GdkWindow
*window
)
3711 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3713 return (window
== m_widget
->window
);
3716 bool wxWindowGTK::SetFont( const wxFont
&font
)
3718 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3720 if (!wxWindowBase::SetFont(font
))
3725 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3726 if ( sysbg
== m_backgroundColour
)
3728 m_backgroundColour
= wxNullColour
;
3730 m_backgroundColour
= sysbg
;
3740 void wxWindowGTK::CaptureMouse()
3742 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3744 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3746 GdkWindow
*window
= (GdkWindow
*) NULL
;
3748 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3750 window
= GetConnectWidget()->window
;
3752 if (!window
) return;
3754 wxCursor
* cursor
= & m_cursor
;
3756 cursor
= wxSTANDARD_CURSOR
;
3758 gdk_pointer_grab( window
, FALSE
,
3760 (GDK_BUTTON_PRESS_MASK
|
3761 GDK_BUTTON_RELEASE_MASK
|
3762 GDK_POINTER_MOTION_HINT_MASK
|
3763 GDK_POINTER_MOTION_MASK
),
3765 cursor
->GetCursor(),
3766 (guint32
)GDK_CURRENT_TIME
);
3767 g_captureWindow
= this;
3768 g_captureWindowHasMouse
= TRUE
;
3771 void wxWindowGTK::ReleaseMouse()
3773 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3775 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3777 GdkWindow
*window
= (GdkWindow
*) NULL
;
3779 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3781 window
= GetConnectWidget()->window
;
3786 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3787 g_captureWindow
= (wxWindowGTK
*) NULL
;
3791 wxWindow
*wxWindowBase::GetCapture()
3793 return (wxWindow
*)g_captureWindow
;
3796 bool wxWindowGTK::IsRetained() const
3801 void wxWindowGTK::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3802 int range
, bool refresh
)
3804 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3806 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3808 m_hasScrolling
= TRUE
;
3810 if (orient
== wxHORIZONTAL
)
3812 float fpos
= (float)pos
;
3813 float frange
= (float)range
;
3814 float fthumb
= (float)thumbVisible
;
3815 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3816 if (fpos
< 0.0) fpos
= 0.0;
3818 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3819 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3821 SetScrollPos( orient
, pos
, refresh
);
3825 m_oldHorizontalPos
= fpos
;
3827 m_hAdjust
->lower
= 0.0;
3828 m_hAdjust
->upper
= frange
;
3829 m_hAdjust
->value
= fpos
;
3830 m_hAdjust
->step_increment
= 1.0;
3831 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3832 m_hAdjust
->page_size
= fthumb
;
3836 float fpos
= (float)pos
;
3837 float frange
= (float)range
;
3838 float fthumb
= (float)thumbVisible
;
3839 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3840 if (fpos
< 0.0) fpos
= 0.0;
3842 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3843 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3845 SetScrollPos( orient
, pos
, refresh
);
3849 m_oldVerticalPos
= fpos
;
3851 m_vAdjust
->lower
= 0.0;
3852 m_vAdjust
->upper
= frange
;
3853 m_vAdjust
->value
= fpos
;
3854 m_vAdjust
->step_increment
= 1.0;
3855 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3856 m_vAdjust
->page_size
= fthumb
;
3859 if (orient
== wxHORIZONTAL
)
3860 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3862 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3865 void wxWindowGTK::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3867 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3869 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3871 if (orient
== wxHORIZONTAL
)
3873 float fpos
= (float)pos
;
3874 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3875 if (fpos
< 0.0) fpos
= 0.0;
3876 m_oldHorizontalPos
= fpos
;
3878 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3879 m_hAdjust
->value
= fpos
;
3883 float fpos
= (float)pos
;
3884 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3885 if (fpos
< 0.0) fpos
= 0.0;
3886 m_oldVerticalPos
= fpos
;
3888 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3889 m_vAdjust
->value
= fpos
;
3892 if (m_wxwindow
->window
)
3894 if (orient
== wxHORIZONTAL
)
3896 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3897 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3899 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3901 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3902 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3906 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3907 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3909 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3911 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3912 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3917 int wxWindowGTK::GetScrollThumb( int orient
) const
3919 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3921 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3923 if (orient
== wxHORIZONTAL
)
3924 return (int)(m_hAdjust
->page_size
+0.5);
3926 return (int)(m_vAdjust
->page_size
+0.5);
3929 int wxWindowGTK::GetScrollPos( int orient
) const
3931 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3933 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3935 if (orient
== wxHORIZONTAL
)
3936 return (int)(m_hAdjust
->value
+0.5);
3938 return (int)(m_vAdjust
->value
+0.5);
3941 int wxWindowGTK::GetScrollRange( int orient
) const
3943 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3945 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3947 if (orient
== wxHORIZONTAL
)
3948 return (int)(m_hAdjust
->upper
+0.5);
3950 return (int)(m_vAdjust
->upper
+0.5);
3953 void wxWindowGTK::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3955 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3957 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3959 if ((dx
== 0) && (dy
== 0)) return;
3961 m_clipPaintRegion
= TRUE
;
3962 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3963 m_clipPaintRegion
= FALSE
;
3966 if (m_children.GetCount() > 0)
3968 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3972 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3974 pizza->xoffset -= dx;
3975 pizza->yoffset -= dy;
3977 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3978 gdk_gc_set_exposures( m_scrollGC, TRUE );
3982 GetClientSize( &cw, &ch );
3983 int w = cw - abs(dx);
3984 int h = ch - abs(dy);
3986 if ((h < 0) || (w < 0))
3994 if (dx < 0) s_x = -dx;
3995 if (dy < 0) s_y = -dy;
3998 if (dx > 0) d_x = dx;
3999 if (dy > 0) d_y = dy;
4001 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
4002 pizza->bin_window, s_x, s_y, w, h );
4005 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
4006 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
4007 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
4008 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
4010 Refresh( TRUE, &rect );
4013 gdk_gc_unref( m_scrollGC );
4018 // Find the wxWindow at the current mouse position, also returning the mouse
4020 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
4022 pt
= wxGetMousePosition();
4023 wxWindow
* found
= wxFindWindowAtPoint(pt
);
4027 // Get the current mouse position.
4028 wxPoint
wxGetMousePosition()
4030 /* This crashes when used within wxHelpContext,
4031 so we have to use the X-specific implementation below.
4033 GdkModifierType *mask;
4034 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
4036 return wxPoint(x, y);
4040 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
4042 return wxPoint(-999, -999);
4044 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
4045 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
4046 Window rootReturn
, childReturn
;
4047 int rootX
, rootY
, winX
, winY
;
4048 unsigned int maskReturn
;
4050 XQueryPointer (display
,
4054 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
4055 return wxPoint(rootX
, rootY
);