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"
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
;
202 static wxWindow
*g_captureWindow
= (wxWindow
*) NULL
;
204 /* extern */ wxWindow
*g_focusWindow
= (wxWindow
*) NULL
;
206 // if we detect that the app has got/lost the focus, we set this variable to
207 // either TRUE or FALSE and an activate event will be sent during the next
208 // OnIdle() call and it is reset to -1: this value means that we shouldn't
209 // send any activate events at all
210 static int g_sendActivateEvent
= -1;
212 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
213 the last click here */
214 static guint32 gs_timeLastClick
= 0;
216 extern bool g_mainThreadLocked
;
218 //-----------------------------------------------------------------------------
220 //-----------------------------------------------------------------------------
223 #define DISABLE_STYLE_IF_BROKEN_THEME 1
229 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
231 # define DEBUG_MAIN_THREAD
234 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
235 GdkEvent
*WXUNUSED(event
),
236 const wxChar
*WXUNUSED(name
) )
239 static bool s_done = FALSE;
242 wxLog::AddTraceMask("focus");
245 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
251 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
253 // suppress warnings about gtk_debug_focus_in_callback being unused with
258 tmp
+= wxT(" FROM ");
261 wxChar
*s
= new wxChar
[tmp
.Length()+1];
265 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
266 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
271 #define DEBUG_MAIN_THREAD
274 //-----------------------------------------------------------------------------
275 // missing gdk functions
276 //-----------------------------------------------------------------------------
279 gdk_window_warp_pointer (GdkWindow
*window
,
284 GdkWindowPrivate
*priv
;
288 window
= GDK_ROOT_PARENT();
291 if (!GDK_WINDOW_DESTROYED(window
))
293 XWarpPointer (GDK_WINDOW_XDISPLAY(window
),
294 None
, /* not source window -> move from anywhere */
295 GDK_WINDOW_XID(window
), /* dest window */
296 0, 0, 0, 0, /* not source window -> move from anywhere */
300 priv
= (GdkWindowPrivate
*) window
;
302 if (!priv
->destroyed
)
304 XWarpPointer (priv
->xdisplay
,
305 None
, /* not source window -> move from anywhere */
306 priv
->xwindow
, /* dest window */
307 0, 0, 0, 0, /* not source window -> move from anywhere */
313 //-----------------------------------------------------------------------------
315 //-----------------------------------------------------------------------------
317 extern void wxapp_install_idle_handler();
318 extern bool g_isIdle
;
320 //-----------------------------------------------------------------------------
321 // local code (see below)
322 //-----------------------------------------------------------------------------
324 // returns the child of win which currently has focus or NULL if not found
325 // Note: can't be static, needed by textctrl.cpp.
326 /* static */ wxWindow
*FindFocusedChild(wxWindow
*win
)
328 wxWindow
*winFocus
= wxWindow::FindFocus();
330 return (wxWindow
*)NULL
;
332 if ( winFocus
== win
)
335 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
337 node
= node
->GetNext() )
339 wxWindow
*child
= FindFocusedChild(node
->GetData());
344 return (wxWindow
*)NULL
;
347 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
355 if (win
->m_hasScrolling
)
357 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
359 GtkRequisition vscroll_req
;
360 vscroll_req
.width
= 2;
361 vscroll_req
.height
= 2;
362 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
363 (scroll_window
->vscrollbar
, &vscroll_req
);
365 GtkRequisition hscroll_req
;
366 hscroll_req
.width
= 2;
367 hscroll_req
.height
= 2;
368 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
369 (scroll_window
->hscrollbar
, &hscroll_req
);
371 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) );
373 if (scroll_window
->vscrollbar_visible
)
375 dw
+= vscroll_req
.width
;
376 dw
+= scroll_class
->scrollbar_spacing
;
379 if (scroll_window
->hscrollbar_visible
)
381 dh
+= hscroll_req
.height
;
382 dh
+= scroll_class
->scrollbar_spacing
;
388 if (GTK_WIDGET_NO_WINDOW (widget
))
390 dx
+= widget
->allocation
.x
;
391 dy
+= widget
->allocation
.y
;
394 if (win
->HasFlag(wxRAISED_BORDER
))
396 gtk_draw_shadow( widget
->style
,
401 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
405 if (win
->HasFlag(wxSUNKEN_BORDER
))
407 gtk_draw_shadow( widget
->style
,
412 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
416 if (win
->HasFlag(wxSIMPLE_BORDER
))
419 gc
= gdk_gc_new( widget
->window
);
420 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
421 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
423 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
429 //-----------------------------------------------------------------------------
430 // "expose_event" of m_widget
431 //-----------------------------------------------------------------------------
433 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
435 if (gdk_event
->count
> 0) return FALSE
;
437 draw_frame( widget
, win
);
442 //-----------------------------------------------------------------------------
443 // "draw" of m_widget
444 //-----------------------------------------------------------------------------
446 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
448 draw_frame( widget
, win
);
451 //-----------------------------------------------------------------------------
452 // key code mapping routines
453 //-----------------------------------------------------------------------------
455 static long map_to_unmodified_wx_keysym( KeySym keysym
)
462 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
464 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
470 case GDK_Super_R
: key_code
= WXK_ALT
; break;
471 case GDK_Menu
: key_code
= WXK_MENU
; break;
472 case GDK_Help
: key_code
= WXK_HELP
; break;
473 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
474 case GDK_ISO_Left_Tab
:
475 case GDK_Tab
: key_code
= WXK_TAB
; break;
476 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
477 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
478 case GDK_Return
: key_code
= WXK_RETURN
; break;
479 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
480 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
481 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
482 case GDK_Delete
: key_code
= WXK_DELETE
; break;
483 case GDK_Home
: key_code
= WXK_HOME
; break;
484 case GDK_Left
: key_code
= WXK_LEFT
; break;
485 case GDK_Up
: key_code
= WXK_UP
; break;
486 case GDK_Right
: key_code
= WXK_RIGHT
; break;
487 case GDK_Down
: key_code
= WXK_DOWN
; break;
488 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
489 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
490 case GDK_Next
: key_code
= WXK_NEXT
; break;
491 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
492 case GDK_End
: key_code
= WXK_END
; break;
493 case GDK_Begin
: key_code
= WXK_HOME
; break;
494 case GDK_Select
: key_code
= WXK_SELECT
; break;
495 case GDK_Print
: key_code
= WXK_PRINT
; break;
496 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
497 case GDK_Insert
: key_code
= WXK_INSERT
; break;
498 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
500 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
501 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
502 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
503 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
504 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
505 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
506 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
507 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
508 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
509 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
510 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
511 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
512 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
513 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
514 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
515 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
516 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
517 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
518 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
519 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
520 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
521 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
522 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
523 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
524 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
525 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
526 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
527 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
528 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
529 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
530 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
531 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
532 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
533 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
534 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
535 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
536 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
538 case GDK_F1
: key_code
= WXK_F1
; break;
539 case GDK_F2
: key_code
= WXK_F2
; break;
540 case GDK_F3
: key_code
= WXK_F3
; break;
541 case GDK_F4
: key_code
= WXK_F4
; break;
542 case GDK_F5
: key_code
= WXK_F5
; break;
543 case GDK_F6
: key_code
= WXK_F6
; break;
544 case GDK_F7
: key_code
= WXK_F7
; break;
545 case GDK_F8
: key_code
= WXK_F8
; break;
546 case GDK_F9
: key_code
= WXK_F9
; break;
547 case GDK_F10
: key_code
= WXK_F10
; break;
548 case GDK_F11
: key_code
= WXK_F11
; break;
549 case GDK_F12
: key_code
= WXK_F12
; break;
552 if ((keysym
& 0xF000) == 0)
554 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
555 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
556 key_code
= (guint
)keysym
;
564 static long map_to_wx_keysym( KeySym keysym
)
570 case GDK_Menu
: key_code
= WXK_MENU
; break;
571 case GDK_Help
: key_code
= WXK_HELP
; break;
572 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
573 case GDK_ISO_Left_Tab
:
574 case GDK_Tab
: key_code
= WXK_TAB
; break;
575 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
576 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
577 case GDK_Return
: key_code
= WXK_RETURN
; break;
578 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
579 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
580 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
581 case GDK_Delete
: key_code
= WXK_DELETE
; break;
582 case GDK_Home
: key_code
= WXK_HOME
; break;
583 case GDK_Left
: key_code
= WXK_LEFT
; break;
584 case GDK_Up
: key_code
= WXK_UP
; break;
585 case GDK_Right
: key_code
= WXK_RIGHT
; break;
586 case GDK_Down
: key_code
= WXK_DOWN
; break;
587 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
588 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
589 case GDK_Next
: key_code
= WXK_NEXT
; break;
590 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
591 case GDK_End
: key_code
= WXK_END
; break;
592 case GDK_Begin
: key_code
= WXK_HOME
; break;
593 case GDK_Select
: key_code
= WXK_SELECT
; break;
594 case GDK_Print
: key_code
= WXK_PRINT
; break;
595 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
596 case GDK_Insert
: key_code
= WXK_INSERT
; break;
597 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
599 case GDK_KP_0
: key_code
= '0'; break;
600 case GDK_KP_1
: key_code
= '1'; break;
601 case GDK_KP_2
: key_code
= '2'; break;
602 case GDK_KP_3
: key_code
= '3'; break;
603 case GDK_KP_4
: key_code
= '4'; break;
604 case GDK_KP_5
: key_code
= '5'; break;
605 case GDK_KP_6
: key_code
= '6'; break;
606 case GDK_KP_7
: key_code
= '7'; break;
607 case GDK_KP_8
: key_code
= '8'; break;
608 case GDK_KP_9
: key_code
= '9'; break;
609 case GDK_KP_Space
: key_code
= ' '; break;
610 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
611 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
612 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
613 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
614 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
615 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
616 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
617 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
618 case GDK_KP_Up
: key_code
= WXK_UP
; break;
619 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
620 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
621 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
622 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
623 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
624 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
625 case GDK_KP_End
: key_code
= WXK_END
; break;
626 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
627 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
628 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
629 case GDK_KP_Equal
: key_code
= '='; break;
630 case GDK_KP_Multiply
: key_code
= '*'; break;
631 case GDK_KP_Add
: key_code
= '+'; break;
632 case GDK_KP_Separator
: key_code
= ','; break;
633 case GDK_KP_Subtract
: key_code
= '-'; break;
634 case GDK_KP_Decimal
: key_code
= '.'; break;
635 case GDK_KP_Divide
: key_code
= '/'; break;
637 case GDK_F1
: key_code
= WXK_F1
; break;
638 case GDK_F2
: key_code
= WXK_F2
; break;
639 case GDK_F3
: key_code
= WXK_F3
; break;
640 case GDK_F4
: key_code
= WXK_F4
; break;
641 case GDK_F5
: key_code
= WXK_F5
; break;
642 case GDK_F6
: key_code
= WXK_F6
; break;
643 case GDK_F7
: key_code
= WXK_F7
; break;
644 case GDK_F8
: key_code
= WXK_F8
; break;
645 case GDK_F9
: key_code
= WXK_F9
; break;
646 case GDK_F10
: key_code
= WXK_F10
; break;
647 case GDK_F11
: key_code
= WXK_F11
; break;
648 case GDK_F12
: key_code
= WXK_F12
; break;
651 if ((keysym
& 0xF000) == 0)
653 key_code
= (guint
)keysym
;
661 //-----------------------------------------------------------------------------
662 // "size_request" of m_widget
663 //-----------------------------------------------------------------------------
665 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
668 win
->GetSize( &w
, &h
);
672 requisition
->height
= h
;
673 requisition
->width
= w
;
676 //-----------------------------------------------------------------------------
677 // "expose_event" of m_wxwindow
678 //-----------------------------------------------------------------------------
680 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
685 wxapp_install_idle_handler();
688 if (win->GetName() == wxT("panel"))
690 wxPrintf( wxT("OnExpose from ") );
691 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
692 wxPrintf( win->GetClassInfo()->GetClassName() );
693 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
694 (int)gdk_event->area.y,
695 (int)gdk_event->area.width,
696 (int)gdk_event->area.height );
700 GtkPizza
*pizza
= GTK_PIZZA (widget
);
702 if (win
->GetThemeEnabled())
704 wxWindow
*parent
= win
->GetParent();
705 while (parent
&& !parent
->IsTopLevel())
706 parent
= parent
->GetParent();
710 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
711 GTK_SHADOW_NONE
, &gdk_event
->area
, parent
->m_widget
, "base", 0, 0, -1, -1);
714 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
716 gdk_event
->area
.width
,
717 gdk_event
->area
.height
);
719 if (gdk_event
->count
== 0)
721 win
->m_clipPaintRegion
= TRUE
;
723 wxEraseEvent
eevent( win
->GetId() );
724 eevent
.SetEventObject( win
);
725 win
->GetEventHandler()->ProcessEvent(eevent
);
727 wxPaintEvent
event( win
->GetId() );
728 event
.SetEventObject( win
);
729 win
->GetEventHandler()->ProcessEvent( event
);
731 win
->GetUpdateRegion().Clear();
733 win
->m_clipPaintRegion
= FALSE
;
736 /* The following code will result in all window-less widgets
737 being redrawn if the wxWindows class is given a chance to
738 paint *anything* because it will then be allowed to paint
739 over the window-less widgets */
741 GList
*children
= pizza
->children
;
744 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
745 children
= children
->next
;
747 GdkEventExpose child_event
= *gdk_event
;
749 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
750 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
751 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
753 child_event
.area
.x
= child
->widget
->allocation
.x
;
754 child_event
.area
.y
= child
->widget
->allocation
.y
;
755 child_event
.area
.width
= child
->widget
->allocation
.width
;
756 child_event
.area
.height
= child
->widget
->allocation
.height
;
757 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
764 //-----------------------------------------------------------------------------
765 // "event" of m_wxwindow
766 //-----------------------------------------------------------------------------
768 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
769 expose events. We need them, of course, so we override the main event
770 procedure in GtkWidget by giving our own handler for all system events.
771 There, we look for expose events ourselves whereas all other events are
774 gint
gtk_window_event_event_callback( GtkWidget
*widget
, GdkEventExpose
*event
, wxWindow
*win
)
776 if (event
->type
== GDK_EXPOSE
)
778 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
785 //-----------------------------------------------------------------------------
786 // "draw" of m_wxwindow
787 //-----------------------------------------------------------------------------
789 /* This callback is a complete replacement of the gtk_pizza_draw() function,
792 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
797 wxapp_install_idle_handler();
799 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
800 (win
->GetChildren().GetCount() == 0))
806 if (win->GetName() == wxT("panel"))
808 wxPrintf( wxT("OnDraw from ") );
809 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
810 wxPrintf( win->GetClassInfo()->GetClassName() );
811 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
818 GtkPizza
*pizza
= GTK_PIZZA (widget
);
820 if (win
->GetThemeEnabled())
822 wxWindow
*parent
= win
->GetParent();
823 while (parent
&& !parent
->IsTopLevel())
824 parent
= parent
->GetParent();
828 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
829 GTK_SHADOW_NONE
, rect
, parent
->m_widget
, "base", 0, 0, -1, -1);
833 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
834 (pizza
->clear_on_draw
))
836 gdk_window_clear_area( pizza
->bin_window
,
837 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
840 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
842 win
->m_clipPaintRegion
= TRUE
;
844 wxEraseEvent
eevent( win
->GetId() );
845 eevent
.SetEventObject( win
);
846 win
->GetEventHandler()->ProcessEvent(eevent
);
848 wxPaintEvent
event( win
->GetId() );
849 event
.SetEventObject( win
);
850 win
->GetEventHandler()->ProcessEvent( event
);
852 win
->GetUpdateRegion().Clear();
854 win
->m_clipPaintRegion
= FALSE
;
857 GList
*children
= pizza
->children
;
860 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
861 children
= children
->next
;
863 GdkRectangle child_area
;
864 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
866 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
871 //-----------------------------------------------------------------------------
872 // "key_press_event" from any window
873 //-----------------------------------------------------------------------------
875 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
880 wxapp_install_idle_handler();
882 if (!win
->m_hasVMT
) return FALSE
;
883 if (g_blockEventsOnDrag
) return FALSE
;
888 tmp += (char)gdk_event->keyval;
889 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
890 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
895 GdkModifierType state
;
896 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
900 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
901 /* sending unknown key events doesn't really make sense */
902 if (key_code
== 0) return FALSE
;
904 wxKeyEvent
event( wxEVT_KEY_DOWN
);
905 event
.SetTimestamp( gdk_event
->time
);
906 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
907 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
908 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
909 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
910 event
.m_keyCode
= key_code
;
911 event
.m_scanCode
= gdk_event
->keyval
;
914 event
.SetEventObject( win
);
915 ret
= win
->GetEventHandler()->ProcessEvent( event
);
920 wxWindow
*ancestor
= win
;
923 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
926 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
927 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
930 if (ancestor
->IsTopLevel())
932 ancestor
= ancestor
->GetParent();
935 #endif // wxUSE_ACCEL
937 /* wxMSW doesn't send char events with Alt pressed */
938 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
939 will only be sent if it is not in an accelerator table. */
940 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
945 wxKeyEvent
event2( wxEVT_CHAR
);
946 event2
.SetTimestamp( gdk_event
->time
);
947 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
948 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
949 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
950 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
951 event2
.m_keyCode
= key_code
;
952 event2
.m_scanCode
= gdk_event
->keyval
;
955 event2
.SetEventObject( win
);
956 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
959 /* win is a control: tab can be propagated up */
961 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
962 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
963 // have this style, yet choose not to process this particular TAB in which
964 // case TAB must still work as a navigational character
966 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
968 (win
->GetParent()) &&
969 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
971 wxNavigationKeyEvent new_event
;
972 new_event
.SetEventObject( win
->GetParent() );
973 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
974 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
975 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
976 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
977 new_event
.SetCurrentFocus( win
);
978 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
981 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
983 (gdk_event
->keyval
== GDK_Escape
) )
985 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
986 new_event
.SetEventObject( win
);
987 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
990 #if (GTK_MINOR_VERSION > 0)
991 /* Pressing F10 will activate the menu bar of the top frame. */
995 (gdk_event->keyval == GDK_F10) )
997 wxWindow *ancestor = win;
1000 if (wxIsKindOf(ancestor,wxFrame))
1002 wxFrame *frame = (wxFrame*) ancestor;
1003 wxMenuBar *menubar = frame->GetMenuBar();
1006 wxNode *node = menubar->GetMenus().First();
1009 wxMenu *firstMenu = (wxMenu*) node->Data();
1010 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
1016 ancestor = ancestor->GetParent();
1024 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1031 //-----------------------------------------------------------------------------
1032 // "key_release_event" from any window
1033 //-----------------------------------------------------------------------------
1035 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
1040 wxapp_install_idle_handler();
1042 if (!win
->m_hasVMT
) return FALSE
;
1043 if (g_blockEventsOnDrag
) return FALSE
;
1046 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
1047 if (gdk_event->state & GDK_SHIFT_MASK)
1048 printf( "ShiftDown.\n" );
1050 printf( "ShiftUp.\n" );
1051 if (gdk_event->state & GDK_CONTROL_MASK)
1052 printf( "ControlDown.\n" );
1054 printf( "ControlUp.\n" );
1058 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
1060 /* sending unknown key events doesn't really make sense */
1061 if (key_code
== 0) return FALSE
;
1065 GdkModifierType state
;
1066 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1068 wxKeyEvent
event( wxEVT_KEY_UP
);
1069 event
.SetTimestamp( gdk_event
->time
);
1070 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1071 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1072 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1073 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1074 event
.m_keyCode
= key_code
;
1075 event
.m_scanCode
= gdk_event
->keyval
;
1078 event
.SetEventObject( win
);
1080 if (win
->GetEventHandler()->ProcessEvent( event
))
1082 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1089 // ----------------------------------------------------------------------------
1090 // mouse event processing helper
1091 // ----------------------------------------------------------------------------
1093 static void AdjustEventButtonState(wxMouseEvent
& event
)
1095 // GDK reports the old state of the button for a button press event, but
1096 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1097 // for a LEFT_DOWN event, not FALSE, so we will invert
1098 // left/right/middleDown for the corresponding click events
1100 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1101 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1102 (event
.GetEventType() == wxEVT_LEFT_UP
))
1104 event
.m_leftDown
= !event
.m_leftDown
;
1108 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1109 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1110 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1112 event
.m_middleDown
= !event
.m_middleDown
;
1116 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1117 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1118 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1120 event
.m_rightDown
= !event
.m_rightDown
;
1125 //-----------------------------------------------------------------------------
1126 // "button_press_event"
1127 //-----------------------------------------------------------------------------
1129 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1134 wxapp_install_idle_handler();
1137 wxPrintf( wxT("1) OnButtonPress from ") );
1138 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1139 wxPrintf( win->GetClassInfo()->GetClassName() );
1140 wxPrintf( wxT(".\n") );
1142 if (!win
->m_hasVMT
) return FALSE
;
1143 if (g_blockEventsOnDrag
) return TRUE
;
1144 if (g_blockEventsOnScroll
) return TRUE
;
1146 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1148 if (win
->m_wxwindow
)
1150 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1152 gtk_widget_grab_focus (win
->m_wxwindow
);
1155 wxPrintf( wxT("GrabFocus from ") );
1156 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1157 wxPrintf( win->GetClassInfo()->GetClassName() );
1158 wxPrintf( wxT(".\n") );
1164 wxEventType event_type
= wxEVT_NULL
;
1166 if (gdk_event
->button
== 1)
1168 switch (gdk_event
->type
)
1170 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1171 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1175 else if (gdk_event
->button
== 2)
1177 switch (gdk_event
->type
)
1179 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1180 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1184 else if (gdk_event
->button
== 3)
1186 switch (gdk_event
->type
)
1188 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1189 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1194 if ( event_type
== wxEVT_NULL
)
1196 // unknown mouse button or click type
1200 wxMouseEvent
event( event_type
);
1201 event
.SetTimestamp( gdk_event
->time
);
1202 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1203 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1204 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1205 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1206 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1207 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1208 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1210 event
.m_x
= (wxCoord
)gdk_event
->x
;
1211 event
.m_y
= (wxCoord
)gdk_event
->y
;
1213 AdjustEventButtonState(event
);
1215 // Some control don't have their own X window and thus cannot get
1218 if (!g_captureWindow
)
1220 wxCoord x
= event
.m_x
;
1221 wxCoord y
= event
.m_y
;
1222 if (win
->m_wxwindow
)
1224 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1225 x
+= pizza
->xoffset
;
1226 y
+= pizza
->yoffset
;
1229 wxNode
*node
= win
->GetChildren().First();
1232 wxWindow
*child
= (wxWindow
*)node
->Data();
1234 node
= node
->Next();
1235 if (!child
->IsShown())
1238 if (child
->m_isStaticBox
)
1240 // wxStaticBox is transparent in the box itself
1241 int xx1
= child
->m_x
;
1242 int yy1
= child
->m_y
;
1243 int xx2
= child
->m_x
+ child
->m_width
;
1244 int yy2
= child
->m_x
+ child
->m_height
;
1247 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1249 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1251 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1253 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1256 event
.m_x
-= child
->m_x
;
1257 event
.m_y
-= child
->m_y
;
1264 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1265 (child
->m_x
<= x
) &&
1266 (child
->m_y
<= y
) &&
1267 (child
->m_x
+child
->m_width
>= x
) &&
1268 (child
->m_y
+child
->m_height
>= y
))
1271 event
.m_x
-= child
->m_x
;
1272 event
.m_y
-= child
->m_y
;
1279 event
.SetEventObject( win
);
1281 gs_timeLastClick
= gdk_event
->time
;
1284 wxPrintf( wxT("2) OnButtonPress from ") );
1285 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1286 wxPrintf( win->GetClassInfo()->GetClassName() );
1287 wxPrintf( wxT(".\n") );
1290 if (win
->GetEventHandler()->ProcessEvent( event
))
1292 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1299 //-----------------------------------------------------------------------------
1300 // "button_release_event"
1301 //-----------------------------------------------------------------------------
1303 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1308 wxapp_install_idle_handler();
1310 if (!win
->m_hasVMT
) return FALSE
;
1311 if (g_blockEventsOnDrag
) return FALSE
;
1312 if (g_blockEventsOnScroll
) return FALSE
;
1314 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1317 printf( "OnButtonRelease from " );
1318 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1319 printf( win->GetClassInfo()->GetClassName() );
1323 wxEventType event_type
= wxEVT_NULL
;
1325 switch (gdk_event
->button
)
1327 case 1: event_type
= wxEVT_LEFT_UP
; break;
1328 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1329 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1330 default: return FALSE
;
1333 wxMouseEvent
event( event_type
);
1334 event
.SetTimestamp( gdk_event
->time
);
1335 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1336 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1337 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1338 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1339 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1340 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1341 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1342 event
.m_x
= (wxCoord
)gdk_event
->x
;
1343 event
.m_y
= (wxCoord
)gdk_event
->y
;
1345 AdjustEventButtonState(event
);
1347 // Some control don't have their own X window and thus cannot get
1350 if (!g_captureWindow
)
1352 wxCoord x
= event
.m_x
;
1353 wxCoord y
= event
.m_y
;
1354 if (win
->m_wxwindow
)
1356 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1357 x
+= pizza
->xoffset
;
1358 y
+= pizza
->yoffset
;
1361 wxNode
*node
= win
->GetChildren().First();
1364 wxWindow
*child
= (wxWindow
*)node
->Data();
1366 node
= node
->Next();
1367 if (!child
->IsShown())
1370 if (child
->m_isStaticBox
)
1372 // wxStaticBox is transparent in the box itself
1373 int xx1
= child
->m_x
;
1374 int yy1
= child
->m_y
;
1375 int xx2
= child
->m_x
+ child
->m_width
;
1376 int yy2
= child
->m_x
+ child
->m_height
;
1379 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1381 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1383 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1385 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1388 event
.m_x
-= child
->m_x
;
1389 event
.m_y
-= child
->m_y
;
1396 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1397 (child
->m_x
<= x
) &&
1398 (child
->m_y
<= y
) &&
1399 (child
->m_x
+child
->m_width
>= x
) &&
1400 (child
->m_y
+child
->m_height
>= y
))
1403 event
.m_x
-= child
->m_x
;
1404 event
.m_y
-= child
->m_y
;
1411 event
.SetEventObject( win
);
1413 if (win
->GetEventHandler()->ProcessEvent( event
))
1415 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1422 //-----------------------------------------------------------------------------
1423 // "motion_notify_event"
1424 //-----------------------------------------------------------------------------
1426 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1431 wxapp_install_idle_handler();
1433 if (!win
->m_hasVMT
) return FALSE
;
1434 if (g_blockEventsOnDrag
) return FALSE
;
1435 if (g_blockEventsOnScroll
) return FALSE
;
1437 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1439 if (gdk_event
->is_hint
)
1443 GdkModifierType state
;
1444 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1450 printf( "OnMotion from " );
1451 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1452 printf( win->GetClassInfo()->GetClassName() );
1456 wxMouseEvent
event( wxEVT_MOTION
);
1457 event
.SetTimestamp( gdk_event
->time
);
1458 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1459 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1460 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1461 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1462 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1463 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1464 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1466 event
.m_x
= (wxCoord
)gdk_event
->x
;
1467 event
.m_y
= (wxCoord
)gdk_event
->y
;
1469 // Some control don't have their own X window and thus cannot get
1472 if (!g_captureWindow
)
1474 wxCoord x
= event
.m_x
;
1475 wxCoord y
= event
.m_y
;
1476 if (win
->m_wxwindow
)
1478 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1479 x
+= pizza
->xoffset
;
1480 y
+= pizza
->yoffset
;
1483 wxNode
*node
= win
->GetChildren().First();
1486 wxWindow
*child
= (wxWindow
*)node
->Data();
1488 node
= node
->Next();
1489 if (!child
->IsShown())
1492 if (child
->m_isStaticBox
)
1494 // wxStaticBox is transparent in the box itself
1495 int xx1
= child
->m_x
;
1496 int yy1
= child
->m_y
;
1497 int xx2
= child
->m_x
+ child
->m_width
;
1498 int yy2
= child
->m_x
+ child
->m_height
;
1501 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1503 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1505 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1507 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1510 event
.m_x
-= child
->m_x
;
1511 event
.m_y
-= child
->m_y
;
1518 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1519 (child
->m_x
<= x
) &&
1520 (child
->m_y
<= y
) &&
1521 (child
->m_x
+child
->m_width
>= x
) &&
1522 (child
->m_y
+child
->m_height
>= y
))
1525 event
.m_x
-= child
->m_x
;
1526 event
.m_y
-= child
->m_y
;
1533 event
.SetEventObject( win
);
1535 if (win
->GetEventHandler()->ProcessEvent( event
))
1537 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1544 //-----------------------------------------------------------------------------
1546 //-----------------------------------------------------------------------------
1548 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1553 wxapp_install_idle_handler();
1555 if (!win
->m_hasVMT
) return FALSE
;
1556 if (g_blockEventsOnDrag
) return FALSE
;
1558 switch ( g_sendActivateEvent
)
1561 // we've got focus from outside, synthtize wxActivateEvent
1562 g_sendActivateEvent
= 1;
1566 // another our window just lost focus, it was already ours before
1567 // - don't send any wxActivateEvent
1568 g_sendActivateEvent
= -1;
1572 g_focusWindow
= win
;
1575 printf( "OnSetFocus from " );
1576 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1577 printf( win->GetClassInfo()->GetClassName() );
1579 printf( WXSTRINGCAST win->GetLabel() );
1583 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1586 panel
->SetLastFocus(win
);
1591 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1595 // caret needs to be informed about focus change
1596 wxCaret
*caret
= win
->GetCaret();
1599 caret
->OnSetFocus();
1601 #endif // wxUSE_CARET
1603 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1604 event
.SetEventObject( win
);
1606 if (win
->GetEventHandler()->ProcessEvent( event
))
1608 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1615 //-----------------------------------------------------------------------------
1616 // "focus_out_event"
1617 //-----------------------------------------------------------------------------
1619 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1624 wxapp_install_idle_handler();
1626 if (!win
->m_hasVMT
) return FALSE
;
1627 if (g_blockEventsOnDrag
) return FALSE
;
1629 // if the focus goes out of our app alltogether, OnIdle() will send
1630 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1631 // g_sendActivateEvent to -1
1632 g_sendActivateEvent
= 0;
1634 wxWindow
*winFocus
= FindFocusedChild(win
);
1638 g_focusWindow
= (wxWindow
*)NULL
;
1641 printf( "OnKillFocus from " );
1642 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1643 printf( win->GetClassInfo()->GetClassName() );
1653 // caret needs to be informed about focus change
1654 wxCaret
*caret
= win
->GetCaret();
1657 caret
->OnKillFocus();
1659 #endif // wxUSE_CARET
1661 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1662 event
.SetEventObject( win
);
1664 if (win
->GetEventHandler()->ProcessEvent( event
))
1666 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1673 //-----------------------------------------------------------------------------
1674 // "enter_notify_event"
1675 //-----------------------------------------------------------------------------
1677 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1682 wxapp_install_idle_handler();
1684 if (!win
->m_hasVMT
) return FALSE
;
1685 if (g_blockEventsOnDrag
) return FALSE
;
1687 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1689 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1690 #if (GTK_MINOR_VERSION > 0)
1691 event
.SetTimestamp( gdk_event
->time
);
1693 event
.SetEventObject( win
);
1697 GdkModifierType state
= (GdkModifierType
)0;
1699 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1701 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1702 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1703 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1704 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1705 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1706 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1707 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1712 if (win
->GetEventHandler()->ProcessEvent( event
))
1714 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1721 //-----------------------------------------------------------------------------
1722 // "leave_notify_event"
1723 //-----------------------------------------------------------------------------
1725 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1730 wxapp_install_idle_handler();
1732 if (!win
->m_hasVMT
) return FALSE
;
1733 if (g_blockEventsOnDrag
) return FALSE
;
1735 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1737 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1738 #if (GTK_MINOR_VERSION > 0)
1739 event
.SetTimestamp( gdk_event
->time
);
1741 event
.SetEventObject( win
);
1745 GdkModifierType state
= (GdkModifierType
)0;
1747 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1749 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1750 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1751 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1752 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1753 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1754 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1755 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1760 if (win
->GetEventHandler()->ProcessEvent( event
))
1762 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1769 //-----------------------------------------------------------------------------
1770 // "value_changed" from m_vAdjust
1771 //-----------------------------------------------------------------------------
1773 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1778 wxapp_install_idle_handler();
1780 if (g_blockEventsOnDrag
) return;
1782 if (!win
->m_hasVMT
) return;
1784 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1785 if (fabs(diff
) < 0.2) return;
1787 win
->m_oldVerticalPos
= adjust
->value
;
1789 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1790 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1792 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1793 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1794 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1795 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1796 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1798 int value
= (int)(adjust
->value
+0.5);
1800 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1801 event
.SetEventObject( win
);
1802 win
->GetEventHandler()->ProcessEvent( event
);
1805 //-----------------------------------------------------------------------------
1806 // "value_changed" from m_hAdjust
1807 //-----------------------------------------------------------------------------
1809 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1814 wxapp_install_idle_handler();
1816 if (g_blockEventsOnDrag
) return;
1817 if (!win
->m_hasVMT
) return;
1819 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1820 if (fabs(diff
) < 0.2) return;
1822 win
->m_oldHorizontalPos
= adjust
->value
;
1824 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1825 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1827 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1828 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1829 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1830 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1831 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1833 int value
= (int)(adjust
->value
+0.5);
1835 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1836 event
.SetEventObject( win
);
1837 win
->GetEventHandler()->ProcessEvent( event
);
1840 //-----------------------------------------------------------------------------
1841 // "button_press_event" from scrollbar
1842 //-----------------------------------------------------------------------------
1844 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1845 GdkEventButton
*gdk_event
,
1851 wxapp_install_idle_handler();
1854 g_blockEventsOnScroll
= TRUE
;
1855 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1860 //-----------------------------------------------------------------------------
1861 // "button_release_event" from scrollbar
1862 //-----------------------------------------------------------------------------
1864 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1865 GdkEventButton
*WXUNUSED(gdk_event
),
1870 // don't test here as we can release the mouse while being over
1871 // a different window than the slider
1873 // if (gdk_event->window != widget->slider) return FALSE;
1875 g_blockEventsOnScroll
= FALSE
;
1877 if (win
->m_isScrolling
)
1879 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
1883 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1884 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1886 value
= (int)(win
->m_hAdjust
->value
+0.5);
1889 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1891 value
= (int)(win
->m_vAdjust
->value
+0.5);
1895 wxScrollWinEvent
event( command
, value
, dir
);
1896 event
.SetEventObject( win
);
1897 win
->GetEventHandler()->ProcessEvent( event
);
1900 win
->m_isScrolling
= FALSE
;
1905 // ----------------------------------------------------------------------------
1906 // this wxWindowBase function is implemented here (in platform-specific file)
1907 // because it is static and so couldn't be made virtual
1908 // ----------------------------------------------------------------------------
1910 wxWindow
*wxWindowBase::FindFocus()
1912 return g_focusWindow
;
1915 //-----------------------------------------------------------------------------
1916 // "realize" from m_widget
1917 //-----------------------------------------------------------------------------
1919 /* We cannot set colours and fonts before the widget has
1920 been realized, so we do this directly after realization. */
1923 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1928 wxapp_install_idle_handler();
1930 if (win
->m_delayedBackgroundColour
)
1931 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1933 if (win
->m_delayedForegroundColour
)
1934 win
->SetForegroundColour( win
->GetForegroundColour() );
1936 wxWindowCreateEvent
event( win
);
1937 event
.SetEventObject( win
);
1938 win
->GetEventHandler()->ProcessEvent( event
);
1943 //-----------------------------------------------------------------------------
1945 //-----------------------------------------------------------------------------
1948 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
1949 GtkAllocation
*WXUNUSED(alloc
),
1953 wxapp_install_idle_handler();
1955 if (!win
->m_hasScrolling
) return;
1957 int client_width
= 0;
1958 int client_height
= 0;
1959 win
->GetClientSize( &client_width
, &client_height
);
1960 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
1963 win
->m_oldClientWidth
= client_width
;
1964 win
->m_oldClientHeight
= client_height
;
1966 if (!win
->m_nativeSizeEvent
)
1968 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
1969 event
.SetEventObject( win
);
1970 win
->GetEventHandler()->ProcessEvent( event
);
1976 #define WXUNUSED_UNLESS_XIM(param) param
1978 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1981 /* Resize XIM window */
1984 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1985 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1986 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1989 wxapp_install_idle_handler();
1995 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1999 gdk_window_get_size (widget
->window
, &width
, &height
);
2000 win
->m_icattr
->preedit_area
.width
= width
;
2001 win
->m_icattr
->preedit_area
.height
= height
;
2002 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2007 //-----------------------------------------------------------------------------
2008 // "realize" from m_wxwindow
2009 //-----------------------------------------------------------------------------
2011 /* Initialize XIM support */
2014 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2015 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
2018 wxapp_install_idle_handler();
2021 if (win
->m_ic
) return FALSE
;
2022 if (!widget
) return FALSE
;
2023 if (!gdk_im_ready()) return FALSE
;
2025 win
->m_icattr
= gdk_ic_attr_new();
2026 if (!win
->m_icattr
) return FALSE
;
2030 GdkColormap
*colormap
;
2031 GdkICAttr
*attr
= win
->m_icattr
;
2032 unsigned attrmask
= GDK_IC_ALL_REQ
;
2034 GdkIMStyle supported_style
= (GdkIMStyle
)
2035 (GDK_IM_PREEDIT_NONE
|
2036 GDK_IM_PREEDIT_NOTHING
|
2037 GDK_IM_PREEDIT_POSITION
|
2038 GDK_IM_STATUS_NONE
|
2039 GDK_IM_STATUS_NOTHING
);
2041 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2042 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2044 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2045 attr
->client_window
= widget
->window
;
2047 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2048 gtk_widget_get_default_colormap ())
2050 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2051 attr
->preedit_colormap
= colormap
;
2054 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2055 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2056 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2057 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2059 switch (style
& GDK_IM_PREEDIT_MASK
)
2061 case GDK_IM_PREEDIT_POSITION
:
2062 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2064 g_warning ("over-the-spot style requires fontset");
2068 gdk_window_get_size (widget
->window
, &width
, &height
);
2070 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2071 attr
->spot_location
.x
= 0;
2072 attr
->spot_location
.y
= height
;
2073 attr
->preedit_area
.x
= 0;
2074 attr
->preedit_area
.y
= 0;
2075 attr
->preedit_area
.width
= width
;
2076 attr
->preedit_area
.height
= height
;
2077 attr
->preedit_fontset
= widget
->style
->font
;
2082 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2084 if (win
->m_ic
== NULL
)
2085 g_warning ("Can't create input context.");
2088 mask
= gdk_window_get_events (widget
->window
);
2089 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2090 gdk_window_set_events (widget
->window
, mask
);
2092 if (GTK_WIDGET_HAS_FOCUS(widget
))
2093 gdk_im_begin (win
->m_ic
, widget
->window
);
2100 //-----------------------------------------------------------------------------
2101 // InsertChild for wxWindow.
2102 //-----------------------------------------------------------------------------
2104 /* Callback for wxWindow. This very strange beast has to be used because
2105 * C++ has no virtual methods in a constructor. We have to emulate a
2106 * virtual function here as wxNotebook requires a different way to insert
2107 * a child in it. I had opted for creating a wxNotebookPage window class
2108 * which would have made this superfluous (such in the MDI window system),
2109 * but no-one was listening to me... */
2111 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
2113 /* the window might have been scrolled already, do we
2114 have to adapt the position */
2115 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2116 child
->m_x
+= pizza
->xoffset
;
2117 child
->m_y
+= pizza
->yoffset
;
2119 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2120 GTK_WIDGET(child
->m_widget
),
2127 //-----------------------------------------------------------------------------
2129 //-----------------------------------------------------------------------------
2131 wxWindow
* wxGetActiveWindow()
2133 return g_focusWindow
;
2136 //-----------------------------------------------------------------------------
2138 //-----------------------------------------------------------------------------
2140 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2142 void wxWindow::Init()
2148 m_widget
= (GtkWidget
*) NULL
;
2149 m_wxwindow
= (GtkWidget
*) NULL
;
2159 m_needParent
= TRUE
;
2160 m_isBeingDeleted
= FALSE
;
2163 m_nativeSizeEvent
= FALSE
;
2165 m_hasScrolling
= FALSE
;
2166 m_isScrolling
= FALSE
;
2168 m_hAdjust
= (GtkAdjustment
*) NULL
;
2169 m_vAdjust
= (GtkAdjustment
*) NULL
;
2170 m_oldHorizontalPos
= 0.0;
2171 m_oldVerticalPos
= 0.0;
2174 m_widgetStyle
= (GtkStyle
*) NULL
;
2176 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2178 m_isStaticBox
= FALSE
;
2179 m_isRadioButton
= FALSE
;
2181 m_acceptsFocus
= FALSE
;
2183 m_clipPaintRegion
= FALSE
;
2185 m_cursor
= *wxSTANDARD_CURSOR
;
2187 m_delayedForegroundColour
= FALSE
;
2188 m_delayedBackgroundColour
= FALSE
;
2191 m_ic
= (GdkIC
*) NULL
;
2192 m_icattr
= (GdkICAttr
*) NULL
;
2196 wxWindow::wxWindow()
2201 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
2202 const wxPoint
&pos
, const wxSize
&size
,
2203 long style
, const wxString
&name
)
2207 Create( parent
, id
, pos
, size
, style
, name
);
2210 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
2211 const wxPoint
&pos
, const wxSize
&size
,
2212 long style
, const wxString
&name
)
2214 if (!PreCreation( parent
, pos
, size
) ||
2215 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2217 wxFAIL_MSG( wxT("wxWindow creation failed") );
2221 m_insertCallback
= wxInsertChildInWindow
;
2223 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2224 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2226 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2228 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2229 scroll_class
->scrollbar_spacing
= 0;
2231 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2233 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2234 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2236 m_wxwindow
= gtk_pizza_new();
2238 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2240 #if (GTK_MINOR_VERSION > 0)
2241 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2243 if (HasFlag(wxRAISED_BORDER
))
2245 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2247 else if (HasFlag(wxSUNKEN_BORDER
))
2249 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2251 else if (HasFlag(wxSIMPLE_BORDER
))
2253 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2257 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2259 #else // GTK_MINOR_VERSION == 0
2260 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2262 if (HasFlag(wxRAISED_BORDER
))
2264 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2266 else if (HasFlag(wxSUNKEN_BORDER
))
2268 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2272 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2274 #endif // GTK_MINOR_VERSION
2276 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2277 m_acceptsFocus
= TRUE
;
2279 #if (GTK_MINOR_VERSION == 0)
2280 // shut the viewport up
2281 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2282 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2283 #endif // GTK_MINOR_VERSION == 0
2285 // I _really_ don't want scrollbars in the beginning
2286 m_vAdjust
->lower
= 0.0;
2287 m_vAdjust
->upper
= 1.0;
2288 m_vAdjust
->value
= 0.0;
2289 m_vAdjust
->step_increment
= 1.0;
2290 m_vAdjust
->page_increment
= 1.0;
2291 m_vAdjust
->page_size
= 5.0;
2292 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2293 m_hAdjust
->lower
= 0.0;
2294 m_hAdjust
->upper
= 1.0;
2295 m_hAdjust
->value
= 0.0;
2296 m_hAdjust
->step_increment
= 1.0;
2297 m_hAdjust
->page_increment
= 1.0;
2298 m_hAdjust
->page_size
= 5.0;
2299 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2301 // these handlers block mouse events to any window during scrolling such as
2302 // motion events and prevent GTK and wxWindows from fighting over where the
2305 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2306 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2308 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2309 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2311 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2312 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2314 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2315 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2317 // these handlers get notified when screen updates are required either when
2318 // scrolling or when the window size (and therefore scrollbar configuration)
2321 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2322 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2323 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2324 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2326 gtk_widget_show( m_wxwindow
);
2329 m_parent
->DoAddChild( this );
2338 wxWindow::~wxWindow()
2340 if (g_focusWindow
== this)
2341 g_focusWindow
= NULL
;
2343 m_isBeingDeleted
= TRUE
;
2352 m_parent
->RemoveChild( this );
2356 gdk_ic_destroy (m_ic
);
2358 gdk_ic_attr_destroy (m_icattr
);
2363 #if DISABLE_STYLE_IF_BROKEN_THEME
2364 // don't delete if it's a pixmap theme style
2365 if (!m_widgetStyle
->engine_data
)
2366 gtk_style_unref( m_widgetStyle
);
2368 m_widgetStyle
= (GtkStyle
*) NULL
;
2373 gtk_widget_destroy( m_wxwindow
);
2374 m_wxwindow
= (GtkWidget
*) NULL
;
2379 gtk_widget_destroy( m_widget
);
2380 m_widget
= (GtkWidget
*) NULL
;
2384 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2386 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2388 /* this turns -1 into 20 so that a minimal window is
2389 visible even although -1,-1 has been given as the
2390 size of the window. the same trick is used in other
2391 ports and should make debugging easier */
2392 m_width
= WidthDefault(size
.x
);
2393 m_height
= HeightDefault(size
.y
);
2398 /* some reasonable defaults */
2403 m_x
= (gdk_screen_width () - m_width
) / 2;
2404 if (m_x
< 10) m_x
= 10;
2408 m_y
= (gdk_screen_height () - m_height
) / 2;
2409 if (m_y
< 10) m_y
= 10;
2416 void wxWindow::PostCreation()
2418 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2424 /* these get reported to wxWindows -> wxPaintEvent */
2426 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2428 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2429 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2431 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2432 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2434 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2436 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2437 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2441 #if (GTK_MINOR_VERSION > 0)
2442 /* these are called when the "sunken" or "raised" borders are drawn */
2443 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2444 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2446 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2447 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2451 if (m_wxwindow
&& m_needParent
)
2453 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2454 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2456 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2457 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2461 // For dialogs and frames, we are interested mainly in
2462 // m_widget's focus.
2464 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2465 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2467 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2468 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2471 GtkWidget
*connect_widget
= GetConnectWidget();
2473 ConnectWidget( connect_widget
);
2475 /* We cannot set colours, fonts and cursors before the widget has
2476 been realized, so we do this directly after realization */
2477 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2478 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2482 // Catch native resize events
2483 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2484 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2486 // Initialize XIM support
2487 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2488 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2490 // And resize XIM window
2491 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2492 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2495 if (!GTK_IS_COMBO(m_widget
))
2497 // This is needed if we want to add our windows into native
2498 // GTK control, such as the toolbar. With this callback, the
2499 // toolbar gets to know the correct size (the one set by the
2500 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2501 // when moving to GTK 2.0.
2502 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2503 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2509 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2511 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2512 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2514 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2515 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2517 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2518 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2520 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2521 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2523 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2524 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2526 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2527 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2529 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2530 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2533 bool wxWindow::Destroy()
2535 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2539 return wxWindowBase::Destroy();
2542 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2544 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2547 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2549 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2550 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2552 if (m_resizing
) return; /* I don't like recursions */
2555 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2557 /* don't set the size for children of wxNotebook, just take the values. */
2565 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2567 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2569 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2570 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2571 if (width
!= -1) m_width
= width
;
2572 if (height
!= -1) m_height
= height
;
2576 m_x
= x
+ pizza
->xoffset
;
2577 m_y
= y
+ pizza
->yoffset
;
2582 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2584 if (width
== -1) m_width
= 80;
2587 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2589 if (height
== -1) m_height
= 26;
2592 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2593 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2594 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2595 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2598 int bottom_border
= 0;
2600 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2602 /* the default button has a border around it */
2607 DoMoveWindow( m_x
-border
,
2610 m_height
+border
+bottom_border
);
2615 /* Sometimes the client area changes size without the
2616 whole windows's size changing, but if the whole
2617 windows's size doesn't change, no wxSizeEvent will
2618 normally be sent. Here we add an extra test if
2619 the client test has been changed and this will
2621 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2625 wxPrintf( "OnSize sent from " );
2626 if (GetClassInfo() && GetClassInfo()->GetClassName())
2627 wxPrintf( GetClassInfo()->GetClassName() );
2628 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2631 if (!m_nativeSizeEvent
)
2633 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2634 event
.SetEventObject( this );
2635 GetEventHandler()->ProcessEvent( event
);
2641 void wxWindow::OnInternalIdle()
2643 if ( g_sendActivateEvent
!= -1 )
2645 bool activate
= g_sendActivateEvent
!= 0;
2648 g_sendActivateEvent
= -1;
2650 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2651 event
.SetEventObject(this);
2653 (void)GetEventHandler()->ProcessEvent(event
);
2656 wxCursor cursor
= m_cursor
;
2657 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2661 /* I now set the cursor anew in every OnInternalIdle call
2662 as setting the cursor in a parent window also effects the
2663 windows above so that checking for the current cursor is
2668 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2670 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2672 if (!g_globalCursor
.Ok())
2673 cursor
= *wxSTANDARD_CURSOR
;
2675 window
= m_widget
->window
;
2676 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2677 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2683 GdkWindow
*window
= m_widget
->window
;
2684 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2685 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2693 void wxWindow::DoGetSize( int *width
, int *height
) const
2695 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2697 if (width
) (*width
) = m_width
;
2698 if (height
) (*height
) = m_height
;
2701 void wxWindow::DoSetClientSize( int width
, int height
)
2703 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2707 SetSize( width
, height
);
2714 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2716 /* when using GTK 1.2 we set the shadow border size to 2 */
2720 if (HasFlag(wxSIMPLE_BORDER
))
2722 /* when using GTK 1.2 we set the simple border size to 1 */
2729 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2731 GtkRequisition vscroll_req
;
2732 vscroll_req
.width
= 2;
2733 vscroll_req
.height
= 2;
2734 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2735 (scroll_window
->vscrollbar
, &vscroll_req
);
2737 GtkRequisition hscroll_req
;
2738 hscroll_req
.width
= 2;
2739 hscroll_req
.height
= 2;
2740 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2741 (scroll_window
->hscrollbar
, &hscroll_req
);
2743 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2745 if (scroll_window
->vscrollbar_visible
)
2747 dw
+= vscroll_req
.width
;
2748 dw
+= scroll_class
->scrollbar_spacing
;
2751 if (scroll_window
->hscrollbar_visible
)
2753 dh
+= hscroll_req
.height
;
2754 dh
+= scroll_class
->scrollbar_spacing
;
2758 SetSize( width
+dw
, height
+dh
);
2762 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2764 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2768 if (width
) (*width
) = m_width
;
2769 if (height
) (*height
) = m_height
;
2776 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2778 /* when using GTK 1.2 we set the shadow border size to 2 */
2782 if (HasFlag(wxSIMPLE_BORDER
))
2784 /* when using GTK 1.2 we set the simple border size to 1 */
2791 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2793 GtkRequisition vscroll_req
;
2794 vscroll_req
.width
= 2;
2795 vscroll_req
.height
= 2;
2796 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2797 (scroll_window
->vscrollbar
, &vscroll_req
);
2799 GtkRequisition hscroll_req
;
2800 hscroll_req
.width
= 2;
2801 hscroll_req
.height
= 2;
2802 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2803 (scroll_window
->hscrollbar
, &hscroll_req
);
2805 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2807 if (scroll_window
->vscrollbar_visible
)
2809 dw
+= vscroll_req
.width
;
2810 dw
+= scroll_class
->scrollbar_spacing
;
2813 if (scroll_window
->hscrollbar_visible
)
2815 dh
+= hscroll_req
.height
;
2816 dh
+= scroll_class
->scrollbar_spacing
;
2820 if (width
) (*width
) = m_width
- dw
;
2821 if (height
) (*height
) = m_height
- dh
;
2825 void wxWindow::DoGetPosition( int *x
, int *y
) const
2827 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2831 if (m_parent
&& m_parent
->m_wxwindow
)
2833 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2834 dx
= pizza
->xoffset
;
2835 dy
= pizza
->yoffset
;
2838 if (x
) (*x
) = m_x
- dx
;
2839 if (y
) (*y
) = m_y
- dy
;
2842 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2844 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2846 if (!m_widget
->window
) return;
2848 GdkWindow
*source
= (GdkWindow
*) NULL
;
2850 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2852 source
= m_widget
->window
;
2856 gdk_window_get_origin( source
, &org_x
, &org_y
);
2860 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2862 org_x
+= m_widget
->allocation
.x
;
2863 org_y
+= m_widget
->allocation
.y
;
2871 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2873 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2875 if (!m_widget
->window
) return;
2877 GdkWindow
*source
= (GdkWindow
*) NULL
;
2879 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2881 source
= m_widget
->window
;
2885 gdk_window_get_origin( source
, &org_x
, &org_y
);
2889 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2891 org_x
+= m_widget
->allocation
.x
;
2892 org_y
+= m_widget
->allocation
.y
;
2900 bool wxWindow::Show( bool show
)
2902 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2904 if (!wxWindowBase::Show(show
))
2911 gtk_widget_show( m_widget
);
2913 gtk_widget_hide( m_widget
);
2918 bool wxWindow::Enable( bool enable
)
2920 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2922 if (!wxWindowBase::Enable(enable
))
2928 gtk_widget_set_sensitive( m_widget
, enable
);
2930 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2935 int wxWindow::GetCharHeight() const
2937 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2939 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2941 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2943 return font
->ascent
+ font
->descent
;
2946 int wxWindow::GetCharWidth() const
2948 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2950 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2952 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2954 return gdk_string_width( font
, "H" );
2957 void wxWindow::GetTextExtent( const wxString
& string
,
2961 int *externalLeading
,
2962 const wxFont
*theFont
) const
2964 wxFont fontToUse
= m_font
;
2965 if (theFont
) fontToUse
= *theFont
;
2967 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2969 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2970 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2971 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2972 if (descent
) (*descent
) = font
->descent
;
2973 if (externalLeading
) (*externalLeading
) = 0; // ??
2976 void wxWindow::SetFocus()
2978 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2982 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2983 gtk_widget_grab_focus (m_wxwindow
);
2989 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2991 gtk_widget_grab_focus (m_widget
);
2993 else if (GTK_IS_CONTAINER(m_widget
))
2995 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
3004 bool wxWindow::AcceptsFocus() const
3006 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3009 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
3011 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3013 wxWindow
*oldParent
= m_parent
,
3014 *newParent
= (wxWindow
*)newParentBase
;
3016 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3018 if ( !wxWindowBase::Reparent(newParent
) )
3021 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3023 /* prevent GTK from deleting the widget arbitrarily */
3024 gtk_widget_ref( m_widget
);
3028 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3031 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3035 /* insert GTK representation */
3036 (*(newParent
->m_insertCallback
))(newParent
, this);
3039 /* reverse: prevent GTK from deleting the widget arbitrarily */
3040 gtk_widget_unref( m_widget
);
3045 void wxWindow::DoAddChild(wxWindow
*child
)
3047 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3049 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3051 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3056 /* insert GTK representation */
3057 (*m_insertCallback
)(this, child
);
3060 void wxWindow::Raise()
3062 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3064 if (!m_widget
->window
) return;
3066 gdk_window_raise( m_widget
->window
);
3069 void wxWindow::Lower()
3071 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3073 if (!m_widget
->window
) return;
3075 gdk_window_lower( m_widget
->window
);
3078 bool wxWindow::SetCursor( const wxCursor
&cursor
)
3080 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3082 if (cursor
== m_cursor
)
3086 wxapp_install_idle_handler();
3088 if (cursor
== wxNullCursor
)
3089 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3091 return wxWindowBase::SetCursor( cursor
);
3094 void wxWindow::WarpPointer( int x
, int y
)
3096 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3098 /* we provide this function ourselves as it is
3099 missing in GDK (top of this file) */
3101 GdkWindow
*window
= (GdkWindow
*) NULL
;
3103 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3105 window
= GetConnectWidget()->window
;
3108 gdk_window_warp_pointer( window
, x
, y
);
3111 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
3113 if (!m_widget
) return;
3114 if (!m_widget
->window
) return;
3116 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3120 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3122 rect
->width
, rect
->height
);
3126 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3130 /* there is no GTK equivalent of "draw only, don't clear" so we
3131 invent our own in the GtkPizza widget */
3139 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3140 gboolean old_clear = pizza->clear_on_draw;
3141 gtk_pizza_set_clear( pizza, FALSE );
3142 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3143 gtk_pizza_set_clear( pizza, old_clear );
3145 GdkEventExpose gdk_event
;
3146 gdk_event
.type
= GDK_EXPOSE
;
3147 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3148 gdk_event
.count
= 0;
3149 gdk_event
.area
.x
= 0;
3150 gdk_event
.area
.y
= 0;
3151 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3152 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3153 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3158 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3167 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3168 gboolean old_clear = pizza->clear_on_draw;
3169 gtk_pizza_set_clear( pizza, FALSE );
3171 GdkRectangle gdk_rect;
3172 gdk_rect.x = rect->x;
3173 gdk_rect.y = rect->y;
3174 gdk_rect.width = rect->width;
3175 gdk_rect.height = rect->height;
3176 gtk_widget_draw( m_wxwindow, &gdk_rect );
3177 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3179 gtk_pizza_set_clear( pizza, old_clear );
3181 GdkEventExpose gdk_event
;
3182 gdk_event
.type
= GDK_EXPOSE
;
3183 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3184 gdk_event
.count
= 0;
3185 gdk_event
.area
.x
= rect
->x
;
3186 gdk_event
.area
.y
= rect
->y
;
3187 gdk_event
.area
.width
= rect
->width
;
3188 gdk_event
.area
.height
= rect
->height
;
3189 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3193 GdkRectangle gdk_rect
;
3194 gdk_rect
.x
= rect
->x
;
3195 gdk_rect
.y
= rect
->y
;
3196 gdk_rect
.width
= rect
->width
;
3197 gdk_rect
.height
= rect
->height
;
3198 gtk_widget_draw( m_widget
, &gdk_rect
);
3203 void wxWindow::Clear()
3205 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3207 if (!m_widget
->window
) return;
3209 if (m_wxwindow
&& m_wxwindow
->window
)
3211 // gdk_window_clear( m_wxwindow->window );
3216 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
3218 wxWindowBase::DoSetToolTip(tip
);
3221 m_tooltip
->Apply( this );
3224 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3226 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3228 #endif // wxUSE_TOOLTIPS
3230 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
3232 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3234 if (!wxWindowBase::SetBackgroundColour(colour
))
3236 // don't leave if the GTK widget has just
3238 if (!m_delayedBackgroundColour
) return FALSE
;
3241 GdkWindow
*window
= (GdkWindow
*) NULL
;
3243 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3245 window
= GetConnectWidget()->window
;
3249 // indicate that a new style has been set
3250 // but it couldn't get applied as the
3251 // widget hasn't been realized yet.
3252 m_delayedBackgroundColour
= TRUE
;
3256 (m_wxwindow
->window
) &&
3257 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3259 /* wxMSW doesn't clear the window here. I don't do that either to
3260 provide compatibility. call Clear() to do the job. */
3262 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3263 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3271 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
3273 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3275 if (!wxWindowBase::SetForegroundColour(colour
))
3277 // don't leave if the GTK widget has just
3279 if (!m_delayedForegroundColour
) return FALSE
;
3282 GdkWindow
*window
= (GdkWindow
*) NULL
;
3284 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3286 window
= GetConnectWidget()->window
;
3290 // indicate that a new style has been set
3291 // but it couldn't get applied as the
3292 // widget hasn't been realized yet.
3293 m_delayedForegroundColour
= TRUE
;
3301 GtkStyle
*wxWindow::GetWidgetStyle()
3305 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3307 /* FIXME: is this necessary? */
3308 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3310 remake
->klass
= m_widgetStyle
->klass
;
3313 gtk_style_unref( m_widgetStyle
);
3314 m_widgetStyle
= remake
;
3318 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3321 def
= gtk_widget_get_default_style();
3323 m_widgetStyle
= gtk_style_copy( def
);
3325 /* FIXME: is this necessary? */
3326 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3328 m_widgetStyle
->klass
= def
->klass
;
3332 return m_widgetStyle
;
3335 void wxWindow::SetWidgetStyle()
3337 #if DISABLE_STYLE_IF_BROKEN_THEM
3338 if (m_widget
->style
->engine_data
)
3340 static bool s_warningPrinted
= FALSE
;
3341 if (!s_warningPrinted
)
3343 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3344 s_warningPrinted
= TRUE
;
3346 m_widgetStyle
= m_widget
->style
;
3351 GtkStyle
*style
= GetWidgetStyle();
3353 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3355 gdk_font_unref( style
->font
);
3356 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3359 if (m_foregroundColour
.Ok())
3361 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3362 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3364 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3365 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3366 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3370 // Try to restore the gtk default style. This is still a little
3371 // oversimplified for what is probably really needed here for controls
3372 // other than buttons, but is better than not being able to (re)set a
3373 // control's foreground colour to *wxBLACK -- RL
3374 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3377 def
= gtk_widget_get_default_style();
3379 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3380 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3381 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3385 if (m_backgroundColour
.Ok())
3387 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3388 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3390 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3391 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3392 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3393 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3394 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3395 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3396 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3397 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3401 // Try to restore the gtk default style. This is still a little
3402 // oversimplified for what is probably really needed here for controls
3403 // other than buttons, but is better than not being able to (re)set a
3404 // control's background colour to default grey and means resetting a
3405 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3407 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3410 def
= gtk_widget_get_default_style();
3412 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3413 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3414 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3415 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3416 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3417 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3418 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3419 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3424 void wxWindow::ApplyWidgetStyle()
3428 //-----------------------------------------------------------------------------
3429 // Pop-up menu stuff
3430 //-----------------------------------------------------------------------------
3432 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3434 *is_waiting
= FALSE
;
3437 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3439 menu
->SetInvokingWindow( win
);
3440 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3443 wxMenuItem
*menuitem
= node
->GetData();
3444 if (menuitem
->IsSubMenu())
3446 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3449 node
= node
->GetNext();
3453 static gint gs_pop_x
= 0;
3454 static gint gs_pop_y
= 0;
3456 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3460 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3465 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3467 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3469 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3471 SetInvokingWindow( menu
, this );
3478 bool is_waiting
= TRUE
;
3480 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3481 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3484 GTK_MENU(menu
->m_menu
),
3485 (GtkWidget
*) NULL
, // parent menu shell
3486 (GtkWidget
*) NULL
, // parent menu item
3487 (GtkMenuPositionFunc
) pop_pos_callback
,
3488 (gpointer
) this, // client data
3489 0, // button used to activate it
3490 gs_timeLastClick
// the time of activation
3495 while (gtk_events_pending())
3496 gtk_main_iteration();
3502 #if wxUSE_DRAG_AND_DROP
3504 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3506 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3508 GtkWidget
*dnd_widget
= GetConnectWidget();
3510 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3512 if (m_dropTarget
) delete m_dropTarget
;
3513 m_dropTarget
= dropTarget
;
3515 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3518 #endif // wxUSE_DRAG_AND_DROP
3520 GtkWidget
* wxWindow::GetConnectWidget()
3522 GtkWidget
*connect_widget
= m_widget
;
3523 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3525 return connect_widget
;
3528 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3531 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3533 return (window
== m_widget
->window
);
3536 bool wxWindow::SetFont( const wxFont
&font
)
3538 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3540 if (!wxWindowBase::SetFont(font
))
3545 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3546 if ( sysbg
== m_backgroundColour
)
3548 m_backgroundColour
= wxNullColour
;
3550 m_backgroundColour
= sysbg
;
3560 void wxWindow::CaptureMouse()
3562 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3564 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3566 GdkWindow
*window
= (GdkWindow
*) NULL
;
3568 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3570 window
= GetConnectWidget()->window
;
3572 if (!window
) return;
3574 wxCursor
* cursor
= & m_cursor
;
3576 cursor
= wxSTANDARD_CURSOR
;
3578 gdk_pointer_grab( window
, FALSE
,
3580 (GDK_BUTTON_PRESS_MASK
|
3581 GDK_BUTTON_RELEASE_MASK
|
3582 GDK_POINTER_MOTION_HINT_MASK
|
3583 GDK_POINTER_MOTION_MASK
),
3585 cursor
->GetCursor(),
3586 (guint32
)GDK_CURRENT_TIME
);
3587 g_captureWindow
= this;
3590 void wxWindow::ReleaseMouse()
3592 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3594 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3596 GdkWindow
*window
= (GdkWindow
*) NULL
;
3598 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3600 window
= GetConnectWidget()->window
;
3605 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3606 g_captureWindow
= (wxWindow
*) NULL
;
3609 bool wxWindow::IsRetained() const
3614 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3615 int range
, bool refresh
)
3617 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3619 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3621 m_hasScrolling
= TRUE
;
3623 if (orient
== wxHORIZONTAL
)
3625 float fpos
= (float)pos
;
3626 float frange
= (float)range
;
3627 float fthumb
= (float)thumbVisible
;
3628 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3629 if (fpos
< 0.0) fpos
= 0.0;
3631 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3632 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3634 SetScrollPos( orient
, pos
, refresh
);
3638 m_oldHorizontalPos
= fpos
;
3640 m_hAdjust
->lower
= 0.0;
3641 m_hAdjust
->upper
= frange
;
3642 m_hAdjust
->value
= fpos
;
3643 m_hAdjust
->step_increment
= 1.0;
3644 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3645 m_hAdjust
->page_size
= fthumb
;
3649 float fpos
= (float)pos
;
3650 float frange
= (float)range
;
3651 float fthumb
= (float)thumbVisible
;
3652 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3653 if (fpos
< 0.0) fpos
= 0.0;
3655 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3656 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3658 SetScrollPos( orient
, pos
, refresh
);
3662 m_oldVerticalPos
= fpos
;
3664 m_vAdjust
->lower
= 0.0;
3665 m_vAdjust
->upper
= frange
;
3666 m_vAdjust
->value
= fpos
;
3667 m_vAdjust
->step_increment
= 1.0;
3668 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3669 m_vAdjust
->page_size
= fthumb
;
3672 if (orient
== wxHORIZONTAL
)
3673 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3675 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3678 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3680 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3682 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3684 if (orient
== wxHORIZONTAL
)
3686 float fpos
= (float)pos
;
3687 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3688 if (fpos
< 0.0) fpos
= 0.0;
3689 m_oldHorizontalPos
= fpos
;
3691 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3692 m_hAdjust
->value
= fpos
;
3696 float fpos
= (float)pos
;
3697 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3698 if (fpos
< 0.0) fpos
= 0.0;
3699 m_oldVerticalPos
= fpos
;
3701 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3702 m_vAdjust
->value
= fpos
;
3705 if (m_wxwindow
->window
)
3707 if (orient
== wxHORIZONTAL
)
3709 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3710 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3712 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3714 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3715 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3719 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3720 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3722 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3724 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3725 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3730 int wxWindow::GetScrollThumb( int orient
) const
3732 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3734 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3736 if (orient
== wxHORIZONTAL
)
3737 return (int)(m_hAdjust
->page_size
+0.5);
3739 return (int)(m_vAdjust
->page_size
+0.5);
3742 int wxWindow::GetScrollPos( int orient
) const
3744 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3746 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3748 if (orient
== wxHORIZONTAL
)
3749 return (int)(m_hAdjust
->value
+0.5);
3751 return (int)(m_vAdjust
->value
+0.5);
3754 int wxWindow::GetScrollRange( int orient
) const
3756 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3758 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3760 if (orient
== wxHORIZONTAL
)
3761 return (int)(m_hAdjust
->upper
+0.5);
3763 return (int)(m_vAdjust
->upper
+0.5);
3766 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3768 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3770 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3772 if ((dx
== 0) && (dy
== 0)) return;
3774 m_clipPaintRegion
= TRUE
;
3775 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3776 m_clipPaintRegion
= FALSE
;
3779 if (m_children.GetCount() > 0)
3781 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3785 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3787 pizza->xoffset -= dx;
3788 pizza->yoffset -= dy;
3790 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3791 gdk_gc_set_exposures( m_scrollGC, TRUE );
3795 GetClientSize( &cw, &ch );
3796 int w = cw - abs(dx);
3797 int h = ch - abs(dy);
3799 if ((h < 0) || (w < 0))
3807 if (dx < 0) s_x = -dx;
3808 if (dy < 0) s_y = -dy;
3811 if (dx > 0) d_x = dx;
3812 if (dy > 0) d_y = dy;
3814 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3815 pizza->bin_window, s_x, s_y, w, h );
3818 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3819 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3820 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3821 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3823 Refresh( TRUE, &rect );
3826 gdk_gc_unref( m_scrollGC );
3831 // Find the wxWindow at the current mouse position, also returning the mouse
3833 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
3835 pt
= wxGetMousePosition();
3836 wxWindow
* found
= wxFindWindowAtPoint(pt
);
3840 // Get the current mouse position.
3841 wxPoint
wxGetMousePosition()
3843 /* This crashes when used within wxHelpContext,
3844 so we have to use the X-specific implementation below.
3846 GdkModifierType *mask;
3847 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
3849 return wxPoint(x, y);
3853 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
3855 return wxPoint(-999, -999);
3857 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
3858 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
3859 Window rootReturn
, childReturn
;
3860 int rootX
, rootY
, winX
, winY
;
3861 unsigned int maskReturn
;
3863 XQueryPointer (display
,
3867 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
3868 return wxPoint(rootX
, rootY
);