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();
623 if (win
->m_queuedFullRedraw
)
627 if (win->GetName() == wxT("htmlWindow"))
629 wxPrintf( wxT("OnExpose from ") );
630 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
631 wxPrintf( win->GetClassInfo()->GetClassName() );
632 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
633 (int)gdk_event->area.y,
634 (int)gdk_event->area.width,
635 (int)gdk_event->area.height );
639 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
641 gdk_event
->area
.width
,
642 gdk_event
->area
.height
);
645 if (gdk_event
->count
> 0)
648 wxEraseEvent
eevent( win
->GetId() );
649 eevent
.SetEventObject( win
);
650 win
->GetEventHandler()->ProcessEvent(eevent
);
652 wxPaintEvent
event( win
->GetId() );
653 event
.SetEventObject( win
);
654 win
->GetEventHandler()->ProcessEvent( event
);
656 win
->GetUpdateRegion().Clear();
658 /* The following code will result in all window-less widgets
659 being redrawn if the wxWindows class is given a chance to
660 paint *anything* because it will then be allowed to paint
661 over the window-less widgets */
663 GtkPizza
*pizza
= GTK_PIZZA (widget
);
665 GList
*children
= pizza
->children
;
668 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
669 children
= children
->next
;
671 GdkEventExpose child_event
= *gdk_event
;
673 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
674 GTK_WIDGET_DRAWABLE (child
->widget
))
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
);
687 //-----------------------------------------------------------------------------
688 // "event" of m_wxwindow
689 //-----------------------------------------------------------------------------
691 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
692 expose events. We need them, of course, so we override the main event
693 procedure in GtkWidget by giving our own handler for all system events,
694 looking for the expose events and then we can always send them. */
696 gint
gtk_window_event_event_callback( GtkWidget
*widget
, GdkEventExpose
*event
, wxWindow
*win
)
698 if (event
->type
== GDK_EXPOSE
)
700 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
708 //-----------------------------------------------------------------------------
709 // "draw" of m_wxwindow
710 //-----------------------------------------------------------------------------
712 /* This callback is a complete replacement of the gtk_pizza_draw() function,
715 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
720 wxapp_install_idle_handler();
722 if (win
->m_queuedFullRedraw
)
725 GtkPizza
*pizza
= GTK_PIZZA (widget
);
727 if ( !(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
728 (pizza
->clear_on_draw
))
730 gdk_window_clear_area( pizza
->bin_window
,
731 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
735 if (win->GetName() == wxT("htmlWindow"))
737 wxPrintf( wxT("OnDraw from ") );
738 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
739 wxPrintf( win->GetClassInfo()->GetClassName() );
740 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
747 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
,
748 rect
->width
, rect
->height
);
750 win
->m_clipPaintRegion
= TRUE
;
752 wxEraseEvent
eevent( win
->GetId() );
753 eevent
.SetEventObject( win
);
754 win
->GetEventHandler()->ProcessEvent(eevent
);
756 wxPaintEvent
event( win
->GetId() );
757 event
.SetEventObject( win
);
758 win
->GetEventHandler()->ProcessEvent( event
);
760 win
->GetUpdateRegion().Clear();
762 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*/ );
778 //-----------------------------------------------------------------------------
779 // "key_press_event" from any window
780 //-----------------------------------------------------------------------------
782 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
787 wxapp_install_idle_handler();
789 if (!win
->m_hasVMT
) return FALSE
;
790 if (g_blockEventsOnDrag
) return FALSE
;
794 tmp += (char)gdk_event->keyval;
795 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
796 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
801 GdkModifierType state
;
802 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
806 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
807 /* sending unknown key events doesn't really make sense */
808 if (key_code
== 0) return FALSE
;
810 wxKeyEvent
event( wxEVT_KEY_DOWN
);
811 event
.SetTimestamp( gdk_event
->time
);
812 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
813 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
814 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
815 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
816 event
.m_keyCode
= key_code
;
817 event
.m_scanCode
= gdk_event
->keyval
;
820 event
.SetEventObject( win
);
821 ret
= win
->GetEventHandler()->ProcessEvent( event
);
826 wxWindow
*ancestor
= win
;
829 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
832 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
833 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
836 if (ancestor
->m_isFrame
)
838 ancestor
= ancestor
->GetParent();
841 #endif // wxUSE_ACCEL
843 /* wxMSW doesn't send char events with Alt pressed */
844 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
845 will only be sent if it is not in an accelerator table. */
846 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
851 wxKeyEvent
event2( wxEVT_CHAR
);
852 event2
.SetTimestamp( gdk_event
->time
);
853 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
854 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
855 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
856 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
857 event2
.m_keyCode
= key_code
;
858 event2
.m_scanCode
= gdk_event
->keyval
;
861 event2
.SetEventObject( win
);
862 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
865 /* win is a control: tab can be propagated up */
867 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
868 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
869 (win
->GetParent()) &&
870 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
872 wxNavigationKeyEvent new_event
;
873 new_event
.SetEventObject( win
->GetParent() );
874 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
875 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
876 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
877 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
878 new_event
.SetCurrentFocus( win
);
879 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
882 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
884 (gdk_event
->keyval
== GDK_Escape
) )
886 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
887 new_event
.SetEventObject( win
);
888 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
891 #if (GTK_MINOR_VERSION > 0)
892 /* Pressing F10 will activate the menu bar of the top frame. */
896 (gdk_event->keyval == GDK_F10) )
898 wxWindow *ancestor = win;
901 if (wxIsKindOf(ancestor,wxFrame))
903 wxFrame *frame = (wxFrame*) ancestor;
904 wxMenuBar *menubar = frame->GetMenuBar();
907 wxNode *node = menubar->GetMenus().First();
910 wxMenu *firstMenu = (wxMenu*) node->Data();
911 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
917 ancestor = ancestor->GetParent();
925 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
932 //-----------------------------------------------------------------------------
933 // "key_release_event" from any window
934 //-----------------------------------------------------------------------------
936 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
941 wxapp_install_idle_handler();
943 if (!win
->m_hasVMT
) return FALSE
;
944 if (g_blockEventsOnDrag
) return FALSE
;
947 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
948 if (gdk_event->state & GDK_SHIFT_MASK)
949 printf( "ShiftDown.\n" );
951 printf( "ShiftUp.\n" );
952 if (gdk_event->state & GDK_CONTROL_MASK)
953 printf( "ControlDown.\n" );
955 printf( "ControlUp.\n" );
959 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
961 /* sending unknown key events doesn't really make sense */
962 if (key_code
== 0) return FALSE
;
966 GdkModifierType state
;
967 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
969 wxKeyEvent
event( wxEVT_KEY_UP
);
970 event
.SetTimestamp( gdk_event
->time
);
971 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
972 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
973 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
974 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
975 event
.m_keyCode
= key_code
;
976 event
.m_scanCode
= gdk_event
->keyval
;
979 event
.SetEventObject( win
);
981 if (win
->GetEventHandler()->ProcessEvent( event
))
983 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
990 // ----------------------------------------------------------------------------
991 // mouse event processing helper
992 // ----------------------------------------------------------------------------
994 static void AdjustEventButtonState(wxMouseEvent
& event
)
996 // GDK reports the old state of the button for a button press event, but
997 // for compatibility with MSW and common sense we want m_leftDown be TRUE
998 // for a LEFT_DOWN event, not FALSE, so we will invert
999 // left/right/middleDown for the corresponding click events
1000 switch ( event
.GetEventType() )
1002 case wxEVT_LEFT_DOWN
:
1003 case wxEVT_LEFT_DCLICK
:
1005 event
.m_leftDown
= !event
.m_leftDown
;
1008 case wxEVT_MIDDLE_DOWN
:
1009 case wxEVT_MIDDLE_DCLICK
:
1010 case wxEVT_MIDDLE_UP
:
1011 event
.m_middleDown
= !event
.m_middleDown
;
1014 case wxEVT_RIGHT_DOWN
:
1015 case wxEVT_RIGHT_DCLICK
:
1016 case wxEVT_RIGHT_UP
:
1017 event
.m_rightDown
= !event
.m_rightDown
;
1022 //-----------------------------------------------------------------------------
1023 // "button_press_event"
1024 //-----------------------------------------------------------------------------
1026 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1031 wxapp_install_idle_handler();
1034 wxPrintf( wxT("1) OnButtonPress from ") );
1035 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1036 wxPrintf( win->GetClassInfo()->GetClassName() );
1037 wxPrintf( wxT(".\n") );
1039 if (!win
->m_hasVMT
) return FALSE
;
1040 if (g_blockEventsOnDrag
) return TRUE
;
1041 if (g_blockEventsOnScroll
) return TRUE
;
1043 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1045 if (win
->m_wxwindow
)
1047 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1049 gtk_widget_grab_focus (win
->m_wxwindow
);
1052 wxPrintf( wxT("GrabFocus from ") );
1053 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1054 wxPrintf( win->GetClassInfo()->GetClassName() );
1055 wxPrintf( wxT(".\n") );
1061 wxEventType event_type
= wxEVT_NULL
;
1063 if (gdk_event
->button
== 1)
1065 switch (gdk_event
->type
)
1067 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1068 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1072 else if (gdk_event
->button
== 2)
1074 switch (gdk_event
->type
)
1076 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1077 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1081 else if (gdk_event
->button
== 3)
1083 switch (gdk_event
->type
)
1085 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1086 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1091 if ( event_type
== wxEVT_NULL
)
1093 // unknown mouse button or click type
1097 wxMouseEvent
event( event_type
);
1098 event
.SetTimestamp( gdk_event
->time
);
1099 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1100 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1101 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1102 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1103 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1104 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1105 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1107 event
.m_x
= (wxCoord
)gdk_event
->x
;
1108 event
.m_y
= (wxCoord
)gdk_event
->y
;
1110 AdjustEventButtonState(event
);
1112 // Some control don't have their own X window and thus cannot get
1115 if (!g_captureWindow
)
1117 wxCoord x
= event
.m_x
;
1118 wxCoord y
= event
.m_y
;
1119 if (win
->m_wxwindow
)
1121 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1122 x
+= pizza
->xoffset
;
1123 y
+= pizza
->yoffset
;
1126 wxNode
*node
= win
->GetChildren().First();
1129 wxWindow
*child
= (wxWindow
*)node
->Data();
1131 node
= node
->Next();
1132 if (!child
->IsShown())
1135 if (child
->m_isStaticBox
)
1137 // wxStaticBox is transparent in the box itself
1138 int xx1
= child
->m_x
;
1139 int yy1
= child
->m_y
;
1140 int xx2
= child
->m_x
+ child
->m_width
;
1141 int yy2
= child
->m_x
+ child
->m_height
;
1144 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1146 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1148 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1150 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1153 event
.m_x
-= child
->m_x
;
1154 event
.m_y
-= child
->m_y
;
1161 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1162 (child
->m_x
<= x
) &&
1163 (child
->m_y
<= y
) &&
1164 (child
->m_x
+child
->m_width
>= x
) &&
1165 (child
->m_y
+child
->m_height
>= y
))
1168 event
.m_x
-= child
->m_x
;
1169 event
.m_y
-= child
->m_y
;
1176 event
.SetEventObject( win
);
1178 gs_timeLastClick
= gdk_event
->time
;
1181 wxPrintf( wxT("2) OnButtonPress from ") );
1182 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1183 wxPrintf( win->GetClassInfo()->GetClassName() );
1184 wxPrintf( wxT(".\n") );
1187 if (win
->GetEventHandler()->ProcessEvent( event
))
1189 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1196 //-----------------------------------------------------------------------------
1197 // "button_release_event"
1198 //-----------------------------------------------------------------------------
1200 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1205 wxapp_install_idle_handler();
1207 if (!win
->m_hasVMT
) return FALSE
;
1208 if (g_blockEventsOnDrag
) return FALSE
;
1209 if (g_blockEventsOnScroll
) return FALSE
;
1211 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1214 printf( "OnButtonRelease from " );
1215 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1216 printf( win->GetClassInfo()->GetClassName() );
1220 wxEventType event_type
= wxEVT_NULL
;
1222 switch (gdk_event
->button
)
1224 case 1: event_type
= wxEVT_LEFT_UP
; break;
1225 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1226 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1227 default: return FALSE
;
1230 wxMouseEvent
event( event_type
);
1231 event
.SetTimestamp( gdk_event
->time
);
1232 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1233 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1234 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1235 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1236 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1237 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1238 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1239 event
.m_x
= (wxCoord
)gdk_event
->x
;
1240 event
.m_y
= (wxCoord
)gdk_event
->y
;
1242 AdjustEventButtonState(event
);
1244 // Some control don't have their own X window and thus cannot get
1247 if (!g_captureWindow
)
1249 wxCoord x
= event
.m_x
;
1250 wxCoord y
= event
.m_y
;
1251 if (win
->m_wxwindow
)
1253 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1254 x
+= pizza
->xoffset
;
1255 y
+= pizza
->yoffset
;
1258 wxNode
*node
= win
->GetChildren().First();
1261 wxWindow
*child
= (wxWindow
*)node
->Data();
1263 node
= node
->Next();
1264 if (!child
->IsShown())
1267 if (child
->m_isStaticBox
)
1269 // wxStaticBox is transparent in the box itself
1270 int xx1
= child
->m_x
;
1271 int yy1
= child
->m_y
;
1272 int xx2
= child
->m_x
+ child
->m_width
;
1273 int yy2
= child
->m_x
+ child
->m_height
;
1276 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1278 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1280 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1282 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1285 event
.m_x
-= child
->m_x
;
1286 event
.m_y
-= child
->m_y
;
1293 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1294 (child
->m_x
<= x
) &&
1295 (child
->m_y
<= y
) &&
1296 (child
->m_x
+child
->m_width
>= x
) &&
1297 (child
->m_y
+child
->m_height
>= y
))
1300 event
.m_x
-= child
->m_x
;
1301 event
.m_y
-= child
->m_y
;
1308 event
.SetEventObject( win
);
1310 if (win
->GetEventHandler()->ProcessEvent( event
))
1312 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1319 //-----------------------------------------------------------------------------
1320 // "motion_notify_event"
1321 //-----------------------------------------------------------------------------
1323 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1328 wxapp_install_idle_handler();
1330 if (!win
->m_hasVMT
) return FALSE
;
1331 if (g_blockEventsOnDrag
) return FALSE
;
1332 if (g_blockEventsOnScroll
) return FALSE
;
1334 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1336 if (gdk_event
->is_hint
)
1340 GdkModifierType state
;
1341 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1347 printf( "OnMotion from " );
1348 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1349 printf( win->GetClassInfo()->GetClassName() );
1353 wxMouseEvent
event( wxEVT_MOTION
);
1354 event
.SetTimestamp( gdk_event
->time
);
1355 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1356 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1357 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1358 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1359 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1360 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1361 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1363 event
.m_x
= (wxCoord
)gdk_event
->x
;
1364 event
.m_y
= (wxCoord
)gdk_event
->y
;
1366 // Some control don't have their own X window and thus cannot get
1369 if (!g_captureWindow
)
1371 wxCoord x
= event
.m_x
;
1372 wxCoord y
= event
.m_y
;
1373 if (win
->m_wxwindow
)
1375 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1376 x
+= pizza
->xoffset
;
1377 y
+= pizza
->yoffset
;
1380 wxNode
*node
= win
->GetChildren().First();
1383 wxWindow
*child
= (wxWindow
*)node
->Data();
1385 node
= node
->Next();
1386 if (!child
->IsShown())
1389 if (child
->m_isStaticBox
)
1391 // wxStaticBox is transparent in the box itself
1392 int xx1
= child
->m_x
;
1393 int yy1
= child
->m_y
;
1394 int xx2
= child
->m_x
+ child
->m_width
;
1395 int yy2
= child
->m_x
+ child
->m_height
;
1398 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1400 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1402 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1404 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1407 event
.m_x
-= child
->m_x
;
1408 event
.m_y
-= child
->m_y
;
1415 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1416 (child
->m_x
<= x
) &&
1417 (child
->m_y
<= y
) &&
1418 (child
->m_x
+child
->m_width
>= x
) &&
1419 (child
->m_y
+child
->m_height
>= y
))
1422 event
.m_x
-= child
->m_x
;
1423 event
.m_y
-= child
->m_y
;
1430 event
.SetEventObject( win
);
1432 if (win
->GetEventHandler()->ProcessEvent( event
))
1434 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1441 //-----------------------------------------------------------------------------
1443 //-----------------------------------------------------------------------------
1445 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1450 wxapp_install_idle_handler();
1452 if (!win
->m_hasVMT
) return FALSE
;
1453 if (g_blockEventsOnDrag
) return FALSE
;
1455 switch ( g_sendActivateEvent
)
1458 // we've got focus from outside, synthtize wxActivateEvent
1459 g_sendActivateEvent
= 1;
1463 // another our window just lost focus, it was already ours before
1464 // - don't send any wxActivateEvent
1465 g_sendActivateEvent
= -1;
1469 g_focusWindow
= win
;
1472 printf( "OnSetFocus from " );
1473 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1474 printf( win->GetClassInfo()->GetClassName() );
1476 printf( WXSTRINGCAST win->GetLabel() );
1480 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1483 panel
->SetLastFocus(win
);
1488 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1491 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1492 event
.SetEventObject( win
);
1494 if (win
->GetEventHandler()->ProcessEvent( event
))
1496 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1503 //-----------------------------------------------------------------------------
1504 // "focus_out_event"
1505 //-----------------------------------------------------------------------------
1507 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1512 wxapp_install_idle_handler();
1514 if (!win
->m_hasVMT
) return FALSE
;
1515 if (g_blockEventsOnDrag
) return FALSE
;
1517 // if the focus goes out of our app alltogether, OnIdle() will send
1518 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1519 // g_sendActivateEvent to -1
1520 g_sendActivateEvent
= 0;
1522 g_focusWindow
= (wxWindow
*)NULL
;
1525 printf( "OnKillFocus from " );
1526 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1527 printf( win->GetClassInfo()->GetClassName() );
1536 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1537 event
.SetEventObject( win
);
1539 if (win
->GetEventHandler()->ProcessEvent( event
))
1541 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1548 //-----------------------------------------------------------------------------
1549 // "enter_notify_event"
1550 //-----------------------------------------------------------------------------
1552 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1557 wxapp_install_idle_handler();
1559 if (!win
->m_hasVMT
) return FALSE
;
1560 if (g_blockEventsOnDrag
) return FALSE
;
1562 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1564 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1565 #if (GTK_MINOR_VERSION > 0)
1566 event
.SetTimestamp( gdk_event
->time
);
1568 event
.SetEventObject( win
);
1572 GdkModifierType state
= (GdkModifierType
)0;
1574 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1576 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1577 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1578 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1579 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1580 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1581 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1582 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1587 if (win
->GetEventHandler()->ProcessEvent( event
))
1589 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1596 //-----------------------------------------------------------------------------
1597 // "leave_notify_event"
1598 //-----------------------------------------------------------------------------
1600 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1605 wxapp_install_idle_handler();
1607 if (!win
->m_hasVMT
) return FALSE
;
1608 if (g_blockEventsOnDrag
) return FALSE
;
1610 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1612 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1613 #if (GTK_MINOR_VERSION > 0)
1614 event
.SetTimestamp( gdk_event
->time
);
1616 event
.SetEventObject( win
);
1620 GdkModifierType state
= (GdkModifierType
)0;
1622 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1624 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1625 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1626 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1627 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1628 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1629 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1630 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1635 if (win
->GetEventHandler()->ProcessEvent( event
))
1637 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1644 //-----------------------------------------------------------------------------
1645 // "value_changed" from m_vAdjust
1646 //-----------------------------------------------------------------------------
1648 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1653 wxapp_install_idle_handler();
1655 if (g_blockEventsOnDrag
) return;
1657 if (!win
->m_hasVMT
) return;
1659 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1660 if (fabs(diff
) < 0.2) return;
1662 win
->m_oldVerticalPos
= adjust
->value
;
1664 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1665 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1667 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1668 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1669 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1670 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1671 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1673 int value
= (int)(adjust
->value
+0.5);
1675 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1676 event
.SetEventObject( win
);
1677 win
->GetEventHandler()->ProcessEvent( event
);
1680 //-----------------------------------------------------------------------------
1681 // "value_changed" from m_hAdjust
1682 //-----------------------------------------------------------------------------
1684 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1689 wxapp_install_idle_handler();
1691 if (g_blockEventsOnDrag
) return;
1692 if (!win
->m_hasVMT
) return;
1694 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1695 if (fabs(diff
) < 0.2) return;
1697 win
->m_oldHorizontalPos
= adjust
->value
;
1699 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1700 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1702 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1703 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1704 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1705 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1706 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1708 int value
= (int)(adjust
->value
+0.5);
1710 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1711 event
.SetEventObject( win
);
1712 win
->GetEventHandler()->ProcessEvent( event
);
1715 //-----------------------------------------------------------------------------
1716 // "button_press_event" from scrollbar
1717 //-----------------------------------------------------------------------------
1719 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1720 GdkEventButton
*gdk_event
,
1726 wxapp_install_idle_handler();
1728 g_blockEventsOnScroll
= TRUE
;
1729 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1734 //-----------------------------------------------------------------------------
1735 // "button_release_event" from scrollbar
1736 //-----------------------------------------------------------------------------
1738 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1739 GdkEventButton
*WXUNUSED(gdk_event
),
1744 // don't test here as we can release the mouse while being over
1745 // a different window than the slider
1747 // if (gdk_event->window != widget->slider) return FALSE;
1749 g_blockEventsOnScroll
= FALSE
;
1751 if (win
->m_isScrolling
)
1753 wxEventType command
= wxEVT_SCROLL_THUMBRELEASE
;
1757 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1758 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1760 value
= (int)(win
->m_hAdjust
->value
+0.5);
1763 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1765 value
= (int)(win
->m_vAdjust
->value
+0.5);
1769 wxScrollWinEvent
event( command
, value
, dir
);
1770 event
.SetEventObject( win
);
1771 win
->GetEventHandler()->ProcessEvent( event
);
1774 win
->m_isScrolling
= FALSE
;
1779 // ----------------------------------------------------------------------------
1780 // this wxWindowBase function is implemented here (in platform-specific file)
1781 // because it is static and so couldn't be made virtual
1782 // ----------------------------------------------------------------------------
1784 wxWindow
*wxWindowBase::FindFocus()
1786 return g_focusWindow
;
1789 //-----------------------------------------------------------------------------
1790 // "realize" from m_widget
1791 //-----------------------------------------------------------------------------
1793 /* We cannot set colours and fonts before the widget has
1794 been realized, so we do this directly after realization. */
1797 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1802 wxapp_install_idle_handler();
1804 if (win
->m_delayedBackgroundColour
)
1805 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1807 if (win
->m_delayedForegroundColour
)
1808 win
->SetForegroundColour( win
->GetForegroundColour() );
1810 wxWindowCreateEvent
event( win
);
1811 event
.SetEventObject( win
);
1812 win
->GetEventHandler()->ProcessEvent( event
);
1817 //-----------------------------------------------------------------------------
1819 //-----------------------------------------------------------------------------
1822 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
1823 GtkAllocation
*WXUNUSED(alloc
),
1827 wxapp_install_idle_handler();
1829 if (!win
->m_hasScrolling
) return;
1831 int client_width
= 0;
1832 int client_height
= 0;
1833 win
->GetClientSize( &client_width
, &client_height
);
1834 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
1837 win
->m_oldClientWidth
= client_width
;
1838 win
->m_oldClientHeight
= client_height
;
1840 if (!win
->m_nativeSizeEvent
)
1842 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
1843 event
.SetEventObject( win
);
1844 win
->GetEventHandler()->ProcessEvent( event
);
1850 #define WXUNUSED_UNLESS_XIM(param) param
1852 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1855 /* Resize XIM window */
1858 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1859 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1860 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1863 wxapp_install_idle_handler();
1869 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1873 gdk_window_get_size (widget
->window
, &width
, &height
);
1874 win
->m_icattr
->preedit_area
.width
= width
;
1875 win
->m_icattr
->preedit_area
.height
= height
;
1876 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
1881 //-----------------------------------------------------------------------------
1882 // "realize" from m_wxwindow
1883 //-----------------------------------------------------------------------------
1885 /* Initialize XIM support */
1888 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1889 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1892 wxapp_install_idle_handler();
1895 if (win
->m_ic
) return FALSE
;
1896 if (!widget
) return FALSE
;
1897 if (!gdk_im_ready()) return FALSE
;
1899 win
->m_icattr
= gdk_ic_attr_new();
1900 if (!win
->m_icattr
) return FALSE
;
1904 GdkColormap
*colormap
;
1905 GdkICAttr
*attr
= win
->m_icattr
;
1906 unsigned attrmask
= GDK_IC_ALL_REQ
;
1908 GdkIMStyle supported_style
= (GdkIMStyle
)
1909 (GDK_IM_PREEDIT_NONE
|
1910 GDK_IM_PREEDIT_NOTHING
|
1911 GDK_IM_PREEDIT_POSITION
|
1912 GDK_IM_STATUS_NONE
|
1913 GDK_IM_STATUS_NOTHING
);
1915 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1916 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
1918 attr
->style
= style
= gdk_im_decide_style (supported_style
);
1919 attr
->client_window
= widget
->window
;
1921 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
1922 gtk_widget_get_default_colormap ())
1924 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
1925 attr
->preedit_colormap
= colormap
;
1928 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
1929 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
1930 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
1931 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
1933 switch (style
& GDK_IM_PREEDIT_MASK
)
1935 case GDK_IM_PREEDIT_POSITION
:
1936 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1938 g_warning ("over-the-spot style requires fontset");
1942 gdk_window_get_size (widget
->window
, &width
, &height
);
1944 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
1945 attr
->spot_location
.x
= 0;
1946 attr
->spot_location
.y
= height
;
1947 attr
->preedit_area
.x
= 0;
1948 attr
->preedit_area
.y
= 0;
1949 attr
->preedit_area
.width
= width
;
1950 attr
->preedit_area
.height
= height
;
1951 attr
->preedit_fontset
= widget
->style
->font
;
1956 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
1958 if (win
->m_ic
== NULL
)
1959 g_warning ("Can't create input context.");
1962 mask
= gdk_window_get_events (widget
->window
);
1963 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
1964 gdk_window_set_events (widget
->window
, mask
);
1966 if (GTK_WIDGET_HAS_FOCUS(widget
))
1967 gdk_im_begin (win
->m_ic
, widget
->window
);
1974 //-----------------------------------------------------------------------------
1975 // InsertChild for wxWindow.
1976 //-----------------------------------------------------------------------------
1978 /* Callback for wxWindow. This very strange beast has to be used because
1979 * C++ has no virtual methods in a constructor. We have to emulate a
1980 * virtual function here as wxNotebook requires a different way to insert
1981 * a child in it. I had opted for creating a wxNotebookPage window class
1982 * which would have made this superfluous (such in the MDI window system),
1983 * but no-one was listening to me... */
1985 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1987 /* the window might have been scrolled already, do we
1988 have to adapt the position */
1989 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
1990 child
->m_x
+= pizza
->xoffset
;
1991 child
->m_y
+= pizza
->yoffset
;
1993 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
1994 GTK_WIDGET(child
->m_widget
),
2001 //-----------------------------------------------------------------------------
2003 //-----------------------------------------------------------------------------
2005 wxWindow
* wxGetActiveWindow()
2007 return g_focusWindow
;
2010 //-----------------------------------------------------------------------------
2012 //-----------------------------------------------------------------------------
2014 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2016 void wxWindow::Init()
2022 m_widget
= (GtkWidget
*) NULL
;
2023 m_wxwindow
= (GtkWidget
*) NULL
;
2033 m_needParent
= TRUE
;
2034 m_isBeingDeleted
= FALSE
;
2037 m_nativeSizeEvent
= FALSE
;
2039 m_hasScrolling
= FALSE
;
2040 m_isScrolling
= FALSE
;
2042 m_hAdjust
= (GtkAdjustment
*) NULL
;
2043 m_vAdjust
= (GtkAdjustment
*) NULL
;
2044 m_oldHorizontalPos
= 0.0;
2045 m_oldVerticalPos
= 0.0;
2048 m_widgetStyle
= (GtkStyle
*) NULL
;
2050 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2052 m_isStaticBox
= FALSE
;
2053 m_isRadioButton
= FALSE
;
2055 m_acceptsFocus
= FALSE
;
2057 m_clipPaintRegion
= FALSE
;
2058 m_queuedFullRedraw
= FALSE
;
2060 m_cursor
= *wxSTANDARD_CURSOR
;
2063 m_ic
= (GdkIC
*) NULL
;
2064 m_icattr
= (GdkICAttr
*) NULL
;
2068 wxWindow::wxWindow()
2073 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
2074 const wxPoint
&pos
, const wxSize
&size
,
2075 long style
, const wxString
&name
)
2079 Create( parent
, id
, pos
, size
, style
, name
);
2082 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
2083 const wxPoint
&pos
, const wxSize
&size
,
2084 long style
, const wxString
&name
)
2086 if (!PreCreation( parent
, pos
, size
) ||
2087 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2089 wxFAIL_MSG( wxT("wxWindow creation failed") );
2093 m_insertCallback
= wxInsertChildInWindow
;
2095 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2096 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2098 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2100 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2101 scroll_class
->scrollbar_spacing
= 0;
2103 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2105 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2106 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2108 m_wxwindow
= gtk_pizza_new();
2110 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2112 #if (GTK_MINOR_VERSION > 0)
2113 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2115 if (HasFlag(wxRAISED_BORDER
))
2117 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2119 else if (HasFlag(wxSUNKEN_BORDER
))
2121 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2123 else if (HasFlag(wxSIMPLE_BORDER
))
2125 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2129 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2131 #else // GTK_MINOR_VERSION == 0
2132 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2134 if (HasFlag(wxRAISED_BORDER
))
2136 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2138 else if (HasFlag(wxSUNKEN_BORDER
))
2140 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2144 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2146 #endif // GTK_MINOR_VERSION
2148 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2149 m_acceptsFocus
= TRUE
;
2151 #if (GTK_MINOR_VERSION == 0)
2152 // shut the viewport up
2153 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2154 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2155 #endif // GTK_MINOR_VERSION == 0
2157 // I _really_ don't want scrollbars in the beginning
2158 m_vAdjust
->lower
= 0.0;
2159 m_vAdjust
->upper
= 1.0;
2160 m_vAdjust
->value
= 0.0;
2161 m_vAdjust
->step_increment
= 1.0;
2162 m_vAdjust
->page_increment
= 1.0;
2163 m_vAdjust
->page_size
= 5.0;
2164 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2165 m_hAdjust
->lower
= 0.0;
2166 m_hAdjust
->upper
= 1.0;
2167 m_hAdjust
->value
= 0.0;
2168 m_hAdjust
->step_increment
= 1.0;
2169 m_hAdjust
->page_increment
= 1.0;
2170 m_hAdjust
->page_size
= 5.0;
2171 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2173 // these handlers block mouse events to any window during scrolling such as
2174 // motion events and prevent GTK and wxWindows from fighting over where the
2177 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2178 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2180 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2181 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2183 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2184 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2186 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2187 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2189 // these handlers get notified when screen updates are required either when
2190 // scrolling or when the window size (and therefore scrollbar configuration)
2193 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2194 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2195 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2196 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2198 gtk_widget_show( m_wxwindow
);
2201 m_parent
->DoAddChild( this );
2210 wxWindow::~wxWindow()
2212 m_isBeingDeleted
= TRUE
;
2221 m_parent
->RemoveChild( this );
2225 gdk_ic_destroy (m_ic
);
2227 gdk_ic_attr_destroy (m_icattr
);
2232 #if DISABLE_STYLE_IF_BROKEN_THEME
2233 // don't delete if it's a pixmap theme style
2234 if (!m_widgetStyle
->engine_data
)
2235 gtk_style_unref( m_widgetStyle
);
2237 m_widgetStyle
= (GtkStyle
*) NULL
;
2242 gtk_widget_destroy( m_wxwindow
);
2243 m_wxwindow
= (GtkWidget
*) NULL
;
2248 gtk_widget_destroy( m_widget
);
2249 m_widget
= (GtkWidget
*) NULL
;
2253 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2255 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2257 /* this turns -1 into 20 so that a minimal window is
2258 visible even although -1,-1 has been given as the
2259 size of the window. the same trick is used in other
2260 ports and should make debugging easier */
2261 m_width
= WidthDefault(size
.x
);
2262 m_height
= HeightDefault(size
.y
);
2267 /* some reasonable defaults */
2272 m_x
= (gdk_screen_width () - m_width
) / 2;
2273 if (m_x
< 10) m_x
= 10;
2277 m_y
= (gdk_screen_height () - m_height
) / 2;
2278 if (m_y
< 10) m_y
= 10;
2285 void wxWindow::PostCreation()
2287 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2293 /* these get reported to wxWindows -> wxPaintEvent */
2294 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2295 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2297 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2298 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2300 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2301 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2304 #if (GTK_MINOR_VERSION > 0)
2305 /* these are called when the "sunken" or "raised" borders are drawn */
2306 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2307 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2309 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2310 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2314 if (m_wxwindow
&& m_needParent
)
2316 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2317 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2319 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2320 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2324 // For dialogs and frames, we are interested mainly in
2325 // m_widget's focus.
2327 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2328 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2330 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2331 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2334 GtkWidget
*connect_widget
= GetConnectWidget();
2336 ConnectWidget( connect_widget
);
2338 /* We cannot set colours, fonts and cursors before the widget has
2339 been realized, so we do this directly after realization */
2340 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2341 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2345 /* Catch native resize events. */
2346 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2347 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2349 /* Initialize XIM support. */
2350 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2351 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2353 /* And resize XIM window. */
2354 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2355 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2361 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2363 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2364 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2366 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2367 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2369 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2370 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2372 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2373 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2375 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2376 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2378 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2379 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2381 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2382 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2385 bool wxWindow::Destroy()
2387 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2391 return wxWindowBase::Destroy();
2394 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2396 if (m_wxwindow
&& GTK_PIZZA(m_wxwindow
)->bin_window
)
2398 /* Normally, GTK will send expose events only for the regions
2399 which actually got exposed. Sadly, wxMSW invalidates
2400 the whole window so we have to do that, too. We could
2401 simply add a complete refresh, but we would then get
2402 the normal GTK expose events in surplus, so we shut
2403 off the expose events and schedule a full redraw to
2404 be done in OnInternalIdle, where we restore the handling
2405 of expose events. */
2407 m_queuedFullRedraw
= TRUE
;
2409 GdkEventMask mask
= gdk_window_get_events( GTK_PIZZA(m_wxwindow
)->bin_window
);
2410 mask
= (GdkEventMask
)(mask
& ~GDK_EXPOSURE_MASK
);
2411 gdk_window_set_events( GTK_PIZZA(m_wxwindow
)->bin_window
, mask
);
2414 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2417 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2419 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2420 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2422 if (m_resizing
) return; /* I don't like recursions */
2425 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2427 /* don't set the size for children of wxNotebook, just take the values. */
2435 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2437 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2439 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2440 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2441 if (width
!= -1) m_width
= width
;
2442 if (height
!= -1) m_height
= height
;
2446 m_x
= x
+ pizza
->xoffset
;
2447 m_y
= y
+ pizza
->yoffset
;
2452 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2454 if (width
== -1) m_width
= 80;
2457 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2459 if (height
== -1) m_height
= 26;
2462 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2463 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2464 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2465 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2468 int bottom_border
= 0;
2470 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2472 /* the default button has a border around it */
2477 DoMoveWindow( m_x
-border
,
2480 m_height
+border
+bottom_border
);
2485 /* Sometimes the client area changes size without the
2486 whole windows's size changing, but if the whole
2487 windows's size doesn't change, no wxSizeEvent will
2488 normally be sent. Here we add an extra test if
2489 the client test has been changed and this will
2491 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2495 wxPrintf( "OnSize sent from " );
2496 if (GetClassInfo() && GetClassInfo()->GetClassName())
2497 wxPrintf( GetClassInfo()->GetClassName() );
2498 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2501 if (!m_nativeSizeEvent
)
2503 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2504 event
.SetEventObject( this );
2505 GetEventHandler()->ProcessEvent( event
);
2511 void wxWindow::OnInternalIdle()
2513 if ( g_sendActivateEvent
!= -1 )
2515 bool activate
= g_sendActivateEvent
!= 0;
2518 g_sendActivateEvent
= -1;
2520 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2521 event
.SetEventObject(this);
2523 (void)GetEventHandler()->ProcessEvent(event
);
2526 wxCursor cursor
= m_cursor
;
2527 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2531 /* I now set the cursor anew in every OnInternalIdle call
2532 as setting the cursor in a parent window also effects the
2533 windows above so that checking for the current cursor is
2538 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2540 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2542 if (!g_globalCursor
.Ok())
2543 cursor
= *wxSTANDARD_CURSOR
;
2545 window
= m_widget
->window
;
2546 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2547 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2553 GdkWindow
*window
= m_widget
->window
;
2554 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2555 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2562 if (m_queuedFullRedraw
)
2564 /* See also wxWindow::DoMoveWindow for explanation of this code. What
2565 we test here is if the requested size of the window is the same as
2566 the actual size of window, in which case all expose events that resulted
2567 from resizing the window have been sent (and discarded) and we can
2568 now do our full redraw and switch on expose event handling again. */
2570 if ((m_width
== m_widget
->allocation
.width
) && (m_height
== m_widget
->allocation
.height
))
2572 m_queuedFullRedraw
= FALSE
;
2573 m_updateRegion
.Clear();
2574 m_updateRegion
.Union( 0,0,m_width
,m_height
);
2575 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2577 GdkEventMask mask
= gdk_window_get_events( GTK_PIZZA(m_wxwindow
)->bin_window
);
2578 mask
= (GdkEventMask
)(mask
| GDK_EXPOSURE_MASK
);
2579 gdk_window_set_events( GTK_PIZZA(m_wxwindow
)->bin_window
, mask
);
2584 void wxWindow::DoGetSize( int *width
, int *height
) const
2586 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2588 if (width
) (*width
) = m_width
;
2589 if (height
) (*height
) = m_height
;
2592 void wxWindow::DoSetClientSize( int width
, int height
)
2594 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2598 SetSize( width
, height
);
2605 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2607 /* when using GTK 1.2 we set the shadow border size to 2 */
2611 if (HasFlag(wxSIMPLE_BORDER
))
2613 /* when using GTK 1.2 we set the simple border size to 1 */
2620 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2622 GtkRequisition vscroll_req
;
2623 vscroll_req
.width
= 2;
2624 vscroll_req
.height
= 2;
2625 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
2626 (scroll_window
->vscrollbar
, &vscroll_req
);
2628 GtkRequisition hscroll_req
;
2629 hscroll_req
.width
= 2;
2630 hscroll_req
.height
= 2;
2631 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
2632 (scroll_window
->hscrollbar
, &hscroll_req
);
2634 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2636 if (scroll_window
->vscrollbar_visible
)
2638 dw
+= vscroll_req
.width
;
2639 dw
+= scroll_class
->scrollbar_spacing
;
2642 if (scroll_window
->hscrollbar_visible
)
2644 dh
+= hscroll_req
.height
;
2645 dh
+= scroll_class
->scrollbar_spacing
;
2649 SetSize( width
+dw
, height
+dh
);
2653 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2655 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2659 if (width
) (*width
) = m_width
;
2660 if (height
) (*height
) = m_height
;
2667 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2669 /* when using GTK 1.2 we set the shadow border size to 2 */
2673 if (HasFlag(wxSIMPLE_BORDER
))
2675 /* when using GTK 1.2 we set the simple border size to 1 */
2682 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2684 GtkRequisition vscroll_req
;
2685 vscroll_req
.width
= 2;
2686 vscroll_req
.height
= 2;
2687 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
2688 (scroll_window
->vscrollbar
, &vscroll_req
);
2690 GtkRequisition hscroll_req
;
2691 hscroll_req
.width
= 2;
2692 hscroll_req
.height
= 2;
2693 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
2694 (scroll_window
->hscrollbar
, &hscroll_req
);
2696 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2698 if (scroll_window
->vscrollbar_visible
)
2700 dw
+= vscroll_req
.width
;
2701 dw
+= scroll_class
->scrollbar_spacing
;
2704 if (scroll_window
->hscrollbar_visible
)
2706 dh
+= hscroll_req
.height
;
2707 dh
+= scroll_class
->scrollbar_spacing
;
2711 if (width
) (*width
) = m_width
- dw
;
2712 if (height
) (*height
) = m_height
- dh
;
2716 void wxWindow::DoGetPosition( int *x
, int *y
) const
2718 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2722 if (m_parent
&& m_parent
->m_wxwindow
)
2724 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2725 dx
= pizza
->xoffset
;
2726 dy
= pizza
->yoffset
;
2729 if (x
) (*x
) = m_x
- dx
;
2730 if (y
) (*y
) = m_y
- dy
;
2733 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2735 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2737 if (!m_widget
->window
) return;
2739 GdkWindow
*source
= (GdkWindow
*) NULL
;
2741 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2743 source
= m_widget
->window
;
2747 gdk_window_get_origin( source
, &org_x
, &org_y
);
2751 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2753 org_x
+= m_widget
->allocation
.x
;
2754 org_y
+= m_widget
->allocation
.y
;
2762 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2764 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2766 if (!m_widget
->window
) return;
2768 GdkWindow
*source
= (GdkWindow
*) NULL
;
2770 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2772 source
= m_widget
->window
;
2776 gdk_window_get_origin( source
, &org_x
, &org_y
);
2780 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2782 org_x
+= m_widget
->allocation
.x
;
2783 org_y
+= m_widget
->allocation
.y
;
2791 bool wxWindow::Show( bool show
)
2793 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2795 if (!wxWindowBase::Show(show
))
2802 gtk_widget_show( m_widget
);
2804 gtk_widget_hide( m_widget
);
2809 bool wxWindow::Enable( bool enable
)
2811 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2813 if (!wxWindowBase::Enable(enable
))
2819 gtk_widget_set_sensitive( m_widget
, enable
);
2821 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2826 int wxWindow::GetCharHeight() const
2828 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2830 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2832 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2834 return font
->ascent
+ font
->descent
;
2837 int wxWindow::GetCharWidth() const
2839 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2841 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2843 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2845 return gdk_string_width( font
, "H" );
2848 void wxWindow::GetTextExtent( const wxString
& string
,
2852 int *externalLeading
,
2853 const wxFont
*theFont
) const
2855 wxFont fontToUse
= m_font
;
2856 if (theFont
) fontToUse
= *theFont
;
2858 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2860 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2861 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2862 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2863 if (descent
) (*descent
) = font
->descent
;
2864 if (externalLeading
) (*externalLeading
) = 0; // ??
2867 void wxWindow::SetFocus()
2869 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2873 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2874 gtk_widget_grab_focus (m_wxwindow
);
2880 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2882 gtk_widget_grab_focus (m_widget
);
2884 else if (GTK_IS_CONTAINER(m_widget
))
2886 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2895 bool wxWindow::AcceptsFocus() const
2897 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2900 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2902 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2904 wxWindow
*oldParent
= m_parent
,
2905 *newParent
= (wxWindow
*)newParentBase
;
2907 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2909 if ( !wxWindowBase::Reparent(newParent
) )
2912 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2914 /* prevent GTK from deleting the widget arbitrarily */
2915 gtk_widget_ref( m_widget
);
2919 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2922 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2926 /* insert GTK representation */
2927 (*(newParent
->m_insertCallback
))(newParent
, this);
2930 /* reverse: prevent GTK from deleting the widget arbitrarily */
2931 gtk_widget_unref( m_widget
);
2936 void wxWindow::DoAddChild(wxWindow
*child
)
2938 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2940 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
2942 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
2947 /* insert GTK representation */
2948 (*m_insertCallback
)(this, child
);
2951 void wxWindow::Raise()
2953 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2955 if (!m_widget
->window
) return;
2957 gdk_window_raise( m_widget
->window
);
2960 void wxWindow::Lower()
2962 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2964 if (!m_widget
->window
) return;
2966 gdk_window_lower( m_widget
->window
);
2969 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2971 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2973 return wxWindowBase::SetCursor( cursor
);
2976 void wxWindow::WarpPointer( int x
, int y
)
2978 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2980 /* we provide this function ourselves as it is
2981 missing in GDK (top of this file) */
2983 GdkWindow
*window
= (GdkWindow
*) NULL
;
2985 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2987 window
= GetConnectWidget()->window
;
2990 gdk_window_warp_pointer( window
, x
, y
);
2993 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2995 if (!m_widget
) return;
2996 if (!m_widget
->window
) return;
2998 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3002 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3004 rect
->width
, rect
->height
);
3008 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3012 /* there is no GTK equivalent of "draw only, don't clear" so we
3013 invent our own in the GtkPizza widget */
3021 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3022 gboolean old_clear = pizza->clear_on_draw;
3023 gtk_pizza_set_clear( pizza, FALSE );
3024 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3025 gtk_pizza_set_clear( pizza, old_clear );
3027 GdkEventExpose gdk_event
;
3028 gdk_event
.count
= 0;
3029 gdk_event
.area
.x
= 0;
3030 gdk_event
.area
.y
= 0;
3031 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3032 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3033 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3038 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3047 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3048 gboolean old_clear = pizza->clear_on_draw;
3049 gtk_pizza_set_clear( pizza, FALSE );
3051 GdkRectangle gdk_rect;
3052 gdk_rect.x = rect->x;
3053 gdk_rect.y = rect->y;
3054 gdk_rect.width = rect->width;
3055 gdk_rect.height = rect->height;
3056 gtk_widget_draw( m_wxwindow, &gdk_rect );
3057 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3059 gtk_pizza_set_clear( pizza, old_clear );
3061 GdkEventExpose gdk_event
;
3062 gdk_event
.count
= 0;
3063 gdk_event
.area
.x
= rect
->x
;
3064 gdk_event
.area
.y
= rect
->y
;
3065 gdk_event
.area
.width
= rect
->width
;
3066 gdk_event
.area
.height
= rect
->height
;
3067 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3071 GdkRectangle gdk_rect
;
3072 gdk_rect
.x
= rect
->x
;
3073 gdk_rect
.y
= rect
->y
;
3074 gdk_rect
.width
= rect
->width
;
3075 gdk_rect
.height
= rect
->height
;
3076 gtk_widget_draw( m_widget
, &gdk_rect
);
3081 void wxWindow::Clear()
3083 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3085 if (!m_widget
->window
) return;
3087 if (m_wxwindow
&& m_wxwindow
->window
)
3089 // gdk_window_clear( m_wxwindow->window );
3094 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
3096 wxWindowBase::DoSetToolTip(tip
);
3099 m_tooltip
->Apply( this );
3102 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3104 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3106 #endif // wxUSE_TOOLTIPS
3108 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
3110 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3112 if (!wxWindowBase::SetBackgroundColour(colour
))
3114 // don't leave if the GTK widget has just
3116 if (!m_delayedBackgroundColour
) return FALSE
;
3119 GdkWindow
*window
= (GdkWindow
*) NULL
;
3121 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3123 window
= GetConnectWidget()->window
;
3127 // indicate that a new style has been set
3128 // but it couldn't get applied as the
3129 // widget hasn't been realized yet.
3130 m_delayedBackgroundColour
= TRUE
;
3134 (m_wxwindow
->window
) &&
3135 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3137 /* wxMSW doesn't clear the window here. I don't do that either to
3138 provide compatibility. call Clear() to do the job. */
3140 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3141 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3149 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
3151 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3153 if (!wxWindowBase::SetForegroundColour(colour
))
3155 // don't leave if the GTK widget has just
3157 if (!m_delayedForegroundColour
) return FALSE
;
3160 GdkWindow
*window
= (GdkWindow
*) NULL
;
3162 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3164 window
= GetConnectWidget()->window
;
3168 // indicate that a new style has been set
3169 // but it couldn't get applied as the
3170 // widget hasn't been realized yet.
3171 m_delayedForegroundColour
= TRUE
;
3179 GtkStyle
*wxWindow::GetWidgetStyle()
3183 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3184 remake
->klass
= m_widgetStyle
->klass
;
3186 gtk_style_unref( m_widgetStyle
);
3187 m_widgetStyle
= remake
;
3191 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3194 def
= gtk_widget_get_default_style();
3196 m_widgetStyle
= gtk_style_copy( def
);
3197 m_widgetStyle
->klass
= def
->klass
;
3200 return m_widgetStyle
;
3203 void wxWindow::SetWidgetStyle()
3205 #if DISABLE_STYLE_IF_BROKEN_THEM
3206 if (m_widget
->style
->engine_data
)
3208 static bool s_warningPrinted
= FALSE
;
3209 if (!s_warningPrinted
)
3211 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3212 s_warningPrinted
= TRUE
;
3214 m_widgetStyle
= m_widget
->style
;
3219 GtkStyle
*style
= GetWidgetStyle();
3221 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3223 gdk_font_unref( style
->font
);
3224 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3227 if (m_foregroundColour
.Ok())
3229 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3230 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3232 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3233 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3234 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3238 if (m_backgroundColour
.Ok())
3240 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3241 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3243 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3244 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3245 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3246 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3247 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3248 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3249 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3250 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3255 void wxWindow::ApplyWidgetStyle()
3259 //-----------------------------------------------------------------------------
3260 // Pop-up menu stuff
3261 //-----------------------------------------------------------------------------
3263 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3265 *is_waiting
= FALSE
;
3268 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3270 menu
->SetInvokingWindow( win
);
3271 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3274 wxMenuItem
*menuitem
= node
->GetData();
3275 if (menuitem
->IsSubMenu())
3277 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3280 node
= node
->GetNext();
3284 static gint gs_pop_x
= 0;
3285 static gint gs_pop_y
= 0;
3287 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3291 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3296 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3298 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3300 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3302 SetInvokingWindow( menu
, this );
3309 bool is_waiting
= TRUE
;
3311 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3312 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3315 GTK_MENU(menu
->m_menu
),
3316 (GtkWidget
*) NULL
, // parent menu shell
3317 (GtkWidget
*) NULL
, // parent menu item
3318 (GtkMenuPositionFunc
) pop_pos_callback
,
3319 (gpointer
) this, // client data
3320 0, // button used to activate it
3321 gs_timeLastClick
// the time of activation
3326 while (gtk_events_pending())
3327 gtk_main_iteration();
3333 #if wxUSE_DRAG_AND_DROP
3335 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3337 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3339 GtkWidget
*dnd_widget
= GetConnectWidget();
3341 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3343 if (m_dropTarget
) delete m_dropTarget
;
3344 m_dropTarget
= dropTarget
;
3346 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3349 #endif // wxUSE_DRAG_AND_DROP
3351 GtkWidget
* wxWindow::GetConnectWidget()
3353 GtkWidget
*connect_widget
= m_widget
;
3354 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3356 return connect_widget
;
3359 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3362 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3364 return (window
== m_widget
->window
);
3367 bool wxWindow::SetFont( const wxFont
&font
)
3369 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3371 if (!wxWindowBase::SetFont(font
))
3376 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3377 if ( sysbg
== m_backgroundColour
)
3379 m_backgroundColour
= wxNullColour
;
3381 m_backgroundColour
= sysbg
;
3391 void wxWindow::CaptureMouse()
3393 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3395 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3397 GdkWindow
*window
= (GdkWindow
*) NULL
;
3399 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3401 window
= GetConnectWidget()->window
;
3403 if (!window
) return;
3405 gdk_pointer_grab( window
, FALSE
,
3407 (GDK_BUTTON_PRESS_MASK
|
3408 GDK_BUTTON_RELEASE_MASK
|
3409 GDK_POINTER_MOTION_HINT_MASK
|
3410 GDK_POINTER_MOTION_MASK
),
3412 m_cursor
.GetCursor(),
3413 (guint32
)GDK_CURRENT_TIME
);
3414 g_captureWindow
= this;
3417 void wxWindow::ReleaseMouse()
3419 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3421 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3423 GdkWindow
*window
= (GdkWindow
*) NULL
;
3425 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3427 window
= GetConnectWidget()->window
;
3432 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3433 g_captureWindow
= (wxWindow
*) NULL
;
3436 bool wxWindow::IsRetained() const
3441 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3442 int range
, bool refresh
)
3444 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3446 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3448 m_hasScrolling
= TRUE
;
3450 if (orient
== wxHORIZONTAL
)
3452 float fpos
= (float)pos
;
3453 float frange
= (float)range
;
3454 float fthumb
= (float)thumbVisible
;
3455 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3456 if (fpos
< 0.0) fpos
= 0.0;
3458 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3459 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3461 SetScrollPos( orient
, pos
, refresh
);
3465 m_oldHorizontalPos
= fpos
;
3467 m_hAdjust
->lower
= 0.0;
3468 m_hAdjust
->upper
= frange
;
3469 m_hAdjust
->value
= fpos
;
3470 m_hAdjust
->step_increment
= 1.0;
3471 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3472 m_hAdjust
->page_size
= fthumb
;
3476 float fpos
= (float)pos
;
3477 float frange
= (float)range
;
3478 float fthumb
= (float)thumbVisible
;
3479 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3480 if (fpos
< 0.0) fpos
= 0.0;
3482 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3483 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3485 SetScrollPos( orient
, pos
, refresh
);
3489 m_oldVerticalPos
= fpos
;
3491 m_vAdjust
->lower
= 0.0;
3492 m_vAdjust
->upper
= frange
;
3493 m_vAdjust
->value
= fpos
;
3494 m_vAdjust
->step_increment
= 1.0;
3495 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3496 m_vAdjust
->page_size
= fthumb
;
3499 if (orient
== wxHORIZONTAL
)
3500 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3502 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3505 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3507 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3509 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3511 if (orient
== wxHORIZONTAL
)
3513 float fpos
= (float)pos
;
3514 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3515 if (fpos
< 0.0) fpos
= 0.0;
3516 m_oldHorizontalPos
= fpos
;
3518 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3519 m_hAdjust
->value
= fpos
;
3523 float fpos
= (float)pos
;
3524 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3525 if (fpos
< 0.0) fpos
= 0.0;
3526 m_oldVerticalPos
= fpos
;
3528 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3529 m_vAdjust
->value
= fpos
;
3532 if (m_wxwindow
->window
)
3534 if (orient
== wxHORIZONTAL
)
3536 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3537 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3539 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3541 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3542 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3546 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3547 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3549 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3551 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3552 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3557 int wxWindow::GetScrollThumb( int orient
) const
3559 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3561 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3563 if (orient
== wxHORIZONTAL
)
3564 return (int)(m_hAdjust
->page_size
+0.5);
3566 return (int)(m_vAdjust
->page_size
+0.5);
3569 int wxWindow::GetScrollPos( int orient
) const
3571 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3573 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3575 if (orient
== wxHORIZONTAL
)
3576 return (int)(m_hAdjust
->value
+0.5);
3578 return (int)(m_vAdjust
->value
+0.5);
3581 int wxWindow::GetScrollRange( int orient
) const
3583 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3585 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3587 if (orient
== wxHORIZONTAL
)
3588 return (int)(m_hAdjust
->upper
+0.5);
3590 return (int)(m_vAdjust
->upper
+0.5);
3593 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3595 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3597 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3599 if ((dx
== 0) && (dy
== 0)) return;
3601 m_clipPaintRegion
= TRUE
;
3602 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3603 m_clipPaintRegion
= FALSE
;
3606 if (m_children.GetCount() > 0)
3608 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3612 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3614 pizza->xoffset -= dx;
3615 pizza->yoffset -= dy;
3617 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3618 gdk_gc_set_exposures( m_scrollGC, TRUE );
3622 GetClientSize( &cw, &ch );
3623 int w = cw - abs(dx);
3624 int h = ch - abs(dy);
3626 if ((h < 0) || (w < 0))
3634 if (dx < 0) s_x = -dx;
3635 if (dy < 0) s_y = -dy;
3638 if (dx > 0) d_x = dx;
3639 if (dy > 0) d_y = dy;
3641 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3642 pizza->bin_window, s_x, s_y, w, h );
3645 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3646 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3647 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3648 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3650 Refresh( TRUE, &rect );
3653 gdk_gc_unref( m_scrollGC );