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 wxEraseEvent
eevent( win
->GetId() );
751 eevent
.SetEventObject( win
);
752 win
->GetEventHandler()->ProcessEvent(eevent
);
754 wxPaintEvent
event( win
->GetId() );
755 event
.SetEventObject( win
);
756 win
->GetEventHandler()->ProcessEvent( event
);
758 win
->GetUpdateRegion().Clear();
760 GList
*children
= pizza
->children
;
763 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
764 children
= children
->next
;
766 GdkRectangle child_area
;
767 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
768 gtk_widget_draw (child
->widget
, (GdkRectangle
*) NULL
);
772 //-----------------------------------------------------------------------------
773 // "key_press_event" from any window
774 //-----------------------------------------------------------------------------
776 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
781 wxapp_install_idle_handler();
783 if (!win
->m_hasVMT
) return FALSE
;
784 if (g_blockEventsOnDrag
) return FALSE
;
788 tmp += (char)gdk_event->keyval;
789 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
790 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
795 GdkModifierType state
;
796 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
800 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
801 /* sending unknown key events doesn't really make sense */
802 if (key_code
== 0) return FALSE
;
804 wxKeyEvent
event( wxEVT_KEY_DOWN
);
805 event
.SetTimestamp( gdk_event
->time
);
806 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
807 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
808 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
809 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
810 event
.m_keyCode
= key_code
;
811 event
.m_scanCode
= gdk_event
->keyval
;
814 event
.SetEventObject( win
);
815 ret
= win
->GetEventHandler()->ProcessEvent( event
);
820 wxWindow
*ancestor
= win
;
823 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
826 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
827 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
830 if (ancestor
->m_isFrame
)
832 ancestor
= ancestor
->GetParent();
835 #endif // wxUSE_ACCEL
837 /* wxMSW doesn't send char events with Alt pressed */
838 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
839 will only be sent if it is not in an accelerator table. */
840 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
845 wxKeyEvent
event2( wxEVT_CHAR
);
846 event2
.SetTimestamp( gdk_event
->time
);
847 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
848 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
849 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
850 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
851 event2
.m_keyCode
= key_code
;
852 event2
.m_scanCode
= gdk_event
->keyval
;
855 event2
.SetEventObject( win
);
856 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
859 /* win is a control: tab can be propagated up */
861 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
862 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
863 (win
->GetParent()) &&
864 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
866 wxNavigationKeyEvent new_event
;
867 new_event
.SetEventObject( win
->GetParent() );
868 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
869 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
870 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
871 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
872 new_event
.SetCurrentFocus( win
);
873 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
876 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
878 (gdk_event
->keyval
== GDK_Escape
) )
880 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
881 new_event
.SetEventObject( win
);
882 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
885 #if (GTK_MINOR_VERSION > 0)
886 /* Pressing F10 will activate the menu bar of the top frame. */
890 (gdk_event->keyval == GDK_F10) )
892 wxWindow *ancestor = win;
895 if (wxIsKindOf(ancestor,wxFrame))
897 wxFrame *frame = (wxFrame*) ancestor;
898 wxMenuBar *menubar = frame->GetMenuBar();
901 wxNode *node = menubar->GetMenus().First();
904 wxMenu *firstMenu = (wxMenu*) node->Data();
905 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
911 ancestor = ancestor->GetParent();
919 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
926 //-----------------------------------------------------------------------------
927 // "key_release_event" from any window
928 //-----------------------------------------------------------------------------
930 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
935 wxapp_install_idle_handler();
937 if (!win
->m_hasVMT
) return FALSE
;
938 if (g_blockEventsOnDrag
) return FALSE
;
941 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
942 if (gdk_event->state & GDK_SHIFT_MASK)
943 printf( "ShiftDown.\n" );
945 printf( "ShiftUp.\n" );
946 if (gdk_event->state & GDK_CONTROL_MASK)
947 printf( "ControlDown.\n" );
949 printf( "ControlUp.\n" );
953 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
955 /* sending unknown key events doesn't really make sense */
956 if (key_code
== 0) return FALSE
;
960 GdkModifierType state
;
961 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
963 wxKeyEvent
event( wxEVT_KEY_UP
);
964 event
.SetTimestamp( gdk_event
->time
);
965 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
966 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
967 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
968 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
969 event
.m_keyCode
= key_code
;
970 event
.m_scanCode
= gdk_event
->keyval
;
973 event
.SetEventObject( win
);
975 if (win
->GetEventHandler()->ProcessEvent( event
))
977 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
984 // ----------------------------------------------------------------------------
985 // mouse event processing helper
986 // ----------------------------------------------------------------------------
988 static void AdjustEventButtonState(wxMouseEvent
& event
)
990 // GDK reports the old state of the button for a button press event, but
991 // for compatibility with MSW and common sense we want m_leftDown be TRUE
992 // for a LEFT_DOWN event, not FALSE, so we will invert
993 // left/right/middleDown for the corresponding click events
994 switch ( event
.GetEventType() )
996 case wxEVT_LEFT_DOWN
:
997 case wxEVT_LEFT_DCLICK
:
999 event
.m_leftDown
= !event
.m_leftDown
;
1002 case wxEVT_MIDDLE_DOWN
:
1003 case wxEVT_MIDDLE_DCLICK
:
1004 case wxEVT_MIDDLE_UP
:
1005 event
.m_middleDown
= !event
.m_middleDown
;
1008 case wxEVT_RIGHT_DOWN
:
1009 case wxEVT_RIGHT_DCLICK
:
1010 case wxEVT_RIGHT_UP
:
1011 event
.m_rightDown
= !event
.m_rightDown
;
1016 //-----------------------------------------------------------------------------
1017 // "button_press_event"
1018 //-----------------------------------------------------------------------------
1020 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1025 wxapp_install_idle_handler();
1028 wxPrintf( wxT("1) OnButtonPress from ") );
1029 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1030 wxPrintf( win->GetClassInfo()->GetClassName() );
1031 wxPrintf( wxT(".\n") );
1033 if (!win
->m_hasVMT
) return FALSE
;
1034 if (g_blockEventsOnDrag
) return TRUE
;
1035 if (g_blockEventsOnScroll
) return TRUE
;
1037 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1039 if (win
->m_wxwindow
)
1041 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1043 gtk_widget_grab_focus (win
->m_wxwindow
);
1046 wxPrintf( wxT("GrabFocus from ") );
1047 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1048 wxPrintf( win->GetClassInfo()->GetClassName() );
1049 wxPrintf( wxT(".\n") );
1055 wxEventType event_type
= wxEVT_NULL
;
1057 if (gdk_event
->button
== 1)
1059 switch (gdk_event
->type
)
1061 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1062 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1066 else if (gdk_event
->button
== 2)
1068 switch (gdk_event
->type
)
1070 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1071 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1075 else if (gdk_event
->button
== 3)
1077 switch (gdk_event
->type
)
1079 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1080 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1085 if ( event_type
== wxEVT_NULL
)
1087 // unknown mouse button or click type
1091 wxMouseEvent
event( event_type
);
1092 event
.SetTimestamp( gdk_event
->time
);
1093 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1094 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1095 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1096 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1097 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1098 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1099 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1101 event
.m_x
= (wxCoord
)gdk_event
->x
;
1102 event
.m_y
= (wxCoord
)gdk_event
->y
;
1104 AdjustEventButtonState(event
);
1106 // Some control don't have their own X window and thus cannot get
1109 if (!g_captureWindow
)
1111 wxCoord x
= event
.m_x
;
1112 wxCoord y
= event
.m_y
;
1113 if (win
->m_wxwindow
)
1115 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1116 x
+= pizza
->xoffset
;
1117 y
+= pizza
->yoffset
;
1120 wxNode
*node
= win
->GetChildren().First();
1123 wxWindow
*child
= (wxWindow
*)node
->Data();
1125 node
= node
->Next();
1126 if (!child
->IsShown())
1129 if (child
->m_isStaticBox
)
1131 // wxStaticBox is transparent in the box itself
1132 int xx1
= child
->m_x
;
1133 int yy1
= child
->m_y
;
1134 int xx2
= child
->m_x
+ child
->m_width
;
1135 int yy2
= child
->m_x
+ child
->m_height
;
1138 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1140 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1142 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1144 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1147 event
.m_x
-= child
->m_x
;
1148 event
.m_y
-= child
->m_y
;
1155 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1156 (child
->m_x
<= x
) &&
1157 (child
->m_y
<= y
) &&
1158 (child
->m_x
+child
->m_width
>= x
) &&
1159 (child
->m_y
+child
->m_height
>= y
))
1162 event
.m_x
-= child
->m_x
;
1163 event
.m_y
-= child
->m_y
;
1170 event
.SetEventObject( win
);
1172 gs_timeLastClick
= gdk_event
->time
;
1175 wxPrintf( wxT("2) OnButtonPress from ") );
1176 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1177 wxPrintf( win->GetClassInfo()->GetClassName() );
1178 wxPrintf( wxT(".\n") );
1181 if (win
->GetEventHandler()->ProcessEvent( event
))
1183 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1190 //-----------------------------------------------------------------------------
1191 // "button_release_event"
1192 //-----------------------------------------------------------------------------
1194 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1199 wxapp_install_idle_handler();
1201 if (!win
->m_hasVMT
) return FALSE
;
1202 if (g_blockEventsOnDrag
) return FALSE
;
1203 if (g_blockEventsOnScroll
) return FALSE
;
1205 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1208 printf( "OnButtonRelease from " );
1209 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1210 printf( win->GetClassInfo()->GetClassName() );
1214 wxEventType event_type
= wxEVT_NULL
;
1216 switch (gdk_event
->button
)
1218 case 1: event_type
= wxEVT_LEFT_UP
; break;
1219 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1220 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1221 default: return FALSE
;
1224 wxMouseEvent
event( event_type
);
1225 event
.SetTimestamp( gdk_event
->time
);
1226 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1227 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1228 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1229 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1230 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1231 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1232 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1233 event
.m_x
= (wxCoord
)gdk_event
->x
;
1234 event
.m_y
= (wxCoord
)gdk_event
->y
;
1236 AdjustEventButtonState(event
);
1238 // Some control don't have their own X window and thus cannot get
1241 if (!g_captureWindow
)
1243 wxCoord x
= event
.m_x
;
1244 wxCoord y
= event
.m_y
;
1245 if (win
->m_wxwindow
)
1247 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1248 x
+= pizza
->xoffset
;
1249 y
+= pizza
->yoffset
;
1252 wxNode
*node
= win
->GetChildren().First();
1255 wxWindow
*child
= (wxWindow
*)node
->Data();
1257 node
= node
->Next();
1258 if (!child
->IsShown())
1261 if (child
->m_isStaticBox
)
1263 // wxStaticBox is transparent in the box itself
1264 int xx1
= child
->m_x
;
1265 int yy1
= child
->m_y
;
1266 int xx2
= child
->m_x
+ child
->m_width
;
1267 int yy2
= child
->m_x
+ child
->m_height
;
1270 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1272 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1274 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1276 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1279 event
.m_x
-= child
->m_x
;
1280 event
.m_y
-= child
->m_y
;
1287 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1288 (child
->m_x
<= x
) &&
1289 (child
->m_y
<= y
) &&
1290 (child
->m_x
+child
->m_width
>= x
) &&
1291 (child
->m_y
+child
->m_height
>= y
))
1294 event
.m_x
-= child
->m_x
;
1295 event
.m_y
-= child
->m_y
;
1302 event
.SetEventObject( win
);
1304 if (win
->GetEventHandler()->ProcessEvent( event
))
1306 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1313 //-----------------------------------------------------------------------------
1314 // "motion_notify_event"
1315 //-----------------------------------------------------------------------------
1317 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1322 wxapp_install_idle_handler();
1324 if (!win
->m_hasVMT
) return FALSE
;
1325 if (g_blockEventsOnDrag
) return FALSE
;
1326 if (g_blockEventsOnScroll
) return FALSE
;
1328 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1330 if (gdk_event
->is_hint
)
1334 GdkModifierType state
;
1335 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1341 printf( "OnMotion from " );
1342 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1343 printf( win->GetClassInfo()->GetClassName() );
1347 wxMouseEvent
event( wxEVT_MOTION
);
1348 event
.SetTimestamp( gdk_event
->time
);
1349 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1350 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1351 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1352 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1353 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1354 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1355 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1357 event
.m_x
= (wxCoord
)gdk_event
->x
;
1358 event
.m_y
= (wxCoord
)gdk_event
->y
;
1360 // Some control don't have their own X window and thus cannot get
1363 if (!g_captureWindow
)
1365 wxCoord x
= event
.m_x
;
1366 wxCoord y
= event
.m_y
;
1367 if (win
->m_wxwindow
)
1369 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1370 x
+= pizza
->xoffset
;
1371 y
+= pizza
->yoffset
;
1374 wxNode
*node
= win
->GetChildren().First();
1377 wxWindow
*child
= (wxWindow
*)node
->Data();
1379 node
= node
->Next();
1380 if (!child
->IsShown())
1383 if (child
->m_isStaticBox
)
1385 // wxStaticBox is transparent in the box itself
1386 int xx1
= child
->m_x
;
1387 int yy1
= child
->m_y
;
1388 int xx2
= child
->m_x
+ child
->m_width
;
1389 int yy2
= child
->m_x
+ child
->m_height
;
1392 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1394 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1396 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1398 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1401 event
.m_x
-= child
->m_x
;
1402 event
.m_y
-= child
->m_y
;
1409 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1410 (child
->m_x
<= x
) &&
1411 (child
->m_y
<= y
) &&
1412 (child
->m_x
+child
->m_width
>= x
) &&
1413 (child
->m_y
+child
->m_height
>= y
))
1416 event
.m_x
-= child
->m_x
;
1417 event
.m_y
-= child
->m_y
;
1424 event
.SetEventObject( win
);
1426 if (win
->GetEventHandler()->ProcessEvent( event
))
1428 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1435 //-----------------------------------------------------------------------------
1437 //-----------------------------------------------------------------------------
1439 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1444 wxapp_install_idle_handler();
1446 if (!win
->m_hasVMT
) return FALSE
;
1447 if (g_blockEventsOnDrag
) return FALSE
;
1449 switch ( g_sendActivateEvent
)
1452 // we've got focus from outside, synthtize wxActivateEvent
1453 g_sendActivateEvent
= 1;
1457 // another our window just lost focus, it was already ours before
1458 // - don't send any wxActivateEvent
1459 g_sendActivateEvent
= -1;
1463 g_focusWindow
= win
;
1466 printf( "OnSetFocus from " );
1467 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1468 printf( win->GetClassInfo()->GetClassName() );
1470 printf( WXSTRINGCAST win->GetLabel() );
1474 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1477 panel
->SetLastFocus(win
);
1482 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1485 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1486 event
.SetEventObject( win
);
1488 if (win
->GetEventHandler()->ProcessEvent( event
))
1490 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1497 //-----------------------------------------------------------------------------
1498 // "focus_out_event"
1499 //-----------------------------------------------------------------------------
1501 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1506 wxapp_install_idle_handler();
1508 if (!win
->m_hasVMT
) return FALSE
;
1509 if (g_blockEventsOnDrag
) return FALSE
;
1511 // if the focus goes out of our app alltogether, OnIdle() will send
1512 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1513 // g_sendActivateEvent to -1
1514 g_sendActivateEvent
= 0;
1516 g_focusWindow
= (wxWindow
*)NULL
;
1519 printf( "OnKillFocus from " );
1520 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1521 printf( win->GetClassInfo()->GetClassName() );
1530 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1531 event
.SetEventObject( win
);
1533 if (win
->GetEventHandler()->ProcessEvent( event
))
1535 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1542 //-----------------------------------------------------------------------------
1543 // "enter_notify_event"
1544 //-----------------------------------------------------------------------------
1546 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1551 wxapp_install_idle_handler();
1553 if (!win
->m_hasVMT
) return FALSE
;
1554 if (g_blockEventsOnDrag
) return FALSE
;
1556 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1558 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1559 #if (GTK_MINOR_VERSION > 0)
1560 event
.SetTimestamp( gdk_event
->time
);
1562 event
.SetEventObject( win
);
1566 GdkModifierType state
= (GdkModifierType
)0;
1568 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1570 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1571 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1572 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1573 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1574 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1575 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1576 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1581 if (win
->GetEventHandler()->ProcessEvent( event
))
1583 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1590 //-----------------------------------------------------------------------------
1591 // "leave_notify_event"
1592 //-----------------------------------------------------------------------------
1594 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1599 wxapp_install_idle_handler();
1601 if (!win
->m_hasVMT
) return FALSE
;
1602 if (g_blockEventsOnDrag
) return FALSE
;
1604 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1606 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1607 #if (GTK_MINOR_VERSION > 0)
1608 event
.SetTimestamp( gdk_event
->time
);
1610 event
.SetEventObject( win
);
1614 GdkModifierType state
= (GdkModifierType
)0;
1616 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1618 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1619 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1620 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1621 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1622 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1623 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1624 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1629 if (win
->GetEventHandler()->ProcessEvent( event
))
1631 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1638 //-----------------------------------------------------------------------------
1639 // "value_changed" from m_vAdjust
1640 //-----------------------------------------------------------------------------
1642 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1647 wxapp_install_idle_handler();
1649 if (g_blockEventsOnDrag
) return;
1651 if (!win
->m_hasVMT
) return;
1653 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1654 if (fabs(diff
) < 0.2) return;
1656 win
->m_oldVerticalPos
= adjust
->value
;
1658 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1659 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1661 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1662 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1663 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1664 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1665 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1667 int value
= (int)(adjust
->value
+0.5);
1669 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1670 event
.SetEventObject( win
);
1671 win
->GetEventHandler()->ProcessEvent( event
);
1674 //-----------------------------------------------------------------------------
1675 // "value_changed" from m_hAdjust
1676 //-----------------------------------------------------------------------------
1678 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1683 wxapp_install_idle_handler();
1685 if (g_blockEventsOnDrag
) return;
1686 if (!win
->m_hasVMT
) return;
1688 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1689 if (fabs(diff
) < 0.2) return;
1691 win
->m_oldHorizontalPos
= adjust
->value
;
1693 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1694 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1696 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1697 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1698 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1699 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1700 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1702 int value
= (int)(adjust
->value
+0.5);
1704 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1705 event
.SetEventObject( win
);
1706 win
->GetEventHandler()->ProcessEvent( event
);
1709 //-----------------------------------------------------------------------------
1710 // "button_press_event" from scrollbar
1711 //-----------------------------------------------------------------------------
1713 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1714 GdkEventButton
*gdk_event
,
1720 wxapp_install_idle_handler();
1722 g_blockEventsOnScroll
= TRUE
;
1723 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1728 //-----------------------------------------------------------------------------
1729 // "button_release_event" from scrollbar
1730 //-----------------------------------------------------------------------------
1732 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1733 GdkEventButton
*WXUNUSED(gdk_event
),
1738 // don't test here as we can release the mouse while being over
1739 // a different window than the slider
1741 // if (gdk_event->window != widget->slider) return FALSE;
1743 g_blockEventsOnScroll
= FALSE
;
1745 if (win
->m_isScrolling
)
1747 wxEventType command
= wxEVT_SCROLL_THUMBRELEASE
;
1751 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1752 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1754 value
= (int)(win
->m_hAdjust
->value
+0.5);
1757 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1759 value
= (int)(win
->m_vAdjust
->value
+0.5);
1763 wxScrollWinEvent
event( command
, value
, dir
);
1764 event
.SetEventObject( win
);
1765 win
->GetEventHandler()->ProcessEvent( event
);
1768 win
->m_isScrolling
= FALSE
;
1773 // ----------------------------------------------------------------------------
1774 // this wxWindowBase function is implemented here (in platform-specific file)
1775 // because it is static and so couldn't be made virtual
1776 // ----------------------------------------------------------------------------
1778 wxWindow
*wxWindowBase::FindFocus()
1780 return g_focusWindow
;
1783 //-----------------------------------------------------------------------------
1784 // "realize" from m_widget
1785 //-----------------------------------------------------------------------------
1787 /* We cannot set colours and fonts before the widget has
1788 been realized, so we do this directly after realization. */
1791 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1796 wxapp_install_idle_handler();
1798 if (win
->m_delayedBackgroundColour
)
1799 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1801 if (win
->m_delayedForegroundColour
)
1802 win
->SetForegroundColour( win
->GetForegroundColour() );
1804 wxWindowCreateEvent
event( win
);
1805 event
.SetEventObject( win
);
1806 win
->GetEventHandler()->ProcessEvent( event
);
1811 //-----------------------------------------------------------------------------
1813 //-----------------------------------------------------------------------------
1816 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
1817 GtkAllocation
*WXUNUSED(alloc
),
1821 wxapp_install_idle_handler();
1823 if (!win
->m_hasScrolling
) return;
1825 int client_width
= 0;
1826 int client_height
= 0;
1827 win
->GetClientSize( &client_width
, &client_height
);
1828 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
1831 win
->m_oldClientWidth
= client_width
;
1832 win
->m_oldClientHeight
= client_height
;
1834 if (!win
->m_nativeSizeEvent
)
1836 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
1837 event
.SetEventObject( win
);
1838 win
->GetEventHandler()->ProcessEvent( event
);
1844 #define WXUNUSED_UNLESS_XIM(param) param
1846 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1849 /* Resize XIM window */
1852 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1853 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1854 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1857 wxapp_install_idle_handler();
1863 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1867 gdk_window_get_size (widget
->window
, &width
, &height
);
1868 win
->m_icattr
->preedit_area
.width
= width
;
1869 win
->m_icattr
->preedit_area
.height
= height
;
1870 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
1875 //-----------------------------------------------------------------------------
1876 // "realize" from m_wxwindow
1877 //-----------------------------------------------------------------------------
1879 /* Initialize XIM support */
1882 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1883 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1886 wxapp_install_idle_handler();
1889 if (win
->m_ic
) return FALSE
;
1890 if (!widget
) return FALSE
;
1891 if (!gdk_im_ready()) return FALSE
;
1893 win
->m_icattr
= gdk_ic_attr_new();
1894 if (!win
->m_icattr
) return FALSE
;
1898 GdkColormap
*colormap
;
1899 GdkICAttr
*attr
= win
->m_icattr
;
1900 unsigned attrmask
= GDK_IC_ALL_REQ
;
1902 GdkIMStyle supported_style
= (GdkIMStyle
)
1903 (GDK_IM_PREEDIT_NONE
|
1904 GDK_IM_PREEDIT_NOTHING
|
1905 GDK_IM_PREEDIT_POSITION
|
1906 GDK_IM_STATUS_NONE
|
1907 GDK_IM_STATUS_NOTHING
);
1909 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1910 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
1912 attr
->style
= style
= gdk_im_decide_style (supported_style
);
1913 attr
->client_window
= widget
->window
;
1915 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
1916 gtk_widget_get_default_colormap ())
1918 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
1919 attr
->preedit_colormap
= colormap
;
1922 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
1923 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
1924 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
1925 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
1927 switch (style
& GDK_IM_PREEDIT_MASK
)
1929 case GDK_IM_PREEDIT_POSITION
:
1930 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1932 g_warning ("over-the-spot style requires fontset");
1936 gdk_window_get_size (widget
->window
, &width
, &height
);
1938 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
1939 attr
->spot_location
.x
= 0;
1940 attr
->spot_location
.y
= height
;
1941 attr
->preedit_area
.x
= 0;
1942 attr
->preedit_area
.y
= 0;
1943 attr
->preedit_area
.width
= width
;
1944 attr
->preedit_area
.height
= height
;
1945 attr
->preedit_fontset
= widget
->style
->font
;
1950 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
1952 if (win
->m_ic
== NULL
)
1953 g_warning ("Can't create input context.");
1956 mask
= gdk_window_get_events (widget
->window
);
1957 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
1958 gdk_window_set_events (widget
->window
, mask
);
1960 if (GTK_WIDGET_HAS_FOCUS(widget
))
1961 gdk_im_begin (win
->m_ic
, widget
->window
);
1968 //-----------------------------------------------------------------------------
1969 // InsertChild for wxWindow.
1970 //-----------------------------------------------------------------------------
1972 /* Callback for wxWindow. This very strange beast has to be used because
1973 * C++ has no virtual methods in a constructor. We have to emulate a
1974 * virtual function here as wxNotebook requires a different way to insert
1975 * a child in it. I had opted for creating a wxNotebookPage window class
1976 * which would have made this superfluous (such in the MDI window system),
1977 * but no-one was listening to me... */
1979 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1981 /* the window might have been scrolled already, do we
1982 have to adapt the position */
1983 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
1984 child
->m_x
+= pizza
->xoffset
;
1985 child
->m_y
+= pizza
->yoffset
;
1987 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
1988 GTK_WIDGET(child
->m_widget
),
1995 //-----------------------------------------------------------------------------
1997 //-----------------------------------------------------------------------------
1999 wxWindow
* wxGetActiveWindow()
2001 return g_focusWindow
;
2004 //-----------------------------------------------------------------------------
2006 //-----------------------------------------------------------------------------
2008 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2010 void wxWindow::Init()
2016 m_widget
= (GtkWidget
*) NULL
;
2017 m_wxwindow
= (GtkWidget
*) NULL
;
2027 m_needParent
= TRUE
;
2028 m_isBeingDeleted
= FALSE
;
2031 m_nativeSizeEvent
= FALSE
;
2033 m_hasScrolling
= FALSE
;
2034 m_isScrolling
= FALSE
;
2036 m_hAdjust
= (GtkAdjustment
*) NULL
;
2037 m_vAdjust
= (GtkAdjustment
*) NULL
;
2038 m_oldHorizontalPos
= 0.0;
2039 m_oldVerticalPos
= 0.0;
2042 m_widgetStyle
= (GtkStyle
*) NULL
;
2044 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2046 m_isStaticBox
= FALSE
;
2047 m_isRadioButton
= FALSE
;
2049 m_acceptsFocus
= FALSE
;
2051 m_clipPaintRegion
= FALSE
;
2052 m_queuedFullRedraw
= FALSE
;
2054 m_cursor
= *wxSTANDARD_CURSOR
;
2057 m_ic
= (GdkIC
*) NULL
;
2058 m_icattr
= (GdkICAttr
*) NULL
;
2062 wxWindow::wxWindow()
2067 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
2068 const wxPoint
&pos
, const wxSize
&size
,
2069 long style
, const wxString
&name
)
2073 Create( parent
, id
, pos
, size
, style
, name
);
2076 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
2077 const wxPoint
&pos
, const wxSize
&size
,
2078 long style
, const wxString
&name
)
2080 if (!PreCreation( parent
, pos
, size
) ||
2081 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2083 wxFAIL_MSG( wxT("wxWindow creation failed") );
2087 m_insertCallback
= wxInsertChildInWindow
;
2089 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2090 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2092 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2094 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2095 scroll_class
->scrollbar_spacing
= 0;
2097 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2099 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2100 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2102 m_wxwindow
= gtk_pizza_new();
2104 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2106 #if (GTK_MINOR_VERSION > 0)
2107 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2109 if (HasFlag(wxRAISED_BORDER
))
2111 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2113 else if (HasFlag(wxSUNKEN_BORDER
))
2115 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2117 else if (HasFlag(wxSIMPLE_BORDER
))
2119 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2123 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2125 #else // GTK_MINOR_VERSION == 0
2126 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2128 if (HasFlag(wxRAISED_BORDER
))
2130 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2132 else if (HasFlag(wxSUNKEN_BORDER
))
2134 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2138 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2140 #endif // GTK_MINOR_VERSION
2142 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2143 m_acceptsFocus
= TRUE
;
2145 #if (GTK_MINOR_VERSION == 0)
2146 // shut the viewport up
2147 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2148 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2149 #endif // GTK_MINOR_VERSION == 0
2151 // I _really_ don't want scrollbars in the beginning
2152 m_vAdjust
->lower
= 0.0;
2153 m_vAdjust
->upper
= 1.0;
2154 m_vAdjust
->value
= 0.0;
2155 m_vAdjust
->step_increment
= 1.0;
2156 m_vAdjust
->page_increment
= 1.0;
2157 m_vAdjust
->page_size
= 5.0;
2158 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2159 m_hAdjust
->lower
= 0.0;
2160 m_hAdjust
->upper
= 1.0;
2161 m_hAdjust
->value
= 0.0;
2162 m_hAdjust
->step_increment
= 1.0;
2163 m_hAdjust
->page_increment
= 1.0;
2164 m_hAdjust
->page_size
= 5.0;
2165 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2167 // these handlers block mouse events to any window during scrolling such as
2168 // motion events and prevent GTK and wxWindows from fighting over where the
2171 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2172 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2174 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2175 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2177 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2178 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2180 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2181 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2183 // these handlers get notified when screen updates are required either when
2184 // scrolling or when the window size (and therefore scrollbar configuration)
2187 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2188 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2189 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2190 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2192 gtk_widget_show( m_wxwindow
);
2195 m_parent
->DoAddChild( this );
2204 wxWindow::~wxWindow()
2206 m_isBeingDeleted
= TRUE
;
2215 m_parent
->RemoveChild( this );
2219 gdk_ic_destroy (m_ic
);
2221 gdk_ic_attr_destroy (m_icattr
);
2226 #if DISABLE_STYLE_IF_BROKEN_THEME
2227 // don't delete if it's a pixmap theme style
2228 if (!m_widgetStyle
->engine_data
)
2229 gtk_style_unref( m_widgetStyle
);
2231 m_widgetStyle
= (GtkStyle
*) NULL
;
2236 gtk_widget_destroy( m_wxwindow
);
2237 m_wxwindow
= (GtkWidget
*) NULL
;
2242 gtk_widget_destroy( m_widget
);
2243 m_widget
= (GtkWidget
*) NULL
;
2247 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2249 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2251 /* this turns -1 into 20 so that a minimal window is
2252 visible even although -1,-1 has been given as the
2253 size of the window. the same trick is used in other
2254 ports and should make debugging easier */
2255 m_width
= WidthDefault(size
.x
);
2256 m_height
= HeightDefault(size
.y
);
2261 /* some reasonable defaults */
2266 m_x
= (gdk_screen_width () - m_width
) / 2;
2267 if (m_x
< 10) m_x
= 10;
2271 m_y
= (gdk_screen_height () - m_height
) / 2;
2272 if (m_y
< 10) m_y
= 10;
2279 void wxWindow::PostCreation()
2281 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2287 /* these get reported to wxWindows -> wxPaintEvent */
2288 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2289 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2291 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2292 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2294 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2295 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2298 #if (GTK_MINOR_VERSION > 0)
2299 /* these are called when the "sunken" or "raised" borders are drawn */
2300 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2301 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2303 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2304 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2308 if (m_wxwindow
&& m_needParent
)
2310 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2311 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2313 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2314 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2318 // For dialogs and frames, we are interested mainly in
2319 // m_widget's focus.
2321 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2322 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2324 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2325 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2328 GtkWidget
*connect_widget
= GetConnectWidget();
2330 ConnectWidget( connect_widget
);
2332 /* We cannot set colours, fonts and cursors before the widget has
2333 been realized, so we do this directly after realization */
2334 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2335 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2339 /* Catch native resize events. */
2340 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2341 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2343 /* Initialize XIM support. */
2344 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2345 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2347 /* And resize XIM window. */
2348 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2349 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2355 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2357 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2358 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2360 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2361 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2363 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2364 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2366 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2367 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2369 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2370 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2372 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2373 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2375 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2376 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2379 bool wxWindow::Destroy()
2381 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2385 return wxWindowBase::Destroy();
2388 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2390 if (m_wxwindow
&& GTK_PIZZA(m_wxwindow
)->bin_window
)
2392 /* Normally, GTK will send expose events only for the regions
2393 which actually got exposed. Sadly, wxMSW invalidates
2394 the whole window so we have to do that, too. We could
2395 simply add a complete refresh, but we would then get
2396 the normal GTK expose events in surplus, so we shut
2397 off the expose events and schedule a full redraw to
2398 be done in OnInternalIdle, where we restore the handling
2399 of expose events. */
2401 m_queuedFullRedraw
= TRUE
;
2403 GdkEventMask mask
= gdk_window_get_events( GTK_PIZZA(m_wxwindow
)->bin_window
);
2404 mask
= (GdkEventMask
)(mask
& ~GDK_EXPOSURE_MASK
);
2405 gdk_window_set_events( GTK_PIZZA(m_wxwindow
)->bin_window
, mask
);
2408 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2411 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2413 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2414 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2416 if (m_resizing
) return; /* I don't like recursions */
2419 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2421 /* don't set the size for children of wxNotebook, just take the values. */
2429 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2431 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2433 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2434 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2435 if (width
!= -1) m_width
= width
;
2436 if (height
!= -1) m_height
= height
;
2440 m_x
= x
+ pizza
->xoffset
;
2441 m_y
= y
+ pizza
->yoffset
;
2446 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2448 if (width
== -1) m_width
= 80;
2451 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2453 if (height
== -1) m_height
= 26;
2456 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2457 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2458 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2459 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2462 int bottom_border
= 0;
2464 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2466 /* the default button has a border around it */
2471 DoMoveWindow( m_x
-border
,
2474 m_height
+border
+bottom_border
);
2479 /* Sometimes the client area changes size without the
2480 whole windows's size changing, but if the whole
2481 windows's size doesn't change, no wxSizeEvent will
2482 normally be sent. Here we add an extra test if
2483 the client test has been changed and this will
2485 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2489 wxPrintf( "OnSize sent from " );
2490 if (GetClassInfo() && GetClassInfo()->GetClassName())
2491 wxPrintf( GetClassInfo()->GetClassName() );
2492 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2495 if (!m_nativeSizeEvent
)
2497 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2498 event
.SetEventObject( this );
2499 GetEventHandler()->ProcessEvent( event
);
2505 void wxWindow::OnInternalIdle()
2507 if ( g_sendActivateEvent
!= -1 )
2509 bool activate
= g_sendActivateEvent
!= 0;
2512 g_sendActivateEvent
= -1;
2514 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2515 event
.SetEventObject(this);
2517 (void)GetEventHandler()->ProcessEvent(event
);
2520 wxCursor cursor
= m_cursor
;
2521 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2525 /* I now set the cursor anew in every OnInternalIdle call
2526 as setting the cursor in a parent window also effects the
2527 windows above so that checking for the current cursor is
2532 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2534 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2536 if (!g_globalCursor
.Ok())
2537 cursor
= *wxSTANDARD_CURSOR
;
2539 window
= m_widget
->window
;
2540 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2541 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2547 GdkWindow
*window
= m_widget
->window
;
2548 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2549 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2556 if (m_queuedFullRedraw
)
2558 /* See also wxWindow::DoMoveWindow for explanation of this code. What
2559 we test here is if the requested size of the window is the same as
2560 the actual size of window, in which case all expose events that resulted
2561 from resizing the window have been sent (and discarded) and we can
2562 now do our full redraw and switch on expose event handling again. */
2564 if ((m_width
== m_widget
->allocation
.width
) && (m_height
== m_widget
->allocation
.height
))
2566 m_queuedFullRedraw
= FALSE
;
2567 m_updateRegion
.Clear();
2568 m_updateRegion
.Union( 0,0,m_width
,m_height
);
2569 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2571 GdkEventMask mask
= gdk_window_get_events( GTK_PIZZA(m_wxwindow
)->bin_window
);
2572 mask
= (GdkEventMask
)(mask
| GDK_EXPOSURE_MASK
);
2573 gdk_window_set_events( GTK_PIZZA(m_wxwindow
)->bin_window
, mask
);
2578 void wxWindow::DoGetSize( int *width
, int *height
) const
2580 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2582 if (width
) (*width
) = m_width
;
2583 if (height
) (*height
) = m_height
;
2586 void wxWindow::DoSetClientSize( int width
, int height
)
2588 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2592 SetSize( width
, height
);
2599 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2601 /* when using GTK 1.2 we set the shadow border size to 2 */
2605 if (HasFlag(wxSIMPLE_BORDER
))
2607 /* when using GTK 1.2 we set the simple border size to 1 */
2614 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2616 GtkRequisition vscroll_req
;
2617 vscroll_req
.width
= 2;
2618 vscroll_req
.height
= 2;
2619 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
2620 (scroll_window
->vscrollbar
, &vscroll_req
);
2622 GtkRequisition hscroll_req
;
2623 hscroll_req
.width
= 2;
2624 hscroll_req
.height
= 2;
2625 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
2626 (scroll_window
->hscrollbar
, &hscroll_req
);
2628 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2630 if (scroll_window
->vscrollbar_visible
)
2632 dw
+= vscroll_req
.width
;
2633 dw
+= scroll_class
->scrollbar_spacing
;
2636 if (scroll_window
->hscrollbar_visible
)
2638 dh
+= hscroll_req
.height
;
2639 dh
+= scroll_class
->scrollbar_spacing
;
2643 SetSize( width
+dw
, height
+dh
);
2647 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2649 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2653 if (width
) (*width
) = m_width
;
2654 if (height
) (*height
) = m_height
;
2661 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2663 /* when using GTK 1.2 we set the shadow border size to 2 */
2667 if (HasFlag(wxSIMPLE_BORDER
))
2669 /* when using GTK 1.2 we set the simple border size to 1 */
2676 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2678 GtkRequisition vscroll_req
;
2679 vscroll_req
.width
= 2;
2680 vscroll_req
.height
= 2;
2681 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
2682 (scroll_window
->vscrollbar
, &vscroll_req
);
2684 GtkRequisition hscroll_req
;
2685 hscroll_req
.width
= 2;
2686 hscroll_req
.height
= 2;
2687 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
2688 (scroll_window
->hscrollbar
, &hscroll_req
);
2690 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2692 if (scroll_window
->vscrollbar_visible
)
2694 dw
+= vscroll_req
.width
;
2695 dw
+= scroll_class
->scrollbar_spacing
;
2698 if (scroll_window
->hscrollbar_visible
)
2700 dh
+= hscroll_req
.height
;
2701 dh
+= scroll_class
->scrollbar_spacing
;
2705 if (width
) (*width
) = m_width
- dw
;
2706 if (height
) (*height
) = m_height
- dh
;
2710 void wxWindow::DoGetPosition( int *x
, int *y
) const
2712 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2716 if (m_parent
&& m_parent
->m_wxwindow
)
2718 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2719 dx
= pizza
->xoffset
;
2720 dy
= pizza
->yoffset
;
2723 if (x
) (*x
) = m_x
- dx
;
2724 if (y
) (*y
) = m_y
- dy
;
2727 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2729 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2731 if (!m_widget
->window
) return;
2733 GdkWindow
*source
= (GdkWindow
*) NULL
;
2735 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2737 source
= m_widget
->window
;
2741 gdk_window_get_origin( source
, &org_x
, &org_y
);
2745 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2747 org_x
+= m_widget
->allocation
.x
;
2748 org_y
+= m_widget
->allocation
.y
;
2756 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2758 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2760 if (!m_widget
->window
) return;
2762 GdkWindow
*source
= (GdkWindow
*) NULL
;
2764 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2766 source
= m_widget
->window
;
2770 gdk_window_get_origin( source
, &org_x
, &org_y
);
2774 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2776 org_x
+= m_widget
->allocation
.x
;
2777 org_y
+= m_widget
->allocation
.y
;
2785 bool wxWindow::Show( bool show
)
2787 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2789 if (!wxWindowBase::Show(show
))
2796 gtk_widget_show( m_widget
);
2798 gtk_widget_hide( m_widget
);
2803 bool wxWindow::Enable( bool enable
)
2805 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2807 if (!wxWindowBase::Enable(enable
))
2813 gtk_widget_set_sensitive( m_widget
, enable
);
2815 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2820 int wxWindow::GetCharHeight() const
2822 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2824 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2826 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2828 return font
->ascent
+ font
->descent
;
2831 int wxWindow::GetCharWidth() const
2833 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2835 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2837 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2839 return gdk_string_width( font
, "H" );
2842 void wxWindow::GetTextExtent( const wxString
& string
,
2846 int *externalLeading
,
2847 const wxFont
*theFont
) const
2849 wxFont fontToUse
= m_font
;
2850 if (theFont
) fontToUse
= *theFont
;
2852 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2854 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2855 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2856 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2857 if (descent
) (*descent
) = font
->descent
;
2858 if (externalLeading
) (*externalLeading
) = 0; // ??
2861 void wxWindow::SetFocus()
2863 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2867 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2868 gtk_widget_grab_focus (m_wxwindow
);
2874 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2876 gtk_widget_grab_focus (m_widget
);
2878 else if (GTK_IS_CONTAINER(m_widget
))
2880 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2889 bool wxWindow::AcceptsFocus() const
2891 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2894 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2896 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2898 wxWindow
*oldParent
= m_parent
,
2899 *newParent
= (wxWindow
*)newParentBase
;
2901 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2903 if ( !wxWindowBase::Reparent(newParent
) )
2906 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2908 /* prevent GTK from deleting the widget arbitrarily */
2909 gtk_widget_ref( m_widget
);
2913 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2916 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2920 /* insert GTK representation */
2921 (*(newParent
->m_insertCallback
))(newParent
, this);
2924 /* reverse: prevent GTK from deleting the widget arbitrarily */
2925 gtk_widget_unref( m_widget
);
2930 void wxWindow::DoAddChild(wxWindow
*child
)
2932 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2934 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
2936 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
2941 /* insert GTK representation */
2942 (*m_insertCallback
)(this, child
);
2945 void wxWindow::Raise()
2947 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2949 if (!m_widget
->window
) return;
2951 gdk_window_raise( m_widget
->window
);
2954 void wxWindow::Lower()
2956 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2958 if (!m_widget
->window
) return;
2960 gdk_window_lower( m_widget
->window
);
2963 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2965 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2967 return wxWindowBase::SetCursor( cursor
);
2970 void wxWindow::WarpPointer( int x
, int y
)
2972 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2974 /* we provide this function ourselves as it is
2975 missing in GDK (top of this file) */
2977 GdkWindow
*window
= (GdkWindow
*) NULL
;
2979 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2981 window
= GetConnectWidget()->window
;
2984 gdk_window_warp_pointer( window
, x
, y
);
2987 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2989 if (!m_widget
) return;
2990 if (!m_widget
->window
) return;
2992 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2996 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
2998 rect
->width
, rect
->height
);
3002 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3006 /* there is no GTK equivalent of "draw only, don't clear" so we
3007 invent our own in the GtkPizza widget */
3015 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3016 gboolean old_clear = pizza->clear_on_draw;
3017 gtk_pizza_set_clear( pizza, FALSE );
3018 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3019 gtk_pizza_set_clear( pizza, old_clear );
3021 GdkEventExpose gdk_event
;
3022 gdk_event
.count
= 0;
3023 gdk_event
.area
.x
= 0;
3024 gdk_event
.area
.y
= 0;
3025 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3026 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3027 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3032 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3041 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3042 gboolean old_clear = pizza->clear_on_draw;
3043 gtk_pizza_set_clear( pizza, FALSE );
3045 GdkRectangle gdk_rect;
3046 gdk_rect.x = rect->x;
3047 gdk_rect.y = rect->y;
3048 gdk_rect.width = rect->width;
3049 gdk_rect.height = rect->height;
3050 gtk_widget_draw( m_wxwindow, &gdk_rect );
3051 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3053 gtk_pizza_set_clear( pizza, old_clear );
3055 GdkEventExpose gdk_event
;
3056 gdk_event
.count
= 0;
3057 gdk_event
.area
.x
= rect
->x
;
3058 gdk_event
.area
.y
= rect
->y
;
3059 gdk_event
.area
.width
= rect
->width
;
3060 gdk_event
.area
.height
= rect
->height
;
3061 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3065 GdkRectangle gdk_rect
;
3066 gdk_rect
.x
= rect
->x
;
3067 gdk_rect
.y
= rect
->y
;
3068 gdk_rect
.width
= rect
->width
;
3069 gdk_rect
.height
= rect
->height
;
3070 gtk_widget_draw( m_widget
, &gdk_rect
);
3075 void wxWindow::Clear()
3077 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3079 if (!m_widget
->window
) return;
3081 if (m_wxwindow
&& m_wxwindow
->window
)
3083 // gdk_window_clear( m_wxwindow->window );
3088 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
3090 wxWindowBase::DoSetToolTip(tip
);
3093 m_tooltip
->Apply( this );
3096 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3098 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3100 #endif // wxUSE_TOOLTIPS
3102 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
3104 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3106 if (!wxWindowBase::SetBackgroundColour(colour
))
3108 // don't leave if the GTK widget has just
3110 if (!m_delayedBackgroundColour
) return FALSE
;
3113 GdkWindow
*window
= (GdkWindow
*) NULL
;
3115 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3117 window
= GetConnectWidget()->window
;
3121 // indicate that a new style has been set
3122 // but it couldn't get applied as the
3123 // widget hasn't been realized yet.
3124 m_delayedBackgroundColour
= TRUE
;
3128 (m_wxwindow
->window
) &&
3129 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3131 /* wxMSW doesn't clear the window here. I don't do that either to
3132 provide compatibility. call Clear() to do the job. */
3134 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3135 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3143 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
3145 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3147 if (!wxWindowBase::SetForegroundColour(colour
))
3149 // don't leave if the GTK widget has just
3151 if (!m_delayedForegroundColour
) return FALSE
;
3154 GdkWindow
*window
= (GdkWindow
*) NULL
;
3156 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3158 window
= GetConnectWidget()->window
;
3162 // indicate that a new style has been set
3163 // but it couldn't get applied as the
3164 // widget hasn't been realized yet.
3165 m_delayedForegroundColour
= TRUE
;
3173 GtkStyle
*wxWindow::GetWidgetStyle()
3177 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3178 remake
->klass
= m_widgetStyle
->klass
;
3180 gtk_style_unref( m_widgetStyle
);
3181 m_widgetStyle
= remake
;
3185 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3188 def
= gtk_widget_get_default_style();
3190 m_widgetStyle
= gtk_style_copy( def
);
3191 m_widgetStyle
->klass
= def
->klass
;
3194 return m_widgetStyle
;
3197 void wxWindow::SetWidgetStyle()
3199 #if DISABLE_STYLE_IF_BROKEN_THEM
3200 if (m_widget
->style
->engine_data
)
3202 static bool s_warningPrinted
= FALSE
;
3203 if (!s_warningPrinted
)
3205 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3206 s_warningPrinted
= TRUE
;
3208 m_widgetStyle
= m_widget
->style
;
3213 GtkStyle
*style
= GetWidgetStyle();
3215 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3217 gdk_font_unref( style
->font
);
3218 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3221 if (m_foregroundColour
.Ok())
3223 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3224 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3226 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3227 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3228 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3232 if (m_backgroundColour
.Ok())
3234 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3235 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3237 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3238 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3239 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3240 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3241 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3242 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3243 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3244 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3249 void wxWindow::ApplyWidgetStyle()
3253 //-----------------------------------------------------------------------------
3254 // Pop-up menu stuff
3255 //-----------------------------------------------------------------------------
3257 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3259 *is_waiting
= FALSE
;
3262 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3264 menu
->SetInvokingWindow( win
);
3265 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3268 wxMenuItem
*menuitem
= node
->GetData();
3269 if (menuitem
->IsSubMenu())
3271 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3274 node
= node
->GetNext();
3278 static gint gs_pop_x
= 0;
3279 static gint gs_pop_y
= 0;
3281 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3285 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3290 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3292 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3294 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3296 SetInvokingWindow( menu
, this );
3303 bool is_waiting
= TRUE
;
3305 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3306 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3309 GTK_MENU(menu
->m_menu
),
3310 (GtkWidget
*) NULL
, // parent menu shell
3311 (GtkWidget
*) NULL
, // parent menu item
3312 (GtkMenuPositionFunc
) pop_pos_callback
,
3313 (gpointer
) this, // client data
3314 0, // button used to activate it
3315 gs_timeLastClick
// the time of activation
3320 while (gtk_events_pending())
3321 gtk_main_iteration();
3327 #if wxUSE_DRAG_AND_DROP
3329 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3331 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3333 GtkWidget
*dnd_widget
= GetConnectWidget();
3335 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3337 if (m_dropTarget
) delete m_dropTarget
;
3338 m_dropTarget
= dropTarget
;
3340 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3343 #endif // wxUSE_DRAG_AND_DROP
3345 GtkWidget
* wxWindow::GetConnectWidget()
3347 GtkWidget
*connect_widget
= m_widget
;
3348 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3350 return connect_widget
;
3353 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3356 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3358 return (window
== m_widget
->window
);
3361 bool wxWindow::SetFont( const wxFont
&font
)
3363 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3365 if (!wxWindowBase::SetFont(font
))
3370 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3371 if ( sysbg
== m_backgroundColour
)
3373 m_backgroundColour
= wxNullColour
;
3375 m_backgroundColour
= sysbg
;
3385 void wxWindow::CaptureMouse()
3387 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3389 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3391 GdkWindow
*window
= (GdkWindow
*) NULL
;
3393 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3395 window
= GetConnectWidget()->window
;
3397 if (!window
) return;
3399 gdk_pointer_grab( window
, FALSE
,
3401 (GDK_BUTTON_PRESS_MASK
|
3402 GDK_BUTTON_RELEASE_MASK
|
3403 GDK_POINTER_MOTION_HINT_MASK
|
3404 GDK_POINTER_MOTION_MASK
),
3406 m_cursor
.GetCursor(),
3407 (guint32
)GDK_CURRENT_TIME
);
3408 g_captureWindow
= this;
3411 void wxWindow::ReleaseMouse()
3413 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3415 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3417 GdkWindow
*window
= (GdkWindow
*) NULL
;
3419 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3421 window
= GetConnectWidget()->window
;
3426 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3427 g_captureWindow
= (wxWindow
*) NULL
;
3430 bool wxWindow::IsRetained() const
3435 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3436 int range
, bool refresh
)
3438 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3440 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3442 m_hasScrolling
= TRUE
;
3444 if (orient
== wxHORIZONTAL
)
3446 float fpos
= (float)pos
;
3447 float frange
= (float)range
;
3448 float fthumb
= (float)thumbVisible
;
3449 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3450 if (fpos
< 0.0) fpos
= 0.0;
3452 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3453 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3455 SetScrollPos( orient
, pos
, refresh
);
3459 m_oldHorizontalPos
= fpos
;
3461 m_hAdjust
->lower
= 0.0;
3462 m_hAdjust
->upper
= frange
;
3463 m_hAdjust
->value
= fpos
;
3464 m_hAdjust
->step_increment
= 1.0;
3465 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3466 m_hAdjust
->page_size
= fthumb
;
3470 float fpos
= (float)pos
;
3471 float frange
= (float)range
;
3472 float fthumb
= (float)thumbVisible
;
3473 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3474 if (fpos
< 0.0) fpos
= 0.0;
3476 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3477 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3479 SetScrollPos( orient
, pos
, refresh
);
3483 m_oldVerticalPos
= fpos
;
3485 m_vAdjust
->lower
= 0.0;
3486 m_vAdjust
->upper
= frange
;
3487 m_vAdjust
->value
= fpos
;
3488 m_vAdjust
->step_increment
= 1.0;
3489 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3490 m_vAdjust
->page_size
= fthumb
;
3493 if (orient
== wxHORIZONTAL
)
3494 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3496 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3499 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3501 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3503 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3505 if (orient
== wxHORIZONTAL
)
3507 float fpos
= (float)pos
;
3508 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3509 if (fpos
< 0.0) fpos
= 0.0;
3510 m_oldHorizontalPos
= fpos
;
3512 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3513 m_hAdjust
->value
= fpos
;
3517 float fpos
= (float)pos
;
3518 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3519 if (fpos
< 0.0) fpos
= 0.0;
3520 m_oldVerticalPos
= fpos
;
3522 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3523 m_vAdjust
->value
= fpos
;
3526 if (m_wxwindow
->window
)
3528 if (orient
== wxHORIZONTAL
)
3530 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3531 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3533 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3535 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3536 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3540 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3541 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3543 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3545 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3546 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3551 int wxWindow::GetScrollThumb( int orient
) const
3553 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3555 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3557 if (orient
== wxHORIZONTAL
)
3558 return (int)(m_hAdjust
->page_size
+0.5);
3560 return (int)(m_vAdjust
->page_size
+0.5);
3563 int wxWindow::GetScrollPos( int orient
) const
3565 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3567 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3569 if (orient
== wxHORIZONTAL
)
3570 return (int)(m_hAdjust
->value
+0.5);
3572 return (int)(m_vAdjust
->value
+0.5);
3575 int wxWindow::GetScrollRange( int orient
) const
3577 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3579 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3581 if (orient
== wxHORIZONTAL
)
3582 return (int)(m_hAdjust
->upper
+0.5);
3584 return (int)(m_vAdjust
->upper
+0.5);
3587 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3589 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3591 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3593 if ((dx
== 0) && (dy
== 0)) return;
3595 m_clipPaintRegion
= TRUE
;
3596 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3597 m_clipPaintRegion
= FALSE
;
3600 if (m_children.GetCount() > 0)
3602 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3606 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3608 pizza->xoffset -= dx;
3609 pizza->yoffset -= dy;
3611 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3612 gdk_gc_set_exposures( m_scrollGC, TRUE );
3616 GetClientSize( &cw, &ch );
3617 int w = cw - abs(dx);
3618 int h = ch - abs(dy);
3620 if ((h < 0) || (w < 0))
3628 if (dx < 0) s_x = -dx;
3629 if (dy < 0) s_y = -dy;
3632 if (dx > 0) d_x = dx;
3633 if (dy > 0) d_y = dy;
3635 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3636 pizza->bin_window, s_x, s_y, w, h );
3639 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3640 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3641 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3642 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3644 Refresh( TRUE, &rect );
3647 gdk_gc_unref( m_scrollGC );