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 //-----------------------------------------------------------------------------
222 #define DISABLE_STYLE_IF_BROKEN_THEME 1
227 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
229 # define DEBUG_MAIN_THREAD
232 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
233 GdkEvent
*WXUNUSED(event
),
234 const wxChar
*WXUNUSED(name
) )
237 static bool s_done = FALSE;
240 wxLog::AddTraceMask("focus");
243 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
249 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
251 // suppress warnings about gtk_debug_focus_in_callback being unused with
256 tmp
+= wxT(" FROM ");
259 wxChar
*s
= new wxChar
[tmp
.Length()+1];
263 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
264 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
269 #define DEBUG_MAIN_THREAD
272 //-----------------------------------------------------------------------------
273 // missing gdk functions
274 //-----------------------------------------------------------------------------
277 gdk_window_warp_pointer (GdkWindow
*window
,
282 GdkWindowPrivate
*priv
;
286 window
= GDK_ROOT_PARENT();
289 if (!GDK_WINDOW_DESTROYED(window
))
291 XWarpPointer (GDK_WINDOW_XDISPLAY(window
),
292 None
, /* not source window -> move from anywhere */
293 GDK_WINDOW_XID(window
), /* dest window */
294 0, 0, 0, 0, /* not source window -> move from anywhere */
298 priv
= (GdkWindowPrivate
*) window
;
300 if (!priv
->destroyed
)
302 XWarpPointer (priv
->xdisplay
,
303 None
, /* not source window -> move from anywhere */
304 priv
->xwindow
, /* dest window */
305 0, 0, 0, 0, /* not source window -> move from anywhere */
311 //-----------------------------------------------------------------------------
313 //-----------------------------------------------------------------------------
315 extern void wxapp_install_idle_handler();
316 extern bool g_isIdle
;
318 //-----------------------------------------------------------------------------
319 // local code (see below)
320 //-----------------------------------------------------------------------------
322 // returns the child of win which currently has focus or NULL if not found
323 static wxWindow
*FindFocusedChild(wxWindow
*win
)
325 wxWindow
*winFocus
= wxWindow::FindFocus();
327 return (wxWindow
*)NULL
;
329 if ( winFocus
== win
)
332 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
334 node
= node
->GetNext() )
336 wxWindow
*child
= FindFocusedChild(node
->GetData());
341 return (wxWindow
*)NULL
;
344 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
352 if (win
->m_hasScrolling
)
354 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
356 GtkRequisition vscroll_req
;
357 vscroll_req
.width
= 2;
358 vscroll_req
.height
= 2;
359 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
360 (scroll_window
->vscrollbar
, &vscroll_req
);
362 GtkRequisition hscroll_req
;
363 hscroll_req
.width
= 2;
364 hscroll_req
.height
= 2;
365 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
366 (scroll_window
->hscrollbar
, &hscroll_req
);
368 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) );
370 if (scroll_window
->vscrollbar_visible
)
372 dw
+= vscroll_req
.width
;
373 dw
+= scroll_class
->scrollbar_spacing
;
376 if (scroll_window
->hscrollbar_visible
)
378 dh
+= hscroll_req
.height
;
379 dh
+= scroll_class
->scrollbar_spacing
;
385 if (GTK_WIDGET_NO_WINDOW (widget
))
387 dx
+= widget
->allocation
.x
;
388 dy
+= widget
->allocation
.y
;
391 if (win
->HasFlag(wxRAISED_BORDER
))
393 gtk_draw_shadow( widget
->style
,
398 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
402 if (win
->HasFlag(wxSUNKEN_BORDER
))
404 gtk_draw_shadow( widget
->style
,
409 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
413 if (win
->HasFlag(wxSIMPLE_BORDER
))
416 gc
= gdk_gc_new( widget
->window
);
417 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
418 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
420 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
426 //-----------------------------------------------------------------------------
427 // "expose_event" of m_widget
428 //-----------------------------------------------------------------------------
430 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
432 if (gdk_event
->count
> 0) return FALSE
;
434 draw_frame( widget
, win
);
439 //-----------------------------------------------------------------------------
440 // "draw" of m_widget
441 //-----------------------------------------------------------------------------
443 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
445 draw_frame( widget
, win
);
448 //-----------------------------------------------------------------------------
449 // key code mapping routines
450 //-----------------------------------------------------------------------------
452 static long map_to_unmodified_wx_keysym( KeySym keysym
)
459 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
461 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
467 case GDK_Super_R
: key_code
= WXK_ALT
; break;
468 case GDK_Menu
: key_code
= WXK_MENU
; break;
469 case GDK_Help
: key_code
= WXK_HELP
; break;
470 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
471 case GDK_ISO_Left_Tab
:
472 case GDK_Tab
: key_code
= WXK_TAB
; break;
473 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
474 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
475 case GDK_Return
: key_code
= WXK_RETURN
; break;
476 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
477 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
478 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
479 case GDK_Delete
: key_code
= WXK_DELETE
; break;
480 case GDK_Home
: key_code
= WXK_HOME
; break;
481 case GDK_Left
: key_code
= WXK_LEFT
; break;
482 case GDK_Up
: key_code
= WXK_UP
; break;
483 case GDK_Right
: key_code
= WXK_RIGHT
; break;
484 case GDK_Down
: key_code
= WXK_DOWN
; break;
485 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
486 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
487 case GDK_Next
: key_code
= WXK_NEXT
; break;
488 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
489 case GDK_End
: key_code
= WXK_END
; break;
490 case GDK_Begin
: key_code
= WXK_HOME
; break;
491 case GDK_Select
: key_code
= WXK_SELECT
; break;
492 case GDK_Print
: key_code
= WXK_PRINT
; break;
493 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
494 case GDK_Insert
: key_code
= WXK_INSERT
; break;
495 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
497 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
498 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
499 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
500 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
501 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
502 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
503 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
504 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
505 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
506 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
507 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
508 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
509 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
510 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
511 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
512 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
513 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
514 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
515 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
516 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
517 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
518 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
519 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
520 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
521 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
522 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
523 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
524 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
525 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
526 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
527 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
528 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
529 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
530 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
531 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
532 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
533 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
535 case GDK_F1
: key_code
= WXK_F1
; break;
536 case GDK_F2
: key_code
= WXK_F2
; break;
537 case GDK_F3
: key_code
= WXK_F3
; break;
538 case GDK_F4
: key_code
= WXK_F4
; break;
539 case GDK_F5
: key_code
= WXK_F5
; break;
540 case GDK_F6
: key_code
= WXK_F6
; break;
541 case GDK_F7
: key_code
= WXK_F7
; break;
542 case GDK_F8
: key_code
= WXK_F8
; break;
543 case GDK_F9
: key_code
= WXK_F9
; break;
544 case GDK_F10
: key_code
= WXK_F10
; break;
545 case GDK_F11
: key_code
= WXK_F11
; break;
546 case GDK_F12
: key_code
= WXK_F12
; break;
549 if ((keysym
& 0xF000) == 0)
551 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
552 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
553 key_code
= (guint
)keysym
;
561 static long map_to_wx_keysym( KeySym keysym
)
567 case GDK_Menu
: key_code
= WXK_MENU
; break;
568 case GDK_Help
: key_code
= WXK_HELP
; break;
569 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
570 case GDK_ISO_Left_Tab
:
571 case GDK_Tab
: key_code
= WXK_TAB
; break;
572 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
573 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
574 case GDK_Return
: key_code
= WXK_RETURN
; break;
575 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
576 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
577 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
578 case GDK_Delete
: key_code
= WXK_DELETE
; break;
579 case GDK_Home
: key_code
= WXK_HOME
; break;
580 case GDK_Left
: key_code
= WXK_LEFT
; break;
581 case GDK_Up
: key_code
= WXK_UP
; break;
582 case GDK_Right
: key_code
= WXK_RIGHT
; break;
583 case GDK_Down
: key_code
= WXK_DOWN
; break;
584 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
585 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
586 case GDK_Next
: key_code
= WXK_NEXT
; break;
587 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
588 case GDK_End
: key_code
= WXK_END
; break;
589 case GDK_Begin
: key_code
= WXK_HOME
; break;
590 case GDK_Select
: key_code
= WXK_SELECT
; break;
591 case GDK_Print
: key_code
= WXK_PRINT
; break;
592 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
593 case GDK_Insert
: key_code
= WXK_INSERT
; break;
594 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
596 case GDK_KP_0
: key_code
= '0'; break;
597 case GDK_KP_1
: key_code
= '1'; break;
598 case GDK_KP_2
: key_code
= '2'; break;
599 case GDK_KP_3
: key_code
= '3'; break;
600 case GDK_KP_4
: key_code
= '4'; break;
601 case GDK_KP_5
: key_code
= '5'; break;
602 case GDK_KP_6
: key_code
= '6'; break;
603 case GDK_KP_7
: key_code
= '7'; break;
604 case GDK_KP_8
: key_code
= '8'; break;
605 case GDK_KP_9
: key_code
= '9'; break;
606 case GDK_KP_Space
: key_code
= ' '; break;
607 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
608 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
609 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
610 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
611 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
612 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
613 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
614 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
615 case GDK_KP_Up
: key_code
= WXK_UP
; break;
616 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
617 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
618 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
619 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
620 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
621 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
622 case GDK_KP_End
: key_code
= WXK_END
; break;
623 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
624 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
625 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
626 case GDK_KP_Equal
: key_code
= '='; break;
627 case GDK_KP_Multiply
: key_code
= '*'; break;
628 case GDK_KP_Add
: key_code
= '+'; break;
629 case GDK_KP_Separator
: key_code
= ','; break;
630 case GDK_KP_Subtract
: key_code
= '-'; break;
631 case GDK_KP_Decimal
: key_code
= '.'; break;
632 case GDK_KP_Divide
: key_code
= '/'; break;
634 case GDK_F1
: key_code
= WXK_F1
; break;
635 case GDK_F2
: key_code
= WXK_F2
; break;
636 case GDK_F3
: key_code
= WXK_F3
; break;
637 case GDK_F4
: key_code
= WXK_F4
; break;
638 case GDK_F5
: key_code
= WXK_F5
; break;
639 case GDK_F6
: key_code
= WXK_F6
; break;
640 case GDK_F7
: key_code
= WXK_F7
; break;
641 case GDK_F8
: key_code
= WXK_F8
; break;
642 case GDK_F9
: key_code
= WXK_F9
; break;
643 case GDK_F10
: key_code
= WXK_F10
; break;
644 case GDK_F11
: key_code
= WXK_F11
; break;
645 case GDK_F12
: key_code
= WXK_F12
; break;
648 if ((keysym
& 0xF000) == 0)
650 key_code
= (guint
)keysym
;
658 //-----------------------------------------------------------------------------
659 // "size_request" of m_widget
660 //-----------------------------------------------------------------------------
662 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
665 win
->GetSize( &w
, &h
);
669 requisition
->height
= h
;
670 requisition
->width
= w
;
673 //-----------------------------------------------------------------------------
674 // "expose_event" of m_wxwindow
675 //-----------------------------------------------------------------------------
677 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
682 wxapp_install_idle_handler();
685 if (win->GetName() == wxT("panel"))
687 wxPrintf( wxT("OnExpose from ") );
688 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
689 wxPrintf( win->GetClassInfo()->GetClassName() );
690 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
691 (int)gdk_event->area.y,
692 (int)gdk_event->area.width,
693 (int)gdk_event->area.height );
697 GtkPizza
*pizza
= GTK_PIZZA (widget
);
699 if (win
->GetThemeEnabled())
701 wxWindow
*parent
= win
->GetParent();
702 while (parent
&& !parent
->IsTopLevel())
703 parent
= parent
->GetParent();
707 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
708 GTK_SHADOW_NONE
, &gdk_event
->area
, parent
->m_widget
, "base", 0, 0, -1, -1);
711 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
713 gdk_event
->area
.width
,
714 gdk_event
->area
.height
);
716 if (gdk_event
->count
== 0)
718 win
->m_clipPaintRegion
= TRUE
;
720 wxEraseEvent
eevent( win
->GetId() );
721 eevent
.SetEventObject( win
);
722 win
->GetEventHandler()->ProcessEvent(eevent
);
724 wxPaintEvent
event( win
->GetId() );
725 event
.SetEventObject( win
);
726 win
->GetEventHandler()->ProcessEvent( event
);
728 win
->GetUpdateRegion().Clear();
730 win
->m_clipPaintRegion
= FALSE
;
733 /* The following code will result in all window-less widgets
734 being redrawn if the wxWindows class is given a chance to
735 paint *anything* because it will then be allowed to paint
736 over the window-less widgets */
738 GList
*children
= pizza
->children
;
741 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
742 children
= children
->next
;
744 GdkEventExpose child_event
= *gdk_event
;
746 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
747 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
748 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
750 child_event
.area
.x
= child
->widget
->allocation
.x
;
751 child_event
.area
.y
= child
->widget
->allocation
.y
;
752 child_event
.area
.width
= child
->widget
->allocation
.width
;
753 child_event
.area
.height
= child
->widget
->allocation
.height
;
754 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
761 //-----------------------------------------------------------------------------
762 // "event" of m_wxwindow
763 //-----------------------------------------------------------------------------
765 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
766 expose events. We need them, of course, so we override the main event
767 procedure in GtkWidget by giving our own handler for all system events.
768 There, we look for expose events ourselves whereas all other events are
771 gint
gtk_window_event_event_callback( GtkWidget
*widget
, GdkEventExpose
*event
, wxWindow
*win
)
773 if (event
->type
== GDK_EXPOSE
)
775 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
782 //-----------------------------------------------------------------------------
783 // "draw" of m_wxwindow
784 //-----------------------------------------------------------------------------
786 /* This callback is a complete replacement of the gtk_pizza_draw() function,
789 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
794 wxapp_install_idle_handler();
796 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
797 (win
->GetChildren().GetCount() == 0))
803 if (win->GetName() == wxT("panel"))
805 wxPrintf( wxT("OnDraw from ") );
806 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
807 wxPrintf( win->GetClassInfo()->GetClassName() );
808 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
815 GtkPizza
*pizza
= GTK_PIZZA (widget
);
817 if (win
->GetThemeEnabled())
819 wxWindow
*parent
= win
->GetParent();
820 while (parent
&& !parent
->IsTopLevel())
821 parent
= parent
->GetParent();
825 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
826 GTK_SHADOW_NONE
, rect
, parent
->m_widget
, "base", 0, 0, -1, -1);
830 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
831 (pizza
->clear_on_draw
))
833 gdk_window_clear_area( pizza
->bin_window
,
834 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
837 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
839 win
->m_clipPaintRegion
= TRUE
;
841 wxEraseEvent
eevent( win
->GetId() );
842 eevent
.SetEventObject( win
);
843 win
->GetEventHandler()->ProcessEvent(eevent
);
845 wxPaintEvent
event( win
->GetId() );
846 event
.SetEventObject( win
);
847 win
->GetEventHandler()->ProcessEvent( event
);
849 win
->GetUpdateRegion().Clear();
851 win
->m_clipPaintRegion
= FALSE
;
854 GList
*children
= pizza
->children
;
857 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
858 children
= children
->next
;
860 GdkRectangle child_area
;
861 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
863 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
868 //-----------------------------------------------------------------------------
869 // "key_press_event" from any window
870 //-----------------------------------------------------------------------------
872 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
877 wxapp_install_idle_handler();
879 if (!win
->m_hasVMT
) return FALSE
;
880 if (g_blockEventsOnDrag
) return FALSE
;
885 tmp += (char)gdk_event->keyval;
886 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
887 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
892 GdkModifierType state
;
893 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
897 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
898 /* sending unknown key events doesn't really make sense */
899 if (key_code
== 0) return FALSE
;
901 wxKeyEvent
event( wxEVT_KEY_DOWN
);
902 event
.SetTimestamp( gdk_event
->time
);
903 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
904 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
905 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
906 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
907 event
.m_keyCode
= key_code
;
908 event
.m_scanCode
= gdk_event
->keyval
;
911 event
.SetEventObject( win
);
912 ret
= win
->GetEventHandler()->ProcessEvent( event
);
917 wxWindow
*ancestor
= win
;
920 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
923 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
924 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
927 if (ancestor
->IsTopLevel())
929 ancestor
= ancestor
->GetParent();
932 #endif // wxUSE_ACCEL
934 /* wxMSW doesn't send char events with Alt pressed */
935 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
936 will only be sent if it is not in an accelerator table. */
937 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
942 wxKeyEvent
event2( wxEVT_CHAR
);
943 event2
.SetTimestamp( gdk_event
->time
);
944 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
945 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
946 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
947 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
948 event2
.m_keyCode
= key_code
;
949 event2
.m_scanCode
= gdk_event
->keyval
;
952 event2
.SetEventObject( win
);
953 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
956 /* win is a control: tab can be propagated up */
958 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
959 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
960 // have this style, yet choose not to process this particular TAB in which
961 // case TAB must still work as a navigational character
963 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
965 (win
->GetParent()) &&
966 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
968 wxNavigationKeyEvent new_event
;
969 new_event
.SetEventObject( win
->GetParent() );
970 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
971 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
972 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
973 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
974 new_event
.SetCurrentFocus( win
);
975 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
978 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
980 (gdk_event
->keyval
== GDK_Escape
) )
982 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
983 new_event
.SetEventObject( win
);
984 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
987 #if (GTK_MINOR_VERSION > 0)
988 /* Pressing F10 will activate the menu bar of the top frame. */
992 (gdk_event->keyval == GDK_F10) )
994 wxWindow *ancestor = win;
997 if (wxIsKindOf(ancestor,wxFrame))
999 wxFrame *frame = (wxFrame*) ancestor;
1000 wxMenuBar *menubar = frame->GetMenuBar();
1003 wxNode *node = menubar->GetMenus().First();
1006 wxMenu *firstMenu = (wxMenu*) node->Data();
1007 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
1013 ancestor = ancestor->GetParent();
1021 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1028 //-----------------------------------------------------------------------------
1029 // "key_release_event" from any window
1030 //-----------------------------------------------------------------------------
1032 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
1037 wxapp_install_idle_handler();
1039 if (!win
->m_hasVMT
) return FALSE
;
1040 if (g_blockEventsOnDrag
) return FALSE
;
1043 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
1044 if (gdk_event->state & GDK_SHIFT_MASK)
1045 printf( "ShiftDown.\n" );
1047 printf( "ShiftUp.\n" );
1048 if (gdk_event->state & GDK_CONTROL_MASK)
1049 printf( "ControlDown.\n" );
1051 printf( "ControlUp.\n" );
1055 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
1057 /* sending unknown key events doesn't really make sense */
1058 if (key_code
== 0) return FALSE
;
1062 GdkModifierType state
;
1063 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1065 wxKeyEvent
event( wxEVT_KEY_UP
);
1066 event
.SetTimestamp( gdk_event
->time
);
1067 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1068 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1069 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1070 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1071 event
.m_keyCode
= key_code
;
1072 event
.m_scanCode
= gdk_event
->keyval
;
1075 event
.SetEventObject( win
);
1077 if (win
->GetEventHandler()->ProcessEvent( event
))
1079 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1086 // ----------------------------------------------------------------------------
1087 // mouse event processing helper
1088 // ----------------------------------------------------------------------------
1090 static void AdjustEventButtonState(wxMouseEvent
& event
)
1092 // GDK reports the old state of the button for a button press event, but
1093 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1094 // for a LEFT_DOWN event, not FALSE, so we will invert
1095 // left/right/middleDown for the corresponding click events
1097 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1098 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1099 (event
.GetEventType() == wxEVT_LEFT_UP
))
1101 event
.m_leftDown
= !event
.m_leftDown
;
1105 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1106 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1107 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1109 event
.m_middleDown
= !event
.m_middleDown
;
1113 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1114 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1115 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1117 event
.m_rightDown
= !event
.m_rightDown
;
1122 //-----------------------------------------------------------------------------
1123 // "button_press_event"
1124 //-----------------------------------------------------------------------------
1126 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1131 wxapp_install_idle_handler();
1134 wxPrintf( wxT("1) OnButtonPress from ") );
1135 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1136 wxPrintf( win->GetClassInfo()->GetClassName() );
1137 wxPrintf( wxT(".\n") );
1139 if (!win
->m_hasVMT
) return FALSE
;
1140 if (g_blockEventsOnDrag
) return TRUE
;
1141 if (g_blockEventsOnScroll
) return TRUE
;
1143 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1145 if (win
->m_wxwindow
)
1147 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1149 gtk_widget_grab_focus (win
->m_wxwindow
);
1152 wxPrintf( wxT("GrabFocus from ") );
1153 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1154 wxPrintf( win->GetClassInfo()->GetClassName() );
1155 wxPrintf( wxT(".\n") );
1161 wxEventType event_type
= wxEVT_NULL
;
1163 if (gdk_event
->button
== 1)
1165 switch (gdk_event
->type
)
1167 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1168 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1172 else if (gdk_event
->button
== 2)
1174 switch (gdk_event
->type
)
1176 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1177 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1181 else if (gdk_event
->button
== 3)
1183 switch (gdk_event
->type
)
1185 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1186 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1191 if ( event_type
== wxEVT_NULL
)
1193 // unknown mouse button or click type
1197 wxMouseEvent
event( event_type
);
1198 event
.SetTimestamp( gdk_event
->time
);
1199 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1200 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1201 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1202 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1203 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1204 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1205 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1207 event
.m_x
= (wxCoord
)gdk_event
->x
;
1208 event
.m_y
= (wxCoord
)gdk_event
->y
;
1210 AdjustEventButtonState(event
);
1212 // Some control don't have their own X window and thus cannot get
1215 if (!g_captureWindow
)
1217 wxCoord x
= event
.m_x
;
1218 wxCoord y
= event
.m_y
;
1219 if (win
->m_wxwindow
)
1221 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1222 x
+= pizza
->xoffset
;
1223 y
+= pizza
->yoffset
;
1226 wxNode
*node
= win
->GetChildren().First();
1229 wxWindow
*child
= (wxWindow
*)node
->Data();
1231 node
= node
->Next();
1232 if (!child
->IsShown())
1235 if (child
->m_isStaticBox
)
1237 // wxStaticBox is transparent in the box itself
1238 int xx1
= child
->m_x
;
1239 int yy1
= child
->m_y
;
1240 int xx2
= child
->m_x
+ child
->m_width
;
1241 int yy2
= child
->m_x
+ child
->m_height
;
1244 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1246 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1248 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1250 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1253 event
.m_x
-= child
->m_x
;
1254 event
.m_y
-= child
->m_y
;
1261 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1262 (child
->m_x
<= x
) &&
1263 (child
->m_y
<= y
) &&
1264 (child
->m_x
+child
->m_width
>= x
) &&
1265 (child
->m_y
+child
->m_height
>= y
))
1268 event
.m_x
-= child
->m_x
;
1269 event
.m_y
-= child
->m_y
;
1276 event
.SetEventObject( win
);
1278 gs_timeLastClick
= gdk_event
->time
;
1281 wxPrintf( wxT("2) OnButtonPress from ") );
1282 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1283 wxPrintf( win->GetClassInfo()->GetClassName() );
1284 wxPrintf( wxT(".\n") );
1287 if (win
->GetEventHandler()->ProcessEvent( event
))
1289 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1296 //-----------------------------------------------------------------------------
1297 // "button_release_event"
1298 //-----------------------------------------------------------------------------
1300 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1305 wxapp_install_idle_handler();
1307 if (!win
->m_hasVMT
) return FALSE
;
1308 if (g_blockEventsOnDrag
) return FALSE
;
1309 if (g_blockEventsOnScroll
) return FALSE
;
1311 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1314 printf( "OnButtonRelease from " );
1315 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1316 printf( win->GetClassInfo()->GetClassName() );
1320 wxEventType event_type
= wxEVT_NULL
;
1322 switch (gdk_event
->button
)
1324 case 1: event_type
= wxEVT_LEFT_UP
; break;
1325 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1326 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1327 default: return FALSE
;
1330 wxMouseEvent
event( event_type
);
1331 event
.SetTimestamp( gdk_event
->time
);
1332 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1333 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1334 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1335 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1336 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1337 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1338 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1339 event
.m_x
= (wxCoord
)gdk_event
->x
;
1340 event
.m_y
= (wxCoord
)gdk_event
->y
;
1342 AdjustEventButtonState(event
);
1344 // Some control don't have their own X window and thus cannot get
1347 if (!g_captureWindow
)
1349 wxCoord x
= event
.m_x
;
1350 wxCoord y
= event
.m_y
;
1351 if (win
->m_wxwindow
)
1353 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1354 x
+= pizza
->xoffset
;
1355 y
+= pizza
->yoffset
;
1358 wxNode
*node
= win
->GetChildren().First();
1361 wxWindow
*child
= (wxWindow
*)node
->Data();
1363 node
= node
->Next();
1364 if (!child
->IsShown())
1367 if (child
->m_isStaticBox
)
1369 // wxStaticBox is transparent in the box itself
1370 int xx1
= child
->m_x
;
1371 int yy1
= child
->m_y
;
1372 int xx2
= child
->m_x
+ child
->m_width
;
1373 int yy2
= child
->m_x
+ child
->m_height
;
1376 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1378 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1380 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1382 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1385 event
.m_x
-= child
->m_x
;
1386 event
.m_y
-= child
->m_y
;
1393 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1394 (child
->m_x
<= x
) &&
1395 (child
->m_y
<= y
) &&
1396 (child
->m_x
+child
->m_width
>= x
) &&
1397 (child
->m_y
+child
->m_height
>= y
))
1400 event
.m_x
-= child
->m_x
;
1401 event
.m_y
-= child
->m_y
;
1408 event
.SetEventObject( win
);
1410 if (win
->GetEventHandler()->ProcessEvent( event
))
1412 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1419 //-----------------------------------------------------------------------------
1420 // "motion_notify_event"
1421 //-----------------------------------------------------------------------------
1423 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1428 wxapp_install_idle_handler();
1430 if (!win
->m_hasVMT
) return FALSE
;
1431 if (g_blockEventsOnDrag
) return FALSE
;
1432 if (g_blockEventsOnScroll
) return FALSE
;
1434 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1436 if (gdk_event
->is_hint
)
1440 GdkModifierType state
;
1441 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1447 printf( "OnMotion from " );
1448 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1449 printf( win->GetClassInfo()->GetClassName() );
1453 wxMouseEvent
event( wxEVT_MOTION
);
1454 event
.SetTimestamp( gdk_event
->time
);
1455 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1456 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1457 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1458 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1459 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1460 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1461 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1463 event
.m_x
= (wxCoord
)gdk_event
->x
;
1464 event
.m_y
= (wxCoord
)gdk_event
->y
;
1466 // Some control don't have their own X window and thus cannot get
1469 if (!g_captureWindow
)
1471 wxCoord x
= event
.m_x
;
1472 wxCoord y
= event
.m_y
;
1473 if (win
->m_wxwindow
)
1475 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1476 x
+= pizza
->xoffset
;
1477 y
+= pizza
->yoffset
;
1480 wxNode
*node
= win
->GetChildren().First();
1483 wxWindow
*child
= (wxWindow
*)node
->Data();
1485 node
= node
->Next();
1486 if (!child
->IsShown())
1489 if (child
->m_isStaticBox
)
1491 // wxStaticBox is transparent in the box itself
1492 int xx1
= child
->m_x
;
1493 int yy1
= child
->m_y
;
1494 int xx2
= child
->m_x
+ child
->m_width
;
1495 int yy2
= child
->m_x
+ child
->m_height
;
1498 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1500 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1502 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1504 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1507 event
.m_x
-= child
->m_x
;
1508 event
.m_y
-= child
->m_y
;
1515 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1516 (child
->m_x
<= x
) &&
1517 (child
->m_y
<= y
) &&
1518 (child
->m_x
+child
->m_width
>= x
) &&
1519 (child
->m_y
+child
->m_height
>= y
))
1522 event
.m_x
-= child
->m_x
;
1523 event
.m_y
-= child
->m_y
;
1530 event
.SetEventObject( win
);
1532 if (win
->GetEventHandler()->ProcessEvent( event
))
1534 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1541 //-----------------------------------------------------------------------------
1543 //-----------------------------------------------------------------------------
1545 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1550 wxapp_install_idle_handler();
1552 if (!win
->m_hasVMT
) return FALSE
;
1553 if (g_blockEventsOnDrag
) return FALSE
;
1555 switch ( g_sendActivateEvent
)
1558 // we've got focus from outside, synthtize wxActivateEvent
1559 g_sendActivateEvent
= 1;
1563 // another our window just lost focus, it was already ours before
1564 // - don't send any wxActivateEvent
1565 g_sendActivateEvent
= -1;
1569 g_focusWindow
= win
;
1572 printf( "OnSetFocus from " );
1573 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1574 printf( win->GetClassInfo()->GetClassName() );
1576 printf( WXSTRINGCAST win->GetLabel() );
1580 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1583 panel
->SetLastFocus(win
);
1588 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1592 // caret needs to be informed about focus change
1593 wxCaret
*caret
= win
->GetCaret();
1596 caret
->OnSetFocus();
1598 #endif // wxUSE_CARET
1600 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1601 event
.SetEventObject( win
);
1603 if (win
->GetEventHandler()->ProcessEvent( event
))
1605 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1612 //-----------------------------------------------------------------------------
1613 // "focus_out_event"
1614 //-----------------------------------------------------------------------------
1616 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1621 wxapp_install_idle_handler();
1623 if (!win
->m_hasVMT
) return FALSE
;
1624 if (g_blockEventsOnDrag
) return FALSE
;
1626 // if the focus goes out of our app alltogether, OnIdle() will send
1627 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1628 // g_sendActivateEvent to -1
1629 g_sendActivateEvent
= 0;
1631 wxWindow
*winFocus
= FindFocusedChild(win
);
1635 g_focusWindow
= (wxWindow
*)NULL
;
1638 printf( "OnKillFocus from " );
1639 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1640 printf( win->GetClassInfo()->GetClassName() );
1650 // caret needs to be informed about focus change
1651 wxCaret
*caret
= win
->GetCaret();
1654 caret
->OnKillFocus();
1656 #endif // wxUSE_CARET
1658 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1659 event
.SetEventObject( win
);
1661 if (win
->GetEventHandler()->ProcessEvent( event
))
1663 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1670 //-----------------------------------------------------------------------------
1671 // "enter_notify_event"
1672 //-----------------------------------------------------------------------------
1674 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1679 wxapp_install_idle_handler();
1681 if (!win
->m_hasVMT
) return FALSE
;
1682 if (g_blockEventsOnDrag
) return FALSE
;
1684 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1686 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1687 #if (GTK_MINOR_VERSION > 0)
1688 event
.SetTimestamp( gdk_event
->time
);
1690 event
.SetEventObject( win
);
1694 GdkModifierType state
= (GdkModifierType
)0;
1696 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1698 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1699 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1700 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1701 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1702 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1703 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1704 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1709 if (win
->GetEventHandler()->ProcessEvent( event
))
1711 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1718 //-----------------------------------------------------------------------------
1719 // "leave_notify_event"
1720 //-----------------------------------------------------------------------------
1722 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1727 wxapp_install_idle_handler();
1729 if (!win
->m_hasVMT
) return FALSE
;
1730 if (g_blockEventsOnDrag
) return FALSE
;
1732 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1734 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1735 #if (GTK_MINOR_VERSION > 0)
1736 event
.SetTimestamp( gdk_event
->time
);
1738 event
.SetEventObject( win
);
1742 GdkModifierType state
= (GdkModifierType
)0;
1744 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1746 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1747 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1748 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1749 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1750 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1751 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1752 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1757 if (win
->GetEventHandler()->ProcessEvent( event
))
1759 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1766 //-----------------------------------------------------------------------------
1767 // "value_changed" from m_vAdjust
1768 //-----------------------------------------------------------------------------
1770 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1775 wxapp_install_idle_handler();
1777 if (g_blockEventsOnDrag
) return;
1779 if (!win
->m_hasVMT
) return;
1781 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1782 if (fabs(diff
) < 0.2) return;
1784 win
->m_oldVerticalPos
= adjust
->value
;
1786 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1787 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1789 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1790 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1791 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1792 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1793 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1795 int value
= (int)(adjust
->value
+0.5);
1797 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1798 event
.SetEventObject( win
);
1799 win
->GetEventHandler()->ProcessEvent( event
);
1802 //-----------------------------------------------------------------------------
1803 // "value_changed" from m_hAdjust
1804 //-----------------------------------------------------------------------------
1806 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1811 wxapp_install_idle_handler();
1813 if (g_blockEventsOnDrag
) return;
1814 if (!win
->m_hasVMT
) return;
1816 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1817 if (fabs(diff
) < 0.2) return;
1819 win
->m_oldHorizontalPos
= adjust
->value
;
1821 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1822 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1824 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1825 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1826 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1827 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1828 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1830 int value
= (int)(adjust
->value
+0.5);
1832 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1833 event
.SetEventObject( win
);
1834 win
->GetEventHandler()->ProcessEvent( event
);
1837 //-----------------------------------------------------------------------------
1838 // "button_press_event" from scrollbar
1839 //-----------------------------------------------------------------------------
1841 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1842 GdkEventButton
*gdk_event
,
1848 wxapp_install_idle_handler();
1851 g_blockEventsOnScroll
= TRUE
;
1852 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1857 //-----------------------------------------------------------------------------
1858 // "button_release_event" from scrollbar
1859 //-----------------------------------------------------------------------------
1861 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1862 GdkEventButton
*WXUNUSED(gdk_event
),
1867 // don't test here as we can release the mouse while being over
1868 // a different window than the slider
1870 // if (gdk_event->window != widget->slider) return FALSE;
1872 g_blockEventsOnScroll
= FALSE
;
1874 if (win
->m_isScrolling
)
1876 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
1880 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1881 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1883 value
= (int)(win
->m_hAdjust
->value
+0.5);
1886 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1888 value
= (int)(win
->m_vAdjust
->value
+0.5);
1892 wxScrollWinEvent
event( command
, value
, dir
);
1893 event
.SetEventObject( win
);
1894 win
->GetEventHandler()->ProcessEvent( event
);
1897 win
->m_isScrolling
= FALSE
;
1902 // ----------------------------------------------------------------------------
1903 // this wxWindowBase function is implemented here (in platform-specific file)
1904 // because it is static and so couldn't be made virtual
1905 // ----------------------------------------------------------------------------
1907 wxWindow
*wxWindowBase::FindFocus()
1909 return g_focusWindow
;
1912 //-----------------------------------------------------------------------------
1913 // "realize" from m_widget
1914 //-----------------------------------------------------------------------------
1916 /* We cannot set colours and fonts before the widget has
1917 been realized, so we do this directly after realization. */
1920 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1925 wxapp_install_idle_handler();
1927 if (win
->m_delayedBackgroundColour
)
1928 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1930 if (win
->m_delayedForegroundColour
)
1931 win
->SetForegroundColour( win
->GetForegroundColour() );
1933 wxWindowCreateEvent
event( win
);
1934 event
.SetEventObject( win
);
1935 win
->GetEventHandler()->ProcessEvent( event
);
1940 //-----------------------------------------------------------------------------
1942 //-----------------------------------------------------------------------------
1945 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
1946 GtkAllocation
*WXUNUSED(alloc
),
1950 wxapp_install_idle_handler();
1952 if (!win
->m_hasScrolling
) return;
1954 int client_width
= 0;
1955 int client_height
= 0;
1956 win
->GetClientSize( &client_width
, &client_height
);
1957 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
1960 win
->m_oldClientWidth
= client_width
;
1961 win
->m_oldClientHeight
= client_height
;
1963 if (!win
->m_nativeSizeEvent
)
1965 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
1966 event
.SetEventObject( win
);
1967 win
->GetEventHandler()->ProcessEvent( event
);
1973 #define WXUNUSED_UNLESS_XIM(param) param
1975 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1978 /* Resize XIM window */
1981 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1982 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1983 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1986 wxapp_install_idle_handler();
1992 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1996 gdk_window_get_size (widget
->window
, &width
, &height
);
1997 win
->m_icattr
->preedit_area
.width
= width
;
1998 win
->m_icattr
->preedit_area
.height
= height
;
1999 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2004 //-----------------------------------------------------------------------------
2005 // "realize" from m_wxwindow
2006 //-----------------------------------------------------------------------------
2008 /* Initialize XIM support */
2011 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2012 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
2015 wxapp_install_idle_handler();
2018 if (win
->m_ic
) return FALSE
;
2019 if (!widget
) return FALSE
;
2020 if (!gdk_im_ready()) return FALSE
;
2022 win
->m_icattr
= gdk_ic_attr_new();
2023 if (!win
->m_icattr
) return FALSE
;
2027 GdkColormap
*colormap
;
2028 GdkICAttr
*attr
= win
->m_icattr
;
2029 unsigned attrmask
= GDK_IC_ALL_REQ
;
2031 GdkIMStyle supported_style
= (GdkIMStyle
)
2032 (GDK_IM_PREEDIT_NONE
|
2033 GDK_IM_PREEDIT_NOTHING
|
2034 GDK_IM_PREEDIT_POSITION
|
2035 GDK_IM_STATUS_NONE
|
2036 GDK_IM_STATUS_NOTHING
);
2038 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2039 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2041 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2042 attr
->client_window
= widget
->window
;
2044 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2045 gtk_widget_get_default_colormap ())
2047 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2048 attr
->preedit_colormap
= colormap
;
2051 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2052 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2053 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2054 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2056 switch (style
& GDK_IM_PREEDIT_MASK
)
2058 case GDK_IM_PREEDIT_POSITION
:
2059 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2061 g_warning ("over-the-spot style requires fontset");
2065 gdk_window_get_size (widget
->window
, &width
, &height
);
2067 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2068 attr
->spot_location
.x
= 0;
2069 attr
->spot_location
.y
= height
;
2070 attr
->preedit_area
.x
= 0;
2071 attr
->preedit_area
.y
= 0;
2072 attr
->preedit_area
.width
= width
;
2073 attr
->preedit_area
.height
= height
;
2074 attr
->preedit_fontset
= widget
->style
->font
;
2079 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2081 if (win
->m_ic
== NULL
)
2082 g_warning ("Can't create input context.");
2085 mask
= gdk_window_get_events (widget
->window
);
2086 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2087 gdk_window_set_events (widget
->window
, mask
);
2089 if (GTK_WIDGET_HAS_FOCUS(widget
))
2090 gdk_im_begin (win
->m_ic
, widget
->window
);
2097 //-----------------------------------------------------------------------------
2098 // InsertChild for wxWindow.
2099 //-----------------------------------------------------------------------------
2101 /* Callback for wxWindow. This very strange beast has to be used because
2102 * C++ has no virtual methods in a constructor. We have to emulate a
2103 * virtual function here as wxNotebook requires a different way to insert
2104 * a child in it. I had opted for creating a wxNotebookPage window class
2105 * which would have made this superfluous (such in the MDI window system),
2106 * but no-one was listening to me... */
2108 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
2110 /* the window might have been scrolled already, do we
2111 have to adapt the position */
2112 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2113 child
->m_x
+= pizza
->xoffset
;
2114 child
->m_y
+= pizza
->yoffset
;
2116 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2117 GTK_WIDGET(child
->m_widget
),
2124 //-----------------------------------------------------------------------------
2126 //-----------------------------------------------------------------------------
2128 wxWindow
* wxGetActiveWindow()
2130 return g_focusWindow
;
2133 //-----------------------------------------------------------------------------
2135 //-----------------------------------------------------------------------------
2137 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2139 void wxWindow::Init()
2145 m_widget
= (GtkWidget
*) NULL
;
2146 m_wxwindow
= (GtkWidget
*) NULL
;
2156 m_needParent
= TRUE
;
2157 m_isBeingDeleted
= FALSE
;
2160 m_nativeSizeEvent
= FALSE
;
2162 m_hasScrolling
= FALSE
;
2163 m_isScrolling
= FALSE
;
2165 m_hAdjust
= (GtkAdjustment
*) NULL
;
2166 m_vAdjust
= (GtkAdjustment
*) NULL
;
2167 m_oldHorizontalPos
= 0.0;
2168 m_oldVerticalPos
= 0.0;
2171 m_widgetStyle
= (GtkStyle
*) NULL
;
2173 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2175 m_isStaticBox
= FALSE
;
2176 m_isRadioButton
= FALSE
;
2178 m_acceptsFocus
= FALSE
;
2180 m_clipPaintRegion
= FALSE
;
2182 m_cursor
= *wxSTANDARD_CURSOR
;
2184 m_delayedForegroundColour
= FALSE
;
2185 m_delayedBackgroundColour
= FALSE
;
2188 m_ic
= (GdkIC
*) NULL
;
2189 m_icattr
= (GdkICAttr
*) NULL
;
2193 wxWindow::wxWindow()
2198 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
2199 const wxPoint
&pos
, const wxSize
&size
,
2200 long style
, const wxString
&name
)
2204 Create( parent
, id
, pos
, size
, style
, name
);
2207 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
2208 const wxPoint
&pos
, const wxSize
&size
,
2209 long style
, const wxString
&name
)
2211 if (!PreCreation( parent
, pos
, size
) ||
2212 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2214 wxFAIL_MSG( wxT("wxWindow creation failed") );
2218 m_insertCallback
= wxInsertChildInWindow
;
2220 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2221 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2223 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2225 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2226 scroll_class
->scrollbar_spacing
= 0;
2228 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2230 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2231 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2233 m_wxwindow
= gtk_pizza_new();
2235 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2237 #if (GTK_MINOR_VERSION > 0)
2238 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2240 if (HasFlag(wxRAISED_BORDER
))
2242 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2244 else if (HasFlag(wxSUNKEN_BORDER
))
2246 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2248 else if (HasFlag(wxSIMPLE_BORDER
))
2250 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2254 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2256 #else // GTK_MINOR_VERSION == 0
2257 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2259 if (HasFlag(wxRAISED_BORDER
))
2261 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2263 else if (HasFlag(wxSUNKEN_BORDER
))
2265 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2269 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2271 #endif // GTK_MINOR_VERSION
2273 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2274 m_acceptsFocus
= TRUE
;
2276 #if (GTK_MINOR_VERSION == 0)
2277 // shut the viewport up
2278 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2279 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2280 #endif // GTK_MINOR_VERSION == 0
2282 // I _really_ don't want scrollbars in the beginning
2283 m_vAdjust
->lower
= 0.0;
2284 m_vAdjust
->upper
= 1.0;
2285 m_vAdjust
->value
= 0.0;
2286 m_vAdjust
->step_increment
= 1.0;
2287 m_vAdjust
->page_increment
= 1.0;
2288 m_vAdjust
->page_size
= 5.0;
2289 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2290 m_hAdjust
->lower
= 0.0;
2291 m_hAdjust
->upper
= 1.0;
2292 m_hAdjust
->value
= 0.0;
2293 m_hAdjust
->step_increment
= 1.0;
2294 m_hAdjust
->page_increment
= 1.0;
2295 m_hAdjust
->page_size
= 5.0;
2296 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2298 // these handlers block mouse events to any window during scrolling such as
2299 // motion events and prevent GTK and wxWindows from fighting over where the
2302 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2303 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2305 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2306 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2308 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2309 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2311 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2312 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2314 // these handlers get notified when screen updates are required either when
2315 // scrolling or when the window size (and therefore scrollbar configuration)
2318 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2319 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2320 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2321 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2323 gtk_widget_show( m_wxwindow
);
2326 m_parent
->DoAddChild( this );
2335 wxWindow::~wxWindow()
2337 m_isBeingDeleted
= TRUE
;
2346 m_parent
->RemoveChild( this );
2350 gdk_ic_destroy (m_ic
);
2352 gdk_ic_attr_destroy (m_icattr
);
2357 #if DISABLE_STYLE_IF_BROKEN_THEME
2358 // don't delete if it's a pixmap theme style
2359 if (!m_widgetStyle
->engine_data
)
2360 gtk_style_unref( m_widgetStyle
);
2362 m_widgetStyle
= (GtkStyle
*) NULL
;
2367 gtk_widget_destroy( m_wxwindow
);
2368 m_wxwindow
= (GtkWidget
*) NULL
;
2373 gtk_widget_destroy( m_widget
);
2374 m_widget
= (GtkWidget
*) NULL
;
2378 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2380 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2382 /* this turns -1 into 20 so that a minimal window is
2383 visible even although -1,-1 has been given as the
2384 size of the window. the same trick is used in other
2385 ports and should make debugging easier */
2386 m_width
= WidthDefault(size
.x
);
2387 m_height
= HeightDefault(size
.y
);
2392 /* some reasonable defaults */
2397 m_x
= (gdk_screen_width () - m_width
) / 2;
2398 if (m_x
< 10) m_x
= 10;
2402 m_y
= (gdk_screen_height () - m_height
) / 2;
2403 if (m_y
< 10) m_y
= 10;
2410 void wxWindow::PostCreation()
2412 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2418 /* these get reported to wxWindows -> wxPaintEvent */
2420 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2422 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2423 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2425 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2426 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2428 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2430 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2431 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2435 #if (GTK_MINOR_VERSION > 0)
2436 /* these are called when the "sunken" or "raised" borders are drawn */
2437 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2438 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2440 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2441 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2445 if (m_wxwindow
&& m_needParent
)
2447 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2448 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2450 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2451 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2455 // For dialogs and frames, we are interested mainly in
2456 // m_widget's focus.
2458 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2459 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2461 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2462 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2465 GtkWidget
*connect_widget
= GetConnectWidget();
2467 ConnectWidget( connect_widget
);
2469 /* We cannot set colours, fonts and cursors before the widget has
2470 been realized, so we do this directly after realization */
2471 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2472 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2476 // Catch native resize events
2477 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2478 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2480 // Initialize XIM support
2481 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2482 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2484 // And resize XIM window
2485 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2486 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2489 if (!GTK_IS_COMBO(m_widget
))
2491 // This is needed if we want to add our windows into native
2492 // GTK control, such as the toolbar. With this callback, the
2493 // toolbar gets to know the correct size (the one set by the
2494 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2495 // when moving to GTK 2.0.
2496 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2497 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2503 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2505 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2506 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2508 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2509 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2511 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2512 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2514 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2515 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2517 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2518 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2520 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2521 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2523 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2524 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2527 bool wxWindow::Destroy()
2529 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2533 return wxWindowBase::Destroy();
2536 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2538 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2541 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2543 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2544 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2546 if (m_resizing
) return; /* I don't like recursions */
2549 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2551 /* don't set the size for children of wxNotebook, just take the values. */
2559 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2561 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2563 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2564 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2565 if (width
!= -1) m_width
= width
;
2566 if (height
!= -1) m_height
= height
;
2570 m_x
= x
+ pizza
->xoffset
;
2571 m_y
= y
+ pizza
->yoffset
;
2576 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2578 if (width
== -1) m_width
= 80;
2581 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2583 if (height
== -1) m_height
= 26;
2586 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2587 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2588 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2589 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2592 int bottom_border
= 0;
2594 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2596 /* the default button has a border around it */
2601 DoMoveWindow( m_x
-border
,
2604 m_height
+border
+bottom_border
);
2609 /* Sometimes the client area changes size without the
2610 whole windows's size changing, but if the whole
2611 windows's size doesn't change, no wxSizeEvent will
2612 normally be sent. Here we add an extra test if
2613 the client test has been changed and this will
2615 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2619 wxPrintf( "OnSize sent from " );
2620 if (GetClassInfo() && GetClassInfo()->GetClassName())
2621 wxPrintf( GetClassInfo()->GetClassName() );
2622 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2625 if (!m_nativeSizeEvent
)
2627 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2628 event
.SetEventObject( this );
2629 GetEventHandler()->ProcessEvent( event
);
2635 void wxWindow::OnInternalIdle()
2637 if ( g_sendActivateEvent
!= -1 )
2639 bool activate
= g_sendActivateEvent
!= 0;
2642 g_sendActivateEvent
= -1;
2644 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2645 event
.SetEventObject(this);
2647 (void)GetEventHandler()->ProcessEvent(event
);
2650 wxCursor cursor
= m_cursor
;
2651 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2655 /* I now set the cursor anew in every OnInternalIdle call
2656 as setting the cursor in a parent window also effects the
2657 windows above so that checking for the current cursor is
2662 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2664 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2666 if (!g_globalCursor
.Ok())
2667 cursor
= *wxSTANDARD_CURSOR
;
2669 window
= m_widget
->window
;
2670 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2671 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2677 GdkWindow
*window
= m_widget
->window
;
2678 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2679 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2687 void wxWindow::DoGetSize( int *width
, int *height
) const
2689 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2691 if (width
) (*width
) = m_width
;
2692 if (height
) (*height
) = m_height
;
2695 void wxWindow::DoSetClientSize( int width
, int height
)
2697 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2701 SetSize( width
, height
);
2708 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2710 /* when using GTK 1.2 we set the shadow border size to 2 */
2714 if (HasFlag(wxSIMPLE_BORDER
))
2716 /* when using GTK 1.2 we set the simple border size to 1 */
2723 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2725 GtkRequisition vscroll_req
;
2726 vscroll_req
.width
= 2;
2727 vscroll_req
.height
= 2;
2728 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2729 (scroll_window
->vscrollbar
, &vscroll_req
);
2731 GtkRequisition hscroll_req
;
2732 hscroll_req
.width
= 2;
2733 hscroll_req
.height
= 2;
2734 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2735 (scroll_window
->hscrollbar
, &hscroll_req
);
2737 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2739 if (scroll_window
->vscrollbar_visible
)
2741 dw
+= vscroll_req
.width
;
2742 dw
+= scroll_class
->scrollbar_spacing
;
2745 if (scroll_window
->hscrollbar_visible
)
2747 dh
+= hscroll_req
.height
;
2748 dh
+= scroll_class
->scrollbar_spacing
;
2752 SetSize( width
+dw
, height
+dh
);
2756 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2758 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2762 if (width
) (*width
) = m_width
;
2763 if (height
) (*height
) = m_height
;
2770 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2772 /* when using GTK 1.2 we set the shadow border size to 2 */
2776 if (HasFlag(wxSIMPLE_BORDER
))
2778 /* when using GTK 1.2 we set the simple border size to 1 */
2785 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2787 GtkRequisition vscroll_req
;
2788 vscroll_req
.width
= 2;
2789 vscroll_req
.height
= 2;
2790 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2791 (scroll_window
->vscrollbar
, &vscroll_req
);
2793 GtkRequisition hscroll_req
;
2794 hscroll_req
.width
= 2;
2795 hscroll_req
.height
= 2;
2796 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2797 (scroll_window
->hscrollbar
, &hscroll_req
);
2799 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2801 if (scroll_window
->vscrollbar_visible
)
2803 dw
+= vscroll_req
.width
;
2804 dw
+= scroll_class
->scrollbar_spacing
;
2807 if (scroll_window
->hscrollbar_visible
)
2809 dh
+= hscroll_req
.height
;
2810 dh
+= scroll_class
->scrollbar_spacing
;
2814 if (width
) (*width
) = m_width
- dw
;
2815 if (height
) (*height
) = m_height
- dh
;
2819 void wxWindow::DoGetPosition( int *x
, int *y
) const
2821 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2825 if (m_parent
&& m_parent
->m_wxwindow
)
2827 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2828 dx
= pizza
->xoffset
;
2829 dy
= pizza
->yoffset
;
2832 if (x
) (*x
) = m_x
- dx
;
2833 if (y
) (*y
) = m_y
- dy
;
2836 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2838 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2840 if (!m_widget
->window
) return;
2842 GdkWindow
*source
= (GdkWindow
*) NULL
;
2844 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2846 source
= m_widget
->window
;
2850 gdk_window_get_origin( source
, &org_x
, &org_y
);
2854 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2856 org_x
+= m_widget
->allocation
.x
;
2857 org_y
+= m_widget
->allocation
.y
;
2865 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2867 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2869 if (!m_widget
->window
) return;
2871 GdkWindow
*source
= (GdkWindow
*) NULL
;
2873 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2875 source
= m_widget
->window
;
2879 gdk_window_get_origin( source
, &org_x
, &org_y
);
2883 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2885 org_x
+= m_widget
->allocation
.x
;
2886 org_y
+= m_widget
->allocation
.y
;
2894 bool wxWindow::Show( bool show
)
2896 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2898 if (!wxWindowBase::Show(show
))
2905 gtk_widget_show( m_widget
);
2907 gtk_widget_hide( m_widget
);
2912 bool wxWindow::Enable( bool enable
)
2914 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2916 if (!wxWindowBase::Enable(enable
))
2922 gtk_widget_set_sensitive( m_widget
, enable
);
2924 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2929 int wxWindow::GetCharHeight() const
2931 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2933 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2935 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2937 return font
->ascent
+ font
->descent
;
2940 int wxWindow::GetCharWidth() const
2942 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2944 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2946 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2948 return gdk_string_width( font
, "H" );
2951 void wxWindow::GetTextExtent( const wxString
& string
,
2955 int *externalLeading
,
2956 const wxFont
*theFont
) const
2958 wxFont fontToUse
= m_font
;
2959 if (theFont
) fontToUse
= *theFont
;
2961 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2963 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2964 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2965 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2966 if (descent
) (*descent
) = font
->descent
;
2967 if (externalLeading
) (*externalLeading
) = 0; // ??
2970 void wxWindow::SetFocus()
2972 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2976 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2977 gtk_widget_grab_focus (m_wxwindow
);
2983 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2985 gtk_widget_grab_focus (m_widget
);
2987 else if (GTK_IS_CONTAINER(m_widget
))
2989 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2998 bool wxWindow::AcceptsFocus() const
3000 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3003 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
3005 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3007 wxWindow
*oldParent
= m_parent
,
3008 *newParent
= (wxWindow
*)newParentBase
;
3010 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3012 if ( !wxWindowBase::Reparent(newParent
) )
3015 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3017 /* prevent GTK from deleting the widget arbitrarily */
3018 gtk_widget_ref( m_widget
);
3022 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3025 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3029 /* insert GTK representation */
3030 (*(newParent
->m_insertCallback
))(newParent
, this);
3033 /* reverse: prevent GTK from deleting the widget arbitrarily */
3034 gtk_widget_unref( m_widget
);
3039 void wxWindow::DoAddChild(wxWindow
*child
)
3041 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3043 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3045 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3050 /* insert GTK representation */
3051 (*m_insertCallback
)(this, child
);
3054 void wxWindow::Raise()
3056 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3058 if (!m_widget
->window
) return;
3060 gdk_window_raise( m_widget
->window
);
3063 void wxWindow::Lower()
3065 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3067 if (!m_widget
->window
) return;
3069 gdk_window_lower( m_widget
->window
);
3072 bool wxWindow::SetCursor( const wxCursor
&cursor
)
3074 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3076 if (cursor
== m_cursor
)
3080 wxapp_install_idle_handler();
3082 if (cursor
== wxNullCursor
)
3083 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3085 return wxWindowBase::SetCursor( cursor
);
3088 void wxWindow::WarpPointer( int x
, int y
)
3090 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3092 /* we provide this function ourselves as it is
3093 missing in GDK (top of this file) */
3095 GdkWindow
*window
= (GdkWindow
*) NULL
;
3097 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3099 window
= GetConnectWidget()->window
;
3102 gdk_window_warp_pointer( window
, x
, y
);
3105 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
3107 if (!m_widget
) return;
3108 if (!m_widget
->window
) return;
3110 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3114 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3116 rect
->width
, rect
->height
);
3120 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3124 /* there is no GTK equivalent of "draw only, don't clear" so we
3125 invent our own in the GtkPizza widget */
3133 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3134 gboolean old_clear = pizza->clear_on_draw;
3135 gtk_pizza_set_clear( pizza, FALSE );
3136 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3137 gtk_pizza_set_clear( pizza, old_clear );
3139 GdkEventExpose gdk_event
;
3140 gdk_event
.type
= GDK_EXPOSE
;
3141 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3142 gdk_event
.count
= 0;
3143 gdk_event
.area
.x
= 0;
3144 gdk_event
.area
.y
= 0;
3145 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3146 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3147 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3152 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3161 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3162 gboolean old_clear = pizza->clear_on_draw;
3163 gtk_pizza_set_clear( pizza, FALSE );
3165 GdkRectangle gdk_rect;
3166 gdk_rect.x = rect->x;
3167 gdk_rect.y = rect->y;
3168 gdk_rect.width = rect->width;
3169 gdk_rect.height = rect->height;
3170 gtk_widget_draw( m_wxwindow, &gdk_rect );
3171 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3173 gtk_pizza_set_clear( pizza, old_clear );
3175 GdkEventExpose gdk_event
;
3176 gdk_event
.type
= GDK_EXPOSE
;
3177 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3178 gdk_event
.count
= 0;
3179 gdk_event
.area
.x
= rect
->x
;
3180 gdk_event
.area
.y
= rect
->y
;
3181 gdk_event
.area
.width
= rect
->width
;
3182 gdk_event
.area
.height
= rect
->height
;
3183 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3187 GdkRectangle gdk_rect
;
3188 gdk_rect
.x
= rect
->x
;
3189 gdk_rect
.y
= rect
->y
;
3190 gdk_rect
.width
= rect
->width
;
3191 gdk_rect
.height
= rect
->height
;
3192 gtk_widget_draw( m_widget
, &gdk_rect
);
3197 void wxWindow::Clear()
3199 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3201 if (!m_widget
->window
) return;
3203 if (m_wxwindow
&& m_wxwindow
->window
)
3205 // gdk_window_clear( m_wxwindow->window );
3210 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
3212 wxWindowBase::DoSetToolTip(tip
);
3215 m_tooltip
->Apply( this );
3218 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3220 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3222 #endif // wxUSE_TOOLTIPS
3224 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
3226 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3228 if (!wxWindowBase::SetBackgroundColour(colour
))
3230 // don't leave if the GTK widget has just
3232 if (!m_delayedBackgroundColour
) return FALSE
;
3235 GdkWindow
*window
= (GdkWindow
*) NULL
;
3237 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3239 window
= GetConnectWidget()->window
;
3243 // indicate that a new style has been set
3244 // but it couldn't get applied as the
3245 // widget hasn't been realized yet.
3246 m_delayedBackgroundColour
= TRUE
;
3250 (m_wxwindow
->window
) &&
3251 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3253 /* wxMSW doesn't clear the window here. I don't do that either to
3254 provide compatibility. call Clear() to do the job. */
3256 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3257 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3265 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
3267 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3269 if (!wxWindowBase::SetForegroundColour(colour
))
3271 // don't leave if the GTK widget has just
3273 if (!m_delayedForegroundColour
) return FALSE
;
3276 GdkWindow
*window
= (GdkWindow
*) NULL
;
3278 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3280 window
= GetConnectWidget()->window
;
3284 // indicate that a new style has been set
3285 // but it couldn't get applied as the
3286 // widget hasn't been realized yet.
3287 m_delayedForegroundColour
= TRUE
;
3295 GtkStyle
*wxWindow::GetWidgetStyle()
3299 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3301 /* FIXME: is this necessary? */
3302 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3304 remake
->klass
= m_widgetStyle
->klass
;
3307 gtk_style_unref( m_widgetStyle
);
3308 m_widgetStyle
= remake
;
3312 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3315 def
= gtk_widget_get_default_style();
3317 m_widgetStyle
= gtk_style_copy( def
);
3319 /* FIXME: is this necessary? */
3320 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3322 m_widgetStyle
->klass
= def
->klass
;
3326 return m_widgetStyle
;
3329 void wxWindow::SetWidgetStyle()
3331 #if DISABLE_STYLE_IF_BROKEN_THEM
3332 if (m_widget
->style
->engine_data
)
3334 static bool s_warningPrinted
= FALSE
;
3335 if (!s_warningPrinted
)
3337 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3338 s_warningPrinted
= TRUE
;
3340 m_widgetStyle
= m_widget
->style
;
3345 GtkStyle
*style
= GetWidgetStyle();
3347 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3349 gdk_font_unref( style
->font
);
3350 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3353 if (m_foregroundColour
.Ok())
3355 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3356 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3358 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3359 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3360 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3364 // Try to restore the gtk default style. This is still a little
3365 // oversimplified for what is probably really needed here for controls
3366 // other than buttons, but is better than not being able to (re)set a
3367 // control's foreground colour to *wxBLACK -- RL
3368 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3371 def
= gtk_widget_get_default_style();
3373 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3374 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3375 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3379 if (m_backgroundColour
.Ok())
3381 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3382 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3384 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3385 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3386 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3387 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3388 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3389 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3390 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3391 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3395 // Try to restore the gtk default style. This is still a little
3396 // oversimplified for what is probably really needed here for controls
3397 // other than buttons, but is better than not being able to (re)set a
3398 // control's background colour to default grey and means resetting a
3399 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3401 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3404 def
= gtk_widget_get_default_style();
3406 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3407 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3408 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3409 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3410 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3411 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3412 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3413 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3418 void wxWindow::ApplyWidgetStyle()
3422 //-----------------------------------------------------------------------------
3423 // Pop-up menu stuff
3424 //-----------------------------------------------------------------------------
3426 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3428 *is_waiting
= FALSE
;
3431 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3433 menu
->SetInvokingWindow( win
);
3434 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3437 wxMenuItem
*menuitem
= node
->GetData();
3438 if (menuitem
->IsSubMenu())
3440 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3443 node
= node
->GetNext();
3447 static gint gs_pop_x
= 0;
3448 static gint gs_pop_y
= 0;
3450 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3454 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3459 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3461 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3463 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3465 SetInvokingWindow( menu
, this );
3472 bool is_waiting
= TRUE
;
3474 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3475 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3478 GTK_MENU(menu
->m_menu
),
3479 (GtkWidget
*) NULL
, // parent menu shell
3480 (GtkWidget
*) NULL
, // parent menu item
3481 (GtkMenuPositionFunc
) pop_pos_callback
,
3482 (gpointer
) this, // client data
3483 0, // button used to activate it
3484 gs_timeLastClick
// the time of activation
3489 while (gtk_events_pending())
3490 gtk_main_iteration();
3496 #if wxUSE_DRAG_AND_DROP
3498 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3500 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3502 GtkWidget
*dnd_widget
= GetConnectWidget();
3504 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3506 if (m_dropTarget
) delete m_dropTarget
;
3507 m_dropTarget
= dropTarget
;
3509 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3512 #endif // wxUSE_DRAG_AND_DROP
3514 GtkWidget
* wxWindow::GetConnectWidget()
3516 GtkWidget
*connect_widget
= m_widget
;
3517 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3519 return connect_widget
;
3522 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3525 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3527 return (window
== m_widget
->window
);
3530 bool wxWindow::SetFont( const wxFont
&font
)
3532 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3534 if (!wxWindowBase::SetFont(font
))
3539 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3540 if ( sysbg
== m_backgroundColour
)
3542 m_backgroundColour
= wxNullColour
;
3544 m_backgroundColour
= sysbg
;
3554 void wxWindow::CaptureMouse()
3556 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3558 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3560 GdkWindow
*window
= (GdkWindow
*) NULL
;
3562 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3564 window
= GetConnectWidget()->window
;
3566 if (!window
) return;
3568 wxCursor
* cursor
= & m_cursor
;
3570 cursor
= wxSTANDARD_CURSOR
;
3572 gdk_pointer_grab( window
, FALSE
,
3574 (GDK_BUTTON_PRESS_MASK
|
3575 GDK_BUTTON_RELEASE_MASK
|
3576 GDK_POINTER_MOTION_HINT_MASK
|
3577 GDK_POINTER_MOTION_MASK
),
3579 cursor
->GetCursor(),
3580 (guint32
)GDK_CURRENT_TIME
);
3581 g_captureWindow
= this;
3584 void wxWindow::ReleaseMouse()
3586 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3588 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3590 GdkWindow
*window
= (GdkWindow
*) NULL
;
3592 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3594 window
= GetConnectWidget()->window
;
3599 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3600 g_captureWindow
= (wxWindow
*) NULL
;
3603 bool wxWindow::IsRetained() const
3608 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3609 int range
, bool refresh
)
3611 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3613 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3615 m_hasScrolling
= TRUE
;
3617 if (orient
== wxHORIZONTAL
)
3619 float fpos
= (float)pos
;
3620 float frange
= (float)range
;
3621 float fthumb
= (float)thumbVisible
;
3622 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3623 if (fpos
< 0.0) fpos
= 0.0;
3625 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3626 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3628 SetScrollPos( orient
, pos
, refresh
);
3632 m_oldHorizontalPos
= fpos
;
3634 m_hAdjust
->lower
= 0.0;
3635 m_hAdjust
->upper
= frange
;
3636 m_hAdjust
->value
= fpos
;
3637 m_hAdjust
->step_increment
= 1.0;
3638 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3639 m_hAdjust
->page_size
= fthumb
;
3643 float fpos
= (float)pos
;
3644 float frange
= (float)range
;
3645 float fthumb
= (float)thumbVisible
;
3646 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3647 if (fpos
< 0.0) fpos
= 0.0;
3649 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3650 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3652 SetScrollPos( orient
, pos
, refresh
);
3656 m_oldVerticalPos
= fpos
;
3658 m_vAdjust
->lower
= 0.0;
3659 m_vAdjust
->upper
= frange
;
3660 m_vAdjust
->value
= fpos
;
3661 m_vAdjust
->step_increment
= 1.0;
3662 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3663 m_vAdjust
->page_size
= fthumb
;
3666 if (orient
== wxHORIZONTAL
)
3667 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3669 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3672 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3674 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3676 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3678 if (orient
== wxHORIZONTAL
)
3680 float fpos
= (float)pos
;
3681 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3682 if (fpos
< 0.0) fpos
= 0.0;
3683 m_oldHorizontalPos
= fpos
;
3685 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3686 m_hAdjust
->value
= fpos
;
3690 float fpos
= (float)pos
;
3691 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3692 if (fpos
< 0.0) fpos
= 0.0;
3693 m_oldVerticalPos
= fpos
;
3695 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3696 m_vAdjust
->value
= fpos
;
3699 if (m_wxwindow
->window
)
3701 if (orient
== wxHORIZONTAL
)
3703 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3704 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3706 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3708 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3709 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3713 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3714 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3716 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3718 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3719 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3724 int wxWindow::GetScrollThumb( int orient
) const
3726 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3728 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3730 if (orient
== wxHORIZONTAL
)
3731 return (int)(m_hAdjust
->page_size
+0.5);
3733 return (int)(m_vAdjust
->page_size
+0.5);
3736 int wxWindow::GetScrollPos( int orient
) const
3738 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3740 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3742 if (orient
== wxHORIZONTAL
)
3743 return (int)(m_hAdjust
->value
+0.5);
3745 return (int)(m_vAdjust
->value
+0.5);
3748 int wxWindow::GetScrollRange( int orient
) const
3750 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3752 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3754 if (orient
== wxHORIZONTAL
)
3755 return (int)(m_hAdjust
->upper
+0.5);
3757 return (int)(m_vAdjust
->upper
+0.5);
3760 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3762 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3764 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3766 if ((dx
== 0) && (dy
== 0)) return;
3768 m_clipPaintRegion
= TRUE
;
3769 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3770 m_clipPaintRegion
= FALSE
;
3773 if (m_children.GetCount() > 0)
3775 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3779 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3781 pizza->xoffset -= dx;
3782 pizza->yoffset -= dy;
3784 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3785 gdk_gc_set_exposures( m_scrollGC, TRUE );
3789 GetClientSize( &cw, &ch );
3790 int w = cw - abs(dx);
3791 int h = ch - abs(dy);
3793 if ((h < 0) || (w < 0))
3801 if (dx < 0) s_x = -dx;
3802 if (dy < 0) s_y = -dy;
3805 if (dx > 0) d_x = dx;
3806 if (dy > 0) d_y = dy;
3808 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3809 pizza->bin_window, s_x, s_y, w, h );
3812 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3813 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3814 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3815 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3817 Refresh( TRUE, &rect );
3820 gdk_gc_unref( m_scrollGC );
3825 // Find the wxWindow at the current mouse position, also returning the mouse
3827 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
3829 pt
= wxGetMousePosition();
3830 wxWindow
* found
= wxFindWindowAtPoint(pt
);
3834 // Get the current mouse position.
3835 wxPoint
wxGetMousePosition()
3837 /* This crashes when used within wxHelpContext,
3838 so we have to use the X-specific implementation below.
3840 GdkModifierType *mask;
3841 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
3843 return wxPoint(x, y);
3847 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
3849 return wxPoint(-999, -999);
3851 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
3852 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
3853 Window rootReturn
, childReturn
;
3854 int rootX
, rootY
, winX
, winY
;
3855 unsigned int maskReturn
;
3857 XQueryPointer (display
,
3861 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
3862 return wxPoint(rootX
, rootY
);