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>
52 #include <gtk/gtkprivate.h>
54 #include "wx/gtk/win_gtk.h"
56 //-----------------------------------------------------------------------------
57 // documentation on internals
58 //-----------------------------------------------------------------------------
61 I have been asked several times about writing some documentation about
62 the GTK port of wxWindows, especially its internal structures. Obviously,
63 you cannot understand wxGTK without knowing a little about the GTK, but
64 some more information about what the wxWindow, which is the base class
65 for all other window classes, does seems required as well.
69 What does wxWindow do? It contains the common interface for the following
70 jobs of its descendants:
72 1) Define the rudimentary behaviour common to all window classes, such as
73 resizing, intercepting user input (so as to make it possible to use these
74 events for special purposes in a derived class), window names etc.
76 2) Provide the possibility to contain and manage children, if the derived
77 class is allowed to contain children, which holds true for those window
78 classes which do not display a native GTK widget. To name them, these
79 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
80 work classes are a special case and are handled a bit differently from
81 the rest. The same holds true for the wxNotebook class.
83 3) Provide the possibility to draw into a client area of a window. This,
84 too, only holds true for classes that do not display a native GTK widget
87 4) Provide the entire mechanism for scrolling widgets. This actual inter-
88 face for this is usually in wxScrolledWindow, but the GTK implementation
91 5) A multitude of helper or extra methods for special purposes, such as
92 Drag'n'Drop, managing validators etc.
94 6) Display a border (sunken, raised, simple or none).
96 Normally one might expect, that one wxWindows window would always correspond
97 to one GTK widget. Under GTK, there is no such allround widget that has all
98 the functionality. Moreover, the GTK defines a client area as a different
99 widget from the actual widget you are handling. Last but not least some
100 special classes (e.g. wxFrame) handle different categories of widgets and
101 still have the possibility to draw something in the client area.
102 It was therefore required to write a special purpose GTK widget, that would
103 represent a client area in the sense of wxWindows capable to do the jobs
104 2), 3) and 4). I have written this class and it resides in win_gtk.c of
107 All windows must have a widget, with which they interact with other under-
108 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
109 thw wxWindow class has a member variable called m_widget which holds a
110 pointer to this widget. When the window class represents a GTK native widget,
111 this is (in most cases) the only GTK widget the class manages. E.g. the
112 wxStatitText class handles only a GtkLabel widget a pointer to which you
113 can find in m_widget (defined in wxWindow)
115 When the class has a client area for drawing into and for containing children
116 it has to handle the client area widget (of the type GtkPizza, defined in
117 win_gtk.c), but there could be any number of widgets, handled by a class
118 The common rule for all windows is only, that the widget that interacts with
119 the rest of GTK must be referenced in m_widget and all other widgets must be
120 children of this widget on the GTK level. The top-most widget, which also
121 represents the client area, must be in the m_wxwindow field and must be of
124 As I said, the window classes that display a GTK native widget only have
125 one widget, so in the case of e.g. the wxButton class m_widget holds a
126 pointer to a GtkButton widget. But windows with client areas (for drawing
127 and children) have a m_widget field that is a pointer to a GtkScrolled-
128 Window and a m_wxwindow field that is pointer to a GtkPizza and this
129 one is (in the GTK sense) a child of the GtkScrolledWindow.
131 If the m_wxwindow field is set, then all input to this widget is inter-
132 cepted and sent to the wxWindows class. If not, all input to the widget
133 that gets pointed to by m_widget gets intercepted and sent to the class.
137 The design of scrolling in wxWindows is markedly different from that offered
138 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
139 clicking on a scrollbar belonging to scrolled window will inevitably move
140 the window. In wxWindows, the scrollbar will only emit an event, send this
141 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
142 which actually moves the window and its subchildren. Note that GtkPizza
143 memorizes how much it has been scrolled but that wxWindows forgets this
144 so that the two coordinates systems have to be kept in synch. This is done
145 in various places using the pizza->xoffset and pizza->yoffset values.
149 Singularily the most broken code in GTK is the code that is supposes to
150 inform subwindows (child windows) about new positions. Very often, duplicate
151 events are sent without changes in size or position, equally often no
152 events are sent at all (All this is due to a bug in the GtkContainer code
153 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
154 GTK's own system and it simply waits for size events for toplevel windows
155 and then iterates down the respective size events to all window. This has
156 the disadvantage, that windows might get size events before the GTK widget
157 actually has the reported size. This doesn't normally pose any problem, but
158 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
159 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
160 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
161 window that is used for OpenGl output really has that size (as reported by
166 If someone at some point of time feels the immense desire to have a look at,
167 change or attempt to optimse the Refresh() logic, this person will need an
168 intimate understanding of what a "draw" and what an "expose" events are and
169 what there are used for, in particular when used in connection with GTK's
170 own windowless widgets. Beware.
174 Cursors, too, have been a constant source of pleasure. The main difficulty
175 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
176 for the parent. To prevent this from doing too much harm, I use idle time
177 to set the cursor over and over again, starting from the toplevel windows
178 and ending with the youngest generation (speaking of parent and child windows).
179 Also don't forget that cursors (like much else) are connected to GdkWindows,
180 not GtkWidgets and that the "window" field of a GtkWidget might very well
181 point to the GdkWindow of the parent widget (-> "window less widget") and
182 that the two obviously have very different meanings.
186 //-----------------------------------------------------------------------------
188 //-----------------------------------------------------------------------------
190 extern wxList wxPendingDelete
;
191 extern bool g_blockEventsOnDrag
;
192 extern bool g_blockEventsOnScroll
;
193 extern wxCursor g_globalCursor
;
194 static wxWindow
*g_captureWindow
= (wxWindow
*) NULL
;
196 /* extern */ wxWindow
*g_focusWindow
= (wxWindow
*) NULL
;
198 // if we detect that the app has got/lost the focus, we set this variable to
199 // either TRUE or FALSE and an activate event will be sent during the next
200 // OnIdle() call and it is reset to -1: this value means that we shouldn't
201 // send any activate events at all
202 static int g_sendActivateEvent
= -1;
204 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
205 the last click here */
206 static guint32 gs_timeLastClick
= 0;
208 extern bool g_mainThreadLocked
;
210 //-----------------------------------------------------------------------------
212 //-----------------------------------------------------------------------------
214 #define DISABLE_STYLE_IF_BROKEN_THEME 1
219 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
221 # define DEBUG_MAIN_THREAD
224 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
225 GdkEvent
*WXUNUSED(event
),
226 const wxChar
*WXUNUSED(name
) )
229 static bool s_done = FALSE;
232 wxLog::AddTraceMask("focus");
235 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
241 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
243 // suppress warnings about gtk_debug_focus_in_callback being unused with
248 tmp
+= wxT(" FROM ");
251 wxChar
*s
= new wxChar
[tmp
.Length()+1];
255 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
256 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
261 #define DEBUG_MAIN_THREAD
264 //-----------------------------------------------------------------------------
265 // missing gdk functions
266 //-----------------------------------------------------------------------------
269 gdk_window_warp_pointer (GdkWindow
*window
,
273 GdkWindowPrivate
*priv
;
276 window
= (GdkWindow
*) &gdk_root_parent
;
278 priv
= (GdkWindowPrivate
*) window
;
280 if (!priv
->destroyed
)
282 XWarpPointer (priv
->xdisplay
,
283 None
, /* not source window -> move from anywhere */
284 priv
->xwindow
, /* dest window */
285 0, 0, 0, 0, /* not source window -> move from anywhere */
290 //-----------------------------------------------------------------------------
292 //-----------------------------------------------------------------------------
294 extern void wxapp_install_idle_handler();
295 extern bool g_isIdle
;
297 //-----------------------------------------------------------------------------
298 // local code (see below)
299 //-----------------------------------------------------------------------------
301 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
309 if (win
->m_hasScrolling
)
311 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
313 GtkRequisition vscroll_req
;
314 vscroll_req
.width
= 2;
315 vscroll_req
.height
= 2;
316 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
317 (scroll_window
->vscrollbar
, &vscroll_req
);
319 GtkRequisition hscroll_req
;
320 hscroll_req
.width
= 2;
321 hscroll_req
.height
= 2;
322 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
323 (scroll_window
->hscrollbar
, &hscroll_req
);
325 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget
)->klass
);
327 if (scroll_window
->vscrollbar_visible
)
329 dw
+= vscroll_req
.width
;
330 dw
+= scroll_class
->scrollbar_spacing
;
333 if (scroll_window
->hscrollbar_visible
)
335 dh
+= hscroll_req
.height
;
336 dh
+= scroll_class
->scrollbar_spacing
;
342 if (GTK_WIDGET_NO_WINDOW (widget
))
344 dx
+= widget
->allocation
.x
;
345 dy
+= widget
->allocation
.y
;
348 if (win
->HasFlag(wxRAISED_BORDER
))
350 gtk_draw_shadow( widget
->style
,
355 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
359 if (win
->HasFlag(wxSUNKEN_BORDER
))
361 gtk_draw_shadow( widget
->style
,
366 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
370 if (win
->HasFlag(wxSIMPLE_BORDER
))
373 gc
= gdk_gc_new( widget
->window
);
374 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
375 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
377 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
383 //-----------------------------------------------------------------------------
384 // "expose_event" of m_widget
385 //-----------------------------------------------------------------------------
387 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
389 if (gdk_event
->count
> 0) return FALSE
;
391 draw_frame( widget
, win
);
396 //-----------------------------------------------------------------------------
397 // "draw" of m_widget
398 //-----------------------------------------------------------------------------
400 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
402 draw_frame( widget
, win
);
405 //-----------------------------------------------------------------------------
406 // key code mapping routines
407 //-----------------------------------------------------------------------------
409 static long map_to_unmodified_wx_keysym( KeySym keysym
)
416 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
418 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
424 case GDK_Super_R
: key_code
= WXK_ALT
; break;
425 case GDK_Menu
: key_code
= WXK_MENU
; break;
426 case GDK_Help
: key_code
= WXK_HELP
; break;
427 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
428 case GDK_ISO_Left_Tab
:
429 case GDK_Tab
: key_code
= WXK_TAB
; break;
430 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
431 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
432 case GDK_Return
: key_code
= WXK_RETURN
; break;
433 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
434 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
435 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
436 case GDK_Delete
: key_code
= WXK_DELETE
; break;
437 case GDK_Home
: key_code
= WXK_HOME
; break;
438 case GDK_Left
: key_code
= WXK_LEFT
; break;
439 case GDK_Up
: key_code
= WXK_UP
; break;
440 case GDK_Right
: key_code
= WXK_RIGHT
; break;
441 case GDK_Down
: key_code
= WXK_DOWN
; break;
442 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
443 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
444 case GDK_Next
: key_code
= WXK_NEXT
; break;
445 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
446 case GDK_End
: key_code
= WXK_END
; break;
447 case GDK_Begin
: key_code
= WXK_HOME
; break;
448 case GDK_Select
: key_code
= WXK_SELECT
; break;
449 case GDK_Print
: key_code
= WXK_PRINT
; break;
450 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
451 case GDK_Insert
: key_code
= WXK_INSERT
; break;
452 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
454 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
455 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
456 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
457 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
458 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
459 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
460 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
461 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
462 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
463 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
464 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
465 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
466 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
467 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
468 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
469 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
470 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
471 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
472 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
473 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
474 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
475 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
476 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
477 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
478 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
479 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
480 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
481 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
482 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
483 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
484 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
485 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
486 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
487 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
488 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
489 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
490 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
492 case GDK_F1
: key_code
= WXK_F1
; break;
493 case GDK_F2
: key_code
= WXK_F2
; break;
494 case GDK_F3
: key_code
= WXK_F3
; break;
495 case GDK_F4
: key_code
= WXK_F4
; break;
496 case GDK_F5
: key_code
= WXK_F5
; break;
497 case GDK_F6
: key_code
= WXK_F6
; break;
498 case GDK_F7
: key_code
= WXK_F7
; break;
499 case GDK_F8
: key_code
= WXK_F8
; break;
500 case GDK_F9
: key_code
= WXK_F9
; break;
501 case GDK_F10
: key_code
= WXK_F10
; break;
502 case GDK_F11
: key_code
= WXK_F11
; break;
503 case GDK_F12
: key_code
= WXK_F12
; break;
508 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
509 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
510 key_code
= (guint
)keysym
;
518 static long map_to_wx_keysym( KeySym keysym
)
524 case GDK_Menu
: key_code
= WXK_MENU
; break;
525 case GDK_Help
: key_code
= WXK_HELP
; break;
526 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
527 case GDK_ISO_Left_Tab
:
528 case GDK_Tab
: key_code
= WXK_TAB
; break;
529 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
530 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
531 case GDK_Return
: key_code
= WXK_RETURN
; break;
532 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
533 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
534 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
535 case GDK_Delete
: key_code
= WXK_DELETE
; break;
536 case GDK_Home
: key_code
= WXK_HOME
; break;
537 case GDK_Left
: key_code
= WXK_LEFT
; break;
538 case GDK_Up
: key_code
= WXK_UP
; break;
539 case GDK_Right
: key_code
= WXK_RIGHT
; break;
540 case GDK_Down
: key_code
= WXK_DOWN
; break;
541 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
542 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
543 case GDK_Next
: key_code
= WXK_NEXT
; break;
544 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
545 case GDK_End
: key_code
= WXK_END
; break;
546 case GDK_Begin
: key_code
= WXK_HOME
; break;
547 case GDK_Select
: key_code
= WXK_SELECT
; break;
548 case GDK_Print
: key_code
= WXK_PRINT
; break;
549 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
550 case GDK_Insert
: key_code
= WXK_INSERT
; break;
551 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
553 case GDK_KP_0
: key_code
= '0'; break;
554 case GDK_KP_1
: key_code
= '1'; break;
555 case GDK_KP_2
: key_code
= '2'; break;
556 case GDK_KP_3
: key_code
= '3'; break;
557 case GDK_KP_4
: key_code
= '4'; break;
558 case GDK_KP_5
: key_code
= '5'; break;
559 case GDK_KP_6
: key_code
= '6'; break;
560 case GDK_KP_7
: key_code
= '7'; break;
561 case GDK_KP_8
: key_code
= '8'; break;
562 case GDK_KP_9
: key_code
= '9'; break;
563 case GDK_KP_Space
: key_code
= ' '; break;
564 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
565 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
566 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
567 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
568 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
569 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
570 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
571 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
572 case GDK_KP_Up
: key_code
= WXK_UP
; break;
573 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
574 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
575 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
576 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
577 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
578 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
579 case GDK_KP_End
: key_code
= WXK_END
; break;
580 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
581 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
582 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
583 case GDK_KP_Equal
: key_code
= '='; break;
584 case GDK_KP_Multiply
: key_code
= '*'; break;
585 case GDK_KP_Add
: key_code
= '+'; break;
586 case GDK_KP_Separator
: key_code
= ','; break;
587 case GDK_KP_Subtract
: key_code
= '-'; break;
588 case GDK_KP_Decimal
: key_code
= '.'; break;
589 case GDK_KP_Divide
: key_code
= '/'; break;
591 case GDK_F1
: key_code
= WXK_F1
; break;
592 case GDK_F2
: key_code
= WXK_F2
; break;
593 case GDK_F3
: key_code
= WXK_F3
; break;
594 case GDK_F4
: key_code
= WXK_F4
; break;
595 case GDK_F5
: key_code
= WXK_F5
; break;
596 case GDK_F6
: key_code
= WXK_F6
; break;
597 case GDK_F7
: key_code
= WXK_F7
; break;
598 case GDK_F8
: key_code
= WXK_F8
; break;
599 case GDK_F9
: key_code
= WXK_F9
; break;
600 case GDK_F10
: key_code
= WXK_F10
; break;
601 case GDK_F11
: key_code
= WXK_F11
; break;
602 case GDK_F12
: key_code
= WXK_F12
; break;
607 key_code
= (guint
)keysym
;
615 //-----------------------------------------------------------------------------
616 // "expose_event" of m_wxwindow
617 //-----------------------------------------------------------------------------
619 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
624 wxapp_install_idle_handler();
627 if (win->GetName() == wxT("panel"))
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 if (!win
->m_queuedFullRedraw
)
642 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
644 gdk_event
->area
.width
,
645 gdk_event
->area
.height
);
647 if (gdk_event
->count
== 0)
649 wxEraseEvent
eevent( win
->GetId() );
650 eevent
.SetEventObject( win
);
651 win
->GetEventHandler()->ProcessEvent(eevent
);
653 wxPaintEvent
event( win
->GetId() );
654 event
.SetEventObject( win
);
655 win
->GetEventHandler()->ProcessEvent( event
);
657 win
->GetUpdateRegion().Clear();
660 /* The following code will result in all window-less widgets
661 being redrawn if the wxWindows class is given a chance to
662 paint *anything* because it will then be allowed to paint
663 over the window-less widgets */
665 GtkPizza
*pizza
= GTK_PIZZA (widget
);
667 GList
*children
= pizza
->children
;
670 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
671 children
= children
->next
;
673 GdkEventExpose child_event
= *gdk_event
;
675 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
676 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
677 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
679 child_event
.area
.x
= child
->widget
->allocation
.x
;
680 child_event
.area
.y
= child
->widget
->allocation
.y
;
681 child_event
.area
.width
= child
->widget
->allocation
.width
;
682 child_event
.area
.height
= child
->widget
->allocation
.height
;
683 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
691 //-----------------------------------------------------------------------------
692 // "event" of m_wxwindow
693 //-----------------------------------------------------------------------------
695 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
696 expose events. We need them, of course, so we override the main event
697 procedure in GtkWidget by giving our own handler for all system events.
698 There, we look for expose events ourselves whereas all other events are
701 gint
gtk_window_event_event_callback( GtkWidget
*widget
, GdkEventExpose
*event
, wxWindow
*win
)
703 if (event
->type
== GDK_EXPOSE
)
705 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
712 //-----------------------------------------------------------------------------
713 // "draw" of m_wxwindow
714 //-----------------------------------------------------------------------------
716 /* This callback is a complete replacement of the gtk_pizza_draw() function,
719 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
724 wxapp_install_idle_handler();
727 if (win->GetName() == wxT("panel"))
729 wxPrintf( wxT("OnDraw from ") );
730 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
731 wxPrintf( win->GetClassInfo()->GetClassName() );
732 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
739 GtkPizza
*pizza
= GTK_PIZZA (widget
);
741 if (!win
->m_queuedFullRedraw
)
744 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
745 (pizza
->clear_on_draw
))
747 gdk_window_clear_area( pizza
->bin_window
,
748 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
751 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
753 win
->m_clipPaintRegion
= TRUE
;
755 wxEraseEvent
eevent( win
->GetId() );
756 eevent
.SetEventObject( win
);
757 win
->GetEventHandler()->ProcessEvent(eevent
);
759 wxPaintEvent
event( win
->GetId() );
760 event
.SetEventObject( win
);
761 win
->GetEventHandler()->ProcessEvent( event
);
763 win
->GetUpdateRegion().Clear();
765 win
->m_clipPaintRegion
= FALSE
;
768 GList
*children
= pizza
->children
;
771 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
772 children
= children
->next
;
774 GdkRectangle child_area
;
775 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
777 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
783 //-----------------------------------------------------------------------------
784 // "key_press_event" from any window
785 //-----------------------------------------------------------------------------
787 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
792 wxapp_install_idle_handler();
794 if (!win
->m_hasVMT
) return FALSE
;
795 if (g_blockEventsOnDrag
) return FALSE
;
799 tmp += (char)gdk_event->keyval;
800 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
801 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
806 GdkModifierType state
;
807 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
811 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
812 /* sending unknown key events doesn't really make sense */
813 if (key_code
== 0) return FALSE
;
815 wxKeyEvent
event( wxEVT_KEY_DOWN
);
816 event
.SetTimestamp( gdk_event
->time
);
817 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
818 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
819 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
820 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
821 event
.m_keyCode
= key_code
;
822 event
.m_scanCode
= gdk_event
->keyval
;
825 event
.SetEventObject( win
);
826 ret
= win
->GetEventHandler()->ProcessEvent( event
);
831 wxWindow
*ancestor
= win
;
834 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
837 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
838 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
841 if (ancestor
->m_isFrame
)
843 ancestor
= ancestor
->GetParent();
846 #endif // wxUSE_ACCEL
848 /* wxMSW doesn't send char events with Alt pressed */
849 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
850 will only be sent if it is not in an accelerator table. */
851 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
856 wxKeyEvent
event2( wxEVT_CHAR
);
857 event2
.SetTimestamp( gdk_event
->time
);
858 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
859 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
860 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
861 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
862 event2
.m_keyCode
= key_code
;
863 event2
.m_scanCode
= gdk_event
->keyval
;
866 event2
.SetEventObject( win
);
867 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
870 /* win is a control: tab can be propagated up */
872 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
873 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
874 (win
->GetParent()) &&
875 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
877 wxNavigationKeyEvent new_event
;
878 new_event
.SetEventObject( win
->GetParent() );
879 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
880 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
881 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
882 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
883 new_event
.SetCurrentFocus( win
);
884 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
887 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
889 (gdk_event
->keyval
== GDK_Escape
) )
891 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
892 new_event
.SetEventObject( win
);
893 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
896 #if (GTK_MINOR_VERSION > 0)
897 /* Pressing F10 will activate the menu bar of the top frame. */
901 (gdk_event->keyval == GDK_F10) )
903 wxWindow *ancestor = win;
906 if (wxIsKindOf(ancestor,wxFrame))
908 wxFrame *frame = (wxFrame*) ancestor;
909 wxMenuBar *menubar = frame->GetMenuBar();
912 wxNode *node = menubar->GetMenus().First();
915 wxMenu *firstMenu = (wxMenu*) node->Data();
916 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
922 ancestor = ancestor->GetParent();
930 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
937 //-----------------------------------------------------------------------------
938 // "key_release_event" from any window
939 //-----------------------------------------------------------------------------
941 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
946 wxapp_install_idle_handler();
948 if (!win
->m_hasVMT
) return FALSE
;
949 if (g_blockEventsOnDrag
) return FALSE
;
952 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
953 if (gdk_event->state & GDK_SHIFT_MASK)
954 printf( "ShiftDown.\n" );
956 printf( "ShiftUp.\n" );
957 if (gdk_event->state & GDK_CONTROL_MASK)
958 printf( "ControlDown.\n" );
960 printf( "ControlUp.\n" );
964 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
966 /* sending unknown key events doesn't really make sense */
967 if (key_code
== 0) return FALSE
;
971 GdkModifierType state
;
972 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
974 wxKeyEvent
event( wxEVT_KEY_UP
);
975 event
.SetTimestamp( gdk_event
->time
);
976 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
977 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
978 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
979 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
980 event
.m_keyCode
= key_code
;
981 event
.m_scanCode
= gdk_event
->keyval
;
984 event
.SetEventObject( win
);
986 if (win
->GetEventHandler()->ProcessEvent( event
))
988 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
995 // ----------------------------------------------------------------------------
996 // mouse event processing helper
997 // ----------------------------------------------------------------------------
999 static void AdjustEventButtonState(wxMouseEvent
& event
)
1001 // GDK reports the old state of the button for a button press event, but
1002 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1003 // for a LEFT_DOWN event, not FALSE, so we will invert
1004 // left/right/middleDown for the corresponding click events
1005 switch ( event
.GetEventType() )
1007 case wxEVT_LEFT_DOWN
:
1008 case wxEVT_LEFT_DCLICK
:
1010 event
.m_leftDown
= !event
.m_leftDown
;
1013 case wxEVT_MIDDLE_DOWN
:
1014 case wxEVT_MIDDLE_DCLICK
:
1015 case wxEVT_MIDDLE_UP
:
1016 event
.m_middleDown
= !event
.m_middleDown
;
1019 case wxEVT_RIGHT_DOWN
:
1020 case wxEVT_RIGHT_DCLICK
:
1021 case wxEVT_RIGHT_UP
:
1022 event
.m_rightDown
= !event
.m_rightDown
;
1027 //-----------------------------------------------------------------------------
1028 // "button_press_event"
1029 //-----------------------------------------------------------------------------
1031 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1036 wxapp_install_idle_handler();
1039 wxPrintf( wxT("1) OnButtonPress from ") );
1040 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1041 wxPrintf( win->GetClassInfo()->GetClassName() );
1042 wxPrintf( wxT(".\n") );
1044 if (!win
->m_hasVMT
) return FALSE
;
1045 if (g_blockEventsOnDrag
) return TRUE
;
1046 if (g_blockEventsOnScroll
) return TRUE
;
1048 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1050 if (win
->m_wxwindow
)
1052 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1054 gtk_widget_grab_focus (win
->m_wxwindow
);
1057 wxPrintf( wxT("GrabFocus from ") );
1058 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1059 wxPrintf( win->GetClassInfo()->GetClassName() );
1060 wxPrintf( wxT(".\n") );
1066 wxEventType event_type
= wxEVT_NULL
;
1068 if (gdk_event
->button
== 1)
1070 switch (gdk_event
->type
)
1072 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1073 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1077 else if (gdk_event
->button
== 2)
1079 switch (gdk_event
->type
)
1081 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1082 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1086 else if (gdk_event
->button
== 3)
1088 switch (gdk_event
->type
)
1090 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1091 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1096 if ( event_type
== wxEVT_NULL
)
1098 // unknown mouse button or click type
1102 wxMouseEvent
event( event_type
);
1103 event
.SetTimestamp( gdk_event
->time
);
1104 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1105 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1106 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1107 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1108 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1109 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1110 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1112 event
.m_x
= (wxCoord
)gdk_event
->x
;
1113 event
.m_y
= (wxCoord
)gdk_event
->y
;
1115 AdjustEventButtonState(event
);
1117 // Some control don't have their own X window and thus cannot get
1120 if (!g_captureWindow
)
1122 wxCoord x
= event
.m_x
;
1123 wxCoord y
= event
.m_y
;
1124 if (win
->m_wxwindow
)
1126 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1127 x
+= pizza
->xoffset
;
1128 y
+= pizza
->yoffset
;
1131 wxNode
*node
= win
->GetChildren().First();
1134 wxWindow
*child
= (wxWindow
*)node
->Data();
1136 node
= node
->Next();
1137 if (!child
->IsShown())
1140 if (child
->m_isStaticBox
)
1142 // wxStaticBox is transparent in the box itself
1143 int xx1
= child
->m_x
;
1144 int yy1
= child
->m_y
;
1145 int xx2
= child
->m_x
+ child
->m_width
;
1146 int yy2
= child
->m_x
+ child
->m_height
;
1149 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1151 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1153 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1155 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1158 event
.m_x
-= child
->m_x
;
1159 event
.m_y
-= child
->m_y
;
1166 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1167 (child
->m_x
<= x
) &&
1168 (child
->m_y
<= y
) &&
1169 (child
->m_x
+child
->m_width
>= x
) &&
1170 (child
->m_y
+child
->m_height
>= y
))
1173 event
.m_x
-= child
->m_x
;
1174 event
.m_y
-= child
->m_y
;
1181 event
.SetEventObject( win
);
1183 gs_timeLastClick
= gdk_event
->time
;
1186 wxPrintf( wxT("2) OnButtonPress from ") );
1187 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1188 wxPrintf( win->GetClassInfo()->GetClassName() );
1189 wxPrintf( wxT(".\n") );
1192 if (win
->GetEventHandler()->ProcessEvent( event
))
1194 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1201 //-----------------------------------------------------------------------------
1202 // "button_release_event"
1203 //-----------------------------------------------------------------------------
1205 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1210 wxapp_install_idle_handler();
1212 if (!win
->m_hasVMT
) return FALSE
;
1213 if (g_blockEventsOnDrag
) return FALSE
;
1214 if (g_blockEventsOnScroll
) return FALSE
;
1216 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1219 printf( "OnButtonRelease from " );
1220 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1221 printf( win->GetClassInfo()->GetClassName() );
1225 wxEventType event_type
= wxEVT_NULL
;
1227 switch (gdk_event
->button
)
1229 case 1: event_type
= wxEVT_LEFT_UP
; break;
1230 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1231 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1232 default: return FALSE
;
1235 wxMouseEvent
event( event_type
);
1236 event
.SetTimestamp( gdk_event
->time
);
1237 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1238 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1239 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1240 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1241 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1242 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1243 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1244 event
.m_x
= (wxCoord
)gdk_event
->x
;
1245 event
.m_y
= (wxCoord
)gdk_event
->y
;
1247 AdjustEventButtonState(event
);
1249 // Some control don't have their own X window and thus cannot get
1252 if (!g_captureWindow
)
1254 wxCoord x
= event
.m_x
;
1255 wxCoord y
= event
.m_y
;
1256 if (win
->m_wxwindow
)
1258 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1259 x
+= pizza
->xoffset
;
1260 y
+= pizza
->yoffset
;
1263 wxNode
*node
= win
->GetChildren().First();
1266 wxWindow
*child
= (wxWindow
*)node
->Data();
1268 node
= node
->Next();
1269 if (!child
->IsShown())
1272 if (child
->m_isStaticBox
)
1274 // wxStaticBox is transparent in the box itself
1275 int xx1
= child
->m_x
;
1276 int yy1
= child
->m_y
;
1277 int xx2
= child
->m_x
+ child
->m_width
;
1278 int yy2
= child
->m_x
+ child
->m_height
;
1281 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1283 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1285 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1287 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1290 event
.m_x
-= child
->m_x
;
1291 event
.m_y
-= child
->m_y
;
1298 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1299 (child
->m_x
<= x
) &&
1300 (child
->m_y
<= y
) &&
1301 (child
->m_x
+child
->m_width
>= x
) &&
1302 (child
->m_y
+child
->m_height
>= y
))
1305 event
.m_x
-= child
->m_x
;
1306 event
.m_y
-= child
->m_y
;
1313 event
.SetEventObject( win
);
1315 if (win
->GetEventHandler()->ProcessEvent( event
))
1317 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1324 //-----------------------------------------------------------------------------
1325 // "motion_notify_event"
1326 //-----------------------------------------------------------------------------
1328 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1333 wxapp_install_idle_handler();
1335 if (!win
->m_hasVMT
) return FALSE
;
1336 if (g_blockEventsOnDrag
) return FALSE
;
1337 if (g_blockEventsOnScroll
) return FALSE
;
1339 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1341 if (gdk_event
->is_hint
)
1345 GdkModifierType state
;
1346 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1352 printf( "OnMotion from " );
1353 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1354 printf( win->GetClassInfo()->GetClassName() );
1358 wxMouseEvent
event( wxEVT_MOTION
);
1359 event
.SetTimestamp( gdk_event
->time
);
1360 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1361 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1362 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1363 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1364 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1365 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1366 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1368 event
.m_x
= (wxCoord
)gdk_event
->x
;
1369 event
.m_y
= (wxCoord
)gdk_event
->y
;
1371 // Some control don't have their own X window and thus cannot get
1374 if (!g_captureWindow
)
1376 wxCoord x
= event
.m_x
;
1377 wxCoord y
= event
.m_y
;
1378 if (win
->m_wxwindow
)
1380 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1381 x
+= pizza
->xoffset
;
1382 y
+= pizza
->yoffset
;
1385 wxNode
*node
= win
->GetChildren().First();
1388 wxWindow
*child
= (wxWindow
*)node
->Data();
1390 node
= node
->Next();
1391 if (!child
->IsShown())
1394 if (child
->m_isStaticBox
)
1396 // wxStaticBox is transparent in the box itself
1397 int xx1
= child
->m_x
;
1398 int yy1
= child
->m_y
;
1399 int xx2
= child
->m_x
+ child
->m_width
;
1400 int yy2
= child
->m_x
+ child
->m_height
;
1403 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1405 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1407 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1409 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1412 event
.m_x
-= child
->m_x
;
1413 event
.m_y
-= child
->m_y
;
1420 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1421 (child
->m_x
<= x
) &&
1422 (child
->m_y
<= y
) &&
1423 (child
->m_x
+child
->m_width
>= x
) &&
1424 (child
->m_y
+child
->m_height
>= y
))
1427 event
.m_x
-= child
->m_x
;
1428 event
.m_y
-= child
->m_y
;
1435 event
.SetEventObject( win
);
1437 if (win
->GetEventHandler()->ProcessEvent( event
))
1439 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1446 //-----------------------------------------------------------------------------
1448 //-----------------------------------------------------------------------------
1450 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1455 wxapp_install_idle_handler();
1457 if (!win
->m_hasVMT
) return FALSE
;
1458 if (g_blockEventsOnDrag
) return FALSE
;
1460 switch ( g_sendActivateEvent
)
1463 // we've got focus from outside, synthtize wxActivateEvent
1464 g_sendActivateEvent
= 1;
1468 // another our window just lost focus, it was already ours before
1469 // - don't send any wxActivateEvent
1470 g_sendActivateEvent
= -1;
1474 g_focusWindow
= win
;
1477 printf( "OnSetFocus from " );
1478 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1479 printf( win->GetClassInfo()->GetClassName() );
1481 printf( WXSTRINGCAST win->GetLabel() );
1485 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1488 panel
->SetLastFocus(win
);
1493 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1496 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1497 event
.SetEventObject( win
);
1499 if (win
->GetEventHandler()->ProcessEvent( event
))
1501 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1508 //-----------------------------------------------------------------------------
1509 // "focus_out_event"
1510 //-----------------------------------------------------------------------------
1512 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1517 wxapp_install_idle_handler();
1519 if (!win
->m_hasVMT
) return FALSE
;
1520 if (g_blockEventsOnDrag
) return FALSE
;
1522 // if the focus goes out of our app alltogether, OnIdle() will send
1523 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1524 // g_sendActivateEvent to -1
1525 g_sendActivateEvent
= 0;
1527 g_focusWindow
= (wxWindow
*)NULL
;
1530 printf( "OnKillFocus from " );
1531 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1532 printf( win->GetClassInfo()->GetClassName() );
1541 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1542 event
.SetEventObject( win
);
1544 if (win
->GetEventHandler()->ProcessEvent( event
))
1546 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1553 //-----------------------------------------------------------------------------
1554 // "enter_notify_event"
1555 //-----------------------------------------------------------------------------
1557 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1562 wxapp_install_idle_handler();
1564 if (!win
->m_hasVMT
) return FALSE
;
1565 if (g_blockEventsOnDrag
) return FALSE
;
1567 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1569 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1570 #if (GTK_MINOR_VERSION > 0)
1571 event
.SetTimestamp( gdk_event
->time
);
1573 event
.SetEventObject( win
);
1577 GdkModifierType state
= (GdkModifierType
)0;
1579 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1581 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1582 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1583 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1584 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1585 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1586 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1587 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1592 if (win
->GetEventHandler()->ProcessEvent( event
))
1594 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1601 //-----------------------------------------------------------------------------
1602 // "leave_notify_event"
1603 //-----------------------------------------------------------------------------
1605 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1610 wxapp_install_idle_handler();
1612 if (!win
->m_hasVMT
) return FALSE
;
1613 if (g_blockEventsOnDrag
) return FALSE
;
1615 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1617 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1618 #if (GTK_MINOR_VERSION > 0)
1619 event
.SetTimestamp( gdk_event
->time
);
1621 event
.SetEventObject( win
);
1625 GdkModifierType state
= (GdkModifierType
)0;
1627 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1629 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1630 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1631 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1632 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1633 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1634 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1635 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1640 if (win
->GetEventHandler()->ProcessEvent( event
))
1642 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1649 //-----------------------------------------------------------------------------
1650 // "value_changed" from m_vAdjust
1651 //-----------------------------------------------------------------------------
1653 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1658 wxapp_install_idle_handler();
1660 if (g_blockEventsOnDrag
) return;
1662 if (!win
->m_hasVMT
) return;
1664 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1665 if (fabs(diff
) < 0.2) return;
1667 win
->m_oldVerticalPos
= adjust
->value
;
1669 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1670 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1672 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1673 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1674 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1675 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1676 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1678 int value
= (int)(adjust
->value
+0.5);
1680 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1681 event
.SetEventObject( win
);
1682 win
->GetEventHandler()->ProcessEvent( event
);
1685 //-----------------------------------------------------------------------------
1686 // "value_changed" from m_hAdjust
1687 //-----------------------------------------------------------------------------
1689 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1694 wxapp_install_idle_handler();
1696 if (g_blockEventsOnDrag
) return;
1697 if (!win
->m_hasVMT
) return;
1699 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1700 if (fabs(diff
) < 0.2) return;
1702 win
->m_oldHorizontalPos
= adjust
->value
;
1704 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1705 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1707 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1708 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1709 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1710 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1711 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1713 int value
= (int)(adjust
->value
+0.5);
1715 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1716 event
.SetEventObject( win
);
1717 win
->GetEventHandler()->ProcessEvent( event
);
1720 //-----------------------------------------------------------------------------
1721 // "button_press_event" from scrollbar
1722 //-----------------------------------------------------------------------------
1724 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1725 GdkEventButton
*gdk_event
,
1731 wxapp_install_idle_handler();
1734 g_blockEventsOnScroll
= TRUE
;
1735 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1740 //-----------------------------------------------------------------------------
1741 // "button_release_event" from scrollbar
1742 //-----------------------------------------------------------------------------
1744 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1745 GdkEventButton
*WXUNUSED(gdk_event
),
1750 // don't test here as we can release the mouse while being over
1751 // a different window than the slider
1753 // if (gdk_event->window != widget->slider) return FALSE;
1755 g_blockEventsOnScroll
= FALSE
;
1757 if (win
->m_isScrolling
)
1759 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
1763 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1764 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1766 value
= (int)(win
->m_hAdjust
->value
+0.5);
1769 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1771 value
= (int)(win
->m_vAdjust
->value
+0.5);
1775 wxScrollWinEvent
event( command
, value
, dir
);
1776 event
.SetEventObject( win
);
1777 win
->GetEventHandler()->ProcessEvent( event
);
1780 win
->m_isScrolling
= FALSE
;
1785 // ----------------------------------------------------------------------------
1786 // this wxWindowBase function is implemented here (in platform-specific file)
1787 // because it is static and so couldn't be made virtual
1788 // ----------------------------------------------------------------------------
1790 wxWindow
*wxWindowBase::FindFocus()
1792 return g_focusWindow
;
1795 //-----------------------------------------------------------------------------
1796 // "realize" from m_widget
1797 //-----------------------------------------------------------------------------
1799 /* We cannot set colours and fonts before the widget has
1800 been realized, so we do this directly after realization. */
1803 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1808 wxapp_install_idle_handler();
1810 if (win
->m_delayedBackgroundColour
)
1811 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1813 if (win
->m_delayedForegroundColour
)
1814 win
->SetForegroundColour( win
->GetForegroundColour() );
1816 wxWindowCreateEvent
event( win
);
1817 event
.SetEventObject( win
);
1818 win
->GetEventHandler()->ProcessEvent( event
);
1823 //-----------------------------------------------------------------------------
1825 //-----------------------------------------------------------------------------
1828 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
1829 GtkAllocation
*WXUNUSED(alloc
),
1833 wxapp_install_idle_handler();
1835 if (!win
->m_hasScrolling
) return;
1837 int client_width
= 0;
1838 int client_height
= 0;
1839 win
->GetClientSize( &client_width
, &client_height
);
1840 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
1843 win
->m_oldClientWidth
= client_width
;
1844 win
->m_oldClientHeight
= client_height
;
1846 if (!win
->m_nativeSizeEvent
)
1848 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
1849 event
.SetEventObject( win
);
1850 win
->GetEventHandler()->ProcessEvent( event
);
1856 #define WXUNUSED_UNLESS_XIM(param) param
1858 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1861 /* Resize XIM window */
1864 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1865 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1866 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1869 wxapp_install_idle_handler();
1875 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1879 gdk_window_get_size (widget
->window
, &width
, &height
);
1880 win
->m_icattr
->preedit_area
.width
= width
;
1881 win
->m_icattr
->preedit_area
.height
= height
;
1882 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
1887 //-----------------------------------------------------------------------------
1888 // "realize" from m_wxwindow
1889 //-----------------------------------------------------------------------------
1891 /* Initialize XIM support */
1894 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1895 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1898 wxapp_install_idle_handler();
1901 if (win
->m_ic
) return FALSE
;
1902 if (!widget
) return FALSE
;
1903 if (!gdk_im_ready()) return FALSE
;
1905 win
->m_icattr
= gdk_ic_attr_new();
1906 if (!win
->m_icattr
) return FALSE
;
1910 GdkColormap
*colormap
;
1911 GdkICAttr
*attr
= win
->m_icattr
;
1912 unsigned attrmask
= GDK_IC_ALL_REQ
;
1914 GdkIMStyle supported_style
= (GdkIMStyle
)
1915 (GDK_IM_PREEDIT_NONE
|
1916 GDK_IM_PREEDIT_NOTHING
|
1917 GDK_IM_PREEDIT_POSITION
|
1918 GDK_IM_STATUS_NONE
|
1919 GDK_IM_STATUS_NOTHING
);
1921 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1922 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
1924 attr
->style
= style
= gdk_im_decide_style (supported_style
);
1925 attr
->client_window
= widget
->window
;
1927 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
1928 gtk_widget_get_default_colormap ())
1930 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
1931 attr
->preedit_colormap
= colormap
;
1934 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
1935 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
1936 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
1937 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
1939 switch (style
& GDK_IM_PREEDIT_MASK
)
1941 case GDK_IM_PREEDIT_POSITION
:
1942 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1944 g_warning ("over-the-spot style requires fontset");
1948 gdk_window_get_size (widget
->window
, &width
, &height
);
1950 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
1951 attr
->spot_location
.x
= 0;
1952 attr
->spot_location
.y
= height
;
1953 attr
->preedit_area
.x
= 0;
1954 attr
->preedit_area
.y
= 0;
1955 attr
->preedit_area
.width
= width
;
1956 attr
->preedit_area
.height
= height
;
1957 attr
->preedit_fontset
= widget
->style
->font
;
1962 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
1964 if (win
->m_ic
== NULL
)
1965 g_warning ("Can't create input context.");
1968 mask
= gdk_window_get_events (widget
->window
);
1969 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
1970 gdk_window_set_events (widget
->window
, mask
);
1972 if (GTK_WIDGET_HAS_FOCUS(widget
))
1973 gdk_im_begin (win
->m_ic
, widget
->window
);
1980 //-----------------------------------------------------------------------------
1981 // InsertChild for wxWindow.
1982 //-----------------------------------------------------------------------------
1984 /* Callback for wxWindow. This very strange beast has to be used because
1985 * C++ has no virtual methods in a constructor. We have to emulate a
1986 * virtual function here as wxNotebook requires a different way to insert
1987 * a child in it. I had opted for creating a wxNotebookPage window class
1988 * which would have made this superfluous (such in the MDI window system),
1989 * but no-one was listening to me... */
1991 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1993 /* the window might have been scrolled already, do we
1994 have to adapt the position */
1995 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
1996 child
->m_x
+= pizza
->xoffset
;
1997 child
->m_y
+= pizza
->yoffset
;
1999 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2000 GTK_WIDGET(child
->m_widget
),
2007 //-----------------------------------------------------------------------------
2009 //-----------------------------------------------------------------------------
2011 wxWindow
* wxGetActiveWindow()
2013 return g_focusWindow
;
2016 //-----------------------------------------------------------------------------
2018 //-----------------------------------------------------------------------------
2020 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2022 void wxWindow::Init()
2028 m_widget
= (GtkWidget
*) NULL
;
2029 m_wxwindow
= (GtkWidget
*) NULL
;
2039 m_needParent
= TRUE
;
2040 m_isBeingDeleted
= FALSE
;
2043 m_nativeSizeEvent
= FALSE
;
2045 m_hasScrolling
= FALSE
;
2046 m_isScrolling
= FALSE
;
2048 m_hAdjust
= (GtkAdjustment
*) NULL
;
2049 m_vAdjust
= (GtkAdjustment
*) NULL
;
2050 m_oldHorizontalPos
= 0.0;
2051 m_oldVerticalPos
= 0.0;
2054 m_widgetStyle
= (GtkStyle
*) NULL
;
2056 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2058 m_isStaticBox
= FALSE
;
2059 m_isRadioButton
= FALSE
;
2061 m_acceptsFocus
= FALSE
;
2063 m_clipPaintRegion
= FALSE
;
2064 m_queuedFullRedraw
= FALSE
;
2066 m_cursor
= *wxSTANDARD_CURSOR
;
2069 m_ic
= (GdkIC
*) NULL
;
2070 m_icattr
= (GdkICAttr
*) NULL
;
2074 wxWindow::wxWindow()
2079 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
2080 const wxPoint
&pos
, const wxSize
&size
,
2081 long style
, const wxString
&name
)
2085 Create( parent
, id
, pos
, size
, style
, name
);
2088 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
2089 const wxPoint
&pos
, const wxSize
&size
,
2090 long style
, const wxString
&name
)
2092 if (!PreCreation( parent
, pos
, size
) ||
2093 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2095 wxFAIL_MSG( wxT("wxWindow creation failed") );
2099 m_insertCallback
= wxInsertChildInWindow
;
2101 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2102 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2104 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2106 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2107 scroll_class
->scrollbar_spacing
= 0;
2109 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2111 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2112 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2114 m_wxwindow
= gtk_pizza_new();
2116 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2118 #if (GTK_MINOR_VERSION > 0)
2119 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2121 if (HasFlag(wxRAISED_BORDER
))
2123 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2125 else if (HasFlag(wxSUNKEN_BORDER
))
2127 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2129 else if (HasFlag(wxSIMPLE_BORDER
))
2131 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2135 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2137 #else // GTK_MINOR_VERSION == 0
2138 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2140 if (HasFlag(wxRAISED_BORDER
))
2142 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2144 else if (HasFlag(wxSUNKEN_BORDER
))
2146 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2150 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2152 #endif // GTK_MINOR_VERSION
2154 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2155 m_acceptsFocus
= TRUE
;
2157 #if (GTK_MINOR_VERSION == 0)
2158 // shut the viewport up
2159 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2160 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2161 #endif // GTK_MINOR_VERSION == 0
2163 // I _really_ don't want scrollbars in the beginning
2164 m_vAdjust
->lower
= 0.0;
2165 m_vAdjust
->upper
= 1.0;
2166 m_vAdjust
->value
= 0.0;
2167 m_vAdjust
->step_increment
= 1.0;
2168 m_vAdjust
->page_increment
= 1.0;
2169 m_vAdjust
->page_size
= 5.0;
2170 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2171 m_hAdjust
->lower
= 0.0;
2172 m_hAdjust
->upper
= 1.0;
2173 m_hAdjust
->value
= 0.0;
2174 m_hAdjust
->step_increment
= 1.0;
2175 m_hAdjust
->page_increment
= 1.0;
2176 m_hAdjust
->page_size
= 5.0;
2177 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2179 // these handlers block mouse events to any window during scrolling such as
2180 // motion events and prevent GTK and wxWindows from fighting over where the
2183 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2184 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2186 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2187 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2189 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2190 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2192 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2193 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2195 // these handlers get notified when screen updates are required either when
2196 // scrolling or when the window size (and therefore scrollbar configuration)
2199 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2200 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2201 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2202 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2204 gtk_widget_show( m_wxwindow
);
2207 m_parent
->DoAddChild( this );
2216 wxWindow::~wxWindow()
2218 m_isBeingDeleted
= TRUE
;
2227 m_parent
->RemoveChild( this );
2231 gdk_ic_destroy (m_ic
);
2233 gdk_ic_attr_destroy (m_icattr
);
2238 #if DISABLE_STYLE_IF_BROKEN_THEME
2239 // don't delete if it's a pixmap theme style
2240 if (!m_widgetStyle
->engine_data
)
2241 gtk_style_unref( m_widgetStyle
);
2243 m_widgetStyle
= (GtkStyle
*) NULL
;
2248 gtk_widget_destroy( m_wxwindow
);
2249 m_wxwindow
= (GtkWidget
*) NULL
;
2254 gtk_widget_destroy( m_widget
);
2255 m_widget
= (GtkWidget
*) NULL
;
2259 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2261 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2263 /* this turns -1 into 20 so that a minimal window is
2264 visible even although -1,-1 has been given as the
2265 size of the window. the same trick is used in other
2266 ports and should make debugging easier */
2267 m_width
= WidthDefault(size
.x
);
2268 m_height
= HeightDefault(size
.y
);
2273 /* some reasonable defaults */
2278 m_x
= (gdk_screen_width () - m_width
) / 2;
2279 if (m_x
< 10) m_x
= 10;
2283 m_y
= (gdk_screen_height () - m_height
) / 2;
2284 if (m_y
< 10) m_y
= 10;
2291 void wxWindow::PostCreation()
2293 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2299 /* these get reported to wxWindows -> wxPaintEvent */
2301 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2303 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2304 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2306 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2307 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2309 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2310 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2313 #if (GTK_MINOR_VERSION > 0)
2314 /* these are called when the "sunken" or "raised" borders are drawn */
2315 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2316 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2318 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2319 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2323 if (m_wxwindow
&& m_needParent
)
2325 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2326 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2328 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2329 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2333 // For dialogs and frames, we are interested mainly in
2334 // m_widget's focus.
2336 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2337 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2339 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2340 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2343 GtkWidget
*connect_widget
= GetConnectWidget();
2345 ConnectWidget( connect_widget
);
2347 /* We cannot set colours, fonts and cursors before the widget has
2348 been realized, so we do this directly after realization */
2349 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2350 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2354 /* Catch native resize events. */
2355 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2356 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2358 /* Initialize XIM support. */
2359 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2360 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2362 /* And resize XIM window. */
2363 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2364 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2370 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2372 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2373 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2375 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2376 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2378 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2379 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2381 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2382 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2384 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2385 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2387 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2388 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2390 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2391 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2394 bool wxWindow::Destroy()
2396 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2400 return wxWindowBase::Destroy();
2403 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2405 if (m_wxwindow
&& GTK_PIZZA(m_wxwindow
)->bin_window
)
2407 /* Normally, GTK will send expose events only for the regions
2408 which actually got exposed. Sadly, wxMSW invalidates
2409 the whole window so we have to do that, too. We could
2410 simply add a complete refresh, but we would then get
2411 the normal GTK expose events in surplus, so we shut
2412 off the expose events and schedule a full redraw to
2413 be done in OnInternalIdle, where we restore the handling
2414 of expose events. */
2416 m_queuedFullRedraw
= TRUE
;
2418 GdkEventMask mask
= gdk_window_get_events( GTK_PIZZA(m_wxwindow
)->bin_window
);
2419 mask
= (GdkEventMask
)(mask
& ~GDK_EXPOSURE_MASK
);
2420 gdk_window_set_events( GTK_PIZZA(m_wxwindow
)->bin_window
, mask
);
2423 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2426 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2428 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2429 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2431 if (m_resizing
) return; /* I don't like recursions */
2434 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2436 /* don't set the size for children of wxNotebook, just take the values. */
2444 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2446 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2448 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2449 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2450 if (width
!= -1) m_width
= width
;
2451 if (height
!= -1) m_height
= height
;
2455 m_x
= x
+ pizza
->xoffset
;
2456 m_y
= y
+ pizza
->yoffset
;
2461 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2463 if (width
== -1) m_width
= 80;
2466 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2468 if (height
== -1) m_height
= 26;
2471 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2472 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2473 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2474 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2477 int bottom_border
= 0;
2479 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2481 /* the default button has a border around it */
2486 DoMoveWindow( m_x
-border
,
2489 m_height
+border
+bottom_border
);
2494 /* Sometimes the client area changes size without the
2495 whole windows's size changing, but if the whole
2496 windows's size doesn't change, no wxSizeEvent will
2497 normally be sent. Here we add an extra test if
2498 the client test has been changed and this will
2500 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2504 wxPrintf( "OnSize sent from " );
2505 if (GetClassInfo() && GetClassInfo()->GetClassName())
2506 wxPrintf( GetClassInfo()->GetClassName() );
2507 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2510 if (!m_nativeSizeEvent
)
2512 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2513 event
.SetEventObject( this );
2514 GetEventHandler()->ProcessEvent( event
);
2520 void wxWindow::OnInternalIdle()
2522 if ( g_sendActivateEvent
!= -1 )
2524 bool activate
= g_sendActivateEvent
!= 0;
2527 g_sendActivateEvent
= -1;
2529 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2530 event
.SetEventObject(this);
2532 (void)GetEventHandler()->ProcessEvent(event
);
2535 wxCursor cursor
= m_cursor
;
2536 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2540 /* I now set the cursor anew in every OnInternalIdle call
2541 as setting the cursor in a parent window also effects the
2542 windows above so that checking for the current cursor is
2547 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2549 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2551 if (!g_globalCursor
.Ok())
2552 cursor
= *wxSTANDARD_CURSOR
;
2554 window
= m_widget
->window
;
2555 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2556 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2562 GdkWindow
*window
= m_widget
->window
;
2563 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2564 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2571 if (m_queuedFullRedraw
)
2573 /* See also wxWindow::DoMoveWindow for explanation of this code. What
2574 we test here is if the requested size of the window is the same as
2575 the actual size of window, in which case all expose events that resulted
2576 from resizing the window have been sent (and discarded) and we can
2577 now do our full redraw and switch on expose event handling again. */
2579 bool child_already_resized
= FALSE
;
2581 child_already_resized
= gtk_pizza_child_resized( GTK_PIZZA(m_wxwindow
->parent
), m_wxwindow
);
2583 child_already_resized
= gtk_pizza_child_resized( GTK_PIZZA(m_widget
->parent
), m_widget
);
2585 if (child_already_resized
)
2587 m_queuedFullRedraw
= FALSE
;
2588 m_updateRegion
.Clear();
2589 m_updateRegion
.Union( 0,0,m_width
,m_height
);
2590 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2592 GdkEventMask mask
= gdk_window_get_events( GTK_PIZZA(m_wxwindow
)->bin_window
);
2593 mask
= (GdkEventMask
)(mask
| GDK_EXPOSURE_MASK
);
2594 gdk_window_set_events( GTK_PIZZA(m_wxwindow
)->bin_window
, mask
);
2599 void wxWindow::DoGetSize( int *width
, int *height
) const
2601 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2603 if (width
) (*width
) = m_width
;
2604 if (height
) (*height
) = m_height
;
2607 void wxWindow::DoSetClientSize( int width
, int height
)
2609 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2613 SetSize( width
, height
);
2620 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2622 /* when using GTK 1.2 we set the shadow border size to 2 */
2626 if (HasFlag(wxSIMPLE_BORDER
))
2628 /* when using GTK 1.2 we set the simple border size to 1 */
2635 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2637 GtkRequisition vscroll_req
;
2638 vscroll_req
.width
= 2;
2639 vscroll_req
.height
= 2;
2640 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
2641 (scroll_window
->vscrollbar
, &vscroll_req
);
2643 GtkRequisition hscroll_req
;
2644 hscroll_req
.width
= 2;
2645 hscroll_req
.height
= 2;
2646 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
2647 (scroll_window
->hscrollbar
, &hscroll_req
);
2649 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2651 if (scroll_window
->vscrollbar_visible
)
2653 dw
+= vscroll_req
.width
;
2654 dw
+= scroll_class
->scrollbar_spacing
;
2657 if (scroll_window
->hscrollbar_visible
)
2659 dh
+= hscroll_req
.height
;
2660 dh
+= scroll_class
->scrollbar_spacing
;
2664 SetSize( width
+dw
, height
+dh
);
2668 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2670 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2674 if (width
) (*width
) = m_width
;
2675 if (height
) (*height
) = m_height
;
2682 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2684 /* when using GTK 1.2 we set the shadow border size to 2 */
2688 if (HasFlag(wxSIMPLE_BORDER
))
2690 /* when using GTK 1.2 we set the simple border size to 1 */
2697 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2699 GtkRequisition vscroll_req
;
2700 vscroll_req
.width
= 2;
2701 vscroll_req
.height
= 2;
2702 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
2703 (scroll_window
->vscrollbar
, &vscroll_req
);
2705 GtkRequisition hscroll_req
;
2706 hscroll_req
.width
= 2;
2707 hscroll_req
.height
= 2;
2708 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
2709 (scroll_window
->hscrollbar
, &hscroll_req
);
2711 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2713 if (scroll_window
->vscrollbar_visible
)
2715 dw
+= vscroll_req
.width
;
2716 dw
+= scroll_class
->scrollbar_spacing
;
2719 if (scroll_window
->hscrollbar_visible
)
2721 dh
+= hscroll_req
.height
;
2722 dh
+= scroll_class
->scrollbar_spacing
;
2726 if (width
) (*width
) = m_width
- dw
;
2727 if (height
) (*height
) = m_height
- dh
;
2731 void wxWindow::DoGetPosition( int *x
, int *y
) const
2733 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2737 if (m_parent
&& m_parent
->m_wxwindow
)
2739 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2740 dx
= pizza
->xoffset
;
2741 dy
= pizza
->yoffset
;
2744 if (x
) (*x
) = m_x
- dx
;
2745 if (y
) (*y
) = m_y
- dy
;
2748 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2750 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2752 if (!m_widget
->window
) return;
2754 GdkWindow
*source
= (GdkWindow
*) NULL
;
2756 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2758 source
= m_widget
->window
;
2762 gdk_window_get_origin( source
, &org_x
, &org_y
);
2766 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2768 org_x
+= m_widget
->allocation
.x
;
2769 org_y
+= m_widget
->allocation
.y
;
2777 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2779 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2781 if (!m_widget
->window
) return;
2783 GdkWindow
*source
= (GdkWindow
*) NULL
;
2785 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2787 source
= m_widget
->window
;
2791 gdk_window_get_origin( source
, &org_x
, &org_y
);
2795 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2797 org_x
+= m_widget
->allocation
.x
;
2798 org_y
+= m_widget
->allocation
.y
;
2806 bool wxWindow::Show( bool show
)
2808 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2810 if (!wxWindowBase::Show(show
))
2817 gtk_widget_show( m_widget
);
2819 gtk_widget_hide( m_widget
);
2824 bool wxWindow::Enable( bool enable
)
2826 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2828 if (!wxWindowBase::Enable(enable
))
2834 gtk_widget_set_sensitive( m_widget
, enable
);
2836 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2841 int wxWindow::GetCharHeight() const
2843 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2845 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2847 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2849 return font
->ascent
+ font
->descent
;
2852 int wxWindow::GetCharWidth() const
2854 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2856 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2858 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2860 return gdk_string_width( font
, "H" );
2863 void wxWindow::GetTextExtent( const wxString
& string
,
2867 int *externalLeading
,
2868 const wxFont
*theFont
) const
2870 wxFont fontToUse
= m_font
;
2871 if (theFont
) fontToUse
= *theFont
;
2873 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2875 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2876 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2877 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2878 if (descent
) (*descent
) = font
->descent
;
2879 if (externalLeading
) (*externalLeading
) = 0; // ??
2882 void wxWindow::SetFocus()
2884 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2888 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2889 gtk_widget_grab_focus (m_wxwindow
);
2895 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2897 gtk_widget_grab_focus (m_widget
);
2899 else if (GTK_IS_CONTAINER(m_widget
))
2901 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2910 bool wxWindow::AcceptsFocus() const
2912 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2915 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2917 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2919 wxWindow
*oldParent
= m_parent
,
2920 *newParent
= (wxWindow
*)newParentBase
;
2922 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2924 if ( !wxWindowBase::Reparent(newParent
) )
2927 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2929 /* prevent GTK from deleting the widget arbitrarily */
2930 gtk_widget_ref( m_widget
);
2934 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2937 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2941 /* insert GTK representation */
2942 (*(newParent
->m_insertCallback
))(newParent
, this);
2945 /* reverse: prevent GTK from deleting the widget arbitrarily */
2946 gtk_widget_unref( m_widget
);
2951 void wxWindow::DoAddChild(wxWindow
*child
)
2953 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2955 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
2957 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
2962 /* insert GTK representation */
2963 (*m_insertCallback
)(this, child
);
2966 void wxWindow::Raise()
2968 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2970 if (!m_widget
->window
) return;
2972 gdk_window_raise( m_widget
->window
);
2975 void wxWindow::Lower()
2977 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2979 if (!m_widget
->window
) return;
2981 gdk_window_lower( m_widget
->window
);
2984 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2986 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2988 return wxWindowBase::SetCursor( cursor
);
2991 void wxWindow::WarpPointer( int x
, int y
)
2993 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2995 /* we provide this function ourselves as it is
2996 missing in GDK (top of this file) */
2998 GdkWindow
*window
= (GdkWindow
*) NULL
;
3000 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3002 window
= GetConnectWidget()->window
;
3005 gdk_window_warp_pointer( window
, x
, y
);
3008 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
3010 if (!m_widget
) return;
3011 if (!m_widget
->window
) return;
3013 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3017 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3019 rect
->width
, rect
->height
);
3023 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3027 /* there is no GTK equivalent of "draw only, don't clear" so we
3028 invent our own in the GtkPizza widget */
3036 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3037 gboolean old_clear = pizza->clear_on_draw;
3038 gtk_pizza_set_clear( pizza, FALSE );
3039 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3040 gtk_pizza_set_clear( pizza, old_clear );
3042 GdkEventExpose gdk_event
;
3043 gdk_event
.type
= GDK_EXPOSE
;
3044 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3045 gdk_event
.count
= 0;
3046 gdk_event
.area
.x
= 0;
3047 gdk_event
.area
.y
= 0;
3048 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3049 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3050 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3055 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3064 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3065 gboolean old_clear = pizza->clear_on_draw;
3066 gtk_pizza_set_clear( pizza, FALSE );
3068 GdkRectangle gdk_rect;
3069 gdk_rect.x = rect->x;
3070 gdk_rect.y = rect->y;
3071 gdk_rect.width = rect->width;
3072 gdk_rect.height = rect->height;
3073 gtk_widget_draw( m_wxwindow, &gdk_rect );
3074 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3076 gtk_pizza_set_clear( pizza, old_clear );
3078 GdkEventExpose gdk_event
;
3079 gdk_event
.type
= GDK_EXPOSE
;
3080 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3081 gdk_event
.count
= 0;
3082 gdk_event
.area
.x
= rect
->x
;
3083 gdk_event
.area
.y
= rect
->y
;
3084 gdk_event
.area
.width
= rect
->width
;
3085 gdk_event
.area
.height
= rect
->height
;
3086 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3090 GdkRectangle gdk_rect
;
3091 gdk_rect
.x
= rect
->x
;
3092 gdk_rect
.y
= rect
->y
;
3093 gdk_rect
.width
= rect
->width
;
3094 gdk_rect
.height
= rect
->height
;
3095 gtk_widget_draw( m_widget
, &gdk_rect
);
3100 void wxWindow::Clear()
3102 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3104 if (!m_widget
->window
) return;
3106 if (m_wxwindow
&& m_wxwindow
->window
)
3108 // gdk_window_clear( m_wxwindow->window );
3113 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
3115 wxWindowBase::DoSetToolTip(tip
);
3118 m_tooltip
->Apply( this );
3121 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3123 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3125 #endif // wxUSE_TOOLTIPS
3127 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
3129 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3131 if (!wxWindowBase::SetBackgroundColour(colour
))
3133 // don't leave if the GTK widget has just
3135 if (!m_delayedBackgroundColour
) return FALSE
;
3138 GdkWindow
*window
= (GdkWindow
*) NULL
;
3140 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3142 window
= GetConnectWidget()->window
;
3146 // indicate that a new style has been set
3147 // but it couldn't get applied as the
3148 // widget hasn't been realized yet.
3149 m_delayedBackgroundColour
= TRUE
;
3153 (m_wxwindow
->window
) &&
3154 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3156 /* wxMSW doesn't clear the window here. I don't do that either to
3157 provide compatibility. call Clear() to do the job. */
3159 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3160 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3168 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
3170 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3172 if (!wxWindowBase::SetForegroundColour(colour
))
3174 // don't leave if the GTK widget has just
3176 if (!m_delayedForegroundColour
) return FALSE
;
3179 GdkWindow
*window
= (GdkWindow
*) NULL
;
3181 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3183 window
= GetConnectWidget()->window
;
3187 // indicate that a new style has been set
3188 // but it couldn't get applied as the
3189 // widget hasn't been realized yet.
3190 m_delayedForegroundColour
= TRUE
;
3198 GtkStyle
*wxWindow::GetWidgetStyle()
3202 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3203 remake
->klass
= m_widgetStyle
->klass
;
3205 gtk_style_unref( m_widgetStyle
);
3206 m_widgetStyle
= remake
;
3210 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3213 def
= gtk_widget_get_default_style();
3215 m_widgetStyle
= gtk_style_copy( def
);
3216 m_widgetStyle
->klass
= def
->klass
;
3219 return m_widgetStyle
;
3222 void wxWindow::SetWidgetStyle()
3224 #if DISABLE_STYLE_IF_BROKEN_THEM
3225 if (m_widget
->style
->engine_data
)
3227 static bool s_warningPrinted
= FALSE
;
3228 if (!s_warningPrinted
)
3230 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3231 s_warningPrinted
= TRUE
;
3233 m_widgetStyle
= m_widget
->style
;
3238 GtkStyle
*style
= GetWidgetStyle();
3240 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3242 gdk_font_unref( style
->font
);
3243 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3246 if (m_foregroundColour
.Ok())
3248 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3249 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3251 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3252 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3253 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3257 if (m_backgroundColour
.Ok())
3259 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3260 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3262 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3263 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3264 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3265 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3266 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3267 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3268 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3269 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3274 void wxWindow::ApplyWidgetStyle()
3278 //-----------------------------------------------------------------------------
3279 // Pop-up menu stuff
3280 //-----------------------------------------------------------------------------
3282 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3284 *is_waiting
= FALSE
;
3287 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3289 menu
->SetInvokingWindow( win
);
3290 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3293 wxMenuItem
*menuitem
= node
->GetData();
3294 if (menuitem
->IsSubMenu())
3296 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3299 node
= node
->GetNext();
3303 static gint gs_pop_x
= 0;
3304 static gint gs_pop_y
= 0;
3306 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3310 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3315 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3317 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3319 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3321 SetInvokingWindow( menu
, this );
3328 bool is_waiting
= TRUE
;
3330 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3331 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3334 GTK_MENU(menu
->m_menu
),
3335 (GtkWidget
*) NULL
, // parent menu shell
3336 (GtkWidget
*) NULL
, // parent menu item
3337 (GtkMenuPositionFunc
) pop_pos_callback
,
3338 (gpointer
) this, // client data
3339 0, // button used to activate it
3340 gs_timeLastClick
// the time of activation
3345 while (gtk_events_pending())
3346 gtk_main_iteration();
3352 #if wxUSE_DRAG_AND_DROP
3354 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3356 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3358 GtkWidget
*dnd_widget
= GetConnectWidget();
3360 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3362 if (m_dropTarget
) delete m_dropTarget
;
3363 m_dropTarget
= dropTarget
;
3365 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3368 #endif // wxUSE_DRAG_AND_DROP
3370 GtkWidget
* wxWindow::GetConnectWidget()
3372 GtkWidget
*connect_widget
= m_widget
;
3373 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3375 return connect_widget
;
3378 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3381 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3383 return (window
== m_widget
->window
);
3386 bool wxWindow::SetFont( const wxFont
&font
)
3388 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3390 if (!wxWindowBase::SetFont(font
))
3395 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3396 if ( sysbg
== m_backgroundColour
)
3398 m_backgroundColour
= wxNullColour
;
3400 m_backgroundColour
= sysbg
;
3410 void wxWindow::CaptureMouse()
3412 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3414 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3416 GdkWindow
*window
= (GdkWindow
*) NULL
;
3418 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3420 window
= GetConnectWidget()->window
;
3422 if (!window
) return;
3424 gdk_pointer_grab( window
, FALSE
,
3426 (GDK_BUTTON_PRESS_MASK
|
3427 GDK_BUTTON_RELEASE_MASK
|
3428 GDK_POINTER_MOTION_HINT_MASK
|
3429 GDK_POINTER_MOTION_MASK
),
3431 m_cursor
.GetCursor(),
3432 (guint32
)GDK_CURRENT_TIME
);
3433 g_captureWindow
= this;
3436 void wxWindow::ReleaseMouse()
3438 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3440 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3442 GdkWindow
*window
= (GdkWindow
*) NULL
;
3444 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3446 window
= GetConnectWidget()->window
;
3451 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3452 g_captureWindow
= (wxWindow
*) NULL
;
3455 bool wxWindow::IsRetained() const
3460 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3461 int range
, bool refresh
)
3463 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3465 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3467 m_hasScrolling
= TRUE
;
3469 if (orient
== wxHORIZONTAL
)
3471 float fpos
= (float)pos
;
3472 float frange
= (float)range
;
3473 float fthumb
= (float)thumbVisible
;
3474 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3475 if (fpos
< 0.0) fpos
= 0.0;
3477 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3478 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3480 SetScrollPos( orient
, pos
, refresh
);
3484 m_oldHorizontalPos
= fpos
;
3486 m_hAdjust
->lower
= 0.0;
3487 m_hAdjust
->upper
= frange
;
3488 m_hAdjust
->value
= fpos
;
3489 m_hAdjust
->step_increment
= 1.0;
3490 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3491 m_hAdjust
->page_size
= fthumb
;
3495 float fpos
= (float)pos
;
3496 float frange
= (float)range
;
3497 float fthumb
= (float)thumbVisible
;
3498 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3499 if (fpos
< 0.0) fpos
= 0.0;
3501 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3502 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3504 SetScrollPos( orient
, pos
, refresh
);
3508 m_oldVerticalPos
= fpos
;
3510 m_vAdjust
->lower
= 0.0;
3511 m_vAdjust
->upper
= frange
;
3512 m_vAdjust
->value
= fpos
;
3513 m_vAdjust
->step_increment
= 1.0;
3514 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3515 m_vAdjust
->page_size
= fthumb
;
3518 if (orient
== wxHORIZONTAL
)
3519 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3521 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3524 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3526 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3528 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3530 if (orient
== wxHORIZONTAL
)
3532 float fpos
= (float)pos
;
3533 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3534 if (fpos
< 0.0) fpos
= 0.0;
3535 m_oldHorizontalPos
= fpos
;
3537 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3538 m_hAdjust
->value
= fpos
;
3542 float fpos
= (float)pos
;
3543 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3544 if (fpos
< 0.0) fpos
= 0.0;
3545 m_oldVerticalPos
= fpos
;
3547 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3548 m_vAdjust
->value
= fpos
;
3551 if (m_wxwindow
->window
)
3553 if (orient
== wxHORIZONTAL
)
3555 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3556 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3558 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3560 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3561 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3565 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3566 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3568 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3570 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3571 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3576 int wxWindow::GetScrollThumb( int orient
) const
3578 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3580 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3582 if (orient
== wxHORIZONTAL
)
3583 return (int)(m_hAdjust
->page_size
+0.5);
3585 return (int)(m_vAdjust
->page_size
+0.5);
3588 int wxWindow::GetScrollPos( int orient
) const
3590 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3592 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3594 if (orient
== wxHORIZONTAL
)
3595 return (int)(m_hAdjust
->value
+0.5);
3597 return (int)(m_vAdjust
->value
+0.5);
3600 int wxWindow::GetScrollRange( int orient
) const
3602 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3604 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3606 if (orient
== wxHORIZONTAL
)
3607 return (int)(m_hAdjust
->upper
+0.5);
3609 return (int)(m_vAdjust
->upper
+0.5);
3612 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3614 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3616 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3618 if ((dx
== 0) && (dy
== 0)) return;
3620 m_clipPaintRegion
= TRUE
;
3621 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3622 m_clipPaintRegion
= FALSE
;
3625 if (m_children.GetCount() > 0)
3627 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3631 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3633 pizza->xoffset -= dx;
3634 pizza->yoffset -= dy;
3636 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3637 gdk_gc_set_exposures( m_scrollGC, TRUE );
3641 GetClientSize( &cw, &ch );
3642 int w = cw - abs(dx);
3643 int h = ch - abs(dy);
3645 if ((h < 0) || (w < 0))
3653 if (dx < 0) s_x = -dx;
3654 if (dy < 0) s_y = -dy;
3657 if (dx > 0) d_x = dx;
3658 if (dy > 0) d_y = dy;
3660 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3661 pizza->bin_window, s_x, s_y, w, h );
3664 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3665 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3666 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3667 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3669 Refresh( TRUE, &rect );
3672 gdk_gc_unref( m_scrollGC );