1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #include "wx/window.h"
20 #include "wx/layout.h"
22 #include "wx/dialog.h"
23 #include "wx/msgdlg.h"
25 #if wxUSE_DRAG_AND_DROP
30 #include "wx/tooltip.h"
34 #include "wx/statusbr.h"
36 #include "wx/settings.h"
40 #include "wx/thread.h"
47 #include <gdk/gdkprivate.h>
48 #include <gdk/gdkkeysyms.h>
49 #include <wx/gtk/win_gtk.h>
53 //-----------------------------------------------------------------------------
54 // documentation on internals
55 //-----------------------------------------------------------------------------
58 I have been asked several times about writing some documentation about
59 the GTK port of wxWindows, especially its internal structures. Obviously,
60 you cannot understand wxGTK without knowing a little about the GTK, but
61 some more information about what the wxWindow, which is the base class
62 for all other window classes, does seems required as well.
66 What does wxWindow do? It contains the common interface for the following
67 jobs of its descendants:
69 1) Define the rudimentary behaviour common to all window classes, such as
70 resizing, intercepting user input (so as to make it possible to use these
71 events for special purposes in a derived class), window names etc.
73 2) Provide the possibility to contain and manage children, if the derived
74 class is allowed to contain children, which holds true for those window
75 classes which do not display a native GTK widget. To name them, these
76 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
77 work classes are a special case and are handled a bit differently from
78 the rest. The same holds true for the wxNotebook class.
80 3) Provide the possibility to draw into a client area of a window. This,
81 too, only holds true for classes that do not display a native GTK widget
84 4) Provide the entire mechanism for scrolling widgets. This actual inter-
85 face for this is usually in wxScrolledWindow, but the GTK implementation
88 5) A multitude of helper or extra methods for special purposes, such as
89 Drag'n'Drop, managing validators etc.
91 6) Display a border (sunken, raised, simple or none).
93 Normally one might expect, that one wxWindows window would always correspond
94 to one GTK widget. Under GTK, there is no such allround widget that has all
95 the functionality. Moreover, the GTK defines a client area as a different
96 widget from the actual widget you are handling. Last but not least some
97 special classes (e.g. wxFrame) handle different categories of widgets and
98 still have the possibility to draw something in the client area.
99 It was therefore required to write a special purpose GTK widget, that would
100 represent a client area in the sense of wxWindows capable to do the jobs
101 2), 3) and 4). I have written this class and it resides in win_gtk.c of
104 All windows must have a widget, with which they interact with other under-
105 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
106 thw wxWindow class has a member variable called m_widget which holds a
107 pointer to this widget. When the window class represents a GTK native widget,
108 this is (in most cases) the only GTK widget the class manages. E.g. the
109 wxStatitText class handles only a GtkLabel widget a pointer to which you
110 can find in m_widget (defined in wxWindow)
112 When the class has a client area for drawing into and for containing children
113 it has to handle the client area widget (of the type GtkPizza, defined in
114 win_gtk.c), but there could be any number of widgets, handled by a class
115 The common rule for all windows is only, that the widget that interacts with
116 the rest of GTK must be referenced in m_widget and all other widgets must be
117 children of this widget on the GTK level. The top-most widget, which also
118 represents the client area, must be in the m_wxwindow field and must be of
121 As I said, the window classes that display a GTK native widget only have
122 one widget, so in the case of e.g. the wxButton class m_widget holds a
123 pointer to a GtkButton widget. But windows with client areas (for drawing
124 and children) have a m_widget field that is a pointer to a GtkScrolled-
125 Window and a m_wxwindow field that is pointer to a GtkPizza and this
126 one is (in the GTK sense) a child of the GtkScrolledWindow.
128 If the m_wxwindow field is set, then all input to this widget is inter-
129 cepted and sent to the wxWindows class. If not, all input to the widget
130 that gets pointed to by m_widget gets intercepted and sent to the class.
134 The design of scrolling in wxWindows is markedly different from that offered
135 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
136 clicking on a scrollbar belonging to scrolled window will inevitably move
137 the window. In wxWindows, the scrollbar will only emit an event, send this
138 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
139 which actually moves the window and its subchildren. Note that GtkPizza
140 memorizes how much it has been scrolled but that wxWindows forgets this
141 so that the two coordinates systems have to be kept in synch. This is done
142 in various places using the pizza->xoffset and pizza->yoffset values.
146 Singularily the most broken code in GTK is the code that is supposes to
147 inform subwindows (child windows) about new positions. Very often, duplicate
148 events are sent without changes in size or position, equally often no
149 events are sent at all (All this is due to a bug in the GtkContainer code
150 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
151 GTK's own system and it simply waits for size events for toplevel windows
152 and then iterates down the respective size events to all window. This has
153 the disadvantage, that windows might get size events before the GTK widget
154 actually has the reported size. This doesn't normally pose any problem, but
155 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
156 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
157 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
158 window that is used for OpenGl output really has that size (as reported by
163 If someone at some point of time feels the immense desire to have a look at,
164 change or attempt to optimse the Refresh() logic, this person will need an
165 intimate understanding of what a "draw" and what an "expose" events are and
166 what there are used for, in particular when used in connection with GTK's
167 own windowless widgets. Beware.
171 Cursors, too, have been a constant source of pleasure. The main difficulty
172 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
173 for the parent. To prevent this from doing too much harm, I use idle time
174 to set the cursor over and over again, starting from the toplevel windows
175 and ending with the youngest generation (speaking of parent and child windows).
176 Also don't forget that cursors (like much else) are connected to GdkWindows,
177 not GtkWidgets and that the "window" field of a GtkWidget might very well
178 point to the GdkWindow of the parent widget (-> "window less widget") and
179 that the two obviously have very different meanings.
183 //-----------------------------------------------------------------------------
185 //-----------------------------------------------------------------------------
187 extern wxList wxPendingDelete
;
188 extern bool g_blockEventsOnDrag
;
189 extern bool g_blockEventsOnScroll
;
190 extern wxCursor g_globalCursor
;
191 static wxWindow
*g_captureWindow
= (wxWindow
*) NULL
;
193 /* extern */ wxWindow
*g_focusWindow
= (wxWindow
*) NULL
;
195 // if we detect that the app has got/lost the focus, we set this variable to
196 // either TRUE or FALSE and an activate event will be sent during the next
197 // OnIdle() call and it is reset to -1: this value means that we shouldn't
198 // send any activate events at all
199 static int g_sendActivateEvent
= -1;
201 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
202 the last click here */
203 static guint32 gs_timeLastClick
= 0;
205 extern bool g_mainThreadLocked
;
207 //-----------------------------------------------------------------------------
209 //-----------------------------------------------------------------------------
211 #define DISABLE_STYLE_IF_BROKEN_THEME 1
216 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
218 # define DEBUG_MAIN_THREAD
221 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
222 GdkEvent
*WXUNUSED(event
),
223 const wxChar
*WXUNUSED(name
) )
226 static bool s_done = FALSE;
229 wxLog::AddTraceMask("focus");
232 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
238 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
240 // suppress warnings about gtk_debug_focus_in_callback being unused with
245 tmp
+= wxT(" FROM ");
248 wxChar
*s
= new wxChar
[tmp
.Length()+1];
252 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
253 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
258 #define DEBUG_MAIN_THREAD
261 //-----------------------------------------------------------------------------
262 // missing gdk functions
263 //-----------------------------------------------------------------------------
266 gdk_window_warp_pointer (GdkWindow
*window
,
270 GdkWindowPrivate
*priv
;
273 window
= (GdkWindow
*) &gdk_root_parent
;
275 priv
= (GdkWindowPrivate
*) window
;
277 if (!priv
->destroyed
)
279 XWarpPointer (priv
->xdisplay
,
280 None
, /* not source window -> move from anywhere */
281 priv
->xwindow
, /* dest window */
282 0, 0, 0, 0, /* not source window -> move from anywhere */
287 //-----------------------------------------------------------------------------
289 //-----------------------------------------------------------------------------
291 extern void wxapp_install_idle_handler();
292 extern bool g_isIdle
;
294 //-----------------------------------------------------------------------------
295 // local code (see below)
296 //-----------------------------------------------------------------------------
298 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
306 if (win
->m_hasScrolling
)
308 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
310 GtkRequisition vscroll_req
;
311 vscroll_req
.width
= 2;
312 vscroll_req
.height
= 2;
313 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
314 (scroll_window
->vscrollbar
, &vscroll_req
);
316 GtkRequisition hscroll_req
;
317 hscroll_req
.width
= 2;
318 hscroll_req
.height
= 2;
319 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
320 (scroll_window
->hscrollbar
, &hscroll_req
);
322 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget
)->klass
);
324 if (scroll_window
->vscrollbar_visible
)
326 dw
+= vscroll_req
.width
;
327 dw
+= scroll_class
->scrollbar_spacing
;
330 if (scroll_window
->hscrollbar_visible
)
332 dh
+= hscroll_req
.height
;
333 dh
+= scroll_class
->scrollbar_spacing
;
339 if (GTK_WIDGET_NO_WINDOW (widget
))
341 dx
+= widget
->allocation
.x
;
342 dy
+= widget
->allocation
.y
;
345 if (win
->HasFlag(wxRAISED_BORDER
))
347 gtk_draw_shadow( widget
->style
,
352 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
356 if (win
->HasFlag(wxSUNKEN_BORDER
))
358 gtk_draw_shadow( widget
->style
,
363 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
367 if (win
->HasFlag(wxSIMPLE_BORDER
))
370 gc
= gdk_gc_new( widget
->window
);
371 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
372 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
374 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
380 //-----------------------------------------------------------------------------
381 // "expose_event" of m_widget
382 //-----------------------------------------------------------------------------
384 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
386 if (gdk_event
->count
> 0) return FALSE
;
388 draw_frame( widget
, win
);
393 //-----------------------------------------------------------------------------
394 // "draw" of m_widget
395 //-----------------------------------------------------------------------------
397 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
399 draw_frame( widget
, win
);
402 //-----------------------------------------------------------------------------
403 // key code mapping routines
404 //-----------------------------------------------------------------------------
406 static long map_to_unmodified_wx_keysym( KeySym keysym
)
413 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
415 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
421 case GDK_Super_R
: key_code
= WXK_ALT
; break;
422 case GDK_Menu
: key_code
= WXK_MENU
; break;
423 case GDK_Help
: key_code
= WXK_HELP
; break;
424 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
425 case GDK_ISO_Left_Tab
:
426 case GDK_Tab
: key_code
= WXK_TAB
; break;
427 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
428 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
429 case GDK_Return
: key_code
= WXK_RETURN
; break;
430 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
431 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
432 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
433 case GDK_Delete
: key_code
= WXK_DELETE
; break;
434 case GDK_Home
: key_code
= WXK_HOME
; break;
435 case GDK_Left
: key_code
= WXK_LEFT
; break;
436 case GDK_Up
: key_code
= WXK_UP
; break;
437 case GDK_Right
: key_code
= WXK_RIGHT
; break;
438 case GDK_Down
: key_code
= WXK_DOWN
; break;
439 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
440 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
441 case GDK_Next
: key_code
= WXK_NEXT
; break;
442 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
443 case GDK_End
: key_code
= WXK_END
; break;
444 case GDK_Begin
: key_code
= WXK_HOME
; break;
445 case GDK_Select
: key_code
= WXK_SELECT
; break;
446 case GDK_Print
: key_code
= WXK_PRINT
; break;
447 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
448 case GDK_Insert
: key_code
= WXK_INSERT
; break;
449 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
451 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
452 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
453 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
454 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
455 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
456 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
457 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
458 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
459 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
460 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
461 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
462 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
463 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
464 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
465 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
466 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
467 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
468 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
469 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
470 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
471 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
472 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
473 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
474 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
475 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
476 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
477 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
478 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
479 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
480 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
481 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
482 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
483 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
484 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
485 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
486 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
487 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
489 case GDK_F1
: key_code
= WXK_F1
; break;
490 case GDK_F2
: key_code
= WXK_F2
; break;
491 case GDK_F3
: key_code
= WXK_F3
; break;
492 case GDK_F4
: key_code
= WXK_F4
; break;
493 case GDK_F5
: key_code
= WXK_F5
; break;
494 case GDK_F6
: key_code
= WXK_F6
; break;
495 case GDK_F7
: key_code
= WXK_F7
; break;
496 case GDK_F8
: key_code
= WXK_F8
; break;
497 case GDK_F9
: key_code
= WXK_F9
; break;
498 case GDK_F10
: key_code
= WXK_F10
; break;
499 case GDK_F11
: key_code
= WXK_F11
; break;
500 case GDK_F12
: key_code
= WXK_F12
; break;
505 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
506 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
507 key_code
= (guint
)keysym
;
515 static long map_to_wx_keysym( KeySym keysym
)
521 case GDK_Menu
: key_code
= WXK_MENU
; break;
522 case GDK_Help
: key_code
= WXK_HELP
; break;
523 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
524 case GDK_ISO_Left_Tab
:
525 case GDK_Tab
: key_code
= WXK_TAB
; break;
526 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
527 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
528 case GDK_Return
: key_code
= WXK_RETURN
; break;
529 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
530 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
531 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
532 case GDK_Delete
: key_code
= WXK_DELETE
; break;
533 case GDK_Home
: key_code
= WXK_HOME
; break;
534 case GDK_Left
: key_code
= WXK_LEFT
; break;
535 case GDK_Up
: key_code
= WXK_UP
; break;
536 case GDK_Right
: key_code
= WXK_RIGHT
; break;
537 case GDK_Down
: key_code
= WXK_DOWN
; break;
538 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
539 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
540 case GDK_Next
: key_code
= WXK_NEXT
; break;
541 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
542 case GDK_End
: key_code
= WXK_END
; break;
543 case GDK_Begin
: key_code
= WXK_HOME
; break;
544 case GDK_Select
: key_code
= WXK_SELECT
; break;
545 case GDK_Print
: key_code
= WXK_PRINT
; break;
546 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
547 case GDK_Insert
: key_code
= WXK_INSERT
; break;
548 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
550 case GDK_KP_0
: key_code
= '0'; break;
551 case GDK_KP_1
: key_code
= '1'; break;
552 case GDK_KP_2
: key_code
= '2'; break;
553 case GDK_KP_3
: key_code
= '3'; break;
554 case GDK_KP_4
: key_code
= '4'; break;
555 case GDK_KP_5
: key_code
= '5'; break;
556 case GDK_KP_6
: key_code
= '6'; break;
557 case GDK_KP_7
: key_code
= '7'; break;
558 case GDK_KP_8
: key_code
= '8'; break;
559 case GDK_KP_9
: key_code
= '9'; break;
560 case GDK_KP_Space
: key_code
= ' '; break;
561 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
562 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
563 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
564 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
565 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
566 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
567 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
568 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
569 case GDK_KP_Up
: key_code
= WXK_UP
; break;
570 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
571 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
572 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
573 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
574 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
575 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
576 case GDK_KP_End
: key_code
= WXK_END
; break;
577 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
578 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
579 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
580 case GDK_KP_Equal
: key_code
= '='; break;
581 case GDK_KP_Multiply
: key_code
= '*'; break;
582 case GDK_KP_Add
: key_code
= '+'; break;
583 case GDK_KP_Separator
: key_code
= ','; break;
584 case GDK_KP_Subtract
: key_code
= '-'; break;
585 case GDK_KP_Decimal
: key_code
= '.'; break;
586 case GDK_KP_Divide
: key_code
= '/'; break;
588 case GDK_F1
: key_code
= WXK_F1
; break;
589 case GDK_F2
: key_code
= WXK_F2
; break;
590 case GDK_F3
: key_code
= WXK_F3
; break;
591 case GDK_F4
: key_code
= WXK_F4
; break;
592 case GDK_F5
: key_code
= WXK_F5
; break;
593 case GDK_F6
: key_code
= WXK_F6
; break;
594 case GDK_F7
: key_code
= WXK_F7
; break;
595 case GDK_F8
: key_code
= WXK_F8
; break;
596 case GDK_F9
: key_code
= WXK_F9
; break;
597 case GDK_F10
: key_code
= WXK_F10
; break;
598 case GDK_F11
: key_code
= WXK_F11
; break;
599 case GDK_F12
: key_code
= WXK_F12
; break;
604 key_code
= (guint
)keysym
;
612 //-----------------------------------------------------------------------------
613 // "expose_event" of m_wxwindow
614 //-----------------------------------------------------------------------------
616 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
621 wxapp_install_idle_handler();
624 if (win->GetName() == wxT("htmlWindow"))
626 wxPrintf( wxT("OnExpose from ") );
627 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
628 wxPrintf( win->GetClassInfo()->GetClassName() );
629 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
630 (int)gdk_event->area.y,
631 (int)gdk_event->area.width,
632 (int)gdk_event->area.height );
636 if (!win
->m_queuedFullRedraw
)
639 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
641 gdk_event
->area
.width
,
642 gdk_event
->area
.height
);
644 if (gdk_event
->count
== 0)
646 wxEraseEvent
eevent( win
->GetId() );
647 eevent
.SetEventObject( win
);
648 win
->GetEventHandler()->ProcessEvent(eevent
);
650 wxPaintEvent
event( win
->GetId() );
651 event
.SetEventObject( win
);
652 win
->GetEventHandler()->ProcessEvent( event
);
654 win
->GetUpdateRegion().Clear();
657 /* The following code will result in all window-less widgets
658 being redrawn if the wxWindows class is given a chance to
659 paint *anything* because it will then be allowed to paint
660 over the window-less widgets */
662 GtkPizza
*pizza
= GTK_PIZZA (widget
);
664 GList
*children
= pizza
->children
;
667 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
668 children
= children
->next
;
670 GdkEventExpose child_event
= *gdk_event
;
672 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
673 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
674 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
676 child_event
.area
.x
= child
->widget
->allocation
.x
;
677 child_event
.area
.y
= child
->widget
->allocation
.y
;
678 child_event
.area
.width
= child
->widget
->allocation
.width
;
679 child_event
.area
.height
= child
->widget
->allocation
.height
;
680 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
688 //-----------------------------------------------------------------------------
689 // "event" of m_wxwindow
690 //-----------------------------------------------------------------------------
692 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
693 expose events. We need them, of course, so we override the main event
694 procedure in GtkWidget by giving our own handler for all system events.
695 There, we look for expose events ourselves whereas all other events are
698 gint
gtk_window_event_event_callback( GtkWidget
*widget
, GdkEventExpose
*event
, wxWindow
*win
)
700 if (event
->type
== GDK_EXPOSE
)
702 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
709 //-----------------------------------------------------------------------------
710 // "draw" of m_wxwindow
711 //-----------------------------------------------------------------------------
713 /* This callback is a complete replacement of the gtk_pizza_draw() function,
716 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
721 wxapp_install_idle_handler();
724 if (win->GetName() == wxT("htmlWindow"))
726 wxPrintf( wxT("OnDraw from ") );
727 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
728 wxPrintf( win->GetClassInfo()->GetClassName() );
729 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
736 GtkPizza
*pizza
= GTK_PIZZA (widget
);
738 if (!win
->m_queuedFullRedraw
)
740 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
741 (pizza
->clear_on_draw
))
743 gdk_window_clear_area( pizza
->bin_window
,
744 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
747 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
749 win
->m_clipPaintRegion
= TRUE
;
751 wxEraseEvent
eevent( win
->GetId() );
752 eevent
.SetEventObject( win
);
753 win
->GetEventHandler()->ProcessEvent(eevent
);
755 wxPaintEvent
event( win
->GetId() );
756 event
.SetEventObject( win
);
757 win
->GetEventHandler()->ProcessEvent( event
);
759 win
->GetUpdateRegion().Clear();
761 win
->m_clipPaintRegion
= FALSE
;
764 GList
*children
= pizza
->children
;
767 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
768 children
= children
->next
;
770 GdkRectangle child_area
;
771 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
773 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
779 //-----------------------------------------------------------------------------
780 // "key_press_event" from any window
781 //-----------------------------------------------------------------------------
783 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
788 wxapp_install_idle_handler();
790 if (!win
->m_hasVMT
) return FALSE
;
791 if (g_blockEventsOnDrag
) return FALSE
;
795 tmp += (char)gdk_event->keyval;
796 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
797 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
802 GdkModifierType state
;
803 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
807 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
808 /* sending unknown key events doesn't really make sense */
809 if (key_code
== 0) return FALSE
;
811 wxKeyEvent
event( wxEVT_KEY_DOWN
);
812 event
.SetTimestamp( gdk_event
->time
);
813 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
814 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
815 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
816 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
817 event
.m_keyCode
= key_code
;
818 event
.m_scanCode
= gdk_event
->keyval
;
821 event
.SetEventObject( win
);
822 ret
= win
->GetEventHandler()->ProcessEvent( event
);
827 wxWindow
*ancestor
= win
;
830 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
833 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
834 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
837 if (ancestor
->m_isFrame
)
839 ancestor
= ancestor
->GetParent();
842 #endif // wxUSE_ACCEL
844 /* wxMSW doesn't send char events with Alt pressed */
845 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
846 will only be sent if it is not in an accelerator table. */
847 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
852 wxKeyEvent
event2( wxEVT_CHAR
);
853 event2
.SetTimestamp( gdk_event
->time
);
854 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
855 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
856 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
857 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
858 event2
.m_keyCode
= key_code
;
859 event2
.m_scanCode
= gdk_event
->keyval
;
862 event2
.SetEventObject( win
);
863 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
866 /* win is a control: tab can be propagated up */
868 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
869 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
870 (win
->GetParent()) &&
871 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
873 wxNavigationKeyEvent new_event
;
874 new_event
.SetEventObject( win
->GetParent() );
875 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
876 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
877 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
878 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
879 new_event
.SetCurrentFocus( win
);
880 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
883 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
885 (gdk_event
->keyval
== GDK_Escape
) )
887 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
888 new_event
.SetEventObject( win
);
889 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
892 #if (GTK_MINOR_VERSION > 0)
893 /* Pressing F10 will activate the menu bar of the top frame. */
897 (gdk_event->keyval == GDK_F10) )
899 wxWindow *ancestor = win;
902 if (wxIsKindOf(ancestor,wxFrame))
904 wxFrame *frame = (wxFrame*) ancestor;
905 wxMenuBar *menubar = frame->GetMenuBar();
908 wxNode *node = menubar->GetMenus().First();
911 wxMenu *firstMenu = (wxMenu*) node->Data();
912 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
918 ancestor = ancestor->GetParent();
926 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
933 //-----------------------------------------------------------------------------
934 // "key_release_event" from any window
935 //-----------------------------------------------------------------------------
937 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
942 wxapp_install_idle_handler();
944 if (!win
->m_hasVMT
) return FALSE
;
945 if (g_blockEventsOnDrag
) return FALSE
;
948 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
949 if (gdk_event->state & GDK_SHIFT_MASK)
950 printf( "ShiftDown.\n" );
952 printf( "ShiftUp.\n" );
953 if (gdk_event->state & GDK_CONTROL_MASK)
954 printf( "ControlDown.\n" );
956 printf( "ControlUp.\n" );
960 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
962 /* sending unknown key events doesn't really make sense */
963 if (key_code
== 0) return FALSE
;
967 GdkModifierType state
;
968 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
970 wxKeyEvent
event( wxEVT_KEY_UP
);
971 event
.SetTimestamp( gdk_event
->time
);
972 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
973 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
974 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
975 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
976 event
.m_keyCode
= key_code
;
977 event
.m_scanCode
= gdk_event
->keyval
;
980 event
.SetEventObject( win
);
982 if (win
->GetEventHandler()->ProcessEvent( event
))
984 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
991 // ----------------------------------------------------------------------------
992 // mouse event processing helper
993 // ----------------------------------------------------------------------------
995 static void AdjustEventButtonState(wxMouseEvent
& event
)
997 // GDK reports the old state of the button for a button press event, but
998 // for compatibility with MSW and common sense we want m_leftDown be TRUE
999 // for a LEFT_DOWN event, not FALSE, so we will invert
1000 // left/right/middleDown for the corresponding click events
1001 switch ( event
.GetEventType() )
1003 case wxEVT_LEFT_DOWN
:
1004 case wxEVT_LEFT_DCLICK
:
1006 event
.m_leftDown
= !event
.m_leftDown
;
1009 case wxEVT_MIDDLE_DOWN
:
1010 case wxEVT_MIDDLE_DCLICK
:
1011 case wxEVT_MIDDLE_UP
:
1012 event
.m_middleDown
= !event
.m_middleDown
;
1015 case wxEVT_RIGHT_DOWN
:
1016 case wxEVT_RIGHT_DCLICK
:
1017 case wxEVT_RIGHT_UP
:
1018 event
.m_rightDown
= !event
.m_rightDown
;
1023 //-----------------------------------------------------------------------------
1024 // "button_press_event"
1025 //-----------------------------------------------------------------------------
1027 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1032 wxapp_install_idle_handler();
1035 wxPrintf( wxT("1) OnButtonPress from ") );
1036 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1037 wxPrintf( win->GetClassInfo()->GetClassName() );
1038 wxPrintf( wxT(".\n") );
1040 if (!win
->m_hasVMT
) return FALSE
;
1041 if (g_blockEventsOnDrag
) return TRUE
;
1042 if (g_blockEventsOnScroll
) return TRUE
;
1044 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1046 if (win
->m_wxwindow
)
1048 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1050 gtk_widget_grab_focus (win
->m_wxwindow
);
1053 wxPrintf( wxT("GrabFocus from ") );
1054 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1055 wxPrintf( win->GetClassInfo()->GetClassName() );
1056 wxPrintf( wxT(".\n") );
1062 wxEventType event_type
= wxEVT_NULL
;
1064 if (gdk_event
->button
== 1)
1066 switch (gdk_event
->type
)
1068 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1069 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1073 else if (gdk_event
->button
== 2)
1075 switch (gdk_event
->type
)
1077 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1078 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1082 else if (gdk_event
->button
== 3)
1084 switch (gdk_event
->type
)
1086 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1087 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1092 if ( event_type
== wxEVT_NULL
)
1094 // unknown mouse button or click type
1098 wxMouseEvent
event( event_type
);
1099 event
.SetTimestamp( gdk_event
->time
);
1100 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1101 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1102 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1103 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1104 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1105 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1106 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1108 event
.m_x
= (wxCoord
)gdk_event
->x
;
1109 event
.m_y
= (wxCoord
)gdk_event
->y
;
1111 AdjustEventButtonState(event
);
1113 // Some control don't have their own X window and thus cannot get
1116 if (!g_captureWindow
)
1118 wxCoord x
= event
.m_x
;
1119 wxCoord y
= event
.m_y
;
1120 if (win
->m_wxwindow
)
1122 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1123 x
+= pizza
->xoffset
;
1124 y
+= pizza
->yoffset
;
1127 wxNode
*node
= win
->GetChildren().First();
1130 wxWindow
*child
= (wxWindow
*)node
->Data();
1132 node
= node
->Next();
1133 if (!child
->IsShown())
1136 if (child
->m_isStaticBox
)
1138 // wxStaticBox is transparent in the box itself
1139 int xx1
= child
->m_x
;
1140 int yy1
= child
->m_y
;
1141 int xx2
= child
->m_x
+ child
->m_width
;
1142 int yy2
= child
->m_x
+ child
->m_height
;
1145 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1147 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1149 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1151 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1154 event
.m_x
-= child
->m_x
;
1155 event
.m_y
-= child
->m_y
;
1162 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1163 (child
->m_x
<= x
) &&
1164 (child
->m_y
<= y
) &&
1165 (child
->m_x
+child
->m_width
>= x
) &&
1166 (child
->m_y
+child
->m_height
>= y
))
1169 event
.m_x
-= child
->m_x
;
1170 event
.m_y
-= child
->m_y
;
1177 event
.SetEventObject( win
);
1179 gs_timeLastClick
= gdk_event
->time
;
1182 wxPrintf( wxT("2) OnButtonPress from ") );
1183 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1184 wxPrintf( win->GetClassInfo()->GetClassName() );
1185 wxPrintf( wxT(".\n") );
1188 if (win
->GetEventHandler()->ProcessEvent( event
))
1190 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1197 //-----------------------------------------------------------------------------
1198 // "button_release_event"
1199 //-----------------------------------------------------------------------------
1201 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1206 wxapp_install_idle_handler();
1208 if (!win
->m_hasVMT
) return FALSE
;
1209 if (g_blockEventsOnDrag
) return FALSE
;
1210 if (g_blockEventsOnScroll
) return FALSE
;
1212 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1215 printf( "OnButtonRelease from " );
1216 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1217 printf( win->GetClassInfo()->GetClassName() );
1221 wxEventType event_type
= wxEVT_NULL
;
1223 switch (gdk_event
->button
)
1225 case 1: event_type
= wxEVT_LEFT_UP
; break;
1226 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1227 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1228 default: return FALSE
;
1231 wxMouseEvent
event( event_type
);
1232 event
.SetTimestamp( gdk_event
->time
);
1233 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1234 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1235 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1236 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1237 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1238 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1239 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1240 event
.m_x
= (wxCoord
)gdk_event
->x
;
1241 event
.m_y
= (wxCoord
)gdk_event
->y
;
1243 AdjustEventButtonState(event
);
1245 // Some control don't have their own X window and thus cannot get
1248 if (!g_captureWindow
)
1250 wxCoord x
= event
.m_x
;
1251 wxCoord y
= event
.m_y
;
1252 if (win
->m_wxwindow
)
1254 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1255 x
+= pizza
->xoffset
;
1256 y
+= pizza
->yoffset
;
1259 wxNode
*node
= win
->GetChildren().First();
1262 wxWindow
*child
= (wxWindow
*)node
->Data();
1264 node
= node
->Next();
1265 if (!child
->IsShown())
1268 if (child
->m_isStaticBox
)
1270 // wxStaticBox is transparent in the box itself
1271 int xx1
= child
->m_x
;
1272 int yy1
= child
->m_y
;
1273 int xx2
= child
->m_x
+ child
->m_width
;
1274 int yy2
= child
->m_x
+ child
->m_height
;
1277 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1279 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1281 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1283 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1286 event
.m_x
-= child
->m_x
;
1287 event
.m_y
-= child
->m_y
;
1294 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1295 (child
->m_x
<= x
) &&
1296 (child
->m_y
<= y
) &&
1297 (child
->m_x
+child
->m_width
>= x
) &&
1298 (child
->m_y
+child
->m_height
>= y
))
1301 event
.m_x
-= child
->m_x
;
1302 event
.m_y
-= child
->m_y
;
1309 event
.SetEventObject( win
);
1311 if (win
->GetEventHandler()->ProcessEvent( event
))
1313 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1320 //-----------------------------------------------------------------------------
1321 // "motion_notify_event"
1322 //-----------------------------------------------------------------------------
1324 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1329 wxapp_install_idle_handler();
1331 if (!win
->m_hasVMT
) return FALSE
;
1332 if (g_blockEventsOnDrag
) return FALSE
;
1333 if (g_blockEventsOnScroll
) return FALSE
;
1335 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1337 if (gdk_event
->is_hint
)
1341 GdkModifierType state
;
1342 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1348 printf( "OnMotion from " );
1349 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1350 printf( win->GetClassInfo()->GetClassName() );
1354 wxMouseEvent
event( wxEVT_MOTION
);
1355 event
.SetTimestamp( gdk_event
->time
);
1356 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1357 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1358 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1359 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1360 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1361 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1362 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1364 event
.m_x
= (wxCoord
)gdk_event
->x
;
1365 event
.m_y
= (wxCoord
)gdk_event
->y
;
1367 // Some control don't have their own X window and thus cannot get
1370 if (!g_captureWindow
)
1372 wxCoord x
= event
.m_x
;
1373 wxCoord y
= event
.m_y
;
1374 if (win
->m_wxwindow
)
1376 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1377 x
+= pizza
->xoffset
;
1378 y
+= pizza
->yoffset
;
1381 wxNode
*node
= win
->GetChildren().First();
1384 wxWindow
*child
= (wxWindow
*)node
->Data();
1386 node
= node
->Next();
1387 if (!child
->IsShown())
1390 if (child
->m_isStaticBox
)
1392 // wxStaticBox is transparent in the box itself
1393 int xx1
= child
->m_x
;
1394 int yy1
= child
->m_y
;
1395 int xx2
= child
->m_x
+ child
->m_width
;
1396 int yy2
= child
->m_x
+ child
->m_height
;
1399 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1401 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1403 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1405 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1408 event
.m_x
-= child
->m_x
;
1409 event
.m_y
-= child
->m_y
;
1416 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1417 (child
->m_x
<= x
) &&
1418 (child
->m_y
<= y
) &&
1419 (child
->m_x
+child
->m_width
>= x
) &&
1420 (child
->m_y
+child
->m_height
>= y
))
1423 event
.m_x
-= child
->m_x
;
1424 event
.m_y
-= child
->m_y
;
1431 event
.SetEventObject( win
);
1433 if (win
->GetEventHandler()->ProcessEvent( event
))
1435 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1442 //-----------------------------------------------------------------------------
1444 //-----------------------------------------------------------------------------
1446 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1451 wxapp_install_idle_handler();
1453 if (!win
->m_hasVMT
) return FALSE
;
1454 if (g_blockEventsOnDrag
) return FALSE
;
1456 switch ( g_sendActivateEvent
)
1459 // we've got focus from outside, synthtize wxActivateEvent
1460 g_sendActivateEvent
= 1;
1464 // another our window just lost focus, it was already ours before
1465 // - don't send any wxActivateEvent
1466 g_sendActivateEvent
= -1;
1470 g_focusWindow
= win
;
1473 printf( "OnSetFocus from " );
1474 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1475 printf( win->GetClassInfo()->GetClassName() );
1477 printf( WXSTRINGCAST win->GetLabel() );
1481 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1484 panel
->SetLastFocus(win
);
1489 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1492 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1493 event
.SetEventObject( win
);
1495 if (win
->GetEventHandler()->ProcessEvent( event
))
1497 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1504 //-----------------------------------------------------------------------------
1505 // "focus_out_event"
1506 //-----------------------------------------------------------------------------
1508 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1513 wxapp_install_idle_handler();
1515 if (!win
->m_hasVMT
) return FALSE
;
1516 if (g_blockEventsOnDrag
) return FALSE
;
1518 // if the focus goes out of our app alltogether, OnIdle() will send
1519 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1520 // g_sendActivateEvent to -1
1521 g_sendActivateEvent
= 0;
1523 g_focusWindow
= (wxWindow
*)NULL
;
1526 printf( "OnKillFocus from " );
1527 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1528 printf( win->GetClassInfo()->GetClassName() );
1537 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1538 event
.SetEventObject( win
);
1540 if (win
->GetEventHandler()->ProcessEvent( event
))
1542 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1549 //-----------------------------------------------------------------------------
1550 // "enter_notify_event"
1551 //-----------------------------------------------------------------------------
1553 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1558 wxapp_install_idle_handler();
1560 if (!win
->m_hasVMT
) return FALSE
;
1561 if (g_blockEventsOnDrag
) return FALSE
;
1563 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1565 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1566 #if (GTK_MINOR_VERSION > 0)
1567 event
.SetTimestamp( gdk_event
->time
);
1569 event
.SetEventObject( win
);
1573 GdkModifierType state
= (GdkModifierType
)0;
1575 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1577 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1578 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1579 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1580 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1581 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1582 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1583 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1588 if (win
->GetEventHandler()->ProcessEvent( event
))
1590 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1597 //-----------------------------------------------------------------------------
1598 // "leave_notify_event"
1599 //-----------------------------------------------------------------------------
1601 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1606 wxapp_install_idle_handler();
1608 if (!win
->m_hasVMT
) return FALSE
;
1609 if (g_blockEventsOnDrag
) return FALSE
;
1611 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1613 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1614 #if (GTK_MINOR_VERSION > 0)
1615 event
.SetTimestamp( gdk_event
->time
);
1617 event
.SetEventObject( win
);
1621 GdkModifierType state
= (GdkModifierType
)0;
1623 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1625 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1626 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1627 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1628 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1629 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1630 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1631 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1636 if (win
->GetEventHandler()->ProcessEvent( event
))
1638 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1645 //-----------------------------------------------------------------------------
1646 // "value_changed" from m_vAdjust
1647 //-----------------------------------------------------------------------------
1649 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1654 wxapp_install_idle_handler();
1656 if (g_blockEventsOnDrag
) return;
1658 if (!win
->m_hasVMT
) return;
1660 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1661 if (fabs(diff
) < 0.2) return;
1663 win
->m_oldVerticalPos
= adjust
->value
;
1665 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1666 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1668 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1669 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1670 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1671 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1672 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1674 int value
= (int)(adjust
->value
+0.5);
1676 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1677 event
.SetEventObject( win
);
1678 win
->GetEventHandler()->ProcessEvent( event
);
1681 //-----------------------------------------------------------------------------
1682 // "value_changed" from m_hAdjust
1683 //-----------------------------------------------------------------------------
1685 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1690 wxapp_install_idle_handler();
1692 if (g_blockEventsOnDrag
) return;
1693 if (!win
->m_hasVMT
) return;
1695 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1696 if (fabs(diff
) < 0.2) return;
1698 win
->m_oldHorizontalPos
= adjust
->value
;
1700 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1701 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1703 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1704 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1705 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1706 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1707 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1709 int value
= (int)(adjust
->value
+0.5);
1711 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1712 event
.SetEventObject( win
);
1713 win
->GetEventHandler()->ProcessEvent( event
);
1716 //-----------------------------------------------------------------------------
1717 // "button_press_event" from scrollbar
1718 //-----------------------------------------------------------------------------
1720 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1721 GdkEventButton
*gdk_event
,
1727 wxapp_install_idle_handler();
1729 g_blockEventsOnScroll
= TRUE
;
1730 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1735 //-----------------------------------------------------------------------------
1736 // "button_release_event" from scrollbar
1737 //-----------------------------------------------------------------------------
1739 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1740 GdkEventButton
*WXUNUSED(gdk_event
),
1745 // don't test here as we can release the mouse while being over
1746 // a different window than the slider
1748 // if (gdk_event->window != widget->slider) return FALSE;
1750 g_blockEventsOnScroll
= FALSE
;
1752 if (win
->m_isScrolling
)
1754 wxEventType command
= wxEVT_SCROLL_THUMBRELEASE
;
1758 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1759 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1761 value
= (int)(win
->m_hAdjust
->value
+0.5);
1764 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1766 value
= (int)(win
->m_vAdjust
->value
+0.5);
1770 wxScrollWinEvent
event( command
, value
, dir
);
1771 event
.SetEventObject( win
);
1772 win
->GetEventHandler()->ProcessEvent( event
);
1775 win
->m_isScrolling
= FALSE
;
1780 // ----------------------------------------------------------------------------
1781 // this wxWindowBase function is implemented here (in platform-specific file)
1782 // because it is static and so couldn't be made virtual
1783 // ----------------------------------------------------------------------------
1785 wxWindow
*wxWindowBase::FindFocus()
1787 return g_focusWindow
;
1790 //-----------------------------------------------------------------------------
1791 // "realize" from m_widget
1792 //-----------------------------------------------------------------------------
1794 /* We cannot set colours and fonts before the widget has
1795 been realized, so we do this directly after realization. */
1798 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1803 wxapp_install_idle_handler();
1805 if (win
->m_delayedBackgroundColour
)
1806 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1808 if (win
->m_delayedForegroundColour
)
1809 win
->SetForegroundColour( win
->GetForegroundColour() );
1811 wxWindowCreateEvent
event( win
);
1812 event
.SetEventObject( win
);
1813 win
->GetEventHandler()->ProcessEvent( event
);
1818 //-----------------------------------------------------------------------------
1820 //-----------------------------------------------------------------------------
1823 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
1824 GtkAllocation
*WXUNUSED(alloc
),
1828 wxapp_install_idle_handler();
1830 if (!win
->m_hasScrolling
) return;
1832 int client_width
= 0;
1833 int client_height
= 0;
1834 win
->GetClientSize( &client_width
, &client_height
);
1835 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
1838 win
->m_oldClientWidth
= client_width
;
1839 win
->m_oldClientHeight
= client_height
;
1841 if (!win
->m_nativeSizeEvent
)
1843 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
1844 event
.SetEventObject( win
);
1845 win
->GetEventHandler()->ProcessEvent( event
);
1851 #define WXUNUSED_UNLESS_XIM(param) param
1853 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1856 /* Resize XIM window */
1859 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1860 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1861 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1864 wxapp_install_idle_handler();
1870 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1874 gdk_window_get_size (widget
->window
, &width
, &height
);
1875 win
->m_icattr
->preedit_area
.width
= width
;
1876 win
->m_icattr
->preedit_area
.height
= height
;
1877 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
1882 //-----------------------------------------------------------------------------
1883 // "realize" from m_wxwindow
1884 //-----------------------------------------------------------------------------
1886 /* Initialize XIM support */
1889 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1890 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1893 wxapp_install_idle_handler();
1896 if (win
->m_ic
) return FALSE
;
1897 if (!widget
) return FALSE
;
1898 if (!gdk_im_ready()) return FALSE
;
1900 win
->m_icattr
= gdk_ic_attr_new();
1901 if (!win
->m_icattr
) return FALSE
;
1905 GdkColormap
*colormap
;
1906 GdkICAttr
*attr
= win
->m_icattr
;
1907 unsigned attrmask
= GDK_IC_ALL_REQ
;
1909 GdkIMStyle supported_style
= (GdkIMStyle
)
1910 (GDK_IM_PREEDIT_NONE
|
1911 GDK_IM_PREEDIT_NOTHING
|
1912 GDK_IM_PREEDIT_POSITION
|
1913 GDK_IM_STATUS_NONE
|
1914 GDK_IM_STATUS_NOTHING
);
1916 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1917 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
1919 attr
->style
= style
= gdk_im_decide_style (supported_style
);
1920 attr
->client_window
= widget
->window
;
1922 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
1923 gtk_widget_get_default_colormap ())
1925 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
1926 attr
->preedit_colormap
= colormap
;
1929 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
1930 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
1931 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
1932 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
1934 switch (style
& GDK_IM_PREEDIT_MASK
)
1936 case GDK_IM_PREEDIT_POSITION
:
1937 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1939 g_warning ("over-the-spot style requires fontset");
1943 gdk_window_get_size (widget
->window
, &width
, &height
);
1945 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
1946 attr
->spot_location
.x
= 0;
1947 attr
->spot_location
.y
= height
;
1948 attr
->preedit_area
.x
= 0;
1949 attr
->preedit_area
.y
= 0;
1950 attr
->preedit_area
.width
= width
;
1951 attr
->preedit_area
.height
= height
;
1952 attr
->preedit_fontset
= widget
->style
->font
;
1957 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
1959 if (win
->m_ic
== NULL
)
1960 g_warning ("Can't create input context.");
1963 mask
= gdk_window_get_events (widget
->window
);
1964 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
1965 gdk_window_set_events (widget
->window
, mask
);
1967 if (GTK_WIDGET_HAS_FOCUS(widget
))
1968 gdk_im_begin (win
->m_ic
, widget
->window
);
1975 //-----------------------------------------------------------------------------
1976 // InsertChild for wxWindow.
1977 //-----------------------------------------------------------------------------
1979 /* Callback for wxWindow. This very strange beast has to be used because
1980 * C++ has no virtual methods in a constructor. We have to emulate a
1981 * virtual function here as wxNotebook requires a different way to insert
1982 * a child in it. I had opted for creating a wxNotebookPage window class
1983 * which would have made this superfluous (such in the MDI window system),
1984 * but no-one was listening to me... */
1986 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1988 /* the window might have been scrolled already, do we
1989 have to adapt the position */
1990 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
1991 child
->m_x
+= pizza
->xoffset
;
1992 child
->m_y
+= pizza
->yoffset
;
1994 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
1995 GTK_WIDGET(child
->m_widget
),
2002 //-----------------------------------------------------------------------------
2004 //-----------------------------------------------------------------------------
2006 wxWindow
* wxGetActiveWindow()
2008 return g_focusWindow
;
2011 //-----------------------------------------------------------------------------
2013 //-----------------------------------------------------------------------------
2015 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2017 void wxWindow::Init()
2023 m_widget
= (GtkWidget
*) NULL
;
2024 m_wxwindow
= (GtkWidget
*) NULL
;
2034 m_needParent
= TRUE
;
2035 m_isBeingDeleted
= FALSE
;
2038 m_nativeSizeEvent
= FALSE
;
2040 m_hasScrolling
= FALSE
;
2041 m_isScrolling
= FALSE
;
2043 m_hAdjust
= (GtkAdjustment
*) NULL
;
2044 m_vAdjust
= (GtkAdjustment
*) NULL
;
2045 m_oldHorizontalPos
= 0.0;
2046 m_oldVerticalPos
= 0.0;
2049 m_widgetStyle
= (GtkStyle
*) NULL
;
2051 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2053 m_isStaticBox
= FALSE
;
2054 m_isRadioButton
= FALSE
;
2056 m_acceptsFocus
= FALSE
;
2058 m_clipPaintRegion
= FALSE
;
2059 m_queuedFullRedraw
= FALSE
;
2061 m_cursor
= *wxSTANDARD_CURSOR
;
2064 m_ic
= (GdkIC
*) NULL
;
2065 m_icattr
= (GdkICAttr
*) NULL
;
2069 wxWindow::wxWindow()
2074 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
2075 const wxPoint
&pos
, const wxSize
&size
,
2076 long style
, const wxString
&name
)
2080 Create( parent
, id
, pos
, size
, style
, name
);
2083 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
2084 const wxPoint
&pos
, const wxSize
&size
,
2085 long style
, const wxString
&name
)
2087 if (!PreCreation( parent
, pos
, size
) ||
2088 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2090 wxFAIL_MSG( wxT("wxWindow creation failed") );
2094 m_insertCallback
= wxInsertChildInWindow
;
2096 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2097 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2099 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2101 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2102 scroll_class
->scrollbar_spacing
= 0;
2104 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2106 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2107 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2109 m_wxwindow
= gtk_pizza_new();
2111 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2113 #if (GTK_MINOR_VERSION > 0)
2114 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2116 if (HasFlag(wxRAISED_BORDER
))
2118 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2120 else if (HasFlag(wxSUNKEN_BORDER
))
2122 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2124 else if (HasFlag(wxSIMPLE_BORDER
))
2126 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2130 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2132 #else // GTK_MINOR_VERSION == 0
2133 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2135 if (HasFlag(wxRAISED_BORDER
))
2137 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2139 else if (HasFlag(wxSUNKEN_BORDER
))
2141 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2145 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2147 #endif // GTK_MINOR_VERSION
2149 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2150 m_acceptsFocus
= TRUE
;
2152 #if (GTK_MINOR_VERSION == 0)
2153 // shut the viewport up
2154 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2155 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2156 #endif // GTK_MINOR_VERSION == 0
2158 // I _really_ don't want scrollbars in the beginning
2159 m_vAdjust
->lower
= 0.0;
2160 m_vAdjust
->upper
= 1.0;
2161 m_vAdjust
->value
= 0.0;
2162 m_vAdjust
->step_increment
= 1.0;
2163 m_vAdjust
->page_increment
= 1.0;
2164 m_vAdjust
->page_size
= 5.0;
2165 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2166 m_hAdjust
->lower
= 0.0;
2167 m_hAdjust
->upper
= 1.0;
2168 m_hAdjust
->value
= 0.0;
2169 m_hAdjust
->step_increment
= 1.0;
2170 m_hAdjust
->page_increment
= 1.0;
2171 m_hAdjust
->page_size
= 5.0;
2172 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2174 // these handlers block mouse events to any window during scrolling such as
2175 // motion events and prevent GTK and wxWindows from fighting over where the
2178 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2179 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2181 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2182 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2184 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2185 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2187 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2188 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2190 // these handlers get notified when screen updates are required either when
2191 // scrolling or when the window size (and therefore scrollbar configuration)
2194 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2195 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2196 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2197 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2199 gtk_widget_show( m_wxwindow
);
2202 m_parent
->DoAddChild( this );
2211 wxWindow::~wxWindow()
2213 m_isBeingDeleted
= TRUE
;
2222 m_parent
->RemoveChild( this );
2226 gdk_ic_destroy (m_ic
);
2228 gdk_ic_attr_destroy (m_icattr
);
2233 #if DISABLE_STYLE_IF_BROKEN_THEME
2234 // don't delete if it's a pixmap theme style
2235 if (!m_widgetStyle
->engine_data
)
2236 gtk_style_unref( m_widgetStyle
);
2238 m_widgetStyle
= (GtkStyle
*) NULL
;
2243 gtk_widget_destroy( m_wxwindow
);
2244 m_wxwindow
= (GtkWidget
*) NULL
;
2249 gtk_widget_destroy( m_widget
);
2250 m_widget
= (GtkWidget
*) NULL
;
2254 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2256 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2258 /* this turns -1 into 20 so that a minimal window is
2259 visible even although -1,-1 has been given as the
2260 size of the window. the same trick is used in other
2261 ports and should make debugging easier */
2262 m_width
= WidthDefault(size
.x
);
2263 m_height
= HeightDefault(size
.y
);
2268 /* some reasonable defaults */
2273 m_x
= (gdk_screen_width () - m_width
) / 2;
2274 if (m_x
< 10) m_x
= 10;
2278 m_y
= (gdk_screen_height () - m_height
) / 2;
2279 if (m_y
< 10) m_y
= 10;
2286 void wxWindow::PostCreation()
2288 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2294 /* these get reported to wxWindows -> wxPaintEvent */
2296 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2298 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2299 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2301 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2302 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2304 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2305 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2308 #if (GTK_MINOR_VERSION > 0)
2309 /* these are called when the "sunken" or "raised" borders are drawn */
2310 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2311 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2313 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2314 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2318 if (m_wxwindow
&& m_needParent
)
2320 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2321 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2323 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2324 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2328 // For dialogs and frames, we are interested mainly in
2329 // m_widget's focus.
2331 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2332 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2334 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2335 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2338 GtkWidget
*connect_widget
= GetConnectWidget();
2340 ConnectWidget( connect_widget
);
2342 /* We cannot set colours, fonts and cursors before the widget has
2343 been realized, so we do this directly after realization */
2344 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2345 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2349 /* Catch native resize events. */
2350 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2351 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2353 /* Initialize XIM support. */
2354 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2355 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2357 /* And resize XIM window. */
2358 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2359 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2365 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2367 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2368 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2370 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2371 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2373 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2374 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2376 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2377 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2379 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2380 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2382 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2383 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2385 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2386 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2389 bool wxWindow::Destroy()
2391 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2395 return wxWindowBase::Destroy();
2398 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2400 if (m_wxwindow
&& GTK_PIZZA(m_wxwindow
)->bin_window
)
2402 /* Normally, GTK will send expose events only for the regions
2403 which actually got exposed. Sadly, wxMSW invalidates
2404 the whole window so we have to do that, too. We could
2405 simply add a complete refresh, but we would then get
2406 the normal GTK expose events in surplus, so we shut
2407 off the expose events and schedule a full redraw to
2408 be done in OnInternalIdle, where we restore the handling
2409 of expose events. */
2411 m_queuedFullRedraw
= TRUE
;
2413 GdkEventMask mask
= gdk_window_get_events( GTK_PIZZA(m_wxwindow
)->bin_window
);
2414 mask
= (GdkEventMask
)(mask
& ~GDK_EXPOSURE_MASK
);
2415 gdk_window_set_events( GTK_PIZZA(m_wxwindow
)->bin_window
, mask
);
2418 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2421 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2423 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2424 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2426 if (m_resizing
) return; /* I don't like recursions */
2429 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2431 /* don't set the size for children of wxNotebook, just take the values. */
2439 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2441 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2443 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2444 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2445 if (width
!= -1) m_width
= width
;
2446 if (height
!= -1) m_height
= height
;
2450 m_x
= x
+ pizza
->xoffset
;
2451 m_y
= y
+ pizza
->yoffset
;
2456 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2458 if (width
== -1) m_width
= 80;
2461 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2463 if (height
== -1) m_height
= 26;
2466 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2467 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2468 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2469 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2472 int bottom_border
= 0;
2474 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2476 /* the default button has a border around it */
2481 DoMoveWindow( m_x
-border
,
2484 m_height
+border
+bottom_border
);
2489 /* Sometimes the client area changes size without the
2490 whole windows's size changing, but if the whole
2491 windows's size doesn't change, no wxSizeEvent will
2492 normally be sent. Here we add an extra test if
2493 the client test has been changed and this will
2495 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2499 wxPrintf( "OnSize sent from " );
2500 if (GetClassInfo() && GetClassInfo()->GetClassName())
2501 wxPrintf( GetClassInfo()->GetClassName() );
2502 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2505 if (!m_nativeSizeEvent
)
2507 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2508 event
.SetEventObject( this );
2509 GetEventHandler()->ProcessEvent( event
);
2515 void wxWindow::OnInternalIdle()
2517 if ( g_sendActivateEvent
!= -1 )
2519 bool activate
= g_sendActivateEvent
!= 0;
2522 g_sendActivateEvent
= -1;
2524 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2525 event
.SetEventObject(this);
2527 (void)GetEventHandler()->ProcessEvent(event
);
2530 wxCursor cursor
= m_cursor
;
2531 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2535 /* I now set the cursor anew in every OnInternalIdle call
2536 as setting the cursor in a parent window also effects the
2537 windows above so that checking for the current cursor is
2542 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2544 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2546 if (!g_globalCursor
.Ok())
2547 cursor
= *wxSTANDARD_CURSOR
;
2549 window
= m_widget
->window
;
2550 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2551 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2557 GdkWindow
*window
= m_widget
->window
;
2558 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2559 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2566 if (m_queuedFullRedraw
)
2568 /* See also wxWindow::DoMoveWindow for explanation of this code. What
2569 we test here is if the requested size of the window is the same as
2570 the actual size of window, in which case all expose events that resulted
2571 from resizing the window have been sent (and discarded) and we can
2572 now do our full redraw and switch on expose event handling again. */
2574 if ((m_width
== m_widget
->allocation
.width
) && (m_height
== m_widget
->allocation
.height
))
2576 m_queuedFullRedraw
= FALSE
;
2577 m_updateRegion
.Clear();
2578 m_updateRegion
.Union( 0,0,m_width
,m_height
);
2579 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2581 GdkEventMask mask
= gdk_window_get_events( GTK_PIZZA(m_wxwindow
)->bin_window
);
2582 mask
= (GdkEventMask
)(mask
| GDK_EXPOSURE_MASK
);
2583 gdk_window_set_events( GTK_PIZZA(m_wxwindow
)->bin_window
, mask
);
2588 void wxWindow::DoGetSize( int *width
, int *height
) const
2590 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2592 if (width
) (*width
) = m_width
;
2593 if (height
) (*height
) = m_height
;
2596 void wxWindow::DoSetClientSize( int width
, int height
)
2598 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2602 SetSize( width
, height
);
2609 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2611 /* when using GTK 1.2 we set the shadow border size to 2 */
2615 if (HasFlag(wxSIMPLE_BORDER
))
2617 /* when using GTK 1.2 we set the simple border size to 1 */
2624 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2626 GtkRequisition vscroll_req
;
2627 vscroll_req
.width
= 2;
2628 vscroll_req
.height
= 2;
2629 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
2630 (scroll_window
->vscrollbar
, &vscroll_req
);
2632 GtkRequisition hscroll_req
;
2633 hscroll_req
.width
= 2;
2634 hscroll_req
.height
= 2;
2635 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
2636 (scroll_window
->hscrollbar
, &hscroll_req
);
2638 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2640 if (scroll_window
->vscrollbar_visible
)
2642 dw
+= vscroll_req
.width
;
2643 dw
+= scroll_class
->scrollbar_spacing
;
2646 if (scroll_window
->hscrollbar_visible
)
2648 dh
+= hscroll_req
.height
;
2649 dh
+= scroll_class
->scrollbar_spacing
;
2653 SetSize( width
+dw
, height
+dh
);
2657 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2659 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2663 if (width
) (*width
) = m_width
;
2664 if (height
) (*height
) = m_height
;
2671 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2673 /* when using GTK 1.2 we set the shadow border size to 2 */
2677 if (HasFlag(wxSIMPLE_BORDER
))
2679 /* when using GTK 1.2 we set the simple border size to 1 */
2686 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2688 GtkRequisition vscroll_req
;
2689 vscroll_req
.width
= 2;
2690 vscroll_req
.height
= 2;
2691 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
2692 (scroll_window
->vscrollbar
, &vscroll_req
);
2694 GtkRequisition hscroll_req
;
2695 hscroll_req
.width
= 2;
2696 hscroll_req
.height
= 2;
2697 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
2698 (scroll_window
->hscrollbar
, &hscroll_req
);
2700 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2702 if (scroll_window
->vscrollbar_visible
)
2704 dw
+= vscroll_req
.width
;
2705 dw
+= scroll_class
->scrollbar_spacing
;
2708 if (scroll_window
->hscrollbar_visible
)
2710 dh
+= hscroll_req
.height
;
2711 dh
+= scroll_class
->scrollbar_spacing
;
2715 if (width
) (*width
) = m_width
- dw
;
2716 if (height
) (*height
) = m_height
- dh
;
2720 void wxWindow::DoGetPosition( int *x
, int *y
) const
2722 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2726 if (m_parent
&& m_parent
->m_wxwindow
)
2728 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2729 dx
= pizza
->xoffset
;
2730 dy
= pizza
->yoffset
;
2733 if (x
) (*x
) = m_x
- dx
;
2734 if (y
) (*y
) = m_y
- dy
;
2737 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2739 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2741 if (!m_widget
->window
) return;
2743 GdkWindow
*source
= (GdkWindow
*) NULL
;
2745 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2747 source
= m_widget
->window
;
2751 gdk_window_get_origin( source
, &org_x
, &org_y
);
2755 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2757 org_x
+= m_widget
->allocation
.x
;
2758 org_y
+= m_widget
->allocation
.y
;
2766 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2768 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2770 if (!m_widget
->window
) return;
2772 GdkWindow
*source
= (GdkWindow
*) NULL
;
2774 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2776 source
= m_widget
->window
;
2780 gdk_window_get_origin( source
, &org_x
, &org_y
);
2784 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2786 org_x
+= m_widget
->allocation
.x
;
2787 org_y
+= m_widget
->allocation
.y
;
2795 bool wxWindow::Show( bool show
)
2797 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2799 if (!wxWindowBase::Show(show
))
2806 gtk_widget_show( m_widget
);
2808 gtk_widget_hide( m_widget
);
2813 bool wxWindow::Enable( bool enable
)
2815 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2817 if (!wxWindowBase::Enable(enable
))
2823 gtk_widget_set_sensitive( m_widget
, enable
);
2825 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2830 int wxWindow::GetCharHeight() const
2832 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2834 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2836 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2838 return font
->ascent
+ font
->descent
;
2841 int wxWindow::GetCharWidth() const
2843 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2845 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2847 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2849 return gdk_string_width( font
, "H" );
2852 void wxWindow::GetTextExtent( const wxString
& string
,
2856 int *externalLeading
,
2857 const wxFont
*theFont
) const
2859 wxFont fontToUse
= m_font
;
2860 if (theFont
) fontToUse
= *theFont
;
2862 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2864 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2865 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2866 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2867 if (descent
) (*descent
) = font
->descent
;
2868 if (externalLeading
) (*externalLeading
) = 0; // ??
2871 void wxWindow::SetFocus()
2873 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2877 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2878 gtk_widget_grab_focus (m_wxwindow
);
2884 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2886 gtk_widget_grab_focus (m_widget
);
2888 else if (GTK_IS_CONTAINER(m_widget
))
2890 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2899 bool wxWindow::AcceptsFocus() const
2901 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2904 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2906 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2908 wxWindow
*oldParent
= m_parent
,
2909 *newParent
= (wxWindow
*)newParentBase
;
2911 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2913 if ( !wxWindowBase::Reparent(newParent
) )
2916 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2918 /* prevent GTK from deleting the widget arbitrarily */
2919 gtk_widget_ref( m_widget
);
2923 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2926 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2930 /* insert GTK representation */
2931 (*(newParent
->m_insertCallback
))(newParent
, this);
2934 /* reverse: prevent GTK from deleting the widget arbitrarily */
2935 gtk_widget_unref( m_widget
);
2940 void wxWindow::DoAddChild(wxWindow
*child
)
2942 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2944 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
2946 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
2951 /* insert GTK representation */
2952 (*m_insertCallback
)(this, child
);
2955 void wxWindow::Raise()
2957 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2959 if (!m_widget
->window
) return;
2961 gdk_window_raise( m_widget
->window
);
2964 void wxWindow::Lower()
2966 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2968 if (!m_widget
->window
) return;
2970 gdk_window_lower( m_widget
->window
);
2973 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2975 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2977 return wxWindowBase::SetCursor( cursor
);
2980 void wxWindow::WarpPointer( int x
, int y
)
2982 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2984 /* we provide this function ourselves as it is
2985 missing in GDK (top of this file) */
2987 GdkWindow
*window
= (GdkWindow
*) NULL
;
2989 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2991 window
= GetConnectWidget()->window
;
2994 gdk_window_warp_pointer( window
, x
, y
);
2997 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2999 if (!m_widget
) return;
3000 if (!m_widget
->window
) return;
3002 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3006 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3008 rect
->width
, rect
->height
);
3012 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3016 /* there is no GTK equivalent of "draw only, don't clear" so we
3017 invent our own in the GtkPizza widget */
3025 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3026 gboolean old_clear = pizza->clear_on_draw;
3027 gtk_pizza_set_clear( pizza, FALSE );
3028 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3029 gtk_pizza_set_clear( pizza, old_clear );
3031 GdkEventExpose gdk_event
;
3032 gdk_event
.count
= 0;
3033 gdk_event
.area
.x
= 0;
3034 gdk_event
.area
.y
= 0;
3035 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3036 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3037 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3042 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3051 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3052 gboolean old_clear = pizza->clear_on_draw;
3053 gtk_pizza_set_clear( pizza, FALSE );
3055 GdkRectangle gdk_rect;
3056 gdk_rect.x = rect->x;
3057 gdk_rect.y = rect->y;
3058 gdk_rect.width = rect->width;
3059 gdk_rect.height = rect->height;
3060 gtk_widget_draw( m_wxwindow, &gdk_rect );
3061 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3063 gtk_pizza_set_clear( pizza, old_clear );
3065 GdkEventExpose gdk_event
;
3066 gdk_event
.count
= 0;
3067 gdk_event
.area
.x
= rect
->x
;
3068 gdk_event
.area
.y
= rect
->y
;
3069 gdk_event
.area
.width
= rect
->width
;
3070 gdk_event
.area
.height
= rect
->height
;
3071 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3075 GdkRectangle gdk_rect
;
3076 gdk_rect
.x
= rect
->x
;
3077 gdk_rect
.y
= rect
->y
;
3078 gdk_rect
.width
= rect
->width
;
3079 gdk_rect
.height
= rect
->height
;
3080 gtk_widget_draw( m_widget
, &gdk_rect
);
3085 void wxWindow::Clear()
3087 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3089 if (!m_widget
->window
) return;
3091 if (m_wxwindow
&& m_wxwindow
->window
)
3093 // gdk_window_clear( m_wxwindow->window );
3098 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
3100 wxWindowBase::DoSetToolTip(tip
);
3103 m_tooltip
->Apply( this );
3106 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3108 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3110 #endif // wxUSE_TOOLTIPS
3112 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
3114 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3116 if (!wxWindowBase::SetBackgroundColour(colour
))
3118 // don't leave if the GTK widget has just
3120 if (!m_delayedBackgroundColour
) return FALSE
;
3123 GdkWindow
*window
= (GdkWindow
*) NULL
;
3125 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3127 window
= GetConnectWidget()->window
;
3131 // indicate that a new style has been set
3132 // but it couldn't get applied as the
3133 // widget hasn't been realized yet.
3134 m_delayedBackgroundColour
= TRUE
;
3138 (m_wxwindow
->window
) &&
3139 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3141 /* wxMSW doesn't clear the window here. I don't do that either to
3142 provide compatibility. call Clear() to do the job. */
3144 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3145 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3153 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
3155 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3157 if (!wxWindowBase::SetForegroundColour(colour
))
3159 // don't leave if the GTK widget has just
3161 if (!m_delayedForegroundColour
) return FALSE
;
3164 GdkWindow
*window
= (GdkWindow
*) NULL
;
3166 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3168 window
= GetConnectWidget()->window
;
3172 // indicate that a new style has been set
3173 // but it couldn't get applied as the
3174 // widget hasn't been realized yet.
3175 m_delayedForegroundColour
= TRUE
;
3183 GtkStyle
*wxWindow::GetWidgetStyle()
3187 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3188 remake
->klass
= m_widgetStyle
->klass
;
3190 gtk_style_unref( m_widgetStyle
);
3191 m_widgetStyle
= remake
;
3195 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3198 def
= gtk_widget_get_default_style();
3200 m_widgetStyle
= gtk_style_copy( def
);
3201 m_widgetStyle
->klass
= def
->klass
;
3204 return m_widgetStyle
;
3207 void wxWindow::SetWidgetStyle()
3209 #if DISABLE_STYLE_IF_BROKEN_THEM
3210 if (m_widget
->style
->engine_data
)
3212 static bool s_warningPrinted
= FALSE
;
3213 if (!s_warningPrinted
)
3215 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3216 s_warningPrinted
= TRUE
;
3218 m_widgetStyle
= m_widget
->style
;
3223 GtkStyle
*style
= GetWidgetStyle();
3225 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3227 gdk_font_unref( style
->font
);
3228 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3231 if (m_foregroundColour
.Ok())
3233 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3234 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3236 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3237 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3238 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3242 if (m_backgroundColour
.Ok())
3244 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3245 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3247 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3248 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3249 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3250 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3251 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3252 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3253 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3254 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3259 void wxWindow::ApplyWidgetStyle()
3263 //-----------------------------------------------------------------------------
3264 // Pop-up menu stuff
3265 //-----------------------------------------------------------------------------
3267 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3269 *is_waiting
= FALSE
;
3272 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3274 menu
->SetInvokingWindow( win
);
3275 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3278 wxMenuItem
*menuitem
= node
->GetData();
3279 if (menuitem
->IsSubMenu())
3281 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3284 node
= node
->GetNext();
3288 static gint gs_pop_x
= 0;
3289 static gint gs_pop_y
= 0;
3291 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3295 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3300 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3302 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3304 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3306 SetInvokingWindow( menu
, this );
3313 bool is_waiting
= TRUE
;
3315 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3316 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3319 GTK_MENU(menu
->m_menu
),
3320 (GtkWidget
*) NULL
, // parent menu shell
3321 (GtkWidget
*) NULL
, // parent menu item
3322 (GtkMenuPositionFunc
) pop_pos_callback
,
3323 (gpointer
) this, // client data
3324 0, // button used to activate it
3325 gs_timeLastClick
// the time of activation
3330 while (gtk_events_pending())
3331 gtk_main_iteration();
3337 #if wxUSE_DRAG_AND_DROP
3339 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3341 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3343 GtkWidget
*dnd_widget
= GetConnectWidget();
3345 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3347 if (m_dropTarget
) delete m_dropTarget
;
3348 m_dropTarget
= dropTarget
;
3350 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3353 #endif // wxUSE_DRAG_AND_DROP
3355 GtkWidget
* wxWindow::GetConnectWidget()
3357 GtkWidget
*connect_widget
= m_widget
;
3358 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3360 return connect_widget
;
3363 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3366 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3368 return (window
== m_widget
->window
);
3371 bool wxWindow::SetFont( const wxFont
&font
)
3373 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3375 if (!wxWindowBase::SetFont(font
))
3380 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3381 if ( sysbg
== m_backgroundColour
)
3383 m_backgroundColour
= wxNullColour
;
3385 m_backgroundColour
= sysbg
;
3395 void wxWindow::CaptureMouse()
3397 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3399 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3401 GdkWindow
*window
= (GdkWindow
*) NULL
;
3403 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3405 window
= GetConnectWidget()->window
;
3407 if (!window
) return;
3409 gdk_pointer_grab( window
, FALSE
,
3411 (GDK_BUTTON_PRESS_MASK
|
3412 GDK_BUTTON_RELEASE_MASK
|
3413 GDK_POINTER_MOTION_HINT_MASK
|
3414 GDK_POINTER_MOTION_MASK
),
3416 m_cursor
.GetCursor(),
3417 (guint32
)GDK_CURRENT_TIME
);
3418 g_captureWindow
= this;
3421 void wxWindow::ReleaseMouse()
3423 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3425 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3427 GdkWindow
*window
= (GdkWindow
*) NULL
;
3429 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3431 window
= GetConnectWidget()->window
;
3436 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3437 g_captureWindow
= (wxWindow
*) NULL
;
3440 bool wxWindow::IsRetained() const
3445 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3446 int range
, bool refresh
)
3448 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3450 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3452 m_hasScrolling
= TRUE
;
3454 if (orient
== wxHORIZONTAL
)
3456 float fpos
= (float)pos
;
3457 float frange
= (float)range
;
3458 float fthumb
= (float)thumbVisible
;
3459 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3460 if (fpos
< 0.0) fpos
= 0.0;
3462 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3463 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3465 SetScrollPos( orient
, pos
, refresh
);
3469 m_oldHorizontalPos
= fpos
;
3471 m_hAdjust
->lower
= 0.0;
3472 m_hAdjust
->upper
= frange
;
3473 m_hAdjust
->value
= fpos
;
3474 m_hAdjust
->step_increment
= 1.0;
3475 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3476 m_hAdjust
->page_size
= fthumb
;
3480 float fpos
= (float)pos
;
3481 float frange
= (float)range
;
3482 float fthumb
= (float)thumbVisible
;
3483 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3484 if (fpos
< 0.0) fpos
= 0.0;
3486 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3487 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3489 SetScrollPos( orient
, pos
, refresh
);
3493 m_oldVerticalPos
= fpos
;
3495 m_vAdjust
->lower
= 0.0;
3496 m_vAdjust
->upper
= frange
;
3497 m_vAdjust
->value
= fpos
;
3498 m_vAdjust
->step_increment
= 1.0;
3499 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3500 m_vAdjust
->page_size
= fthumb
;
3503 if (orient
== wxHORIZONTAL
)
3504 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3506 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3509 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3511 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3513 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3515 if (orient
== wxHORIZONTAL
)
3517 float fpos
= (float)pos
;
3518 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3519 if (fpos
< 0.0) fpos
= 0.0;
3520 m_oldHorizontalPos
= fpos
;
3522 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3523 m_hAdjust
->value
= fpos
;
3527 float fpos
= (float)pos
;
3528 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3529 if (fpos
< 0.0) fpos
= 0.0;
3530 m_oldVerticalPos
= fpos
;
3532 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3533 m_vAdjust
->value
= fpos
;
3536 if (m_wxwindow
->window
)
3538 if (orient
== wxHORIZONTAL
)
3540 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3541 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3543 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3545 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3546 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3550 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3551 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3553 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3555 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3556 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3561 int wxWindow::GetScrollThumb( int orient
) const
3563 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3565 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3567 if (orient
== wxHORIZONTAL
)
3568 return (int)(m_hAdjust
->page_size
+0.5);
3570 return (int)(m_vAdjust
->page_size
+0.5);
3573 int wxWindow::GetScrollPos( int orient
) const
3575 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3577 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3579 if (orient
== wxHORIZONTAL
)
3580 return (int)(m_hAdjust
->value
+0.5);
3582 return (int)(m_vAdjust
->value
+0.5);
3585 int wxWindow::GetScrollRange( int orient
) const
3587 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3589 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3591 if (orient
== wxHORIZONTAL
)
3592 return (int)(m_hAdjust
->upper
+0.5);
3594 return (int)(m_vAdjust
->upper
+0.5);
3597 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3599 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3601 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3603 if ((dx
== 0) && (dy
== 0)) return;
3605 m_clipPaintRegion
= TRUE
;
3606 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3607 m_clipPaintRegion
= FALSE
;
3610 if (m_children.GetCount() > 0)
3612 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3616 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3618 pizza->xoffset -= dx;
3619 pizza->yoffset -= dy;
3621 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3622 gdk_gc_set_exposures( m_scrollGC, TRUE );
3626 GetClientSize( &cw, &ch );
3627 int w = cw - abs(dx);
3628 int h = ch - abs(dy);
3630 if ((h < 0) || (w < 0))
3638 if (dx < 0) s_x = -dx;
3639 if (dy < 0) s_y = -dy;
3642 if (dx > 0) d_x = dx;
3643 if (dy > 0) d_y = dy;
3645 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3646 pizza->bin_window, s_x, s_y, w, h );
3649 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3650 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3651 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3652 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3654 Refresh( TRUE, &rect );
3657 gdk_gc_unref( m_scrollGC );