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
= 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;
506 if ((keysym
& 0xF000) == 0)
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;
605 if ((keysym
& 0xF000) == 0)
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
;
800 tmp += (char)gdk_event->keyval;
801 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
802 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
807 GdkModifierType state
;
808 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
812 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
813 /* sending unknown key events doesn't really make sense */
814 if (key_code
== 0) return FALSE
;
816 wxKeyEvent
event( wxEVT_KEY_DOWN
);
817 event
.SetTimestamp( gdk_event
->time
);
818 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
819 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
820 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
821 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
822 event
.m_keyCode
= key_code
;
823 event
.m_scanCode
= gdk_event
->keyval
;
826 event
.SetEventObject( win
);
827 ret
= win
->GetEventHandler()->ProcessEvent( event
);
832 wxWindow
*ancestor
= win
;
835 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
838 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
839 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
842 if (ancestor
->m_isFrame
)
844 ancestor
= ancestor
->GetParent();
847 #endif // wxUSE_ACCEL
849 /* wxMSW doesn't send char events with Alt pressed */
850 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
851 will only be sent if it is not in an accelerator table. */
852 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
857 wxKeyEvent
event2( wxEVT_CHAR
);
858 event2
.SetTimestamp( gdk_event
->time
);
859 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
860 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
861 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
862 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
863 event2
.m_keyCode
= key_code
;
864 event2
.m_scanCode
= gdk_event
->keyval
;
867 event2
.SetEventObject( win
);
868 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
871 /* win is a control: tab can be propagated up */
873 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
874 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
875 (win
->GetParent()) &&
876 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
878 wxNavigationKeyEvent new_event
;
879 new_event
.SetEventObject( win
->GetParent() );
880 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
881 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
882 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
883 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
884 new_event
.SetCurrentFocus( win
);
885 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
888 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
890 (gdk_event
->keyval
== GDK_Escape
) )
892 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
893 new_event
.SetEventObject( win
);
894 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
897 #if (GTK_MINOR_VERSION > 0)
898 /* Pressing F10 will activate the menu bar of the top frame. */
902 (gdk_event->keyval == GDK_F10) )
904 wxWindow *ancestor = win;
907 if (wxIsKindOf(ancestor,wxFrame))
909 wxFrame *frame = (wxFrame*) ancestor;
910 wxMenuBar *menubar = frame->GetMenuBar();
913 wxNode *node = menubar->GetMenus().First();
916 wxMenu *firstMenu = (wxMenu*) node->Data();
917 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
923 ancestor = ancestor->GetParent();
931 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
938 //-----------------------------------------------------------------------------
939 // "key_release_event" from any window
940 //-----------------------------------------------------------------------------
942 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
947 wxapp_install_idle_handler();
949 if (!win
->m_hasVMT
) return FALSE
;
950 if (g_blockEventsOnDrag
) return FALSE
;
953 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
954 if (gdk_event->state & GDK_SHIFT_MASK)
955 printf( "ShiftDown.\n" );
957 printf( "ShiftUp.\n" );
958 if (gdk_event->state & GDK_CONTROL_MASK)
959 printf( "ControlDown.\n" );
961 printf( "ControlUp.\n" );
965 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
967 /* sending unknown key events doesn't really make sense */
968 if (key_code
== 0) return FALSE
;
972 GdkModifierType state
;
973 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
975 wxKeyEvent
event( wxEVT_KEY_UP
);
976 event
.SetTimestamp( gdk_event
->time
);
977 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
978 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
979 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
980 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
981 event
.m_keyCode
= key_code
;
982 event
.m_scanCode
= gdk_event
->keyval
;
985 event
.SetEventObject( win
);
987 if (win
->GetEventHandler()->ProcessEvent( event
))
989 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
996 // ----------------------------------------------------------------------------
997 // mouse event processing helper
998 // ----------------------------------------------------------------------------
1000 static void AdjustEventButtonState(wxMouseEvent
& event
)
1002 // GDK reports the old state of the button for a button press event, but
1003 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1004 // for a LEFT_DOWN event, not FALSE, so we will invert
1005 // left/right/middleDown for the corresponding click events
1006 switch ( event
.GetEventType() )
1008 case wxEVT_LEFT_DOWN
:
1009 case wxEVT_LEFT_DCLICK
:
1011 event
.m_leftDown
= !event
.m_leftDown
;
1014 case wxEVT_MIDDLE_DOWN
:
1015 case wxEVT_MIDDLE_DCLICK
:
1016 case wxEVT_MIDDLE_UP
:
1017 event
.m_middleDown
= !event
.m_middleDown
;
1020 case wxEVT_RIGHT_DOWN
:
1021 case wxEVT_RIGHT_DCLICK
:
1022 case wxEVT_RIGHT_UP
:
1023 event
.m_rightDown
= !event
.m_rightDown
;
1028 //-----------------------------------------------------------------------------
1029 // "button_press_event"
1030 //-----------------------------------------------------------------------------
1032 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1037 wxapp_install_idle_handler();
1040 wxPrintf( wxT("1) OnButtonPress from ") );
1041 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1042 wxPrintf( win->GetClassInfo()->GetClassName() );
1043 wxPrintf( wxT(".\n") );
1045 if (!win
->m_hasVMT
) return FALSE
;
1046 if (g_blockEventsOnDrag
) return TRUE
;
1047 if (g_blockEventsOnScroll
) return TRUE
;
1049 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1051 if (win
->m_wxwindow
)
1053 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1055 gtk_widget_grab_focus (win
->m_wxwindow
);
1058 wxPrintf( wxT("GrabFocus from ") );
1059 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1060 wxPrintf( win->GetClassInfo()->GetClassName() );
1061 wxPrintf( wxT(".\n") );
1067 wxEventType event_type
= wxEVT_NULL
;
1069 if (gdk_event
->button
== 1)
1071 switch (gdk_event
->type
)
1073 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1074 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1078 else if (gdk_event
->button
== 2)
1080 switch (gdk_event
->type
)
1082 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1083 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1087 else if (gdk_event
->button
== 3)
1089 switch (gdk_event
->type
)
1091 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1092 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1097 if ( event_type
== wxEVT_NULL
)
1099 // unknown mouse button or click type
1103 wxMouseEvent
event( event_type
);
1104 event
.SetTimestamp( gdk_event
->time
);
1105 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1106 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1107 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1108 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1109 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1110 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1111 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1113 event
.m_x
= (wxCoord
)gdk_event
->x
;
1114 event
.m_y
= (wxCoord
)gdk_event
->y
;
1116 AdjustEventButtonState(event
);
1118 // Some control don't have their own X window and thus cannot get
1121 if (!g_captureWindow
)
1123 wxCoord x
= event
.m_x
;
1124 wxCoord y
= event
.m_y
;
1125 if (win
->m_wxwindow
)
1127 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1128 x
+= pizza
->xoffset
;
1129 y
+= pizza
->yoffset
;
1132 wxNode
*node
= win
->GetChildren().First();
1135 wxWindow
*child
= (wxWindow
*)node
->Data();
1137 node
= node
->Next();
1138 if (!child
->IsShown())
1141 if (child
->m_isStaticBox
)
1143 // wxStaticBox is transparent in the box itself
1144 int xx1
= child
->m_x
;
1145 int yy1
= child
->m_y
;
1146 int xx2
= child
->m_x
+ child
->m_width
;
1147 int yy2
= child
->m_x
+ child
->m_height
;
1150 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1152 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1154 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1156 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1159 event
.m_x
-= child
->m_x
;
1160 event
.m_y
-= child
->m_y
;
1167 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1168 (child
->m_x
<= x
) &&
1169 (child
->m_y
<= y
) &&
1170 (child
->m_x
+child
->m_width
>= x
) &&
1171 (child
->m_y
+child
->m_height
>= y
))
1174 event
.m_x
-= child
->m_x
;
1175 event
.m_y
-= child
->m_y
;
1182 event
.SetEventObject( win
);
1184 gs_timeLastClick
= gdk_event
->time
;
1187 wxPrintf( wxT("2) OnButtonPress from ") );
1188 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1189 wxPrintf( win->GetClassInfo()->GetClassName() );
1190 wxPrintf( wxT(".\n") );
1193 if (win
->GetEventHandler()->ProcessEvent( event
))
1195 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1202 //-----------------------------------------------------------------------------
1203 // "button_release_event"
1204 //-----------------------------------------------------------------------------
1206 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1211 wxapp_install_idle_handler();
1213 if (!win
->m_hasVMT
) return FALSE
;
1214 if (g_blockEventsOnDrag
) return FALSE
;
1215 if (g_blockEventsOnScroll
) return FALSE
;
1217 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1220 printf( "OnButtonRelease from " );
1221 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1222 printf( win->GetClassInfo()->GetClassName() );
1226 wxEventType event_type
= wxEVT_NULL
;
1228 switch (gdk_event
->button
)
1230 case 1: event_type
= wxEVT_LEFT_UP
; break;
1231 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1232 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1233 default: return FALSE
;
1236 wxMouseEvent
event( event_type
);
1237 event
.SetTimestamp( gdk_event
->time
);
1238 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1239 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1240 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1241 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1242 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1243 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1244 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1245 event
.m_x
= (wxCoord
)gdk_event
->x
;
1246 event
.m_y
= (wxCoord
)gdk_event
->y
;
1248 AdjustEventButtonState(event
);
1250 // Some control don't have their own X window and thus cannot get
1253 if (!g_captureWindow
)
1255 wxCoord x
= event
.m_x
;
1256 wxCoord y
= event
.m_y
;
1257 if (win
->m_wxwindow
)
1259 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1260 x
+= pizza
->xoffset
;
1261 y
+= pizza
->yoffset
;
1264 wxNode
*node
= win
->GetChildren().First();
1267 wxWindow
*child
= (wxWindow
*)node
->Data();
1269 node
= node
->Next();
1270 if (!child
->IsShown())
1273 if (child
->m_isStaticBox
)
1275 // wxStaticBox is transparent in the box itself
1276 int xx1
= child
->m_x
;
1277 int yy1
= child
->m_y
;
1278 int xx2
= child
->m_x
+ child
->m_width
;
1279 int yy2
= child
->m_x
+ child
->m_height
;
1282 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1284 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1286 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1288 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1291 event
.m_x
-= child
->m_x
;
1292 event
.m_y
-= child
->m_y
;
1299 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1300 (child
->m_x
<= x
) &&
1301 (child
->m_y
<= y
) &&
1302 (child
->m_x
+child
->m_width
>= x
) &&
1303 (child
->m_y
+child
->m_height
>= y
))
1306 event
.m_x
-= child
->m_x
;
1307 event
.m_y
-= child
->m_y
;
1314 event
.SetEventObject( win
);
1316 if (win
->GetEventHandler()->ProcessEvent( event
))
1318 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1325 //-----------------------------------------------------------------------------
1326 // "motion_notify_event"
1327 //-----------------------------------------------------------------------------
1329 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1334 wxapp_install_idle_handler();
1336 if (!win
->m_hasVMT
) return FALSE
;
1337 if (g_blockEventsOnDrag
) return FALSE
;
1338 if (g_blockEventsOnScroll
) return FALSE
;
1340 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1342 if (gdk_event
->is_hint
)
1346 GdkModifierType state
;
1347 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1353 printf( "OnMotion from " );
1354 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1355 printf( win->GetClassInfo()->GetClassName() );
1359 wxMouseEvent
event( wxEVT_MOTION
);
1360 event
.SetTimestamp( gdk_event
->time
);
1361 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1362 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1363 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1364 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1365 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1366 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1367 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1369 event
.m_x
= (wxCoord
)gdk_event
->x
;
1370 event
.m_y
= (wxCoord
)gdk_event
->y
;
1372 // Some control don't have their own X window and thus cannot get
1375 if (!g_captureWindow
)
1377 wxCoord x
= event
.m_x
;
1378 wxCoord y
= event
.m_y
;
1379 if (win
->m_wxwindow
)
1381 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1382 x
+= pizza
->xoffset
;
1383 y
+= pizza
->yoffset
;
1386 wxNode
*node
= win
->GetChildren().First();
1389 wxWindow
*child
= (wxWindow
*)node
->Data();
1391 node
= node
->Next();
1392 if (!child
->IsShown())
1395 if (child
->m_isStaticBox
)
1397 // wxStaticBox is transparent in the box itself
1398 int xx1
= child
->m_x
;
1399 int yy1
= child
->m_y
;
1400 int xx2
= child
->m_x
+ child
->m_width
;
1401 int yy2
= child
->m_x
+ child
->m_height
;
1404 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1406 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1408 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1410 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1413 event
.m_x
-= child
->m_x
;
1414 event
.m_y
-= child
->m_y
;
1421 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1422 (child
->m_x
<= x
) &&
1423 (child
->m_y
<= y
) &&
1424 (child
->m_x
+child
->m_width
>= x
) &&
1425 (child
->m_y
+child
->m_height
>= y
))
1428 event
.m_x
-= child
->m_x
;
1429 event
.m_y
-= child
->m_y
;
1436 event
.SetEventObject( win
);
1438 if (win
->GetEventHandler()->ProcessEvent( event
))
1440 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1447 //-----------------------------------------------------------------------------
1449 //-----------------------------------------------------------------------------
1451 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1456 wxapp_install_idle_handler();
1458 if (!win
->m_hasVMT
) return FALSE
;
1459 if (g_blockEventsOnDrag
) return FALSE
;
1461 switch ( g_sendActivateEvent
)
1464 // we've got focus from outside, synthtize wxActivateEvent
1465 g_sendActivateEvent
= 1;
1469 // another our window just lost focus, it was already ours before
1470 // - don't send any wxActivateEvent
1471 g_sendActivateEvent
= -1;
1475 g_focusWindow
= win
;
1478 printf( "OnSetFocus from " );
1479 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1480 printf( win->GetClassInfo()->GetClassName() );
1482 printf( WXSTRINGCAST win->GetLabel() );
1486 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1489 panel
->SetLastFocus(win
);
1494 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1497 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1498 event
.SetEventObject( win
);
1500 if (win
->GetEventHandler()->ProcessEvent( event
))
1502 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1509 //-----------------------------------------------------------------------------
1510 // "focus_out_event"
1511 //-----------------------------------------------------------------------------
1513 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1518 wxapp_install_idle_handler();
1520 if (!win
->m_hasVMT
) return FALSE
;
1521 if (g_blockEventsOnDrag
) return FALSE
;
1523 // if the focus goes out of our app alltogether, OnIdle() will send
1524 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1525 // g_sendActivateEvent to -1
1526 g_sendActivateEvent
= 0;
1528 g_focusWindow
= (wxWindow
*)NULL
;
1531 printf( "OnKillFocus from " );
1532 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1533 printf( win->GetClassInfo()->GetClassName() );
1542 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1543 event
.SetEventObject( win
);
1545 if (win
->GetEventHandler()->ProcessEvent( event
))
1547 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1554 //-----------------------------------------------------------------------------
1555 // "enter_notify_event"
1556 //-----------------------------------------------------------------------------
1558 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1563 wxapp_install_idle_handler();
1565 if (!win
->m_hasVMT
) return FALSE
;
1566 if (g_blockEventsOnDrag
) return FALSE
;
1568 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1570 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1571 #if (GTK_MINOR_VERSION > 0)
1572 event
.SetTimestamp( gdk_event
->time
);
1574 event
.SetEventObject( win
);
1578 GdkModifierType state
= (GdkModifierType
)0;
1580 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1582 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1583 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1584 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1585 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1586 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1587 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1588 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1593 if (win
->GetEventHandler()->ProcessEvent( event
))
1595 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1602 //-----------------------------------------------------------------------------
1603 // "leave_notify_event"
1604 //-----------------------------------------------------------------------------
1606 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1611 wxapp_install_idle_handler();
1613 if (!win
->m_hasVMT
) return FALSE
;
1614 if (g_blockEventsOnDrag
) return FALSE
;
1616 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1618 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1619 #if (GTK_MINOR_VERSION > 0)
1620 event
.SetTimestamp( gdk_event
->time
);
1622 event
.SetEventObject( win
);
1626 GdkModifierType state
= (GdkModifierType
)0;
1628 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1630 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1631 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1632 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1633 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1634 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1635 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1636 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1641 if (win
->GetEventHandler()->ProcessEvent( event
))
1643 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1650 //-----------------------------------------------------------------------------
1651 // "value_changed" from m_vAdjust
1652 //-----------------------------------------------------------------------------
1654 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1659 wxapp_install_idle_handler();
1661 if (g_blockEventsOnDrag
) return;
1663 if (!win
->m_hasVMT
) return;
1665 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1666 if (fabs(diff
) < 0.2) return;
1668 win
->m_oldVerticalPos
= adjust
->value
;
1670 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1671 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1673 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1674 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1675 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1676 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1677 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1679 int value
= (int)(adjust
->value
+0.5);
1681 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1682 event
.SetEventObject( win
);
1683 win
->GetEventHandler()->ProcessEvent( event
);
1686 //-----------------------------------------------------------------------------
1687 // "value_changed" from m_hAdjust
1688 //-----------------------------------------------------------------------------
1690 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1695 wxapp_install_idle_handler();
1697 if (g_blockEventsOnDrag
) return;
1698 if (!win
->m_hasVMT
) return;
1700 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1701 if (fabs(diff
) < 0.2) return;
1703 win
->m_oldHorizontalPos
= adjust
->value
;
1705 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1706 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1708 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1709 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1710 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1711 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1712 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1714 int value
= (int)(adjust
->value
+0.5);
1716 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1717 event
.SetEventObject( win
);
1718 win
->GetEventHandler()->ProcessEvent( event
);
1721 //-----------------------------------------------------------------------------
1722 // "button_press_event" from scrollbar
1723 //-----------------------------------------------------------------------------
1725 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1726 GdkEventButton
*gdk_event
,
1732 wxapp_install_idle_handler();
1735 g_blockEventsOnScroll
= TRUE
;
1736 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1741 //-----------------------------------------------------------------------------
1742 // "button_release_event" from scrollbar
1743 //-----------------------------------------------------------------------------
1745 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1746 GdkEventButton
*WXUNUSED(gdk_event
),
1751 // don't test here as we can release the mouse while being over
1752 // a different window than the slider
1754 // if (gdk_event->window != widget->slider) return FALSE;
1756 g_blockEventsOnScroll
= FALSE
;
1758 if (win
->m_isScrolling
)
1760 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
1764 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1765 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1767 value
= (int)(win
->m_hAdjust
->value
+0.5);
1770 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1772 value
= (int)(win
->m_vAdjust
->value
+0.5);
1776 wxScrollWinEvent
event( command
, value
, dir
);
1777 event
.SetEventObject( win
);
1778 win
->GetEventHandler()->ProcessEvent( event
);
1781 win
->m_isScrolling
= FALSE
;
1786 // ----------------------------------------------------------------------------
1787 // this wxWindowBase function is implemented here (in platform-specific file)
1788 // because it is static and so couldn't be made virtual
1789 // ----------------------------------------------------------------------------
1791 wxWindow
*wxWindowBase::FindFocus()
1793 return g_focusWindow
;
1796 //-----------------------------------------------------------------------------
1797 // "realize" from m_widget
1798 //-----------------------------------------------------------------------------
1800 /* We cannot set colours and fonts before the widget has
1801 been realized, so we do this directly after realization. */
1804 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1809 wxapp_install_idle_handler();
1811 if (win
->m_delayedBackgroundColour
)
1812 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1814 if (win
->m_delayedForegroundColour
)
1815 win
->SetForegroundColour( win
->GetForegroundColour() );
1817 wxWindowCreateEvent
event( win
);
1818 event
.SetEventObject( win
);
1819 win
->GetEventHandler()->ProcessEvent( event
);
1824 //-----------------------------------------------------------------------------
1826 //-----------------------------------------------------------------------------
1829 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
1830 GtkAllocation
*WXUNUSED(alloc
),
1834 wxapp_install_idle_handler();
1836 if (!win
->m_hasScrolling
) return;
1838 int client_width
= 0;
1839 int client_height
= 0;
1840 win
->GetClientSize( &client_width
, &client_height
);
1841 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
1844 win
->m_oldClientWidth
= client_width
;
1845 win
->m_oldClientHeight
= client_height
;
1847 if (!win
->m_nativeSizeEvent
)
1849 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
1850 event
.SetEventObject( win
);
1851 win
->GetEventHandler()->ProcessEvent( event
);
1857 #define WXUNUSED_UNLESS_XIM(param) param
1859 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1862 /* Resize XIM window */
1865 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1866 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1867 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1870 wxapp_install_idle_handler();
1876 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1880 gdk_window_get_size (widget
->window
, &width
, &height
);
1881 win
->m_icattr
->preedit_area
.width
= width
;
1882 win
->m_icattr
->preedit_area
.height
= height
;
1883 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
1888 //-----------------------------------------------------------------------------
1889 // "realize" from m_wxwindow
1890 //-----------------------------------------------------------------------------
1892 /* Initialize XIM support */
1895 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1896 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1899 wxapp_install_idle_handler();
1902 if (win
->m_ic
) return FALSE
;
1903 if (!widget
) return FALSE
;
1904 if (!gdk_im_ready()) return FALSE
;
1906 win
->m_icattr
= gdk_ic_attr_new();
1907 if (!win
->m_icattr
) return FALSE
;
1911 GdkColormap
*colormap
;
1912 GdkICAttr
*attr
= win
->m_icattr
;
1913 unsigned attrmask
= GDK_IC_ALL_REQ
;
1915 GdkIMStyle supported_style
= (GdkIMStyle
)
1916 (GDK_IM_PREEDIT_NONE
|
1917 GDK_IM_PREEDIT_NOTHING
|
1918 GDK_IM_PREEDIT_POSITION
|
1919 GDK_IM_STATUS_NONE
|
1920 GDK_IM_STATUS_NOTHING
);
1922 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1923 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
1925 attr
->style
= style
= gdk_im_decide_style (supported_style
);
1926 attr
->client_window
= widget
->window
;
1928 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
1929 gtk_widget_get_default_colormap ())
1931 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
1932 attr
->preedit_colormap
= colormap
;
1935 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
1936 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
1937 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
1938 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
1940 switch (style
& GDK_IM_PREEDIT_MASK
)
1942 case GDK_IM_PREEDIT_POSITION
:
1943 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1945 g_warning ("over-the-spot style requires fontset");
1949 gdk_window_get_size (widget
->window
, &width
, &height
);
1951 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
1952 attr
->spot_location
.x
= 0;
1953 attr
->spot_location
.y
= height
;
1954 attr
->preedit_area
.x
= 0;
1955 attr
->preedit_area
.y
= 0;
1956 attr
->preedit_area
.width
= width
;
1957 attr
->preedit_area
.height
= height
;
1958 attr
->preedit_fontset
= widget
->style
->font
;
1963 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
1965 if (win
->m_ic
== NULL
)
1966 g_warning ("Can't create input context.");
1969 mask
= gdk_window_get_events (widget
->window
);
1970 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
1971 gdk_window_set_events (widget
->window
, mask
);
1973 if (GTK_WIDGET_HAS_FOCUS(widget
))
1974 gdk_im_begin (win
->m_ic
, widget
->window
);
1981 //-----------------------------------------------------------------------------
1982 // InsertChild for wxWindow.
1983 //-----------------------------------------------------------------------------
1985 /* Callback for wxWindow. This very strange beast has to be used because
1986 * C++ has no virtual methods in a constructor. We have to emulate a
1987 * virtual function here as wxNotebook requires a different way to insert
1988 * a child in it. I had opted for creating a wxNotebookPage window class
1989 * which would have made this superfluous (such in the MDI window system),
1990 * but no-one was listening to me... */
1992 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1994 /* the window might have been scrolled already, do we
1995 have to adapt the position */
1996 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
1997 child
->m_x
+= pizza
->xoffset
;
1998 child
->m_y
+= pizza
->yoffset
;
2000 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2001 GTK_WIDGET(child
->m_widget
),
2008 //-----------------------------------------------------------------------------
2010 //-----------------------------------------------------------------------------
2012 wxWindow
* wxGetActiveWindow()
2014 return g_focusWindow
;
2017 //-----------------------------------------------------------------------------
2019 //-----------------------------------------------------------------------------
2021 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2023 void wxWindow::Init()
2029 m_widget
= (GtkWidget
*) NULL
;
2030 m_wxwindow
= (GtkWidget
*) NULL
;
2040 m_needParent
= TRUE
;
2041 m_isBeingDeleted
= FALSE
;
2044 m_nativeSizeEvent
= FALSE
;
2046 m_hasScrolling
= FALSE
;
2047 m_isScrolling
= FALSE
;
2049 m_hAdjust
= (GtkAdjustment
*) NULL
;
2050 m_vAdjust
= (GtkAdjustment
*) NULL
;
2051 m_oldHorizontalPos
= 0.0;
2052 m_oldVerticalPos
= 0.0;
2055 m_widgetStyle
= (GtkStyle
*) NULL
;
2057 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2059 m_isStaticBox
= FALSE
;
2060 m_isRadioButton
= FALSE
;
2062 m_acceptsFocus
= FALSE
;
2064 m_clipPaintRegion
= FALSE
;
2065 m_queuedFullRedraw
= FALSE
;
2067 m_cursor
= *wxSTANDARD_CURSOR
;
2070 m_ic
= (GdkIC
*) NULL
;
2071 m_icattr
= (GdkICAttr
*) NULL
;
2075 wxWindow::wxWindow()
2080 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
2081 const wxPoint
&pos
, const wxSize
&size
,
2082 long style
, const wxString
&name
)
2086 Create( parent
, id
, pos
, size
, style
, name
);
2089 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
2090 const wxPoint
&pos
, const wxSize
&size
,
2091 long style
, const wxString
&name
)
2093 if (!PreCreation( parent
, pos
, size
) ||
2094 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2096 wxFAIL_MSG( wxT("wxWindow creation failed") );
2100 m_insertCallback
= wxInsertChildInWindow
;
2102 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2103 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2105 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2107 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2108 scroll_class
->scrollbar_spacing
= 0;
2110 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2112 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2113 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2115 m_wxwindow
= gtk_pizza_new();
2117 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2119 #if (GTK_MINOR_VERSION > 0)
2120 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2122 if (HasFlag(wxRAISED_BORDER
))
2124 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2126 else if (HasFlag(wxSUNKEN_BORDER
))
2128 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2130 else if (HasFlag(wxSIMPLE_BORDER
))
2132 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2136 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2138 #else // GTK_MINOR_VERSION == 0
2139 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2141 if (HasFlag(wxRAISED_BORDER
))
2143 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2145 else if (HasFlag(wxSUNKEN_BORDER
))
2147 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2151 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2153 #endif // GTK_MINOR_VERSION
2155 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2156 m_acceptsFocus
= TRUE
;
2158 #if (GTK_MINOR_VERSION == 0)
2159 // shut the viewport up
2160 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2161 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2162 #endif // GTK_MINOR_VERSION == 0
2164 // I _really_ don't want scrollbars in the beginning
2165 m_vAdjust
->lower
= 0.0;
2166 m_vAdjust
->upper
= 1.0;
2167 m_vAdjust
->value
= 0.0;
2168 m_vAdjust
->step_increment
= 1.0;
2169 m_vAdjust
->page_increment
= 1.0;
2170 m_vAdjust
->page_size
= 5.0;
2171 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2172 m_hAdjust
->lower
= 0.0;
2173 m_hAdjust
->upper
= 1.0;
2174 m_hAdjust
->value
= 0.0;
2175 m_hAdjust
->step_increment
= 1.0;
2176 m_hAdjust
->page_increment
= 1.0;
2177 m_hAdjust
->page_size
= 5.0;
2178 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2180 // these handlers block mouse events to any window during scrolling such as
2181 // motion events and prevent GTK and wxWindows from fighting over where the
2184 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2185 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2187 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2188 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2190 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2191 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2193 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2194 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2196 // these handlers get notified when screen updates are required either when
2197 // scrolling or when the window size (and therefore scrollbar configuration)
2200 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2201 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2202 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2203 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2205 gtk_widget_show( m_wxwindow
);
2208 m_parent
->DoAddChild( this );
2217 wxWindow::~wxWindow()
2219 m_isBeingDeleted
= TRUE
;
2228 m_parent
->RemoveChild( this );
2232 gdk_ic_destroy (m_ic
);
2234 gdk_ic_attr_destroy (m_icattr
);
2239 #if DISABLE_STYLE_IF_BROKEN_THEME
2240 // don't delete if it's a pixmap theme style
2241 if (!m_widgetStyle
->engine_data
)
2242 gtk_style_unref( m_widgetStyle
);
2244 m_widgetStyle
= (GtkStyle
*) NULL
;
2249 gtk_widget_destroy( m_wxwindow
);
2250 m_wxwindow
= (GtkWidget
*) NULL
;
2255 gtk_widget_destroy( m_widget
);
2256 m_widget
= (GtkWidget
*) NULL
;
2260 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2262 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2264 /* this turns -1 into 20 so that a minimal window is
2265 visible even although -1,-1 has been given as the
2266 size of the window. the same trick is used in other
2267 ports and should make debugging easier */
2268 m_width
= WidthDefault(size
.x
);
2269 m_height
= HeightDefault(size
.y
);
2274 /* some reasonable defaults */
2279 m_x
= (gdk_screen_width () - m_width
) / 2;
2280 if (m_x
< 10) m_x
= 10;
2284 m_y
= (gdk_screen_height () - m_height
) / 2;
2285 if (m_y
< 10) m_y
= 10;
2292 void wxWindow::PostCreation()
2294 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2300 /* these get reported to wxWindows -> wxPaintEvent */
2302 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2304 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2305 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2307 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2308 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2310 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2311 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2314 #if (GTK_MINOR_VERSION > 0)
2315 /* these are called when the "sunken" or "raised" borders are drawn */
2316 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2317 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2319 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2320 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2324 if (m_wxwindow
&& m_needParent
)
2326 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2327 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2329 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2330 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2334 // For dialogs and frames, we are interested mainly in
2335 // m_widget's focus.
2337 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2338 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2340 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2341 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2344 GtkWidget
*connect_widget
= GetConnectWidget();
2346 ConnectWidget( connect_widget
);
2348 /* We cannot set colours, fonts and cursors before the widget has
2349 been realized, so we do this directly after realization */
2350 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2351 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2355 /* Catch native resize events. */
2356 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2357 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2359 /* Initialize XIM support. */
2360 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2361 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2363 /* And resize XIM window. */
2364 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2365 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2371 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2373 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2374 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2376 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2377 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2379 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2380 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2382 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2383 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2385 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2386 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2388 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2389 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2391 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2392 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2395 bool wxWindow::Destroy()
2397 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2401 return wxWindowBase::Destroy();
2404 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2406 if (m_wxwindow
&& GTK_PIZZA(m_wxwindow
)->bin_window
)
2408 /* Normally, GTK will send expose events only for the regions
2409 which actually got exposed. Sadly, wxMSW invalidates
2410 the whole window so we have to do that, too. We could
2411 simply add a complete refresh, but we would then get
2412 the normal GTK expose events in surplus, so we shut
2413 off the expose events and schedule a full redraw to
2414 be done in OnInternalIdle, where we restore the handling
2415 of expose events. */
2417 m_queuedFullRedraw
= TRUE
;
2419 GdkEventMask mask
= gdk_window_get_events( GTK_PIZZA(m_wxwindow
)->bin_window
);
2420 mask
= (GdkEventMask
)(mask
& ~GDK_EXPOSURE_MASK
);
2421 gdk_window_set_events( GTK_PIZZA(m_wxwindow
)->bin_window
, mask
);
2424 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2427 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2429 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2430 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2432 if (m_resizing
) return; /* I don't like recursions */
2435 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2437 /* don't set the size for children of wxNotebook, just take the values. */
2445 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2447 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2449 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2450 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2451 if (width
!= -1) m_width
= width
;
2452 if (height
!= -1) m_height
= height
;
2456 m_x
= x
+ pizza
->xoffset
;
2457 m_y
= y
+ pizza
->yoffset
;
2462 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2464 if (width
== -1) m_width
= 80;
2467 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2469 if (height
== -1) m_height
= 26;
2472 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2473 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2474 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2475 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2478 int bottom_border
= 0;
2480 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2482 /* the default button has a border around it */
2487 DoMoveWindow( m_x
-border
,
2490 m_height
+border
+bottom_border
);
2495 /* Sometimes the client area changes size without the
2496 whole windows's size changing, but if the whole
2497 windows's size doesn't change, no wxSizeEvent will
2498 normally be sent. Here we add an extra test if
2499 the client test has been changed and this will
2501 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2505 wxPrintf( "OnSize sent from " );
2506 if (GetClassInfo() && GetClassInfo()->GetClassName())
2507 wxPrintf( GetClassInfo()->GetClassName() );
2508 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2511 if (!m_nativeSizeEvent
)
2513 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2514 event
.SetEventObject( this );
2515 GetEventHandler()->ProcessEvent( event
);
2521 void wxWindow::OnInternalIdle()
2523 if ( g_sendActivateEvent
!= -1 )
2525 bool activate
= g_sendActivateEvent
!= 0;
2528 g_sendActivateEvent
= -1;
2530 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2531 event
.SetEventObject(this);
2533 (void)GetEventHandler()->ProcessEvent(event
);
2536 wxCursor cursor
= m_cursor
;
2537 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2541 /* I now set the cursor anew in every OnInternalIdle call
2542 as setting the cursor in a parent window also effects the
2543 windows above so that checking for the current cursor is
2548 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2550 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2552 if (!g_globalCursor
.Ok())
2553 cursor
= *wxSTANDARD_CURSOR
;
2555 window
= m_widget
->window
;
2556 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2557 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2563 GdkWindow
*window
= m_widget
->window
;
2564 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2565 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2572 if (m_queuedFullRedraw
)
2574 /* See also wxWindow::DoMoveWindow for explanation of this code. What
2575 we test here is if the requested size of the window is the same as
2576 the actual size of window, in which case all expose events that resulted
2577 from resizing the window have been sent (and discarded) and we can
2578 now do our full redraw and switch on expose event handling again. */
2580 bool child_already_resized
= FALSE
;
2582 child_already_resized
= gtk_pizza_child_resized( GTK_PIZZA(m_wxwindow
->parent
), m_wxwindow
);
2584 child_already_resized
= gtk_pizza_child_resized( GTK_PIZZA(m_widget
->parent
), m_widget
);
2586 if (child_already_resized
)
2588 m_queuedFullRedraw
= FALSE
;
2589 m_updateRegion
.Clear();
2590 m_updateRegion
.Union( 0,0,m_width
,m_height
);
2591 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2593 GdkEventMask mask
= gdk_window_get_events( GTK_PIZZA(m_wxwindow
)->bin_window
);
2594 mask
= (GdkEventMask
)(mask
| GDK_EXPOSURE_MASK
);
2595 gdk_window_set_events( GTK_PIZZA(m_wxwindow
)->bin_window
, mask
);
2600 void wxWindow::DoGetSize( int *width
, int *height
) const
2602 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2604 if (width
) (*width
) = m_width
;
2605 if (height
) (*height
) = m_height
;
2608 void wxWindow::DoSetClientSize( int width
, int height
)
2610 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2614 SetSize( width
, height
);
2621 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2623 /* when using GTK 1.2 we set the shadow border size to 2 */
2627 if (HasFlag(wxSIMPLE_BORDER
))
2629 /* when using GTK 1.2 we set the simple border size to 1 */
2636 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2638 GtkRequisition vscroll_req
;
2639 vscroll_req
.width
= 2;
2640 vscroll_req
.height
= 2;
2641 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
2642 (scroll_window
->vscrollbar
, &vscroll_req
);
2644 GtkRequisition hscroll_req
;
2645 hscroll_req
.width
= 2;
2646 hscroll_req
.height
= 2;
2647 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
2648 (scroll_window
->hscrollbar
, &hscroll_req
);
2650 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2652 if (scroll_window
->vscrollbar_visible
)
2654 dw
+= vscroll_req
.width
;
2655 dw
+= scroll_class
->scrollbar_spacing
;
2658 if (scroll_window
->hscrollbar_visible
)
2660 dh
+= hscroll_req
.height
;
2661 dh
+= scroll_class
->scrollbar_spacing
;
2665 SetSize( width
+dw
, height
+dh
);
2669 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2671 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2675 if (width
) (*width
) = m_width
;
2676 if (height
) (*height
) = m_height
;
2683 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2685 /* when using GTK 1.2 we set the shadow border size to 2 */
2689 if (HasFlag(wxSIMPLE_BORDER
))
2691 /* when using GTK 1.2 we set the simple border size to 1 */
2698 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2700 GtkRequisition vscroll_req
;
2701 vscroll_req
.width
= 2;
2702 vscroll_req
.height
= 2;
2703 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
2704 (scroll_window
->vscrollbar
, &vscroll_req
);
2706 GtkRequisition hscroll_req
;
2707 hscroll_req
.width
= 2;
2708 hscroll_req
.height
= 2;
2709 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
2710 (scroll_window
->hscrollbar
, &hscroll_req
);
2712 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2714 if (scroll_window
->vscrollbar_visible
)
2716 dw
+= vscroll_req
.width
;
2717 dw
+= scroll_class
->scrollbar_spacing
;
2720 if (scroll_window
->hscrollbar_visible
)
2722 dh
+= hscroll_req
.height
;
2723 dh
+= scroll_class
->scrollbar_spacing
;
2727 if (width
) (*width
) = m_width
- dw
;
2728 if (height
) (*height
) = m_height
- dh
;
2732 void wxWindow::DoGetPosition( int *x
, int *y
) const
2734 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2738 if (m_parent
&& m_parent
->m_wxwindow
)
2740 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2741 dx
= pizza
->xoffset
;
2742 dy
= pizza
->yoffset
;
2745 if (x
) (*x
) = m_x
- dx
;
2746 if (y
) (*y
) = m_y
- dy
;
2749 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2751 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2753 if (!m_widget
->window
) return;
2755 GdkWindow
*source
= (GdkWindow
*) NULL
;
2757 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2759 source
= m_widget
->window
;
2763 gdk_window_get_origin( source
, &org_x
, &org_y
);
2767 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2769 org_x
+= m_widget
->allocation
.x
;
2770 org_y
+= m_widget
->allocation
.y
;
2778 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2780 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2782 if (!m_widget
->window
) return;
2784 GdkWindow
*source
= (GdkWindow
*) NULL
;
2786 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2788 source
= m_widget
->window
;
2792 gdk_window_get_origin( source
, &org_x
, &org_y
);
2796 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2798 org_x
+= m_widget
->allocation
.x
;
2799 org_y
+= m_widget
->allocation
.y
;
2807 bool wxWindow::Show( bool show
)
2809 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2811 if (!wxWindowBase::Show(show
))
2818 gtk_widget_show( m_widget
);
2820 gtk_widget_hide( m_widget
);
2825 bool wxWindow::Enable( bool enable
)
2827 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2829 if (!wxWindowBase::Enable(enable
))
2835 gtk_widget_set_sensitive( m_widget
, enable
);
2837 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2842 int wxWindow::GetCharHeight() const
2844 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2846 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2848 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2850 return font
->ascent
+ font
->descent
;
2853 int wxWindow::GetCharWidth() const
2855 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2857 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2859 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2861 return gdk_string_width( font
, "H" );
2864 void wxWindow::GetTextExtent( const wxString
& string
,
2868 int *externalLeading
,
2869 const wxFont
*theFont
) const
2871 wxFont fontToUse
= m_font
;
2872 if (theFont
) fontToUse
= *theFont
;
2874 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2876 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2877 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2878 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2879 if (descent
) (*descent
) = font
->descent
;
2880 if (externalLeading
) (*externalLeading
) = 0; // ??
2883 void wxWindow::SetFocus()
2885 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2889 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2890 gtk_widget_grab_focus (m_wxwindow
);
2896 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2898 gtk_widget_grab_focus (m_widget
);
2900 else if (GTK_IS_CONTAINER(m_widget
))
2902 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2911 bool wxWindow::AcceptsFocus() const
2913 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2916 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2918 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2920 wxWindow
*oldParent
= m_parent
,
2921 *newParent
= (wxWindow
*)newParentBase
;
2923 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2925 if ( !wxWindowBase::Reparent(newParent
) )
2928 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2930 /* prevent GTK from deleting the widget arbitrarily */
2931 gtk_widget_ref( m_widget
);
2935 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2938 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2942 /* insert GTK representation */
2943 (*(newParent
->m_insertCallback
))(newParent
, this);
2946 /* reverse: prevent GTK from deleting the widget arbitrarily */
2947 gtk_widget_unref( m_widget
);
2952 void wxWindow::DoAddChild(wxWindow
*child
)
2954 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2956 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
2958 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
2963 /* insert GTK representation */
2964 (*m_insertCallback
)(this, child
);
2967 void wxWindow::Raise()
2969 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2971 if (!m_widget
->window
) return;
2973 gdk_window_raise( m_widget
->window
);
2976 void wxWindow::Lower()
2978 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2980 if (!m_widget
->window
) return;
2982 gdk_window_lower( m_widget
->window
);
2985 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2987 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2989 return wxWindowBase::SetCursor( cursor
);
2992 void wxWindow::WarpPointer( int x
, int y
)
2994 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2996 /* we provide this function ourselves as it is
2997 missing in GDK (top of this file) */
2999 GdkWindow
*window
= (GdkWindow
*) NULL
;
3001 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3003 window
= GetConnectWidget()->window
;
3006 gdk_window_warp_pointer( window
, x
, y
);
3009 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
3011 if (!m_widget
) return;
3012 if (!m_widget
->window
) return;
3014 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3018 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3020 rect
->width
, rect
->height
);
3024 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3028 /* there is no GTK equivalent of "draw only, don't clear" so we
3029 invent our own in the GtkPizza widget */
3037 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3038 gboolean old_clear = pizza->clear_on_draw;
3039 gtk_pizza_set_clear( pizza, FALSE );
3040 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3041 gtk_pizza_set_clear( pizza, old_clear );
3043 GdkEventExpose gdk_event
;
3044 gdk_event
.type
= GDK_EXPOSE
;
3045 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3046 gdk_event
.count
= 0;
3047 gdk_event
.area
.x
= 0;
3048 gdk_event
.area
.y
= 0;
3049 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3050 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3051 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3056 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3065 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3066 gboolean old_clear = pizza->clear_on_draw;
3067 gtk_pizza_set_clear( pizza, FALSE );
3069 GdkRectangle gdk_rect;
3070 gdk_rect.x = rect->x;
3071 gdk_rect.y = rect->y;
3072 gdk_rect.width = rect->width;
3073 gdk_rect.height = rect->height;
3074 gtk_widget_draw( m_wxwindow, &gdk_rect );
3075 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3077 gtk_pizza_set_clear( pizza, old_clear );
3079 GdkEventExpose gdk_event
;
3080 gdk_event
.type
= GDK_EXPOSE
;
3081 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3082 gdk_event
.count
= 0;
3083 gdk_event
.area
.x
= rect
->x
;
3084 gdk_event
.area
.y
= rect
->y
;
3085 gdk_event
.area
.width
= rect
->width
;
3086 gdk_event
.area
.height
= rect
->height
;
3087 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3091 GdkRectangle gdk_rect
;
3092 gdk_rect
.x
= rect
->x
;
3093 gdk_rect
.y
= rect
->y
;
3094 gdk_rect
.width
= rect
->width
;
3095 gdk_rect
.height
= rect
->height
;
3096 gtk_widget_draw( m_widget
, &gdk_rect
);
3101 void wxWindow::Clear()
3103 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3105 if (!m_widget
->window
) return;
3107 if (m_wxwindow
&& m_wxwindow
->window
)
3109 // gdk_window_clear( m_wxwindow->window );
3114 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
3116 wxWindowBase::DoSetToolTip(tip
);
3119 m_tooltip
->Apply( this );
3122 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3124 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3126 #endif // wxUSE_TOOLTIPS
3128 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
3130 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3132 if (!wxWindowBase::SetBackgroundColour(colour
))
3134 // don't leave if the GTK widget has just
3136 if (!m_delayedBackgroundColour
) return FALSE
;
3139 GdkWindow
*window
= (GdkWindow
*) NULL
;
3141 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3143 window
= GetConnectWidget()->window
;
3147 // indicate that a new style has been set
3148 // but it couldn't get applied as the
3149 // widget hasn't been realized yet.
3150 m_delayedBackgroundColour
= TRUE
;
3154 (m_wxwindow
->window
) &&
3155 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3157 /* wxMSW doesn't clear the window here. I don't do that either to
3158 provide compatibility. call Clear() to do the job. */
3160 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3161 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3169 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
3171 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3173 if (!wxWindowBase::SetForegroundColour(colour
))
3175 // don't leave if the GTK widget has just
3177 if (!m_delayedForegroundColour
) return FALSE
;
3180 GdkWindow
*window
= (GdkWindow
*) NULL
;
3182 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3184 window
= GetConnectWidget()->window
;
3188 // indicate that a new style has been set
3189 // but it couldn't get applied as the
3190 // widget hasn't been realized yet.
3191 m_delayedForegroundColour
= TRUE
;
3199 GtkStyle
*wxWindow::GetWidgetStyle()
3203 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3204 remake
->klass
= m_widgetStyle
->klass
;
3206 gtk_style_unref( m_widgetStyle
);
3207 m_widgetStyle
= remake
;
3211 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3214 def
= gtk_widget_get_default_style();
3216 m_widgetStyle
= gtk_style_copy( def
);
3217 m_widgetStyle
->klass
= def
->klass
;
3220 return m_widgetStyle
;
3223 void wxWindow::SetWidgetStyle()
3225 #if DISABLE_STYLE_IF_BROKEN_THEM
3226 if (m_widget
->style
->engine_data
)
3228 static bool s_warningPrinted
= FALSE
;
3229 if (!s_warningPrinted
)
3231 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3232 s_warningPrinted
= TRUE
;
3234 m_widgetStyle
= m_widget
->style
;
3239 GtkStyle
*style
= GetWidgetStyle();
3241 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3243 gdk_font_unref( style
->font
);
3244 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3247 if (m_foregroundColour
.Ok())
3249 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3250 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3252 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3253 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3254 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3258 if (m_backgroundColour
.Ok())
3260 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3261 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3263 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3264 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3265 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3266 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3267 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3268 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3269 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3270 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3275 void wxWindow::ApplyWidgetStyle()
3279 //-----------------------------------------------------------------------------
3280 // Pop-up menu stuff
3281 //-----------------------------------------------------------------------------
3283 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3285 *is_waiting
= FALSE
;
3288 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3290 menu
->SetInvokingWindow( win
);
3291 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3294 wxMenuItem
*menuitem
= node
->GetData();
3295 if (menuitem
->IsSubMenu())
3297 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3300 node
= node
->GetNext();
3304 static gint gs_pop_x
= 0;
3305 static gint gs_pop_y
= 0;
3307 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3311 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3316 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3318 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3320 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3322 SetInvokingWindow( menu
, this );
3329 bool is_waiting
= TRUE
;
3331 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3332 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3335 GTK_MENU(menu
->m_menu
),
3336 (GtkWidget
*) NULL
, // parent menu shell
3337 (GtkWidget
*) NULL
, // parent menu item
3338 (GtkMenuPositionFunc
) pop_pos_callback
,
3339 (gpointer
) this, // client data
3340 0, // button used to activate it
3341 gs_timeLastClick
// the time of activation
3346 while (gtk_events_pending())
3347 gtk_main_iteration();
3353 #if wxUSE_DRAG_AND_DROP
3355 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3357 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3359 GtkWidget
*dnd_widget
= GetConnectWidget();
3361 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3363 if (m_dropTarget
) delete m_dropTarget
;
3364 m_dropTarget
= dropTarget
;
3366 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3369 #endif // wxUSE_DRAG_AND_DROP
3371 GtkWidget
* wxWindow::GetConnectWidget()
3373 GtkWidget
*connect_widget
= m_widget
;
3374 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3376 return connect_widget
;
3379 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3382 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3384 return (window
== m_widget
->window
);
3387 bool wxWindow::SetFont( const wxFont
&font
)
3389 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3391 if (!wxWindowBase::SetFont(font
))
3396 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3397 if ( sysbg
== m_backgroundColour
)
3399 m_backgroundColour
= wxNullColour
;
3401 m_backgroundColour
= sysbg
;
3411 void wxWindow::CaptureMouse()
3413 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3415 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3417 GdkWindow
*window
= (GdkWindow
*) NULL
;
3419 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3421 window
= GetConnectWidget()->window
;
3423 if (!window
) return;
3425 wxCursor
* cursor
= & m_cursor
;
3427 cursor
= wxSTANDARD_CURSOR
;
3429 gdk_pointer_grab( window
, FALSE
,
3431 (GDK_BUTTON_PRESS_MASK
|
3432 GDK_BUTTON_RELEASE_MASK
|
3433 GDK_POINTER_MOTION_HINT_MASK
|
3434 GDK_POINTER_MOTION_MASK
),
3436 cursor
->GetCursor(),
3437 (guint32
)GDK_CURRENT_TIME
);
3438 g_captureWindow
= this;
3441 void wxWindow::ReleaseMouse()
3443 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3445 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3447 GdkWindow
*window
= (GdkWindow
*) NULL
;
3449 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3451 window
= GetConnectWidget()->window
;
3456 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3457 g_captureWindow
= (wxWindow
*) NULL
;
3460 bool wxWindow::IsRetained() const
3465 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3466 int range
, bool refresh
)
3468 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3470 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3472 m_hasScrolling
= TRUE
;
3474 if (orient
== wxHORIZONTAL
)
3476 float fpos
= (float)pos
;
3477 float frange
= (float)range
;
3478 float fthumb
= (float)thumbVisible
;
3479 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3480 if (fpos
< 0.0) fpos
= 0.0;
3482 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3483 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3485 SetScrollPos( orient
, pos
, refresh
);
3489 m_oldHorizontalPos
= fpos
;
3491 m_hAdjust
->lower
= 0.0;
3492 m_hAdjust
->upper
= frange
;
3493 m_hAdjust
->value
= fpos
;
3494 m_hAdjust
->step_increment
= 1.0;
3495 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3496 m_hAdjust
->page_size
= fthumb
;
3500 float fpos
= (float)pos
;
3501 float frange
= (float)range
;
3502 float fthumb
= (float)thumbVisible
;
3503 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3504 if (fpos
< 0.0) fpos
= 0.0;
3506 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3507 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3509 SetScrollPos( orient
, pos
, refresh
);
3513 m_oldVerticalPos
= fpos
;
3515 m_vAdjust
->lower
= 0.0;
3516 m_vAdjust
->upper
= frange
;
3517 m_vAdjust
->value
= fpos
;
3518 m_vAdjust
->step_increment
= 1.0;
3519 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3520 m_vAdjust
->page_size
= fthumb
;
3523 if (orient
== wxHORIZONTAL
)
3524 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3526 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3529 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3531 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3533 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3535 if (orient
== wxHORIZONTAL
)
3537 float fpos
= (float)pos
;
3538 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3539 if (fpos
< 0.0) fpos
= 0.0;
3540 m_oldHorizontalPos
= fpos
;
3542 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3543 m_hAdjust
->value
= fpos
;
3547 float fpos
= (float)pos
;
3548 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3549 if (fpos
< 0.0) fpos
= 0.0;
3550 m_oldVerticalPos
= fpos
;
3552 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3553 m_vAdjust
->value
= fpos
;
3556 if (m_wxwindow
->window
)
3558 if (orient
== wxHORIZONTAL
)
3560 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3561 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3563 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3565 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3566 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3570 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3571 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3573 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3575 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3576 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3581 int wxWindow::GetScrollThumb( int orient
) const
3583 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3585 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3587 if (orient
== wxHORIZONTAL
)
3588 return (int)(m_hAdjust
->page_size
+0.5);
3590 return (int)(m_vAdjust
->page_size
+0.5);
3593 int wxWindow::GetScrollPos( int orient
) const
3595 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3597 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3599 if (orient
== wxHORIZONTAL
)
3600 return (int)(m_hAdjust
->value
+0.5);
3602 return (int)(m_vAdjust
->value
+0.5);
3605 int wxWindow::GetScrollRange( int orient
) const
3607 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3609 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3611 if (orient
== wxHORIZONTAL
)
3612 return (int)(m_hAdjust
->upper
+0.5);
3614 return (int)(m_vAdjust
->upper
+0.5);
3617 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3619 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3621 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3623 if ((dx
== 0) && (dy
== 0)) return;
3625 m_clipPaintRegion
= TRUE
;
3626 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3627 m_clipPaintRegion
= FALSE
;
3630 if (m_children.GetCount() > 0)
3632 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3636 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3638 pizza->xoffset -= dx;
3639 pizza->yoffset -= dy;
3641 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3642 gdk_gc_set_exposures( m_scrollGC, TRUE );
3646 GetClientSize( &cw, &ch );
3647 int w = cw - abs(dx);
3648 int h = ch - abs(dy);
3650 if ((h < 0) || (w < 0))
3658 if (dx < 0) s_x = -dx;
3659 if (dy < 0) s_y = -dy;
3662 if (dx > 0) d_x = dx;
3663 if (dy > 0) d_y = dy;
3665 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3666 pizza->bin_window, s_x, s_y, w, h );
3669 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3670 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3671 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3672 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3674 Refresh( TRUE, &rect );
3677 gdk_gc_unref( m_scrollGC );