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
1096 switch ( event
.GetEventType() )
1098 case wxEVT_LEFT_DOWN
:
1099 case wxEVT_LEFT_DCLICK
:
1101 event
.m_leftDown
= !event
.m_leftDown
;
1104 case wxEVT_MIDDLE_DOWN
:
1105 case wxEVT_MIDDLE_DCLICK
:
1106 case wxEVT_MIDDLE_UP
:
1107 event
.m_middleDown
= !event
.m_middleDown
;
1110 case wxEVT_RIGHT_DOWN
:
1111 case wxEVT_RIGHT_DCLICK
:
1112 case wxEVT_RIGHT_UP
:
1113 event
.m_rightDown
= !event
.m_rightDown
;
1118 //-----------------------------------------------------------------------------
1119 // "button_press_event"
1120 //-----------------------------------------------------------------------------
1122 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1127 wxapp_install_idle_handler();
1130 wxPrintf( wxT("1) OnButtonPress from ") );
1131 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1132 wxPrintf( win->GetClassInfo()->GetClassName() );
1133 wxPrintf( wxT(".\n") );
1135 if (!win
->m_hasVMT
) return FALSE
;
1136 if (g_blockEventsOnDrag
) return TRUE
;
1137 if (g_blockEventsOnScroll
) return TRUE
;
1139 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1141 if (win
->m_wxwindow
)
1143 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1145 gtk_widget_grab_focus (win
->m_wxwindow
);
1148 wxPrintf( wxT("GrabFocus from ") );
1149 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1150 wxPrintf( win->GetClassInfo()->GetClassName() );
1151 wxPrintf( wxT(".\n") );
1157 wxEventType event_type
= wxEVT_NULL
;
1159 if (gdk_event
->button
== 1)
1161 switch (gdk_event
->type
)
1163 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1164 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1168 else if (gdk_event
->button
== 2)
1170 switch (gdk_event
->type
)
1172 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1173 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1177 else if (gdk_event
->button
== 3)
1179 switch (gdk_event
->type
)
1181 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1182 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1187 if ( event_type
== wxEVT_NULL
)
1189 // unknown mouse button or click type
1193 wxMouseEvent
event( event_type
);
1194 event
.SetTimestamp( gdk_event
->time
);
1195 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1196 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1197 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1198 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1199 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1200 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1201 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1203 event
.m_x
= (wxCoord
)gdk_event
->x
;
1204 event
.m_y
= (wxCoord
)gdk_event
->y
;
1206 AdjustEventButtonState(event
);
1208 // Some control don't have their own X window and thus cannot get
1211 if (!g_captureWindow
)
1213 wxCoord x
= event
.m_x
;
1214 wxCoord y
= event
.m_y
;
1215 if (win
->m_wxwindow
)
1217 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1218 x
+= pizza
->xoffset
;
1219 y
+= pizza
->yoffset
;
1222 wxNode
*node
= win
->GetChildren().First();
1225 wxWindow
*child
= (wxWindow
*)node
->Data();
1227 node
= node
->Next();
1228 if (!child
->IsShown())
1231 if (child
->m_isStaticBox
)
1233 // wxStaticBox is transparent in the box itself
1234 int xx1
= child
->m_x
;
1235 int yy1
= child
->m_y
;
1236 int xx2
= child
->m_x
+ child
->m_width
;
1237 int yy2
= child
->m_x
+ child
->m_height
;
1240 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1242 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1244 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1246 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1249 event
.m_x
-= child
->m_x
;
1250 event
.m_y
-= child
->m_y
;
1257 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1258 (child
->m_x
<= x
) &&
1259 (child
->m_y
<= y
) &&
1260 (child
->m_x
+child
->m_width
>= x
) &&
1261 (child
->m_y
+child
->m_height
>= y
))
1264 event
.m_x
-= child
->m_x
;
1265 event
.m_y
-= child
->m_y
;
1272 event
.SetEventObject( win
);
1274 gs_timeLastClick
= gdk_event
->time
;
1277 wxPrintf( wxT("2) OnButtonPress from ") );
1278 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1279 wxPrintf( win->GetClassInfo()->GetClassName() );
1280 wxPrintf( wxT(".\n") );
1283 if (win
->GetEventHandler()->ProcessEvent( event
))
1285 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1292 //-----------------------------------------------------------------------------
1293 // "button_release_event"
1294 //-----------------------------------------------------------------------------
1296 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1301 wxapp_install_idle_handler();
1303 if (!win
->m_hasVMT
) return FALSE
;
1304 if (g_blockEventsOnDrag
) return FALSE
;
1305 if (g_blockEventsOnScroll
) return FALSE
;
1307 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1310 printf( "OnButtonRelease from " );
1311 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1312 printf( win->GetClassInfo()->GetClassName() );
1316 wxEventType event_type
= wxEVT_NULL
;
1318 switch (gdk_event
->button
)
1320 case 1: event_type
= wxEVT_LEFT_UP
; break;
1321 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1322 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1323 default: return FALSE
;
1326 wxMouseEvent
event( event_type
);
1327 event
.SetTimestamp( gdk_event
->time
);
1328 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1329 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1330 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1331 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1332 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1333 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1334 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1335 event
.m_x
= (wxCoord
)gdk_event
->x
;
1336 event
.m_y
= (wxCoord
)gdk_event
->y
;
1338 AdjustEventButtonState(event
);
1340 // Some control don't have their own X window and thus cannot get
1343 if (!g_captureWindow
)
1345 wxCoord x
= event
.m_x
;
1346 wxCoord y
= event
.m_y
;
1347 if (win
->m_wxwindow
)
1349 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1350 x
+= pizza
->xoffset
;
1351 y
+= pizza
->yoffset
;
1354 wxNode
*node
= win
->GetChildren().First();
1357 wxWindow
*child
= (wxWindow
*)node
->Data();
1359 node
= node
->Next();
1360 if (!child
->IsShown())
1363 if (child
->m_isStaticBox
)
1365 // wxStaticBox is transparent in the box itself
1366 int xx1
= child
->m_x
;
1367 int yy1
= child
->m_y
;
1368 int xx2
= child
->m_x
+ child
->m_width
;
1369 int yy2
= child
->m_x
+ child
->m_height
;
1372 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1374 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1376 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1378 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1381 event
.m_x
-= child
->m_x
;
1382 event
.m_y
-= child
->m_y
;
1389 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1390 (child
->m_x
<= x
) &&
1391 (child
->m_y
<= y
) &&
1392 (child
->m_x
+child
->m_width
>= x
) &&
1393 (child
->m_y
+child
->m_height
>= y
))
1396 event
.m_x
-= child
->m_x
;
1397 event
.m_y
-= child
->m_y
;
1404 event
.SetEventObject( win
);
1406 if (win
->GetEventHandler()->ProcessEvent( event
))
1408 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1415 //-----------------------------------------------------------------------------
1416 // "motion_notify_event"
1417 //-----------------------------------------------------------------------------
1419 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1424 wxapp_install_idle_handler();
1426 if (!win
->m_hasVMT
) return FALSE
;
1427 if (g_blockEventsOnDrag
) return FALSE
;
1428 if (g_blockEventsOnScroll
) return FALSE
;
1430 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1432 if (gdk_event
->is_hint
)
1436 GdkModifierType state
;
1437 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1443 printf( "OnMotion from " );
1444 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1445 printf( win->GetClassInfo()->GetClassName() );
1449 wxMouseEvent
event( wxEVT_MOTION
);
1450 event
.SetTimestamp( gdk_event
->time
);
1451 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1452 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1453 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1454 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1455 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1456 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1457 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1459 event
.m_x
= (wxCoord
)gdk_event
->x
;
1460 event
.m_y
= (wxCoord
)gdk_event
->y
;
1462 // Some control don't have their own X window and thus cannot get
1465 if (!g_captureWindow
)
1467 wxCoord x
= event
.m_x
;
1468 wxCoord y
= event
.m_y
;
1469 if (win
->m_wxwindow
)
1471 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1472 x
+= pizza
->xoffset
;
1473 y
+= pizza
->yoffset
;
1476 wxNode
*node
= win
->GetChildren().First();
1479 wxWindow
*child
= (wxWindow
*)node
->Data();
1481 node
= node
->Next();
1482 if (!child
->IsShown())
1485 if (child
->m_isStaticBox
)
1487 // wxStaticBox is transparent in the box itself
1488 int xx1
= child
->m_x
;
1489 int yy1
= child
->m_y
;
1490 int xx2
= child
->m_x
+ child
->m_width
;
1491 int yy2
= child
->m_x
+ child
->m_height
;
1494 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1496 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1498 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1500 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1503 event
.m_x
-= child
->m_x
;
1504 event
.m_y
-= child
->m_y
;
1511 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1512 (child
->m_x
<= x
) &&
1513 (child
->m_y
<= y
) &&
1514 (child
->m_x
+child
->m_width
>= x
) &&
1515 (child
->m_y
+child
->m_height
>= y
))
1518 event
.m_x
-= child
->m_x
;
1519 event
.m_y
-= child
->m_y
;
1526 event
.SetEventObject( win
);
1528 if (win
->GetEventHandler()->ProcessEvent( event
))
1530 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1537 //-----------------------------------------------------------------------------
1539 //-----------------------------------------------------------------------------
1541 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1546 wxapp_install_idle_handler();
1548 if (!win
->m_hasVMT
) return FALSE
;
1549 if (g_blockEventsOnDrag
) return FALSE
;
1551 switch ( g_sendActivateEvent
)
1554 // we've got focus from outside, synthtize wxActivateEvent
1555 g_sendActivateEvent
= 1;
1559 // another our window just lost focus, it was already ours before
1560 // - don't send any wxActivateEvent
1561 g_sendActivateEvent
= -1;
1565 g_focusWindow
= win
;
1568 printf( "OnSetFocus from " );
1569 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1570 printf( win->GetClassInfo()->GetClassName() );
1572 printf( WXSTRINGCAST win->GetLabel() );
1576 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1579 panel
->SetLastFocus(win
);
1584 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1588 // caret needs to be informed about focus change
1589 wxCaret
*caret
= win
->GetCaret();
1592 caret
->OnSetFocus();
1594 #endif // wxUSE_CARET
1596 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1597 event
.SetEventObject( win
);
1599 if (win
->GetEventHandler()->ProcessEvent( event
))
1601 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1608 //-----------------------------------------------------------------------------
1609 // "focus_out_event"
1610 //-----------------------------------------------------------------------------
1612 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1617 wxapp_install_idle_handler();
1619 if (!win
->m_hasVMT
) return FALSE
;
1620 if (g_blockEventsOnDrag
) return FALSE
;
1622 // if the focus goes out of our app alltogether, OnIdle() will send
1623 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1624 // g_sendActivateEvent to -1
1625 g_sendActivateEvent
= 0;
1627 wxWindow
*winFocus
= FindFocusedChild(win
);
1631 g_focusWindow
= (wxWindow
*)NULL
;
1634 printf( "OnKillFocus from " );
1635 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1636 printf( win->GetClassInfo()->GetClassName() );
1646 // caret needs to be informed about focus change
1647 wxCaret
*caret
= win
->GetCaret();
1650 caret
->OnKillFocus();
1652 #endif // wxUSE_CARET
1654 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1655 event
.SetEventObject( win
);
1657 if (win
->GetEventHandler()->ProcessEvent( event
))
1659 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1666 //-----------------------------------------------------------------------------
1667 // "enter_notify_event"
1668 //-----------------------------------------------------------------------------
1670 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1675 wxapp_install_idle_handler();
1677 if (!win
->m_hasVMT
) return FALSE
;
1678 if (g_blockEventsOnDrag
) return FALSE
;
1680 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1682 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1683 #if (GTK_MINOR_VERSION > 0)
1684 event
.SetTimestamp( gdk_event
->time
);
1686 event
.SetEventObject( win
);
1690 GdkModifierType state
= (GdkModifierType
)0;
1692 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1694 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1695 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1696 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1697 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1698 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1699 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1700 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1705 if (win
->GetEventHandler()->ProcessEvent( event
))
1707 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1714 //-----------------------------------------------------------------------------
1715 // "leave_notify_event"
1716 //-----------------------------------------------------------------------------
1718 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1723 wxapp_install_idle_handler();
1725 if (!win
->m_hasVMT
) return FALSE
;
1726 if (g_blockEventsOnDrag
) return FALSE
;
1728 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1730 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1731 #if (GTK_MINOR_VERSION > 0)
1732 event
.SetTimestamp( gdk_event
->time
);
1734 event
.SetEventObject( win
);
1738 GdkModifierType state
= (GdkModifierType
)0;
1740 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1742 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1743 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1744 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1745 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1746 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1747 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1748 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1753 if (win
->GetEventHandler()->ProcessEvent( event
))
1755 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1762 //-----------------------------------------------------------------------------
1763 // "value_changed" from m_vAdjust
1764 //-----------------------------------------------------------------------------
1766 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1771 wxapp_install_idle_handler();
1773 if (g_blockEventsOnDrag
) return;
1775 if (!win
->m_hasVMT
) return;
1777 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1778 if (fabs(diff
) < 0.2) return;
1780 win
->m_oldVerticalPos
= adjust
->value
;
1782 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1783 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1785 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1786 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1787 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1788 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1789 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1791 int value
= (int)(adjust
->value
+0.5);
1793 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1794 event
.SetEventObject( win
);
1795 win
->GetEventHandler()->ProcessEvent( event
);
1798 //-----------------------------------------------------------------------------
1799 // "value_changed" from m_hAdjust
1800 //-----------------------------------------------------------------------------
1802 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1807 wxapp_install_idle_handler();
1809 if (g_blockEventsOnDrag
) return;
1810 if (!win
->m_hasVMT
) return;
1812 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1813 if (fabs(diff
) < 0.2) return;
1815 win
->m_oldHorizontalPos
= adjust
->value
;
1817 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1818 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1820 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1821 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1822 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1823 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1824 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1826 int value
= (int)(adjust
->value
+0.5);
1828 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1829 event
.SetEventObject( win
);
1830 win
->GetEventHandler()->ProcessEvent( event
);
1833 //-----------------------------------------------------------------------------
1834 // "button_press_event" from scrollbar
1835 //-----------------------------------------------------------------------------
1837 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1838 GdkEventButton
*gdk_event
,
1844 wxapp_install_idle_handler();
1847 g_blockEventsOnScroll
= TRUE
;
1848 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1853 //-----------------------------------------------------------------------------
1854 // "button_release_event" from scrollbar
1855 //-----------------------------------------------------------------------------
1857 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1858 GdkEventButton
*WXUNUSED(gdk_event
),
1863 // don't test here as we can release the mouse while being over
1864 // a different window than the slider
1866 // if (gdk_event->window != widget->slider) return FALSE;
1868 g_blockEventsOnScroll
= FALSE
;
1870 if (win
->m_isScrolling
)
1872 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
1876 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1877 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1879 value
= (int)(win
->m_hAdjust
->value
+0.5);
1882 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1884 value
= (int)(win
->m_vAdjust
->value
+0.5);
1888 wxScrollWinEvent
event( command
, value
, dir
);
1889 event
.SetEventObject( win
);
1890 win
->GetEventHandler()->ProcessEvent( event
);
1893 win
->m_isScrolling
= FALSE
;
1898 // ----------------------------------------------------------------------------
1899 // this wxWindowBase function is implemented here (in platform-specific file)
1900 // because it is static and so couldn't be made virtual
1901 // ----------------------------------------------------------------------------
1903 wxWindow
*wxWindowBase::FindFocus()
1905 return g_focusWindow
;
1908 //-----------------------------------------------------------------------------
1909 // "realize" from m_widget
1910 //-----------------------------------------------------------------------------
1912 /* We cannot set colours and fonts before the widget has
1913 been realized, so we do this directly after realization. */
1916 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1921 wxapp_install_idle_handler();
1923 if (win
->m_delayedBackgroundColour
)
1924 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1926 if (win
->m_delayedForegroundColour
)
1927 win
->SetForegroundColour( win
->GetForegroundColour() );
1929 wxWindowCreateEvent
event( win
);
1930 event
.SetEventObject( win
);
1931 win
->GetEventHandler()->ProcessEvent( event
);
1936 //-----------------------------------------------------------------------------
1938 //-----------------------------------------------------------------------------
1941 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
1942 GtkAllocation
*WXUNUSED(alloc
),
1946 wxapp_install_idle_handler();
1948 if (!win
->m_hasScrolling
) return;
1950 int client_width
= 0;
1951 int client_height
= 0;
1952 win
->GetClientSize( &client_width
, &client_height
);
1953 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
1956 win
->m_oldClientWidth
= client_width
;
1957 win
->m_oldClientHeight
= client_height
;
1959 if (!win
->m_nativeSizeEvent
)
1961 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
1962 event
.SetEventObject( win
);
1963 win
->GetEventHandler()->ProcessEvent( event
);
1969 #define WXUNUSED_UNLESS_XIM(param) param
1971 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1974 /* Resize XIM window */
1977 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1978 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1979 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1982 wxapp_install_idle_handler();
1988 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1992 gdk_window_get_size (widget
->window
, &width
, &height
);
1993 win
->m_icattr
->preedit_area
.width
= width
;
1994 win
->m_icattr
->preedit_area
.height
= height
;
1995 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2000 //-----------------------------------------------------------------------------
2001 // "realize" from m_wxwindow
2002 //-----------------------------------------------------------------------------
2004 /* Initialize XIM support */
2007 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2008 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
2011 wxapp_install_idle_handler();
2014 if (win
->m_ic
) return FALSE
;
2015 if (!widget
) return FALSE
;
2016 if (!gdk_im_ready()) return FALSE
;
2018 win
->m_icattr
= gdk_ic_attr_new();
2019 if (!win
->m_icattr
) return FALSE
;
2023 GdkColormap
*colormap
;
2024 GdkICAttr
*attr
= win
->m_icattr
;
2025 unsigned attrmask
= GDK_IC_ALL_REQ
;
2027 GdkIMStyle supported_style
= (GdkIMStyle
)
2028 (GDK_IM_PREEDIT_NONE
|
2029 GDK_IM_PREEDIT_NOTHING
|
2030 GDK_IM_PREEDIT_POSITION
|
2031 GDK_IM_STATUS_NONE
|
2032 GDK_IM_STATUS_NOTHING
);
2034 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2035 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2037 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2038 attr
->client_window
= widget
->window
;
2040 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2041 gtk_widget_get_default_colormap ())
2043 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2044 attr
->preedit_colormap
= colormap
;
2047 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2048 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2049 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2050 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2052 switch (style
& GDK_IM_PREEDIT_MASK
)
2054 case GDK_IM_PREEDIT_POSITION
:
2055 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2057 g_warning ("over-the-spot style requires fontset");
2061 gdk_window_get_size (widget
->window
, &width
, &height
);
2063 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2064 attr
->spot_location
.x
= 0;
2065 attr
->spot_location
.y
= height
;
2066 attr
->preedit_area
.x
= 0;
2067 attr
->preedit_area
.y
= 0;
2068 attr
->preedit_area
.width
= width
;
2069 attr
->preedit_area
.height
= height
;
2070 attr
->preedit_fontset
= widget
->style
->font
;
2075 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2077 if (win
->m_ic
== NULL
)
2078 g_warning ("Can't create input context.");
2081 mask
= gdk_window_get_events (widget
->window
);
2082 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2083 gdk_window_set_events (widget
->window
, mask
);
2085 if (GTK_WIDGET_HAS_FOCUS(widget
))
2086 gdk_im_begin (win
->m_ic
, widget
->window
);
2093 //-----------------------------------------------------------------------------
2094 // InsertChild for wxWindow.
2095 //-----------------------------------------------------------------------------
2097 /* Callback for wxWindow. This very strange beast has to be used because
2098 * C++ has no virtual methods in a constructor. We have to emulate a
2099 * virtual function here as wxNotebook requires a different way to insert
2100 * a child in it. I had opted for creating a wxNotebookPage window class
2101 * which would have made this superfluous (such in the MDI window system),
2102 * but no-one was listening to me... */
2104 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
2106 /* the window might have been scrolled already, do we
2107 have to adapt the position */
2108 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2109 child
->m_x
+= pizza
->xoffset
;
2110 child
->m_y
+= pizza
->yoffset
;
2112 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2113 GTK_WIDGET(child
->m_widget
),
2120 //-----------------------------------------------------------------------------
2122 //-----------------------------------------------------------------------------
2124 wxWindow
* wxGetActiveWindow()
2126 return g_focusWindow
;
2129 //-----------------------------------------------------------------------------
2131 //-----------------------------------------------------------------------------
2133 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2135 void wxWindow::Init()
2141 m_widget
= (GtkWidget
*) NULL
;
2142 m_wxwindow
= (GtkWidget
*) NULL
;
2152 m_needParent
= TRUE
;
2153 m_isBeingDeleted
= FALSE
;
2156 m_nativeSizeEvent
= FALSE
;
2158 m_hasScrolling
= FALSE
;
2159 m_isScrolling
= FALSE
;
2161 m_hAdjust
= (GtkAdjustment
*) NULL
;
2162 m_vAdjust
= (GtkAdjustment
*) NULL
;
2163 m_oldHorizontalPos
= 0.0;
2164 m_oldVerticalPos
= 0.0;
2167 m_widgetStyle
= (GtkStyle
*) NULL
;
2169 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2171 m_isStaticBox
= FALSE
;
2172 m_isRadioButton
= FALSE
;
2174 m_acceptsFocus
= FALSE
;
2176 m_clipPaintRegion
= FALSE
;
2178 m_cursor
= *wxSTANDARD_CURSOR
;
2180 m_delayedForegroundColour
= FALSE
;
2181 m_delayedBackgroundColour
= FALSE
;
2184 m_ic
= (GdkIC
*) NULL
;
2185 m_icattr
= (GdkICAttr
*) NULL
;
2189 wxWindow::wxWindow()
2194 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
2195 const wxPoint
&pos
, const wxSize
&size
,
2196 long style
, const wxString
&name
)
2200 Create( parent
, id
, pos
, size
, style
, name
);
2203 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
2204 const wxPoint
&pos
, const wxSize
&size
,
2205 long style
, const wxString
&name
)
2207 if (!PreCreation( parent
, pos
, size
) ||
2208 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2210 wxFAIL_MSG( wxT("wxWindow creation failed") );
2214 m_insertCallback
= wxInsertChildInWindow
;
2216 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2217 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2219 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2221 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2222 scroll_class
->scrollbar_spacing
= 0;
2224 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2226 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2227 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2229 m_wxwindow
= gtk_pizza_new();
2231 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2233 #if (GTK_MINOR_VERSION > 0)
2234 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2236 if (HasFlag(wxRAISED_BORDER
))
2238 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2240 else if (HasFlag(wxSUNKEN_BORDER
))
2242 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2244 else if (HasFlag(wxSIMPLE_BORDER
))
2246 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2250 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2252 #else // GTK_MINOR_VERSION == 0
2253 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2255 if (HasFlag(wxRAISED_BORDER
))
2257 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2259 else if (HasFlag(wxSUNKEN_BORDER
))
2261 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2265 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2267 #endif // GTK_MINOR_VERSION
2269 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2270 m_acceptsFocus
= TRUE
;
2272 #if (GTK_MINOR_VERSION == 0)
2273 // shut the viewport up
2274 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2275 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2276 #endif // GTK_MINOR_VERSION == 0
2278 // I _really_ don't want scrollbars in the beginning
2279 m_vAdjust
->lower
= 0.0;
2280 m_vAdjust
->upper
= 1.0;
2281 m_vAdjust
->value
= 0.0;
2282 m_vAdjust
->step_increment
= 1.0;
2283 m_vAdjust
->page_increment
= 1.0;
2284 m_vAdjust
->page_size
= 5.0;
2285 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2286 m_hAdjust
->lower
= 0.0;
2287 m_hAdjust
->upper
= 1.0;
2288 m_hAdjust
->value
= 0.0;
2289 m_hAdjust
->step_increment
= 1.0;
2290 m_hAdjust
->page_increment
= 1.0;
2291 m_hAdjust
->page_size
= 5.0;
2292 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2294 // these handlers block mouse events to any window during scrolling such as
2295 // motion events and prevent GTK and wxWindows from fighting over where the
2298 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2299 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2301 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2302 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2304 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2305 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2307 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2308 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2310 // these handlers get notified when screen updates are required either when
2311 // scrolling or when the window size (and therefore scrollbar configuration)
2314 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2315 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2316 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2317 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2319 gtk_widget_show( m_wxwindow
);
2322 m_parent
->DoAddChild( this );
2331 wxWindow::~wxWindow()
2333 m_isBeingDeleted
= TRUE
;
2342 m_parent
->RemoveChild( this );
2346 gdk_ic_destroy (m_ic
);
2348 gdk_ic_attr_destroy (m_icattr
);
2353 #if DISABLE_STYLE_IF_BROKEN_THEME
2354 // don't delete if it's a pixmap theme style
2355 if (!m_widgetStyle
->engine_data
)
2356 gtk_style_unref( m_widgetStyle
);
2358 m_widgetStyle
= (GtkStyle
*) NULL
;
2363 gtk_widget_destroy( m_wxwindow
);
2364 m_wxwindow
= (GtkWidget
*) NULL
;
2369 gtk_widget_destroy( m_widget
);
2370 m_widget
= (GtkWidget
*) NULL
;
2374 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2376 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2378 /* this turns -1 into 20 so that a minimal window is
2379 visible even although -1,-1 has been given as the
2380 size of the window. the same trick is used in other
2381 ports and should make debugging easier */
2382 m_width
= WidthDefault(size
.x
);
2383 m_height
= HeightDefault(size
.y
);
2388 /* some reasonable defaults */
2393 m_x
= (gdk_screen_width () - m_width
) / 2;
2394 if (m_x
< 10) m_x
= 10;
2398 m_y
= (gdk_screen_height () - m_height
) / 2;
2399 if (m_y
< 10) m_y
= 10;
2406 void wxWindow::PostCreation()
2408 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2414 /* these get reported to wxWindows -> wxPaintEvent */
2416 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2418 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2419 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2421 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2422 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2424 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2426 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2427 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2431 #if (GTK_MINOR_VERSION > 0)
2432 /* these are called when the "sunken" or "raised" borders are drawn */
2433 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2434 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2436 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2437 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2441 if (m_wxwindow
&& m_needParent
)
2443 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2444 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2446 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2447 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2451 // For dialogs and frames, we are interested mainly in
2452 // m_widget's focus.
2454 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2455 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2457 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2458 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2461 GtkWidget
*connect_widget
= GetConnectWidget();
2463 ConnectWidget( connect_widget
);
2465 /* We cannot set colours, fonts and cursors before the widget has
2466 been realized, so we do this directly after realization */
2467 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2468 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2472 // Catch native resize events
2473 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2474 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2476 // Initialize XIM support
2477 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2478 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2480 // And resize XIM window
2481 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2482 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2485 if (!GTK_IS_COMBO(m_widget
))
2487 // This is needed if we want to add our windows into native
2488 // GTK control, such as the toolbar. With this callback, the
2489 // toolbar gets to know the correct size (the one set by the
2490 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2491 // when moving to GTK 2.0.
2492 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2493 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2499 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2501 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2502 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2504 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2505 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2507 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2508 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2510 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2511 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2513 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2514 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2516 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2517 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2519 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2520 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2523 bool wxWindow::Destroy()
2525 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2529 return wxWindowBase::Destroy();
2532 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2534 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2537 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2539 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2540 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2542 if (m_resizing
) return; /* I don't like recursions */
2545 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2547 /* don't set the size for children of wxNotebook, just take the values. */
2555 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2557 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2559 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2560 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2561 if (width
!= -1) m_width
= width
;
2562 if (height
!= -1) m_height
= height
;
2566 m_x
= x
+ pizza
->xoffset
;
2567 m_y
= y
+ pizza
->yoffset
;
2572 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2574 if (width
== -1) m_width
= 80;
2577 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2579 if (height
== -1) m_height
= 26;
2582 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2583 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2584 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2585 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2588 int bottom_border
= 0;
2590 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2592 /* the default button has a border around it */
2597 DoMoveWindow( m_x
-border
,
2600 m_height
+border
+bottom_border
);
2605 /* Sometimes the client area changes size without the
2606 whole windows's size changing, but if the whole
2607 windows's size doesn't change, no wxSizeEvent will
2608 normally be sent. Here we add an extra test if
2609 the client test has been changed and this will
2611 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2615 wxPrintf( "OnSize sent from " );
2616 if (GetClassInfo() && GetClassInfo()->GetClassName())
2617 wxPrintf( GetClassInfo()->GetClassName() );
2618 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2621 if (!m_nativeSizeEvent
)
2623 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2624 event
.SetEventObject( this );
2625 GetEventHandler()->ProcessEvent( event
);
2631 void wxWindow::OnInternalIdle()
2633 if ( g_sendActivateEvent
!= -1 )
2635 bool activate
= g_sendActivateEvent
!= 0;
2638 g_sendActivateEvent
= -1;
2640 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2641 event
.SetEventObject(this);
2643 (void)GetEventHandler()->ProcessEvent(event
);
2646 wxCursor cursor
= m_cursor
;
2647 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2651 /* I now set the cursor anew in every OnInternalIdle call
2652 as setting the cursor in a parent window also effects the
2653 windows above so that checking for the current cursor is
2658 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2660 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2662 if (!g_globalCursor
.Ok())
2663 cursor
= *wxSTANDARD_CURSOR
;
2665 window
= m_widget
->window
;
2666 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2667 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2673 GdkWindow
*window
= m_widget
->window
;
2674 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2675 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2683 void wxWindow::DoGetSize( int *width
, int *height
) const
2685 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2687 if (width
) (*width
) = m_width
;
2688 if (height
) (*height
) = m_height
;
2691 void wxWindow::DoSetClientSize( int width
, int height
)
2693 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2697 SetSize( width
, height
);
2704 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2706 /* when using GTK 1.2 we set the shadow border size to 2 */
2710 if (HasFlag(wxSIMPLE_BORDER
))
2712 /* when using GTK 1.2 we set the simple border size to 1 */
2719 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2721 GtkRequisition vscroll_req
;
2722 vscroll_req
.width
= 2;
2723 vscroll_req
.height
= 2;
2724 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2725 (scroll_window
->vscrollbar
, &vscroll_req
);
2727 GtkRequisition hscroll_req
;
2728 hscroll_req
.width
= 2;
2729 hscroll_req
.height
= 2;
2730 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2731 (scroll_window
->hscrollbar
, &hscroll_req
);
2733 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2735 if (scroll_window
->vscrollbar_visible
)
2737 dw
+= vscroll_req
.width
;
2738 dw
+= scroll_class
->scrollbar_spacing
;
2741 if (scroll_window
->hscrollbar_visible
)
2743 dh
+= hscroll_req
.height
;
2744 dh
+= scroll_class
->scrollbar_spacing
;
2748 SetSize( width
+dw
, height
+dh
);
2752 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2754 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2758 if (width
) (*width
) = m_width
;
2759 if (height
) (*height
) = m_height
;
2766 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2768 /* when using GTK 1.2 we set the shadow border size to 2 */
2772 if (HasFlag(wxSIMPLE_BORDER
))
2774 /* when using GTK 1.2 we set the simple border size to 1 */
2781 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2783 GtkRequisition vscroll_req
;
2784 vscroll_req
.width
= 2;
2785 vscroll_req
.height
= 2;
2786 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2787 (scroll_window
->vscrollbar
, &vscroll_req
);
2789 GtkRequisition hscroll_req
;
2790 hscroll_req
.width
= 2;
2791 hscroll_req
.height
= 2;
2792 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2793 (scroll_window
->hscrollbar
, &hscroll_req
);
2795 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2797 if (scroll_window
->vscrollbar_visible
)
2799 dw
+= vscroll_req
.width
;
2800 dw
+= scroll_class
->scrollbar_spacing
;
2803 if (scroll_window
->hscrollbar_visible
)
2805 dh
+= hscroll_req
.height
;
2806 dh
+= scroll_class
->scrollbar_spacing
;
2810 if (width
) (*width
) = m_width
- dw
;
2811 if (height
) (*height
) = m_height
- dh
;
2815 void wxWindow::DoGetPosition( int *x
, int *y
) const
2817 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2821 if (m_parent
&& m_parent
->m_wxwindow
)
2823 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2824 dx
= pizza
->xoffset
;
2825 dy
= pizza
->yoffset
;
2828 if (x
) (*x
) = m_x
- dx
;
2829 if (y
) (*y
) = m_y
- dy
;
2832 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2834 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2836 if (!m_widget
->window
) return;
2838 GdkWindow
*source
= (GdkWindow
*) NULL
;
2840 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2842 source
= m_widget
->window
;
2846 gdk_window_get_origin( source
, &org_x
, &org_y
);
2850 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2852 org_x
+= m_widget
->allocation
.x
;
2853 org_y
+= m_widget
->allocation
.y
;
2861 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2863 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2865 if (!m_widget
->window
) return;
2867 GdkWindow
*source
= (GdkWindow
*) NULL
;
2869 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2871 source
= m_widget
->window
;
2875 gdk_window_get_origin( source
, &org_x
, &org_y
);
2879 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2881 org_x
+= m_widget
->allocation
.x
;
2882 org_y
+= m_widget
->allocation
.y
;
2890 bool wxWindow::Show( bool show
)
2892 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2894 if (!wxWindowBase::Show(show
))
2901 gtk_widget_show( m_widget
);
2903 gtk_widget_hide( m_widget
);
2908 bool wxWindow::Enable( bool enable
)
2910 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2912 if (!wxWindowBase::Enable(enable
))
2918 gtk_widget_set_sensitive( m_widget
, enable
);
2920 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2925 int wxWindow::GetCharHeight() const
2927 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2929 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2931 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2933 return font
->ascent
+ font
->descent
;
2936 int wxWindow::GetCharWidth() const
2938 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2940 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2942 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2944 return gdk_string_width( font
, "H" );
2947 void wxWindow::GetTextExtent( const wxString
& string
,
2951 int *externalLeading
,
2952 const wxFont
*theFont
) const
2954 wxFont fontToUse
= m_font
;
2955 if (theFont
) fontToUse
= *theFont
;
2957 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2959 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2960 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2961 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2962 if (descent
) (*descent
) = font
->descent
;
2963 if (externalLeading
) (*externalLeading
) = 0; // ??
2966 void wxWindow::SetFocus()
2968 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2972 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2973 gtk_widget_grab_focus (m_wxwindow
);
2979 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2981 gtk_widget_grab_focus (m_widget
);
2983 else if (GTK_IS_CONTAINER(m_widget
))
2985 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2994 bool wxWindow::AcceptsFocus() const
2996 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2999 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
3001 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3003 wxWindow
*oldParent
= m_parent
,
3004 *newParent
= (wxWindow
*)newParentBase
;
3006 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3008 if ( !wxWindowBase::Reparent(newParent
) )
3011 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3013 /* prevent GTK from deleting the widget arbitrarily */
3014 gtk_widget_ref( m_widget
);
3018 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3021 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3025 /* insert GTK representation */
3026 (*(newParent
->m_insertCallback
))(newParent
, this);
3029 /* reverse: prevent GTK from deleting the widget arbitrarily */
3030 gtk_widget_unref( m_widget
);
3035 void wxWindow::DoAddChild(wxWindow
*child
)
3037 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3039 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3041 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3046 /* insert GTK representation */
3047 (*m_insertCallback
)(this, child
);
3050 void wxWindow::Raise()
3052 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3054 if (!m_widget
->window
) return;
3056 gdk_window_raise( m_widget
->window
);
3059 void wxWindow::Lower()
3061 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3063 if (!m_widget
->window
) return;
3065 gdk_window_lower( m_widget
->window
);
3068 bool wxWindow::SetCursor( const wxCursor
&cursor
)
3070 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3072 if (cursor
== m_cursor
)
3076 wxapp_install_idle_handler();
3078 if (cursor
== wxNullCursor
)
3079 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3081 return wxWindowBase::SetCursor( cursor
);
3084 void wxWindow::WarpPointer( int x
, int y
)
3086 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3088 /* we provide this function ourselves as it is
3089 missing in GDK (top of this file) */
3091 GdkWindow
*window
= (GdkWindow
*) NULL
;
3093 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3095 window
= GetConnectWidget()->window
;
3098 gdk_window_warp_pointer( window
, x
, y
);
3101 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
3103 if (!m_widget
) return;
3104 if (!m_widget
->window
) return;
3106 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3110 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3112 rect
->width
, rect
->height
);
3116 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3120 /* there is no GTK equivalent of "draw only, don't clear" so we
3121 invent our own in the GtkPizza widget */
3129 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3130 gboolean old_clear = pizza->clear_on_draw;
3131 gtk_pizza_set_clear( pizza, FALSE );
3132 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3133 gtk_pizza_set_clear( pizza, old_clear );
3135 GdkEventExpose gdk_event
;
3136 gdk_event
.type
= GDK_EXPOSE
;
3137 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3138 gdk_event
.count
= 0;
3139 gdk_event
.area
.x
= 0;
3140 gdk_event
.area
.y
= 0;
3141 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3142 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3143 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3148 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3157 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3158 gboolean old_clear = pizza->clear_on_draw;
3159 gtk_pizza_set_clear( pizza, FALSE );
3161 GdkRectangle gdk_rect;
3162 gdk_rect.x = rect->x;
3163 gdk_rect.y = rect->y;
3164 gdk_rect.width = rect->width;
3165 gdk_rect.height = rect->height;
3166 gtk_widget_draw( m_wxwindow, &gdk_rect );
3167 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3169 gtk_pizza_set_clear( pizza, old_clear );
3171 GdkEventExpose gdk_event
;
3172 gdk_event
.type
= GDK_EXPOSE
;
3173 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3174 gdk_event
.count
= 0;
3175 gdk_event
.area
.x
= rect
->x
;
3176 gdk_event
.area
.y
= rect
->y
;
3177 gdk_event
.area
.width
= rect
->width
;
3178 gdk_event
.area
.height
= rect
->height
;
3179 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3183 GdkRectangle gdk_rect
;
3184 gdk_rect
.x
= rect
->x
;
3185 gdk_rect
.y
= rect
->y
;
3186 gdk_rect
.width
= rect
->width
;
3187 gdk_rect
.height
= rect
->height
;
3188 gtk_widget_draw( m_widget
, &gdk_rect
);
3193 void wxWindow::Clear()
3195 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3197 if (!m_widget
->window
) return;
3199 if (m_wxwindow
&& m_wxwindow
->window
)
3201 // gdk_window_clear( m_wxwindow->window );
3206 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
3208 wxWindowBase::DoSetToolTip(tip
);
3211 m_tooltip
->Apply( this );
3214 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3216 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3218 #endif // wxUSE_TOOLTIPS
3220 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
3222 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3224 if (!wxWindowBase::SetBackgroundColour(colour
))
3226 // don't leave if the GTK widget has just
3228 if (!m_delayedBackgroundColour
) return FALSE
;
3231 GdkWindow
*window
= (GdkWindow
*) NULL
;
3233 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3235 window
= GetConnectWidget()->window
;
3239 // indicate that a new style has been set
3240 // but it couldn't get applied as the
3241 // widget hasn't been realized yet.
3242 m_delayedBackgroundColour
= TRUE
;
3246 (m_wxwindow
->window
) &&
3247 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3249 /* wxMSW doesn't clear the window here. I don't do that either to
3250 provide compatibility. call Clear() to do the job. */
3252 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3253 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3261 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
3263 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3265 if (!wxWindowBase::SetForegroundColour(colour
))
3267 // don't leave if the GTK widget has just
3269 if (!m_delayedForegroundColour
) return FALSE
;
3272 GdkWindow
*window
= (GdkWindow
*) NULL
;
3274 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3276 window
= GetConnectWidget()->window
;
3280 // indicate that a new style has been set
3281 // but it couldn't get applied as the
3282 // widget hasn't been realized yet.
3283 m_delayedForegroundColour
= TRUE
;
3291 GtkStyle
*wxWindow::GetWidgetStyle()
3295 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3297 /* FIXME: is this necessary? */
3298 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3300 remake
->klass
= m_widgetStyle
->klass
;
3303 gtk_style_unref( m_widgetStyle
);
3304 m_widgetStyle
= remake
;
3308 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3311 def
= gtk_widget_get_default_style();
3313 m_widgetStyle
= gtk_style_copy( def
);
3315 /* FIXME: is this necessary? */
3316 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3318 m_widgetStyle
->klass
= def
->klass
;
3322 return m_widgetStyle
;
3325 void wxWindow::SetWidgetStyle()
3327 #if DISABLE_STYLE_IF_BROKEN_THEM
3328 if (m_widget
->style
->engine_data
)
3330 static bool s_warningPrinted
= FALSE
;
3331 if (!s_warningPrinted
)
3333 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3334 s_warningPrinted
= TRUE
;
3336 m_widgetStyle
= m_widget
->style
;
3341 GtkStyle
*style
= GetWidgetStyle();
3343 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3345 gdk_font_unref( style
->font
);
3346 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3349 if (m_foregroundColour
.Ok())
3351 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3352 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3354 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3355 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3356 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3360 // Try to restore the gtk default style. This is still a little
3361 // oversimplified for what is probably really needed here for controls
3362 // other than buttons, but is better than not being able to (re)set a
3363 // control's foreground colour to *wxBLACK -- RL
3364 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3367 def
= gtk_widget_get_default_style();
3369 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3370 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3371 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3375 if (m_backgroundColour
.Ok())
3377 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3378 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3380 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3381 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3382 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3383 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3384 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3385 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3386 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3387 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3391 // Try to restore the gtk default style. This is still a little
3392 // oversimplified for what is probably really needed here for controls
3393 // other than buttons, but is better than not being able to (re)set a
3394 // control's background colour to default grey and means resetting a
3395 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3397 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3400 def
= gtk_widget_get_default_style();
3402 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3403 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3404 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3405 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3406 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3407 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3408 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3409 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3414 void wxWindow::ApplyWidgetStyle()
3418 //-----------------------------------------------------------------------------
3419 // Pop-up menu stuff
3420 //-----------------------------------------------------------------------------
3422 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3424 *is_waiting
= FALSE
;
3427 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3429 menu
->SetInvokingWindow( win
);
3430 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3433 wxMenuItem
*menuitem
= node
->GetData();
3434 if (menuitem
->IsSubMenu())
3436 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3439 node
= node
->GetNext();
3443 static gint gs_pop_x
= 0;
3444 static gint gs_pop_y
= 0;
3446 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3450 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3455 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3457 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3459 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3461 SetInvokingWindow( menu
, this );
3468 bool is_waiting
= TRUE
;
3470 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3471 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3474 GTK_MENU(menu
->m_menu
),
3475 (GtkWidget
*) NULL
, // parent menu shell
3476 (GtkWidget
*) NULL
, // parent menu item
3477 (GtkMenuPositionFunc
) pop_pos_callback
,
3478 (gpointer
) this, // client data
3479 0, // button used to activate it
3480 gs_timeLastClick
// the time of activation
3485 while (gtk_events_pending())
3486 gtk_main_iteration();
3492 #if wxUSE_DRAG_AND_DROP
3494 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3496 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3498 GtkWidget
*dnd_widget
= GetConnectWidget();
3500 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3502 if (m_dropTarget
) delete m_dropTarget
;
3503 m_dropTarget
= dropTarget
;
3505 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3508 #endif // wxUSE_DRAG_AND_DROP
3510 GtkWidget
* wxWindow::GetConnectWidget()
3512 GtkWidget
*connect_widget
= m_widget
;
3513 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3515 return connect_widget
;
3518 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3521 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3523 return (window
== m_widget
->window
);
3526 bool wxWindow::SetFont( const wxFont
&font
)
3528 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3530 if (!wxWindowBase::SetFont(font
))
3535 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3536 if ( sysbg
== m_backgroundColour
)
3538 m_backgroundColour
= wxNullColour
;
3540 m_backgroundColour
= sysbg
;
3550 void wxWindow::CaptureMouse()
3552 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3554 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3556 GdkWindow
*window
= (GdkWindow
*) NULL
;
3558 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3560 window
= GetConnectWidget()->window
;
3562 if (!window
) return;
3564 wxCursor
* cursor
= & m_cursor
;
3566 cursor
= wxSTANDARD_CURSOR
;
3568 gdk_pointer_grab( window
, FALSE
,
3570 (GDK_BUTTON_PRESS_MASK
|
3571 GDK_BUTTON_RELEASE_MASK
|
3572 GDK_POINTER_MOTION_HINT_MASK
|
3573 GDK_POINTER_MOTION_MASK
),
3575 cursor
->GetCursor(),
3576 (guint32
)GDK_CURRENT_TIME
);
3577 g_captureWindow
= this;
3580 void wxWindow::ReleaseMouse()
3582 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3584 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3586 GdkWindow
*window
= (GdkWindow
*) NULL
;
3588 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3590 window
= GetConnectWidget()->window
;
3595 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3596 g_captureWindow
= (wxWindow
*) NULL
;
3599 bool wxWindow::IsRetained() const
3604 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3605 int range
, bool refresh
)
3607 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3609 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3611 m_hasScrolling
= TRUE
;
3613 if (orient
== wxHORIZONTAL
)
3615 float fpos
= (float)pos
;
3616 float frange
= (float)range
;
3617 float fthumb
= (float)thumbVisible
;
3618 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3619 if (fpos
< 0.0) fpos
= 0.0;
3621 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3622 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3624 SetScrollPos( orient
, pos
, refresh
);
3628 m_oldHorizontalPos
= fpos
;
3630 m_hAdjust
->lower
= 0.0;
3631 m_hAdjust
->upper
= frange
;
3632 m_hAdjust
->value
= fpos
;
3633 m_hAdjust
->step_increment
= 1.0;
3634 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3635 m_hAdjust
->page_size
= fthumb
;
3639 float fpos
= (float)pos
;
3640 float frange
= (float)range
;
3641 float fthumb
= (float)thumbVisible
;
3642 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3643 if (fpos
< 0.0) fpos
= 0.0;
3645 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3646 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3648 SetScrollPos( orient
, pos
, refresh
);
3652 m_oldVerticalPos
= fpos
;
3654 m_vAdjust
->lower
= 0.0;
3655 m_vAdjust
->upper
= frange
;
3656 m_vAdjust
->value
= fpos
;
3657 m_vAdjust
->step_increment
= 1.0;
3658 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3659 m_vAdjust
->page_size
= fthumb
;
3662 if (orient
== wxHORIZONTAL
)
3663 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3665 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3668 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3670 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3672 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3674 if (orient
== wxHORIZONTAL
)
3676 float fpos
= (float)pos
;
3677 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3678 if (fpos
< 0.0) fpos
= 0.0;
3679 m_oldHorizontalPos
= fpos
;
3681 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3682 m_hAdjust
->value
= fpos
;
3686 float fpos
= (float)pos
;
3687 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3688 if (fpos
< 0.0) fpos
= 0.0;
3689 m_oldVerticalPos
= fpos
;
3691 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3692 m_vAdjust
->value
= fpos
;
3695 if (m_wxwindow
->window
)
3697 if (orient
== wxHORIZONTAL
)
3699 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3700 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3702 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3704 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3705 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3709 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3710 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3712 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3714 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3715 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3720 int wxWindow::GetScrollThumb( int orient
) const
3722 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3724 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3726 if (orient
== wxHORIZONTAL
)
3727 return (int)(m_hAdjust
->page_size
+0.5);
3729 return (int)(m_vAdjust
->page_size
+0.5);
3732 int wxWindow::GetScrollPos( int orient
) const
3734 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3736 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3738 if (orient
== wxHORIZONTAL
)
3739 return (int)(m_hAdjust
->value
+0.5);
3741 return (int)(m_vAdjust
->value
+0.5);
3744 int wxWindow::GetScrollRange( int orient
) const
3746 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3748 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3750 if (orient
== wxHORIZONTAL
)
3751 return (int)(m_hAdjust
->upper
+0.5);
3753 return (int)(m_vAdjust
->upper
+0.5);
3756 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3758 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3760 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3762 if ((dx
== 0) && (dy
== 0)) return;
3764 m_clipPaintRegion
= TRUE
;
3765 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3766 m_clipPaintRegion
= FALSE
;
3769 if (m_children.GetCount() > 0)
3771 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3775 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3777 pizza->xoffset -= dx;
3778 pizza->yoffset -= dy;
3780 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3781 gdk_gc_set_exposures( m_scrollGC, TRUE );
3785 GetClientSize( &cw, &ch );
3786 int w = cw - abs(dx);
3787 int h = ch - abs(dy);
3789 if ((h < 0) || (w < 0))
3797 if (dx < 0) s_x = -dx;
3798 if (dy < 0) s_y = -dy;
3801 if (dx > 0) d_x = dx;
3802 if (dy > 0) d_y = dy;
3804 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3805 pizza->bin_window, s_x, s_y, w, h );
3808 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3809 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3810 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3811 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3813 Refresh( TRUE, &rect );
3816 gdk_gc_unref( m_scrollGC );
3821 // Find the wxWindow at the current mouse position, also returning the mouse
3823 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
3825 pt
= wxGetMousePosition();
3826 wxWindow
* found
= wxFindWindowAtPoint(pt
);
3830 // Get the current mouse position.
3831 wxPoint
wxGetMousePosition()
3833 /* This crashes when used within wxHelpContext,
3834 so we have to use the X-specific implementation below.
3836 GdkModifierType *mask;
3837 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
3839 return wxPoint(x, y);
3843 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
3845 return wxPoint(-999, -999);
3847 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
3848 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
3849 Window rootReturn
, childReturn
;
3850 int rootX
, rootY
, winX
, winY
;
3851 unsigned int maskReturn
;
3853 XQueryPointer (display
,
3857 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
3858 return wxPoint(rootX
, rootY
);