]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/window.cpp
Added to wxSystemSettings for better GTK+ themes compatibility
[wxWidgets.git] / src / gtk1 / window.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
f6bcfd97 2// Name: gtk/window.cpp
c801d85f
KB
3// Purpose:
4// Author: Robert Roebling
c67d8618 5// Id: $Id$
01111366 6// Copyright: (c) 1998 Robert Roebling, Julian Smart
5e0aa05a 7// Licence: wxWindows licence
c801d85f
KB
8/////////////////////////////////////////////////////////////////////////////
9
10
11#ifdef __GNUG__
bfc6fde4 12 #pragma implementation "window.h"
c801d85f
KB
13#endif
14
d02af7bb
JJ
15#ifdef __VMS
16#define XWarpPointer XWARPPOINTER
17#endif
18
c801d85f
KB
19#include "wx/defs.h"
20#include "wx/window.h"
21#include "wx/dc.h"
22#include "wx/frame.h"
23#include "wx/app.h"
24#include "wx/layout.h"
25#include "wx/utils.h"
26#include "wx/dialog.h"
27#include "wx/msgdlg.h"
bfc6fde4 28
06cfab17 29#if wxUSE_DRAG_AND_DROP
bfc6fde4 30 #include "wx/dnd.h"
ac57418f 31#endif
bfc6fde4 32
cad880f5 33#if wxUSE_TOOLTIPS
bfc6fde4 34 #include "wx/tooltip.h"
cad880f5 35#endif
bfc6fde4 36
f6bcfd97
BP
37#if wxUSE_CARET
38 #include "wx/caret.h"
39#endif // wxUSE_CARET
40
30dea054 41#include "wx/menu.h"
d4c99d6f 42#include "wx/statusbr.h"
b4071e91 43#include "wx/intl.h"
3bc755fc 44#include "wx/settings.h"
3069ac4e 45#include "wx/log.h"
b4071e91 46
3ac8d3bc
RR
47#ifdef __WXDEBUG__
48 #include "wx/thread.h"
49#endif
50
b4071e91 51#include <math.h>
c801d85f 52
3ac8d3bc
RR
53#include <gdk/gdk.h>
54#include <gtk/gtk.h>
55#include <gdk/gdkprivate.h>
56#include <gdk/gdkkeysyms.h>
3ac8d3bc 57#include <gdk/gdkx.h>
6bc8a1c8 58
8cb9f0d0
RR
59#include <gtk/gtk.h>
60#include <gtk/gtkprivate.h>
61
62#include "wx/gtk/win_gtk.h"
63
868a2826
RR
64//-----------------------------------------------------------------------------
65// documentation on internals
66//-----------------------------------------------------------------------------
67
68/*
69 I have been asked several times about writing some documentation about
70 the GTK port of wxWindows, especially its internal structures. Obviously,
71 you cannot understand wxGTK without knowing a little about the GTK, but
47d67540 72 some more information about what the wxWindow, which is the base class
868a2826 73 for all other window classes, does seems required as well.
47d67540 74
30760ce7
RR
75 I)
76
868a2826 77 What does wxWindow do? It contains the common interface for the following
e380f72b 78 jobs of its descendants:
47d67540 79
868a2826 80 1) Define the rudimentary behaviour common to all window classes, such as
e380f72b
RR
81 resizing, intercepting user input (so as to make it possible to use these
82 events for special purposes in a derived class), window names etc.
868a2826
RR
83
84 2) Provide the possibility to contain and manage children, if the derived
85 class is allowed to contain children, which holds true for those window
e380f72b 86 classes which do not display a native GTK widget. To name them, these
868a2826 87 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
47d67540 88 work classes are a special case and are handled a bit differently from
e380f72b 89 the rest. The same holds true for the wxNotebook class.
47d67540 90
868a2826
RR
91 3) Provide the possibility to draw into a client area of a window. This,
92 too, only holds true for classes that do not display a native GTK widget
93 as above.
47d67540 94
e380f72b
RR
95 4) Provide the entire mechanism for scrolling widgets. This actual inter-
96 face for this is usually in wxScrolledWindow, but the GTK implementation
868a2826 97 is in this class.
47d67540 98
868a2826
RR
99 5) A multitude of helper or extra methods for special purposes, such as
100 Drag'n'Drop, managing validators etc.
47d67540 101
30760ce7
RR
102 6) Display a border (sunken, raised, simple or none).
103
e380f72b
RR
104 Normally one might expect, that one wxWindows window would always correspond
105 to one GTK widget. Under GTK, there is no such allround widget that has all
868a2826
RR
106 the functionality. Moreover, the GTK defines a client area as a different
107 widget from the actual widget you are handling. Last but not least some
108 special classes (e.g. wxFrame) handle different categories of widgets and
109 still have the possibility to draw something in the client area.
110 It was therefore required to write a special purpose GTK widget, that would
111 represent a client area in the sense of wxWindows capable to do the jobs
112 2), 3) and 4). I have written this class and it resides in win_gtk.c of
113 this directory.
47d67540 114
868a2826 115 All windows must have a widget, with which they interact with other under-
e380f72b 116 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
868a2826 117 thw wxWindow class has a member variable called m_widget which holds a
e380f72b
RR
118 pointer to this widget. When the window class represents a GTK native widget,
119 this is (in most cases) the only GTK widget the class manages. E.g. the
120 wxStatitText class handles only a GtkLabel widget a pointer to which you
121 can find in m_widget (defined in wxWindow)
8bbe427f 122
e380f72b 123 When the class has a client area for drawing into and for containing children
da048e3d 124 it has to handle the client area widget (of the type GtkPizza, defined in
8bbe427f
VZ
125 win_gtk.c), but there could be any number of widgets, handled by a class
126 The common rule for all windows is only, that the widget that interacts with
127 the rest of GTK must be referenced in m_widget and all other widgets must be
128 children of this widget on the GTK level. The top-most widget, which also
129 represents the client area, must be in the m_wxwindow field and must be of
da048e3d 130 the type GtkPizza.
47d67540 131
868a2826
RR
132 As I said, the window classes that display a GTK native widget only have
133 one widget, so in the case of e.g. the wxButton class m_widget holds a
134 pointer to a GtkButton widget. But windows with client areas (for drawing
135 and children) have a m_widget field that is a pointer to a GtkScrolled-
da048e3d 136 Window and a m_wxwindow field that is pointer to a GtkPizza and this
868a2826 137 one is (in the GTK sense) a child of the GtkScrolledWindow.
47d67540 138
868a2826
RR
139 If the m_wxwindow field is set, then all input to this widget is inter-
140 cepted and sent to the wxWindows class. If not, all input to the widget
141 that gets pointed to by m_widget gets intercepted and sent to the class.
148cd9b6 142
30760ce7 143 II)
148cd9b6 144
30760ce7
RR
145 The design of scrolling in wxWindows is markedly different from that offered
146 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
147 clicking on a scrollbar belonging to scrolled window will inevitably move
148 the window. In wxWindows, the scrollbar will only emit an event, send this
149 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
da048e3d 150 which actually moves the window and its subchildren. Note that GtkPizza
30760ce7
RR
151 memorizes how much it has been scrolled but that wxWindows forgets this
152 so that the two coordinates systems have to be kept in synch. This is done
da048e3d 153 in various places using the pizza->xoffset and pizza->yoffset values.
148cd9b6
VZ
154
155 III)
156
30760ce7
RR
157 Singularily the most broken code in GTK is the code that is supposes to
158 inform subwindows (child windows) about new positions. Very often, duplicate
159 events are sent without changes in size or position, equally often no
160 events are sent at all (All this is due to a bug in the GtkContainer code
161 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
162 GTK's own system and it simply waits for size events for toplevel windows
163 and then iterates down the respective size events to all window. This has
164 the disadvantage, that windows might get size events before the GTK widget
165 actually has the reported size. This doesn't normally pose any problem, but
3017f78d 166 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
30760ce7
RR
167 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
168 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
169 window that is used for OpenGl output really has that size (as reported by
170 GTK).
171
172 IV)
148cd9b6 173
30760ce7
RR
174 If someone at some point of time feels the immense desire to have a look at,
175 change or attempt to optimse the Refresh() logic, this person will need an
176 intimate understanding of what a "draw" and what an "expose" events are and
177 what there are used for, in particular when used in connection with GTK's
178 own windowless widgets. Beware.
148cd9b6 179
30760ce7 180 V)
148cd9b6 181
30760ce7
RR
182 Cursors, too, have been a constant source of pleasure. The main difficulty
183 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
184 for the parent. To prevent this from doing too much harm, I use idle time
185 to set the cursor over and over again, starting from the toplevel windows
186 and ending with the youngest generation (speaking of parent and child windows).
187 Also don't forget that cursors (like much else) are connected to GdkWindows,
188 not GtkWidgets and that the "window" field of a GtkWidget might very well
148cd9b6 189 point to the GdkWindow of the parent widget (-> "window less widget") and
30760ce7 190 that the two obviously have very different meanings.
868a2826
RR
191
192*/
193
f03fc89f
VZ
194//-----------------------------------------------------------------------------
195// data
196//-----------------------------------------------------------------------------
197
198extern wxList wxPendingDelete;
199extern bool g_blockEventsOnDrag;
200extern bool g_blockEventsOnScroll;
238d735d 201extern wxCursor g_globalCursor;
72195a0f 202static wxWindow *g_captureWindow = (wxWindow*) NULL;
f68586e5
VZ
203
204/* extern */ wxWindow *g_focusWindow = (wxWindow*) NULL;
148cd9b6
VZ
205
206// if we detect that the app has got/lost the focus, we set this variable to
207// either TRUE or FALSE and an activate event will be sent during the next
208// OnIdle() call and it is reset to -1: this value means that we shouldn't
209// send any activate events at all
210static int g_sendActivateEvent = -1;
f03fc89f
VZ
211
212/* hack: we need something to pass to gtk_menu_popup, so we store the time of
213 the last click here */
214static guint32 gs_timeLastClick = 0;
215
3ac8d3bc
RR
216extern bool g_mainThreadLocked;
217
2e563988
RR
218//-----------------------------------------------------------------------------
219// debug
220//-----------------------------------------------------------------------------
221
a56fcaaf
RR
222#define DISABLE_STYLE_IF_BROKEN_THEME 1
223
2e563988
RR
224#ifdef __WXDEBUG__
225
c6e62f74
KB
226#if wxUSE_THREADS
227# define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
228#else
229# define DEBUG_MAIN_THREAD
230#endif
3ac8d3bc 231
2e563988
RR
232static gint gtk_debug_focus_in_callback( GtkWidget *WXUNUSED(widget),
233 GdkEvent *WXUNUSED(event),
014b0d06 234 const wxChar *WXUNUSED(name) )
2e563988 235{
053dcf1a 236/*
167e3718
VZ
237 static bool s_done = FALSE;
238 if ( !s_done )
239 {
240 wxLog::AddTraceMask("focus");
241 s_done = TRUE;
242 }
223d09f6 243 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
053dcf1a 244*/
2e563988
RR
245
246 return FALSE;
247}
248
249void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window )
250{
9a8c7620
VZ
251 // suppress warnings about gtk_debug_focus_in_callback being unused with
252 // this "if ( 0 )"
253 if ( 0 )
254 {
255 wxString tmp = name;
256 tmp += wxT(" FROM ");
257 tmp += window;
2e563988 258
9a8c7620 259 wxChar *s = new wxChar[tmp.Length()+1];
2e563988 260
9a8c7620 261 wxStrcpy( s, tmp );
2e563988 262
9a8c7620
VZ
263 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
264 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback), (gpointer)s );
265 }
2e563988
RR
266}
267
559d79aa
BJ
268#else
269#define DEBUG_MAIN_THREAD
f03fc89f 270#endif // Debug
ff8bfdbb 271
85eb36c2
RR
272//-----------------------------------------------------------------------------
273// missing gdk functions
274//-----------------------------------------------------------------------------
275
276void
277gdk_window_warp_pointer (GdkWindow *window,
c50f1fb9
VZ
278 gint x,
279 gint y)
85eb36c2 280{
dd00f3f6 281#ifndef __WXGTK20__
85eb36c2 282 GdkWindowPrivate *priv;
dd00f3f6 283#endif
c50f1fb9 284
85eb36c2 285 if (!window)
27df579a 286 window = GDK_ROOT_PARENT();
c50f1fb9 287
dd00f3f6
OK
288#ifdef __WXGTK20__
289 if (!GDK_WINDOW_DESTROYED(window))
290 {
291 XWarpPointer (GDK_WINDOW_XDISPLAY(window),
292 None, /* not source window -> move from anywhere */
293 GDK_WINDOW_XID(window), /* dest window */
294 0, 0, 0, 0, /* not source window -> move from anywhere */
295 x, y );
296 }
297#else
85eb36c2 298 priv = (GdkWindowPrivate*) window;
c50f1fb9 299
85eb36c2
RR
300 if (!priv->destroyed)
301 {
c50f1fb9 302 XWarpPointer (priv->xdisplay,
85eb36c2 303 None, /* not source window -> move from anywhere */
c50f1fb9 304 priv->xwindow, /* dest window */
85eb36c2 305 0, 0, 0, 0, /* not source window -> move from anywhere */
c50f1fb9 306 x, y );
85eb36c2 307 }
dd00f3f6 308#endif
85eb36c2
RR
309}
310
acfd422a 311//-----------------------------------------------------------------------------
a2053b27 312// idle system
acfd422a
RR
313//-----------------------------------------------------------------------------
314
a2053b27
RR
315extern void wxapp_install_idle_handler();
316extern bool g_isIdle;
317
ed673c6a
RR
318//-----------------------------------------------------------------------------
319// local code (see below)
320//-----------------------------------------------------------------------------
321
f6bcfd97
BP
322// returns the child of win which currently has focus or NULL if not found
323static wxWindow *FindFocusedChild(wxWindow *win)
324{
325 wxWindow *winFocus = wxWindow::FindFocus();
326 if ( !winFocus )
327 return (wxWindow *)NULL;
328
329 if ( winFocus == win )
330 return win;
331
332 for ( wxWindowList::Node *node = win->GetChildren().GetFirst();
333 node;
334 node = node->GetNext() )
335 {
336 wxWindow *child = FindFocusedChild(node->GetData());
337 if ( child )
338 return child;
339 }
340
341 return (wxWindow *)NULL;
342}
343
ed673c6a
RR
344static void draw_frame( GtkWidget *widget, wxWindow *win )
345{
346 if (!win->m_hasVMT)
347 return;
348
349 int dw = 0;
350 int dh = 0;
351
5b8a521e 352 if (win->m_hasScrolling)
ed673c6a 353 {
9000c624 354 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(widget);
2daa0ce9 355
9000c624
RR
356 GtkRequisition vscroll_req;
357 vscroll_req.width = 2;
358 vscroll_req.height = 2;
dd00f3f6 359 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
9000c624 360 (scroll_window->vscrollbar, &vscroll_req );
2daa0ce9 361
9000c624
RR
362 GtkRequisition hscroll_req;
363 hscroll_req.width = 2;
364 hscroll_req.height = 2;
dd00f3f6 365 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
9000c624
RR
366 (scroll_window->hscrollbar, &hscroll_req );
367
dd00f3f6 368 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget) );
ed673c6a 369
9000c624
RR
370 if (scroll_window->vscrollbar_visible)
371 {
372 dw += vscroll_req.width;
373 dw += scroll_class->scrollbar_spacing;
374 }
ed673c6a 375
9000c624
RR
376 if (scroll_window->hscrollbar_visible)
377 {
378 dh += hscroll_req.height;
379 dh += scroll_class->scrollbar_spacing;
380 }
ed673c6a
RR
381 }
382
383 int dx = 0;
384 int dy = 0;
385 if (GTK_WIDGET_NO_WINDOW (widget))
386 {
387 dx += widget->allocation.x;
388 dy += widget->allocation.y;
389 }
390
391 if (win->HasFlag(wxRAISED_BORDER))
392 {
393 gtk_draw_shadow( widget->style,
394 widget->window,
395 GTK_STATE_NORMAL,
396 GTK_SHADOW_OUT,
397 dx, dy,
07f5b19a 398 widget->allocation.width-dw, widget->allocation.height-dh );
ed673c6a
RR
399 return;
400 }
401
402 if (win->HasFlag(wxSUNKEN_BORDER))
403 {
404 gtk_draw_shadow( widget->style,
405 widget->window,
406 GTK_STATE_NORMAL,
407 GTK_SHADOW_IN,
408 dx, dy,
07f5b19a 409 widget->allocation.width-dw, widget->allocation.height-dh );
ed673c6a
RR
410 return;
411 }
148cd9b6 412
ed673c6a
RR
413 if (win->HasFlag(wxSIMPLE_BORDER))
414 {
415 GdkGC *gc;
b02da6b1 416 gc = gdk_gc_new( widget->window );
ed673c6a 417 gdk_gc_set_foreground( gc, &widget->style->black );
148cd9b6 418 gdk_draw_rectangle( widget->window, gc, FALSE,
ed673c6a 419 dx, dy,
07f5b19a 420 widget->allocation.width-dw-1, widget->allocation.height-dh-1 );
ed673c6a
RR
421 gdk_gc_unref( gc );
422 return;
423 }
424}
425
426//-----------------------------------------------------------------------------
427// "expose_event" of m_widget
428//-----------------------------------------------------------------------------
429
b6fa52db 430gint gtk_window_own_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindow *win )
ed673c6a 431{
b6fa52db
RR
432 if (gdk_event->count > 0) return FALSE;
433
ed673c6a 434 draw_frame( widget, win );
b6fa52db
RR
435
436 return TRUE;
ed673c6a
RR
437}
438
439//-----------------------------------------------------------------------------
147bc491 440// "draw" of m_widget
ed673c6a
RR
441//-----------------------------------------------------------------------------
442
443static void gtk_window_own_draw_callback( GtkWidget *widget, GdkRectangle *WXUNUSED(rect), wxWindow *win )
444{
445 draw_frame( widget, win );
446}
447
c5b42c87 448//-----------------------------------------------------------------------------
da048e3d 449// key code mapping routines
c5b42c87
RR
450//-----------------------------------------------------------------------------
451
452static long map_to_unmodified_wx_keysym( KeySym keysym )
453{
454 guint key_code = 0;
455
456 switch (keysym)
457 {
458 case GDK_Shift_L:
459 case GDK_Shift_R: key_code = WXK_SHIFT; break;
460 case GDK_Control_L:
461 case GDK_Control_R: key_code = WXK_CONTROL; break;
c50f1fb9
VZ
462 case GDK_Meta_L:
463 case GDK_Meta_R:
464 case GDK_Alt_L:
465 case GDK_Alt_R:
466 case GDK_Super_L:
467 case GDK_Super_R: key_code = WXK_ALT; break;
c5b42c87
RR
468 case GDK_Menu: key_code = WXK_MENU; break;
469 case GDK_Help: key_code = WXK_HELP; break;
470 case GDK_BackSpace: key_code = WXK_BACK; break;
471 case GDK_ISO_Left_Tab:
472 case GDK_Tab: key_code = WXK_TAB; break;
473 case GDK_Linefeed: key_code = WXK_RETURN; break;
474 case GDK_Clear: key_code = WXK_CLEAR; break;
475 case GDK_Return: key_code = WXK_RETURN; break;
476 case GDK_Pause: key_code = WXK_PAUSE; break;
477 case GDK_Scroll_Lock: key_code = WXK_SCROLL; break;
478 case GDK_Escape: key_code = WXK_ESCAPE; break;
479 case GDK_Delete: key_code = WXK_DELETE; break;
480 case GDK_Home: key_code = WXK_HOME; break;
481 case GDK_Left: key_code = WXK_LEFT; break;
482 case GDK_Up: key_code = WXK_UP; break;
483 case GDK_Right: key_code = WXK_RIGHT; break;
484 case GDK_Down: key_code = WXK_DOWN; break;
485 case GDK_Prior: key_code = WXK_PRIOR; break;
486// case GDK_Page_Up: key_code = WXK_PAGEUP; break;
487 case GDK_Next: key_code = WXK_NEXT; break;
488// case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
489 case GDK_End: key_code = WXK_END; break;
490 case GDK_Begin: key_code = WXK_HOME; break;
491 case GDK_Select: key_code = WXK_SELECT; break;
492 case GDK_Print: key_code = WXK_PRINT; break;
493 case GDK_Execute: key_code = WXK_EXECUTE; break;
494 case GDK_Insert: key_code = WXK_INSERT; break;
495 case GDK_Num_Lock: key_code = WXK_NUMLOCK; break;
496
497 case GDK_KP_0: key_code = WXK_NUMPAD0; break;
498 case GDK_KP_1: key_code = WXK_NUMPAD1; break;
499 case GDK_KP_2: key_code = WXK_NUMPAD2; break;
500 case GDK_KP_3: key_code = WXK_NUMPAD3; break;
501 case GDK_KP_4: key_code = WXK_NUMPAD4; break;
502 case GDK_KP_5: key_code = WXK_NUMPAD5; break;
503 case GDK_KP_6: key_code = WXK_NUMPAD6; break;
504 case GDK_KP_7: key_code = WXK_NUMPAD7; break;
505 case GDK_KP_8: key_code = WXK_NUMPAD8; break;
506 case GDK_KP_9: key_code = WXK_NUMPAD9; break;
507 case GDK_KP_Space: key_code = WXK_NUMPAD_SPACE; break;
508 case GDK_KP_Tab: key_code = WXK_NUMPAD_TAB; break;
509 case GDK_KP_Enter: key_code = WXK_NUMPAD_ENTER; break;
510 case GDK_KP_F1: key_code = WXK_NUMPAD_F1; break;
511 case GDK_KP_F2: key_code = WXK_NUMPAD_F2; break;
512 case GDK_KP_F3: key_code = WXK_NUMPAD_F3; break;
513 case GDK_KP_F4: key_code = WXK_NUMPAD_F4; break;
514 case GDK_KP_Home: key_code = WXK_NUMPAD_HOME; break;
515 case GDK_KP_Left: key_code = WXK_NUMPAD_LEFT; break;
516 case GDK_KP_Up: key_code = WXK_NUMPAD_UP; break;
517 case GDK_KP_Right: key_code = WXK_NUMPAD_RIGHT; break;
518 case GDK_KP_Down: key_code = WXK_NUMPAD_DOWN; break;
519 case GDK_KP_Prior: key_code = WXK_NUMPAD_PRIOR; break;
520// case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
21884766 521 case GDK_KP_Next: key_code = WXK_NUMPAD_NEXT; break;
c5b42c87
RR
522// case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
523 case GDK_KP_End: key_code = WXK_NUMPAD_END; break;
524 case GDK_KP_Begin: key_code = WXK_NUMPAD_BEGIN; break;
525 case GDK_KP_Insert: key_code = WXK_NUMPAD_INSERT; break;
526 case GDK_KP_Delete: key_code = WXK_NUMPAD_DELETE; break;
527 case GDK_KP_Equal: key_code = WXK_NUMPAD_EQUAL; break;
528 case GDK_KP_Multiply: key_code = WXK_NUMPAD_MULTIPLY; break;
529 case GDK_KP_Add: key_code = WXK_NUMPAD_ADD; break;
530 case GDK_KP_Separator: key_code = WXK_NUMPAD_SEPARATOR; break;
531 case GDK_KP_Subtract: key_code = WXK_NUMPAD_SUBTRACT; break;
532 case GDK_KP_Decimal: key_code = WXK_NUMPAD_DECIMAL; break;
533 case GDK_KP_Divide: key_code = WXK_NUMPAD_DIVIDE; break;
c50f1fb9 534
c5b42c87
RR
535 case GDK_F1: key_code = WXK_F1; break;
536 case GDK_F2: key_code = WXK_F2; break;
537 case GDK_F3: key_code = WXK_F3; break;
538 case GDK_F4: key_code = WXK_F4; break;
539 case GDK_F5: key_code = WXK_F5; break;
540 case GDK_F6: key_code = WXK_F6; break;
541 case GDK_F7: key_code = WXK_F7; break;
542 case GDK_F8: key_code = WXK_F8; break;
543 case GDK_F9: key_code = WXK_F9; break;
544 case GDK_F10: key_code = WXK_F10; break;
545 case GDK_F11: key_code = WXK_F11; break;
546 case GDK_F12: key_code = WXK_F12; break;
547 default:
548 {
3d6f7261 549 if ((keysym & 0xF000) == 0)
c5b42c87 550 {
b02da6b1 551 guint upper = gdk_keyval_to_upper( (guint)keysym );
c5b42c87 552 keysym = (upper != 0 ? upper : keysym ); /* to be MSW compatible */
b02da6b1 553 key_code = (guint)keysym;
c5b42c87
RR
554 }
555 }
556 }
557
558 return (key_code);
559}
560
561static long map_to_wx_keysym( KeySym keysym )
562{
563 guint key_code = 0;
564
565 switch (keysym)
566 {
c5b42c87
RR
567 case GDK_Menu: key_code = WXK_MENU; break;
568 case GDK_Help: key_code = WXK_HELP; break;
569 case GDK_BackSpace: key_code = WXK_BACK; break;
570 case GDK_ISO_Left_Tab:
571 case GDK_Tab: key_code = WXK_TAB; break;
572 case GDK_Linefeed: key_code = WXK_RETURN; break;
573 case GDK_Clear: key_code = WXK_CLEAR; break;
574 case GDK_Return: key_code = WXK_RETURN; break;
575 case GDK_Pause: key_code = WXK_PAUSE; break;
576 case GDK_Scroll_Lock: key_code = WXK_SCROLL; break;
577 case GDK_Escape: key_code = WXK_ESCAPE; break;
578 case GDK_Delete: key_code = WXK_DELETE; break;
579 case GDK_Home: key_code = WXK_HOME; break;
580 case GDK_Left: key_code = WXK_LEFT; break;
581 case GDK_Up: key_code = WXK_UP; break;
582 case GDK_Right: key_code = WXK_RIGHT; break;
583 case GDK_Down: key_code = WXK_DOWN; break;
584 case GDK_Prior: key_code = WXK_PRIOR; break;
585// case GDK_Page_Up: key_code = WXK_PAGEUP; break;
586 case GDK_Next: key_code = WXK_NEXT; break;
587// case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
588 case GDK_End: key_code = WXK_END; break;
589 case GDK_Begin: key_code = WXK_HOME; break;
590 case GDK_Select: key_code = WXK_SELECT; break;
591 case GDK_Print: key_code = WXK_PRINT; break;
592 case GDK_Execute: key_code = WXK_EXECUTE; break;
593 case GDK_Insert: key_code = WXK_INSERT; break;
594 case GDK_Num_Lock: key_code = WXK_NUMLOCK; break;
595
596 case GDK_KP_0: key_code = '0'; break;
597 case GDK_KP_1: key_code = '1'; break;
598 case GDK_KP_2: key_code = '2'; break;
599 case GDK_KP_3: key_code = '3'; break;
600 case GDK_KP_4: key_code = '4'; break;
601 case GDK_KP_5: key_code = '5'; break;
602 case GDK_KP_6: key_code = '6'; break;
603 case GDK_KP_7: key_code = '7'; break;
604 case GDK_KP_8: key_code = '8'; break;
605 case GDK_KP_9: key_code = '9'; break;
606 case GDK_KP_Space: key_code = ' '; break;
607 case GDK_KP_Tab: key_code = WXK_TAB; break; /* or '\t' ??? */
608 case GDK_KP_Enter: key_code = WXK_RETURN; break; /* or '\r' ??? */
609 case GDK_KP_F1: key_code = WXK_NUMPAD_F1; break;
610 case GDK_KP_F2: key_code = WXK_NUMPAD_F2; break;
611 case GDK_KP_F3: key_code = WXK_NUMPAD_F3; break;
612 case GDK_KP_F4: key_code = WXK_NUMPAD_F4; break;
613 case GDK_KP_Home: key_code = WXK_HOME; break;
614 case GDK_KP_Left: key_code = WXK_LEFT; break;
615 case GDK_KP_Up: key_code = WXK_UP; break;
616 case GDK_KP_Right: key_code = WXK_RIGHT; break;
617 case GDK_KP_Down: key_code = WXK_DOWN; break;
618 case GDK_KP_Prior: key_code = WXK_PRIOR; break;
619// case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
21884766 620 case GDK_KP_Next: key_code = WXK_NEXT; break;
c5b42c87
RR
621// case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
622 case GDK_KP_End: key_code = WXK_END; break;
623 case GDK_KP_Begin: key_code = WXK_HOME; break;
624 case GDK_KP_Insert: key_code = WXK_INSERT; break;
625 case GDK_KP_Delete: key_code = WXK_DELETE; break;
626 case GDK_KP_Equal: key_code = '='; break;
627 case GDK_KP_Multiply: key_code = '*'; break;
628 case GDK_KP_Add: key_code = '+'; break;
629 case GDK_KP_Separator: key_code = ','; break;
630 case GDK_KP_Subtract: key_code = '-'; break;
631 case GDK_KP_Decimal: key_code = '.'; break;
632 case GDK_KP_Divide: key_code = '/'; break;
c50f1fb9 633
c5b42c87
RR
634 case GDK_F1: key_code = WXK_F1; break;
635 case GDK_F2: key_code = WXK_F2; break;
636 case GDK_F3: key_code = WXK_F3; break;
637 case GDK_F4: key_code = WXK_F4; break;
638 case GDK_F5: key_code = WXK_F5; break;
639 case GDK_F6: key_code = WXK_F6; break;
640 case GDK_F7: key_code = WXK_F7; break;
641 case GDK_F8: key_code = WXK_F8; break;
642 case GDK_F9: key_code = WXK_F9; break;
643 case GDK_F10: key_code = WXK_F10; break;
644 case GDK_F11: key_code = WXK_F11; break;
645 case GDK_F12: key_code = WXK_F12; break;
646 default:
647 {
3d6f7261 648 if ((keysym & 0xF000) == 0)
c5b42c87 649 {
b02da6b1 650 key_code = (guint)keysym;
c5b42c87
RR
651 }
652 }
653 }
654
655 return (key_code);
656}
657
c801d85f 658//-----------------------------------------------------------------------------
034be888 659// "expose_event" of m_wxwindow
c801d85f
KB
660//-----------------------------------------------------------------------------
661
b6fa52db 662static int gtk_window_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindow *win )
47d67540 663{
3ac8d3bc
RR
664 DEBUG_MAIN_THREAD
665
b6fa52db
RR
666 if (g_isIdle)
667 wxapp_install_idle_handler();
668
40c70187 669/*
8cb9f0d0 670 if (win->GetName() == wxT("panel"))
3d2d8da1
RR
671 {
672 wxPrintf( wxT("OnExpose from ") );
673 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
674 wxPrintf( win->GetClassInfo()->GetClassName() );
675 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
676 (int)gdk_event->area.y,
677 (int)gdk_event->area.width,
678 (int)gdk_event->area.height );
679 }
40c70187 680*/
3d2d8da1 681
b420fb6a
RR
682 win->GetUpdateRegion().Union( gdk_event->area.x,
683 gdk_event->area.y,
684 gdk_event->area.width,
685 gdk_event->area.height );
0e09f76e 686
b420fb6a
RR
687 if (gdk_event->count == 0)
688 {
689 wxEraseEvent eevent( win->GetId() );
690 eevent.SetEventObject( win );
691 win->GetEventHandler()->ProcessEvent(eevent);
148cd9b6 692
b420fb6a
RR
693 wxPaintEvent event( win->GetId() );
694 event.SetEventObject( win );
695 win->GetEventHandler()->ProcessEvent( event );
f7a11f8c 696
b420fb6a
RR
697 win->GetUpdateRegion().Clear();
698 }
b6fa52db 699
b420fb6a
RR
700 /* The following code will result in all window-less widgets
701 being redrawn if the wxWindows class is given a chance to
702 paint *anything* because it will then be allowed to paint
703 over the window-less widgets */
b6fa52db 704
b420fb6a 705 GtkPizza *pizza = GTK_PIZZA (widget);
b6fa52db 706
b420fb6a
RR
707 GList *children = pizza->children;
708 while (children)
709 {
710 GtkPizzaChild *child = (GtkPizzaChild*) children->data;
711 children = children->next;
b6fa52db 712
b420fb6a 713 GdkEventExpose child_event = *gdk_event;
b6fa52db 714
b420fb6a
RR
715 if (GTK_WIDGET_NO_WINDOW (child->widget) &&
716 GTK_WIDGET_DRAWABLE (child->widget) /* &&
717 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
718 {
719 child_event.area.x = child->widget->allocation.x;
720 child_event.area.y = child->widget->allocation.y;
721 child_event.area.width = child->widget->allocation.width;
722 child_event.area.height = child->widget->allocation.height;
723 gtk_widget_event (child->widget, (GdkEvent*) &child_event);
724 }
b6fa52db 725 }
b6fa52db
RR
726
727 return TRUE;
728}
729
730//-----------------------------------------------------------------------------
731// "event" of m_wxwindow
732//-----------------------------------------------------------------------------
733
734/* GTK thinks it is clever and filters out a certain amount of "unneeded"
735 expose events. We need them, of course, so we override the main event
b420fb6a
RR
736 procedure in GtkWidget by giving our own handler for all system events.
737 There, we look for expose events ourselves whereas all other events are
738 handled normally. */
b6fa52db
RR
739
740gint gtk_window_event_event_callback( GtkWidget *widget, GdkEventExpose *event, wxWindow *win )
741{
742 if (event->type == GDK_EXPOSE)
743 {
744 gint ret = gtk_window_expose_callback( widget, event, win );
745 return ret;
746 }
747
b6fa52db 748 return FALSE;
362c6693 749}
c801d85f
KB
750
751//-----------------------------------------------------------------------------
034be888 752// "draw" of m_wxwindow
2f2aa628 753//-----------------------------------------------------------------------------
c801d85f 754
b6fa52db
RR
755/* This callback is a complete replacement of the gtk_pizza_draw() function,
756 which disabled. */
757
758static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxWindow *win )
47d67540 759{
3ac8d3bc
RR
760 DEBUG_MAIN_THREAD
761
c50f1fb9 762 if (g_isIdle)
a2053b27 763 wxapp_install_idle_handler();
0e09f76e 764
40c70187 765/*
8cb9f0d0 766 if (win->GetName() == wxT("panel"))
3d2d8da1
RR
767 {
768 wxPrintf( wxT("OnDraw from ") );
769 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
770 wxPrintf( win->GetClassInfo()->GetClassName() );
771 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
772 (int)rect->y,
773 (int)rect->width,
774 (int)rect->height );
775 }
40c70187 776*/
b6fa52db 777
b420fb6a
RR
778 GtkPizza *pizza = GTK_PIZZA (widget);
779
b420fb6a
RR
780 if (!(GTK_WIDGET_APP_PAINTABLE (widget)) &&
781 (pizza->clear_on_draw))
782 {
783 gdk_window_clear_area( pizza->bin_window,
784 rect->x, rect->y, rect->width, rect->height);
785 }
786
787 win->GetUpdateRegion().Union( rect->x, rect->y, rect->width, rect->height );
148cd9b6 788
b420fb6a 789 win->m_clipPaintRegion = TRUE;
304e5625 790
b420fb6a
RR
791 wxEraseEvent eevent( win->GetId() );
792 eevent.SetEventObject( win );
793 win->GetEventHandler()->ProcessEvent(eevent);
148cd9b6 794
b420fb6a
RR
795 wxPaintEvent event( win->GetId() );
796 event.SetEventObject( win );
797 win->GetEventHandler()->ProcessEvent( event );
47d67540 798
b420fb6a 799 win->GetUpdateRegion().Clear();
b6fa52db 800
b420fb6a 801 win->m_clipPaintRegion = FALSE;
304e5625 802
b420fb6a
RR
803
804 GList *children = pizza->children;
805 while (children)
304e5625 806 {
b420fb6a
RR
807 GtkPizzaChild *child = (GtkPizzaChild*) children->data;
808 children = children->next;
809
810 GdkRectangle child_area;
811 if (gtk_widget_intersect (child->widget, rect, &child_area))
812 {
813 gtk_widget_draw (child->widget, &child_area /* (GdkRectangle*) NULL*/ );
814 }
304e5625 815 }
362c6693 816}
c801d85f
KB
817
818//-----------------------------------------------------------------------------
b292e2f5 819// "key_press_event" from any window
c801d85f 820//-----------------------------------------------------------------------------
c801d85f 821
2f2aa628 822static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
47d67540 823{
3ac8d3bc
RR
824 DEBUG_MAIN_THREAD
825
c50f1fb9 826 if (g_isIdle)
a2053b27
RR
827 wxapp_install_idle_handler();
828
829 if (!win->m_hasVMT) return FALSE;
f5e27805 830 if (g_blockEventsOnDrag) return FALSE;
c801d85f 831
3d6f7261 832
7be4c594 833/*
b79395c5
RR
834 wxString tmp;
835 tmp += (char)gdk_event->keyval;
836 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
d1367c3d 837 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
7be4c594 838*/
2daa0ce9 839
b0e813a0
RR
840 int x = 0;
841 int y = 0;
842 GdkModifierType state;
843 if (gdk_event->window) gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
47d67540 844
3017f78d 845 bool ret = FALSE;
148cd9b6 846
74505862 847 long key_code = map_to_unmodified_wx_keysym( gdk_event->keyval );
f0492f7d
RR
848 /* sending unknown key events doesn't really make sense */
849 if (key_code == 0) return FALSE;
850
c50f1fb9 851 wxKeyEvent event( wxEVT_KEY_DOWN );
d1367c3d 852 event.SetTimestamp( gdk_event->time );
f5e27805
RR
853 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
854 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
855 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
856 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
857 event.m_keyCode = key_code;
b0e813a0
RR
858 event.m_scanCode = gdk_event->keyval;
859 event.m_x = x;
860 event.m_y = y;
f5e27805 861 event.SetEventObject( win );
c5b42c87 862 ret = win->GetEventHandler()->ProcessEvent( event );
c50f1fb9 863
88ac883a 864#if wxUSE_ACCEL
f5e27805 865 if (!ret)
47d67540 866 {
f5e27805
RR
867 wxWindow *ancestor = win;
868 while (ancestor)
869 {
870 int command = ancestor->GetAcceleratorTable()->GetCommand( event );
871 if (command != -1)
872 {
873 wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
874 ret = ancestor->GetEventHandler()->ProcessEvent( command_event );
875 break;
876 }
f6bcfd97 877 if (ancestor->IsTopLevel())
b02da6b1 878 break;
f5e27805
RR
879 ancestor = ancestor->GetParent();
880 }
bcf1fa6b 881 }
88ac883a 882#endif // wxUSE_ACCEL
3017f78d 883
d728dd40
KB
884 /* wxMSW doesn't send char events with Alt pressed */
885 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
3017f78d
RR
886 will only be sent if it is not in an accelerator table. */
887 key_code = map_to_wx_keysym( gdk_event->keyval );
148cd9b6 888
3017f78d
RR
889 if ( (!ret) &&
890 (key_code != 0))
d728dd40 891 {
c50f1fb9 892 wxKeyEvent event2( wxEVT_CHAR );
d728dd40
KB
893 event2.SetTimestamp( gdk_event->time );
894 event2.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
895 event2.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
896 event2.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
897 event2.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
898 event2.m_keyCode = key_code;
899 event2.m_scanCode = gdk_event->keyval;
900 event2.m_x = x;
901 event2.m_y = y;
902 event2.SetEventObject( win );
3017f78d 903 ret = win->GetEventHandler()->ProcessEvent( event2 );
d728dd40
KB
904 }
905
053f9cc1 906 /* win is a control: tab can be propagated up */
ca298c88 907 if ( (!ret) &&
5664fc32 908 ((gdk_event->keyval == GDK_Tab) || (gdk_event->keyval == GDK_ISO_Left_Tab)) &&
f6bcfd97
BP
909// VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
910// have this style, yet choose not to process this particular TAB in which
911// case TAB must still work as a navigational character
912#if 0
3da17724 913 (!win->HasFlag(wxTE_PROCESS_TAB)) &&
f6bcfd97 914#endif // 0
b02da6b1
VZ
915 (win->GetParent()) &&
916 (win->GetParent()->HasFlag( wxTAB_TRAVERSAL)) )
b292e2f5
RR
917 {
918 wxNavigationKeyEvent new_event;
8253c7fd 919 new_event.SetEventObject( win->GetParent() );
f03fc89f 920 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
5664fc32 921 new_event.SetDirection( (gdk_event->keyval == GDK_Tab) );
f03fc89f 922 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
b98d804b 923 new_event.SetWindowChange( (gdk_event->state & GDK_CONTROL_MASK) );
b292e2f5 924 new_event.SetCurrentFocus( win );
8253c7fd 925 ret = win->GetParent()->GetEventHandler()->ProcessEvent( new_event );
b292e2f5 926 }
ff8bfdbb 927
801aa178 928 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
ca298c88 929 if ( (!ret) &&
b98d804b
RR
930 (gdk_event->keyval == GDK_Escape) )
931 {
932 wxCommandEvent new_event(wxEVT_COMMAND_BUTTON_CLICKED,wxID_CANCEL);
933 new_event.SetEventObject( win );
934 ret = win->GetEventHandler()->ProcessEvent( new_event );
935 }
c50f1fb9 936
6bc8a1c8 937#if (GTK_MINOR_VERSION > 0)
da048e3d
RR
938 /* Pressing F10 will activate the menu bar of the top frame. */
939 /* Doesn't work. */
3017f78d 940/*
801aa178
RR
941 if ( (!ret) &&
942 (gdk_event->keyval == GDK_F10) )
943 {
944 wxWindow *ancestor = win;
945 while (ancestor)
946 {
947 if (wxIsKindOf(ancestor,wxFrame))
c50f1fb9
VZ
948 {
949 wxFrame *frame = (wxFrame*) ancestor;
801aa178 950 wxMenuBar *menubar = frame->GetMenuBar();
c50f1fb9
VZ
951 if (menubar)
952 {
801aa178 953 wxNode *node = menubar->GetMenus().First();
c50f1fb9
VZ
954 if (node)
955 {
3017f78d
RR
956 wxMenu *firstMenu = (wxMenu*) node->Data();
957 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
958 ret = TRUE;
c50f1fb9
VZ
959 break;
960 }
961 }
962 }
801aa178
RR
963 ancestor = ancestor->GetParent();
964 }
965 }
3017f78d 966*/
6bc8a1c8 967#endif
ca298c88 968
f5e27805
RR
969 if (ret)
970 {
b292e2f5 971 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
f03fc89f 972 return TRUE;
f5e27805 973 }
47d67540 974
034be888 975 return FALSE;
362c6693 976}
c801d85f 977
b666df2c
RR
978//-----------------------------------------------------------------------------
979// "key_release_event" from any window
980//-----------------------------------------------------------------------------
981
982static gint gtk_window_key_release_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
983{
3ac8d3bc
RR
984 DEBUG_MAIN_THREAD
985
c50f1fb9 986 if (g_isIdle)
a2053b27
RR
987 wxapp_install_idle_handler();
988
989 if (!win->m_hasVMT) return FALSE;
b666df2c
RR
990 if (g_blockEventsOnDrag) return FALSE;
991
992/*
d1367c3d
RR
993 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
994 if (gdk_event->state & GDK_SHIFT_MASK)
995 printf( "ShiftDown.\n" );
996 else
997 printf( "ShiftUp.\n" );
998 if (gdk_event->state & GDK_CONTROL_MASK)
999 printf( "ControlDown.\n" );
1000 else
1001 printf( "ControlUp.\n" );
1002 printf( "\n" );
b666df2c
RR
1003*/
1004
74505862 1005 long key_code = map_to_unmodified_wx_keysym( gdk_event->keyval );
c50f1fb9 1006
f0492f7d
RR
1007 /* sending unknown key events doesn't really make sense */
1008 if (key_code == 0) return FALSE;
b666df2c 1009
b0e813a0
RR
1010 int x = 0;
1011 int y = 0;
1012 GdkModifierType state;
1013 if (gdk_event->window) gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
b666df2c
RR
1014
1015 wxKeyEvent event( wxEVT_KEY_UP );
d1367c3d 1016 event.SetTimestamp( gdk_event->time );
b666df2c
RR
1017 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
1018 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
1019 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
1020 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
1021 event.m_keyCode = key_code;
b0e813a0
RR
1022 event.m_scanCode = gdk_event->keyval;
1023 event.m_x = x;
1024 event.m_y = y;
b666df2c
RR
1025 event.SetEventObject( win );
1026
034be888 1027 if (win->GetEventHandler()->ProcessEvent( event ))
b666df2c 1028 {
b98d804b 1029 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_release_event" );
f03fc89f 1030 return TRUE;
b666df2c
RR
1031 }
1032
034be888 1033 return FALSE;
b666df2c
RR
1034}
1035
2daa0ce9
VZ
1036// ----------------------------------------------------------------------------
1037// mouse event processing helper
1038// ----------------------------------------------------------------------------
1039
1040static void AdjustEventButtonState(wxMouseEvent& event)
1041{
1042 // GDK reports the old state of the button for a button press event, but
1043 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1044 // for a LEFT_DOWN event, not FALSE, so we will invert
1045 // left/right/middleDown for the corresponding click events
1046 switch ( event.GetEventType() )
1047 {
1048 case wxEVT_LEFT_DOWN:
1049 case wxEVT_LEFT_DCLICK:
1050 case wxEVT_LEFT_UP:
1051 event.m_leftDown = !event.m_leftDown;
1052 break;
1053
1054 case wxEVT_MIDDLE_DOWN:
1055 case wxEVT_MIDDLE_DCLICK:
1056 case wxEVT_MIDDLE_UP:
1057 event.m_middleDown = !event.m_middleDown;
1058 break;
1059
1060 case wxEVT_RIGHT_DOWN:
1061 case wxEVT_RIGHT_DCLICK:
1062 case wxEVT_RIGHT_UP:
1063 event.m_rightDown = !event.m_rightDown;
1064 break;
1065 }
1066}
1067
c801d85f 1068//-----------------------------------------------------------------------------
2f2aa628
RR
1069// "button_press_event"
1070//-----------------------------------------------------------------------------
c801d85f 1071
2f2aa628 1072static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
903f689b 1073{
3ac8d3bc
RR
1074 DEBUG_MAIN_THREAD
1075
c50f1fb9 1076 if (g_isIdle)
a2053b27
RR
1077 wxapp_install_idle_handler();
1078
1079/*
223d09f6 1080 wxPrintf( wxT("1) OnButtonPress from ") );
a2053b27
RR
1081 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1082 wxPrintf( win->GetClassInfo()->GetClassName() );
223d09f6 1083 wxPrintf( wxT(".\n") );
a2053b27 1084*/
a2053b27 1085 if (!win->m_hasVMT) return FALSE;
f5e27805 1086 if (g_blockEventsOnDrag) return TRUE;
76ed8f8d 1087 if (g_blockEventsOnScroll) return TRUE;
c801d85f 1088
034be888
RR
1089 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
1090
a2053b27 1091 if (win->m_wxwindow)
c801d85f 1092 {
a2053b27 1093 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow) && !GTK_WIDGET_HAS_FOCUS (win->m_wxwindow) )
f5e27805 1094 {
a2053b27 1095 gtk_widget_grab_focus (win->m_wxwindow);
47d67540 1096
c801d85f 1097/*
223d09f6 1098 wxPrintf( wxT("GrabFocus from ") );
f5e27805 1099 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
a2053b27 1100 wxPrintf( win->GetClassInfo()->GetClassName() );
223d09f6 1101 wxPrintf( wxT(".\n") );
c801d85f 1102*/
47d67540 1103
f5e27805 1104 }
362c6693 1105 }
47d67540 1106
2daa0ce9 1107 wxEventType event_type = wxEVT_NULL;
47d67540 1108
f5e27805 1109 if (gdk_event->button == 1)
c801d85f 1110 {
f5e27805
RR
1111 switch (gdk_event->type)
1112 {
1113 case GDK_BUTTON_PRESS: event_type = wxEVT_LEFT_DOWN; break;
1114 case GDK_2BUTTON_PRESS: event_type = wxEVT_LEFT_DCLICK; break;
1115 default: break;
1116 }
362c6693 1117 }
f5e27805 1118 else if (gdk_event->button == 2)
c801d85f 1119 {
f5e27805
RR
1120 switch (gdk_event->type)
1121 {
1122 case GDK_BUTTON_PRESS: event_type = wxEVT_MIDDLE_DOWN; break;
1123 case GDK_2BUTTON_PRESS: event_type = wxEVT_MIDDLE_DCLICK; break;
1124 default: break;
1125 }
362c6693 1126 }
f5e27805 1127 else if (gdk_event->button == 3)
c801d85f 1128 {
f5e27805
RR
1129 switch (gdk_event->type)
1130 {
1131 case GDK_BUTTON_PRESS: event_type = wxEVT_RIGHT_DOWN; break;
1132 case GDK_2BUTTON_PRESS: event_type = wxEVT_RIGHT_DCLICK; break;
1133 default: break;
1134 }
362c6693 1135 }
47d67540 1136
2daa0ce9
VZ
1137 if ( event_type == wxEVT_NULL )
1138 {
1139 // unknown mouse button or click type
1140 return FALSE;
1141 }
1142
f5e27805 1143 wxMouseEvent event( event_type );
d1367c3d 1144 event.SetTimestamp( gdk_event->time );
f5e27805
RR
1145 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
1146 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
1147 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
1148 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
1149 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
1150 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
1151 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
47d67540 1152
13111b2a
VZ
1153 event.m_x = (wxCoord)gdk_event->x;
1154 event.m_y = (wxCoord)gdk_event->y;
47d67540 1155
2daa0ce9
VZ
1156 AdjustEventButtonState(event);
1157
f5e27805
RR
1158 // Some control don't have their own X window and thus cannot get
1159 // any events.
47d67540 1160
72195a0f 1161 if (!g_captureWindow)
2f2aa628 1162 {
b02da6b1
VZ
1163 wxCoord x = event.m_x;
1164 wxCoord y = event.m_y;
2f073eb2
RR
1165 if (win->m_wxwindow)
1166 {
da048e3d 1167 GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
b02da6b1
VZ
1168 x += pizza->xoffset;
1169 y += pizza->yoffset;
2f073eb2
RR
1170 }
1171
db1b4961 1172 wxNode *node = win->GetChildren().First();
f5e27805
RR
1173 while (node)
1174 {
1175 wxWindow *child = (wxWindow*)node->Data();
148cd9b6 1176
f96ac56a 1177 node = node->Next();
b02da6b1
VZ
1178 if (!child->IsShown())
1179 continue;
ff8bfdbb 1180
a2053b27 1181 if (child->m_isStaticBox)
ff8bfdbb
VZ
1182 {
1183 // wxStaticBox is transparent in the box itself
a2053b27
RR
1184 int xx1 = child->m_x;
1185 int yy1 = child->m_y;
1186 int xx2 = child->m_x + child->m_width;
1187 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
1188
1189 // left
1190 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
1191 // right
1192 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1193 // top
1194 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1195 // bottom
1196 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1197 {
1ecc4d80 1198 win = child;
a2053b27
RR
1199 event.m_x -= child->m_x;
1200 event.m_y -= child->m_y;
1ecc4d80 1201 break;
ff8bfdbb
VZ
1202 }
1203
1204 }
1205 else
1206 {
a2053b27 1207 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
2f073eb2
RR
1208 (child->m_x <= x) &&
1209 (child->m_y <= y) &&
1210 (child->m_x+child->m_width >= x) &&
1211 (child->m_y+child->m_height >= y))
1ecc4d80
RR
1212 {
1213 win = child;
a2053b27
RR
1214 event.m_x -= child->m_x;
1215 event.m_y -= child->m_y;
1ecc4d80 1216 break;
ff8bfdbb 1217 }
f5e27805 1218 }
f5e27805 1219 }
2f2aa628 1220 }
ff8bfdbb 1221
f5e27805 1222 event.SetEventObject( win );
47d67540 1223
f5e27805 1224 gs_timeLastClick = gdk_event->time;
47d67540 1225
2f073eb2
RR
1226/*
1227 wxPrintf( wxT("2) OnButtonPress from ") );
1228 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1229 wxPrintf( win->GetClassInfo()->GetClassName() );
1230 wxPrintf( wxT(".\n") );
1231*/
1232
f5e27805 1233 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1234 {
f5e27805 1235 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_press_event" );
f03fc89f 1236 return TRUE;
034be888 1237 }
47d67540 1238
034be888 1239 return FALSE;
362c6693 1240}
c801d85f
KB
1241
1242//-----------------------------------------------------------------------------
97b3455a 1243// "button_release_event"
2f2aa628 1244//-----------------------------------------------------------------------------
c801d85f 1245
2f2aa628 1246static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
47d67540 1247{
3ac8d3bc
RR
1248 DEBUG_MAIN_THREAD
1249
c50f1fb9 1250 if (g_isIdle)
a2053b27
RR
1251 wxapp_install_idle_handler();
1252
1253 if (!win->m_hasVMT) return FALSE;
034be888
RR
1254 if (g_blockEventsOnDrag) return FALSE;
1255 if (g_blockEventsOnScroll) return FALSE;
c801d85f 1256
034be888 1257 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
47d67540 1258
c801d85f 1259/*
f5e27805
RR
1260 printf( "OnButtonRelease from " );
1261 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1262 printf( win->GetClassInfo()->GetClassName() );
1263 printf( ".\n" );
c801d85f 1264*/
47d67540 1265
f5e27805 1266 wxEventType event_type = wxEVT_NULL;
47d67540 1267
f5e27805
RR
1268 switch (gdk_event->button)
1269 {
1270 case 1: event_type = wxEVT_LEFT_UP; break;
1271 case 2: event_type = wxEVT_MIDDLE_UP; break;
1272 case 3: event_type = wxEVT_RIGHT_UP; break;
2daa0ce9 1273 default: return FALSE;
f5e27805 1274 }
47d67540 1275
f5e27805 1276 wxMouseEvent event( event_type );
d1367c3d 1277 event.SetTimestamp( gdk_event->time );
f5e27805
RR
1278 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
1279 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
1280 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
1281 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
1282 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
1283 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
1284 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
13111b2a
VZ
1285 event.m_x = (wxCoord)gdk_event->x;
1286 event.m_y = (wxCoord)gdk_event->y;
f5e27805 1287
2daa0ce9
VZ
1288 AdjustEventButtonState(event);
1289
f5e27805
RR
1290 // Some control don't have their own X window and thus cannot get
1291 // any events.
1292
72195a0f 1293 if (!g_captureWindow)
2f2aa628 1294 {
b02da6b1
VZ
1295 wxCoord x = event.m_x;
1296 wxCoord y = event.m_y;
2f073eb2
RR
1297 if (win->m_wxwindow)
1298 {
da048e3d 1299 GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
b02da6b1
VZ
1300 x += pizza->xoffset;
1301 y += pizza->yoffset;
2f073eb2
RR
1302 }
1303
db1b4961 1304 wxNode *node = win->GetChildren().First();
f5e27805
RR
1305 while (node)
1306 {
1307 wxWindow *child = (wxWindow*)node->Data();
ff8bfdbb 1308
f96ac56a 1309 node = node->Next();
b02da6b1
VZ
1310 if (!child->IsShown())
1311 continue;
f96ac56a 1312
a2053b27 1313 if (child->m_isStaticBox)
ff8bfdbb
VZ
1314 {
1315 // wxStaticBox is transparent in the box itself
a2053b27
RR
1316 int xx1 = child->m_x;
1317 int yy1 = child->m_y;
1318 int xx2 = child->m_x + child->m_width;
1319 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
1320
1321 // left
1322 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
1323 // right
1324 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1325 // top
1326 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1327 // bottom
1328 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1329 {
1ecc4d80 1330 win = child;
a2053b27
RR
1331 event.m_x -= child->m_x;
1332 event.m_y -= child->m_y;
1ecc4d80 1333 break;
ff8bfdbb
VZ
1334 }
1335
1336 }
1337 else
1338 {
a2053b27 1339 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
2f073eb2
RR
1340 (child->m_x <= x) &&
1341 (child->m_y <= y) &&
1342 (child->m_x+child->m_width >= x) &&
1343 (child->m_y+child->m_height >= y))
1ecc4d80
RR
1344 {
1345 win = child;
a2053b27
RR
1346 event.m_x -= child->m_x;
1347 event.m_y -= child->m_y;
1ecc4d80 1348 break;
ff8bfdbb 1349 }
f5e27805 1350 }
f5e27805 1351 }
2f2aa628 1352 }
47d67540 1353
f5e27805 1354 event.SetEventObject( win );
47d67540 1355
f5e27805 1356 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1357 {
f5e27805 1358 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_release_event" );
f03fc89f 1359 return TRUE;
034be888 1360 }
47d67540 1361
034be888 1362 return FALSE;
362c6693 1363}
c801d85f
KB
1364
1365//-----------------------------------------------------------------------------
2f2aa628
RR
1366// "motion_notify_event"
1367//-----------------------------------------------------------------------------
c801d85f 1368
2f2aa628 1369static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win )
47d67540 1370{
3ac8d3bc
RR
1371 DEBUG_MAIN_THREAD
1372
c50f1fb9 1373 if (g_isIdle)
a2053b27
RR
1374 wxapp_install_idle_handler();
1375
1376 if (!win->m_hasVMT) return FALSE;
034be888
RR
1377 if (g_blockEventsOnDrag) return FALSE;
1378 if (g_blockEventsOnScroll) return FALSE;
148cd9b6 1379
034be888
RR
1380 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
1381
ff8bfdbb 1382 if (gdk_event->is_hint)
aae24d21 1383 {
f7a11f8c
RR
1384 int x = 0;
1385 int y = 0;
1386 GdkModifierType state;
1387 gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
1388 gdk_event->x = x;
1389 gdk_event->y = y;
aae24d21 1390 }
ff8bfdbb 1391
c801d85f 1392/*
e380f72b
RR
1393 printf( "OnMotion from " );
1394 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1395 printf( win->GetClassInfo()->GetClassName() );
1396 printf( ".\n" );
aae24d21 1397*/
47d67540 1398
e380f72b 1399 wxMouseEvent event( wxEVT_MOTION );
d1367c3d 1400 event.SetTimestamp( gdk_event->time );
e380f72b
RR
1401 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
1402 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
1403 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
1404 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
1405 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
1406 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
1407 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
1408
13111b2a
VZ
1409 event.m_x = (wxCoord)gdk_event->x;
1410 event.m_y = (wxCoord)gdk_event->y;
e380f72b
RR
1411
1412 // Some control don't have their own X window and thus cannot get
1413 // any events.
1414
72195a0f 1415 if (!g_captureWindow)
2f2aa628 1416 {
b02da6b1
VZ
1417 wxCoord x = event.m_x;
1418 wxCoord y = event.m_y;
2f073eb2
RR
1419 if (win->m_wxwindow)
1420 {
da048e3d 1421 GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
b02da6b1
VZ
1422 x += pizza->xoffset;
1423 y += pizza->yoffset;
2f073eb2
RR
1424 }
1425
db1b4961 1426 wxNode *node = win->GetChildren().First();
e380f72b
RR
1427 while (node)
1428 {
1429 wxWindow *child = (wxWindow*)node->Data();
ff8bfdbb 1430
f96ac56a 1431 node = node->Next();
b02da6b1
VZ
1432 if (!child->IsShown())
1433 continue;
f96ac56a 1434
a2053b27 1435 if (child->m_isStaticBox)
ff8bfdbb
VZ
1436 {
1437 // wxStaticBox is transparent in the box itself
a2053b27
RR
1438 int xx1 = child->m_x;
1439 int yy1 = child->m_y;
1440 int xx2 = child->m_x + child->m_width;
1441 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
1442
1443 // left
1444 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
1445 // right
1446 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1447 // top
1448 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1449 // bottom
1450 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1451 {
1ecc4d80 1452 win = child;
a2053b27
RR
1453 event.m_x -= child->m_x;
1454 event.m_y -= child->m_y;
1ecc4d80 1455 break;
ff8bfdbb
VZ
1456 }
1457
1458 }
1459 else
1460 {
a2053b27 1461 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
2f073eb2
RR
1462 (child->m_x <= x) &&
1463 (child->m_y <= y) &&
1464 (child->m_x+child->m_width >= x) &&
1465 (child->m_y+child->m_height >= y))
1ecc4d80
RR
1466 {
1467 win = child;
a2053b27
RR
1468 event.m_x -= child->m_x;
1469 event.m_y -= child->m_y;
1ecc4d80 1470 break;
ff8bfdbb 1471 }
e380f72b 1472 }
e380f72b 1473 }
2f2aa628 1474 }
47d67540 1475
e380f72b 1476 event.SetEventObject( win );
47d67540 1477
e380f72b 1478 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1479 {
e380f72b 1480 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "motion_notify_event" );
f03fc89f 1481 return TRUE;
034be888 1482 }
47d67540 1483
034be888 1484 return FALSE;
362c6693 1485}
c801d85f
KB
1486
1487//-----------------------------------------------------------------------------
2f2aa628
RR
1488// "focus_in_event"
1489//-----------------------------------------------------------------------------
c801d85f 1490
2f2aa628 1491static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
c801d85f 1492{
3ac8d3bc
RR
1493 DEBUG_MAIN_THREAD
1494
c50f1fb9 1495 if (g_isIdle)
a2053b27
RR
1496 wxapp_install_idle_handler();
1497
1498 if (!win->m_hasVMT) return FALSE;
034be888 1499 if (g_blockEventsOnDrag) return FALSE;
ff8bfdbb 1500
148cd9b6
VZ
1501 switch ( g_sendActivateEvent )
1502 {
1503 case -1:
1504 // we've got focus from outside, synthtize wxActivateEvent
1505 g_sendActivateEvent = 1;
1506 break;
1507
1508 case 0:
1509 // another our window just lost focus, it was already ours before
1510 // - don't send any wxActivateEvent
1511 g_sendActivateEvent = -1;
1512 break;
1513 }
1514
b292e2f5 1515 g_focusWindow = win;
ff8bfdbb 1516
c801d85f 1517/*
f03fc89f 1518 printf( "OnSetFocus from " );
e380f72b 1519 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
f03fc89f
VZ
1520 printf( win->GetClassInfo()->GetClassName() );
1521 printf( " " );
1522 printf( WXSTRINGCAST win->GetLabel() );
1523 printf( ".\n" );
c801d85f 1524*/
47d67540 1525
3da17724
RR
1526 wxPanel *panel = wxDynamicCast(win->GetParent(), wxPanel);
1527 if (panel)
1528 {
1529 panel->SetLastFocus(win);
1530 }
148cd9b6 1531
b79395c5
RR
1532#ifdef HAVE_XIM
1533 if (win->m_ic)
1534 gdk_im_begin(win->m_ic, win->m_wxwindow->window);
1535#endif
1536
f6bcfd97
BP
1537#ifdef wxUSE_CARET
1538 // caret needs to be informed about focus change
1539 wxCaret *caret = win->GetCaret();
1540 if ( caret )
1541 {
1542 caret->OnSetFocus();
1543 }
1544#endif // wxUSE_CARET
1545
e380f72b
RR
1546 wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
1547 event.SetEventObject( win );
47d67540 1548
e380f72b 1549 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1550 {
e380f72b 1551 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
034be888
RR
1552 return TRUE;
1553 }
ca298c88 1554
034be888 1555 return FALSE;
362c6693 1556}
c801d85f
KB
1557
1558//-----------------------------------------------------------------------------
2f2aa628
RR
1559// "focus_out_event"
1560//-----------------------------------------------------------------------------
c801d85f 1561
2f2aa628 1562static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
c801d85f 1563{
3ac8d3bc
RR
1564 DEBUG_MAIN_THREAD
1565
c50f1fb9 1566 if (g_isIdle)
a2053b27
RR
1567 wxapp_install_idle_handler();
1568
1569 if (!win->m_hasVMT) return FALSE;
034be888 1570 if (g_blockEventsOnDrag) return FALSE;
ca298c88 1571
148cd9b6
VZ
1572 // if the focus goes out of our app alltogether, OnIdle() will send
1573 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1574 // g_sendActivateEvent to -1
1575 g_sendActivateEvent = 0;
1576
f6bcfd97
BP
1577 wxWindow *winFocus = FindFocusedChild(win);
1578 if ( winFocus )
1579 win = winFocus;
1580
148cd9b6
VZ
1581 g_focusWindow = (wxWindow *)NULL;
1582
c801d85f 1583/*
f03fc89f 1584 printf( "OnKillFocus from " );
e380f72b 1585 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
f03fc89f
VZ
1586 printf( win->GetClassInfo()->GetClassName() );
1587 printf( ".\n" );
c801d85f 1588*/
47d67540 1589
b79395c5
RR
1590#ifdef HAVE_XIM
1591 if (win->m_ic)
1592 gdk_im_end();
1593#endif
1594
f6bcfd97
BP
1595#ifdef wxUSE_CARET
1596 // caret needs to be informed about focus change
1597 wxCaret *caret = win->GetCaret();
1598 if ( caret )
1599 {
1600 caret->OnKillFocus();
1601 }
1602#endif // wxUSE_CARET
1603
e380f72b
RR
1604 wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
1605 event.SetEventObject( win );
47d67540 1606
e380f72b 1607 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1608 {
e380f72b 1609 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
034be888
RR
1610 return TRUE;
1611 }
ca298c88 1612
034be888 1613 return FALSE;
362c6693 1614}
c801d85f 1615
b4071e91
RR
1616//-----------------------------------------------------------------------------
1617// "enter_notify_event"
1618//-----------------------------------------------------------------------------
1619
1620static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
1621{
3ac8d3bc
RR
1622 DEBUG_MAIN_THREAD
1623
c50f1fb9 1624 if (g_isIdle)
a2053b27 1625 wxapp_install_idle_handler();
ca298c88 1626
a2053b27
RR
1627 if (!win->m_hasVMT) return FALSE;
1628 if (g_blockEventsOnDrag) return FALSE;
47d67540 1629
a2053b27 1630 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
b292e2f5 1631
e380f72b 1632 wxMouseEvent event( wxEVT_ENTER_WINDOW );
6bc8a1c8 1633#if (GTK_MINOR_VERSION > 0)
d1367c3d 1634 event.SetTimestamp( gdk_event->time );
6bc8a1c8 1635#endif
e380f72b 1636 event.SetEventObject( win );
ff8bfdbb 1637
4a33eba6
RR
1638 int x = 0;
1639 int y = 0;
1640 GdkModifierType state = (GdkModifierType)0;
ff8bfdbb 1641
a2053b27 1642 gdk_window_get_pointer( widget->window, &x, &y, &state );
ff8bfdbb 1643
4a33eba6
RR
1644 event.m_shiftDown = (state & GDK_SHIFT_MASK);
1645 event.m_controlDown = (state & GDK_CONTROL_MASK);
1646 event.m_altDown = (state & GDK_MOD1_MASK);
1647 event.m_metaDown = (state & GDK_MOD2_MASK);
1648 event.m_leftDown = (state & GDK_BUTTON1_MASK);
1649 event.m_middleDown = (state & GDK_BUTTON2_MASK);
1650 event.m_rightDown = (state & GDK_BUTTON3_MASK);
1651
13111b2a
VZ
1652 event.m_x = x;
1653 event.m_y = y;
ff8bfdbb 1654
e380f72b 1655 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1656 {
e380f72b 1657 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "enter_notify_event" );
034be888
RR
1658 return TRUE;
1659 }
ca298c88 1660
034be888 1661 return FALSE;
b4071e91 1662}
47d67540 1663
b4071e91
RR
1664//-----------------------------------------------------------------------------
1665// "leave_notify_event"
1666//-----------------------------------------------------------------------------
1667
1668static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
1669{
3ac8d3bc
RR
1670 DEBUG_MAIN_THREAD
1671
c50f1fb9 1672 if (g_isIdle)
a2053b27 1673 wxapp_install_idle_handler();
acfd422a 1674
a2053b27
RR
1675 if (!win->m_hasVMT) return FALSE;
1676 if (g_blockEventsOnDrag) return FALSE;
b292e2f5 1677
a2053b27 1678 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
c50f1fb9 1679
e380f72b 1680 wxMouseEvent event( wxEVT_LEAVE_WINDOW );
6bc8a1c8 1681#if (GTK_MINOR_VERSION > 0)
d1367c3d 1682 event.SetTimestamp( gdk_event->time );
6bc8a1c8 1683#endif
e380f72b 1684 event.SetEventObject( win );
47d67540 1685
4a33eba6
RR
1686 int x = 0;
1687 int y = 0;
1688 GdkModifierType state = (GdkModifierType)0;
ff8bfdbb 1689
4a33eba6 1690 gdk_window_get_pointer( widget->window, &x, &y, &state );
ff8bfdbb 1691
4a33eba6
RR
1692 event.m_shiftDown = (state & GDK_SHIFT_MASK);
1693 event.m_controlDown = (state & GDK_CONTROL_MASK);
1694 event.m_altDown = (state & GDK_MOD1_MASK);
1695 event.m_metaDown = (state & GDK_MOD2_MASK);
1696 event.m_leftDown = (state & GDK_BUTTON1_MASK);
1697 event.m_middleDown = (state & GDK_BUTTON2_MASK);
1698 event.m_rightDown = (state & GDK_BUTTON3_MASK);
1699
13111b2a
VZ
1700 event.m_x = x;
1701 event.m_y = y;
ff8bfdbb 1702
e380f72b 1703 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1704 {
e380f72b 1705 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "leave_notify_event" );
034be888
RR
1706 return TRUE;
1707 }
ca298c88 1708
034be888 1709 return FALSE;
b4071e91 1710}
47d67540 1711
c801d85f 1712//-----------------------------------------------------------------------------
2f2aa628
RR
1713// "value_changed" from m_vAdjust
1714//-----------------------------------------------------------------------------
c801d85f 1715
5e014a0c 1716static void gtk_window_vscroll_callback( GtkAdjustment *adjust, wxWindow *win )
c801d85f 1717{
3ac8d3bc
RR
1718 DEBUG_MAIN_THREAD
1719
c50f1fb9 1720 if (g_isIdle)
a2053b27 1721 wxapp_install_idle_handler();
c801d85f 1722
a2053b27 1723 if (g_blockEventsOnDrag) return;
47d67540 1724
a2053b27 1725 if (!win->m_hasVMT) return;
148cd9b6 1726
5e014a0c 1727 float diff = adjust->value - win->m_oldVerticalPos;
e380f72b 1728 if (fabs(diff) < 0.2) return;
148cd9b6 1729
5e014a0c 1730 win->m_oldVerticalPos = adjust->value;
47d67540 1731
5e014a0c
RR
1732 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
1733 GtkRange *range = GTK_RANGE( scrolledWindow->vscrollbar );
148cd9b6 1734
5e014a0c
RR
1735 wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
1736 if (range->scroll_type == GTK_SCROLL_STEP_BACKWARD) command = wxEVT_SCROLLWIN_LINEUP;
1737 else if (range->scroll_type == GTK_SCROLL_STEP_FORWARD) command = wxEVT_SCROLLWIN_LINEDOWN;
1738 else if (range->scroll_type == GTK_SCROLL_PAGE_BACKWARD) command = wxEVT_SCROLLWIN_PAGEUP;
1739 else if (range->scroll_type == GTK_SCROLL_PAGE_FORWARD) command = wxEVT_SCROLLWIN_PAGEDOWN;
148cd9b6 1740
5e014a0c 1741 int value = (int)(adjust->value+0.5);
c801d85f 1742
c5b42c87 1743 wxScrollWinEvent event( command, value, wxVERTICAL );
e380f72b
RR
1744 event.SetEventObject( win );
1745 win->GetEventHandler()->ProcessEvent( event );
362c6693 1746}
c801d85f
KB
1747
1748//-----------------------------------------------------------------------------
2f2aa628
RR
1749// "value_changed" from m_hAdjust
1750//-----------------------------------------------------------------------------
c801d85f 1751
5e014a0c 1752static void gtk_window_hscroll_callback( GtkAdjustment *adjust, wxWindow *win )
47d67540 1753{
3ac8d3bc
RR
1754 DEBUG_MAIN_THREAD
1755
c50f1fb9 1756 if (g_isIdle)
a2053b27 1757 wxapp_install_idle_handler();
47d67540 1758
a2053b27
RR
1759 if (g_blockEventsOnDrag) return;
1760 if (!win->m_hasVMT) return;
47d67540 1761
5e014a0c 1762 float diff = adjust->value - win->m_oldHorizontalPos;
e380f72b 1763 if (fabs(diff) < 0.2) return;
148cd9b6 1764
5e014a0c 1765 win->m_oldHorizontalPos = adjust->value;
8bbe427f 1766
5e014a0c
RR
1767 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
1768 GtkRange *range = GTK_RANGE( scrolledWindow->hscrollbar );
148cd9b6 1769
5e014a0c
RR
1770 wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
1771 if (range->scroll_type == GTK_SCROLL_STEP_BACKWARD) command = wxEVT_SCROLLWIN_LINEUP;
1772 else if (range->scroll_type == GTK_SCROLL_STEP_FORWARD) command = wxEVT_SCROLLWIN_LINEDOWN;
1773 else if (range->scroll_type == GTK_SCROLL_PAGE_BACKWARD) command = wxEVT_SCROLLWIN_PAGEUP;
1774 else if (range->scroll_type == GTK_SCROLL_PAGE_FORWARD) command = wxEVT_SCROLLWIN_PAGEDOWN;
148cd9b6 1775
5e014a0c 1776 int value = (int)(adjust->value+0.5);
47d67540 1777
c5b42c87 1778 wxScrollWinEvent event( command, value, wxHORIZONTAL );
e380f72b
RR
1779 event.SetEventObject( win );
1780 win->GetEventHandler()->ProcessEvent( event );
362c6693 1781}
c801d85f 1782
cb43b372
RR
1783//-----------------------------------------------------------------------------
1784// "button_press_event" from scrollbar
1785//-----------------------------------------------------------------------------
1786
2a23d363
RR
1787static gint gtk_scrollbar_button_press_callback( GtkRange *widget,
1788 GdkEventButton *gdk_event,
846e1424 1789 wxWindow *win)
cb43b372 1790{
3ac8d3bc
RR
1791 DEBUG_MAIN_THREAD
1792
c50f1fb9 1793 if (g_isIdle)
a2053b27
RR
1794 wxapp_install_idle_handler();
1795
d6d26e04 1796
5b8a521e 1797 g_blockEventsOnScroll = TRUE;
2a23d363 1798 win->m_isScrolling = (gdk_event->window == widget->slider);
47d67540 1799
e380f72b 1800 return FALSE;
cb43b372
RR
1801}
1802
1803//-----------------------------------------------------------------------------
1804// "button_release_event" from scrollbar
1805//-----------------------------------------------------------------------------
1806
88413fec 1807static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
8bbe427f 1808 GdkEventButton *WXUNUSED(gdk_event),
846e1424 1809 wxWindow *win)
cb43b372 1810{
3ac8d3bc
RR
1811 DEBUG_MAIN_THREAD
1812
1ecc4d80 1813// don't test here as we can release the mouse while being over
5e014a0c 1814// a different window than the slider
76ed8f8d
RR
1815//
1816// if (gdk_event->window != widget->slider) return FALSE;
cb43b372 1817
5b8a521e 1818 g_blockEventsOnScroll = FALSE;
47d67540 1819
2a23d363 1820 if (win->m_isScrolling)
88413fec 1821 {
d6d26e04 1822 wxEventType command = wxEVT_SCROLLWIN_THUMBRELEASE;
2a23d363
RR
1823 int value = -1;
1824 int dir = -1;
2daa0ce9 1825
2a23d363
RR
1826 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
1827 if (widget == GTK_RANGE(scrolledWindow->hscrollbar))
1828 {
1829 value = (int)(win->m_hAdjust->value+0.5);
1830 dir = wxHORIZONTAL;
1831 }
1832 if (widget == GTK_RANGE(scrolledWindow->vscrollbar))
1833 {
1834 value = (int)(win->m_vAdjust->value+0.5);
1835 dir = wxVERTICAL;
1836 }
2daa0ce9 1837
2a23d363 1838 wxScrollWinEvent event( command, value, dir );
2a23d363
RR
1839 event.SetEventObject( win );
1840 win->GetEventHandler()->ProcessEvent( event );
88413fec
RR
1841 }
1842
2a23d363 1843 win->m_isScrolling = FALSE;
2daa0ce9 1844
e380f72b 1845 return FALSE;
cb43b372
RR
1846}
1847
f03fc89f
VZ
1848// ----------------------------------------------------------------------------
1849// this wxWindowBase function is implemented here (in platform-specific file)
1850// because it is static and so couldn't be made virtual
1851// ----------------------------------------------------------------------------
2b07d713 1852
f03fc89f 1853wxWindow *wxWindowBase::FindFocus()
2b07d713 1854{
f03fc89f 1855 return g_focusWindow;
2b07d713 1856}
ca298c88 1857
a2053b27
RR
1858//-----------------------------------------------------------------------------
1859// "realize" from m_widget
1860//-----------------------------------------------------------------------------
1861
b79395c5
RR
1862/* We cannot set colours and fonts before the widget has
1863 been realized, so we do this directly after realization. */
a2053b27
RR
1864
1865static gint
63081513 1866gtk_window_realized_callback( GtkWidget *WXUNUSED(m_widget), wxWindow *win )
a2053b27 1867{
3ac8d3bc
RR
1868 DEBUG_MAIN_THREAD
1869
c50f1fb9 1870 if (g_isIdle)
a2053b27
RR
1871 wxapp_install_idle_handler();
1872
739730ca
RR
1873 if (win->m_delayedBackgroundColour)
1874 win->SetBackgroundColour( win->GetBackgroundColour() );
a2053b27 1875
739730ca
RR
1876 if (win->m_delayedForegroundColour)
1877 win->SetForegroundColour( win->GetForegroundColour() );
a2053b27 1878
3c679789
RR
1879 wxWindowCreateEvent event( win );
1880 event.SetEventObject( win );
1881 win->GetEventHandler()->ProcessEvent( event );
3d2d8da1 1882
a2053b27
RR
1883 return FALSE;
1884}
1885
b79395c5
RR
1886//-----------------------------------------------------------------------------
1887// "size_allocate"
1888//-----------------------------------------------------------------------------
1889
8f75cb6c 1890static
adc1999b
RR
1891void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
1892 GtkAllocation *WXUNUSED(alloc),
8f75cb6c
RR
1893 wxWindow *win )
1894{
1895 if (g_isIdle)
1896 wxapp_install_idle_handler();
2daa0ce9 1897
5b8a521e 1898 if (!win->m_hasScrolling) return;
2daa0ce9 1899
5b8a521e
RR
1900 int client_width = 0;
1901 int client_height = 0;
1902 win->GetClientSize( &client_width, &client_height );
1903 if ((client_width == win->m_oldClientWidth) && (client_height == win->m_oldClientHeight))
1904 return;
2daa0ce9 1905
5b8a521e
RR
1906 win->m_oldClientWidth = client_width;
1907 win->m_oldClientHeight = client_height;
2daa0ce9 1908
5b8a521e
RR
1909 if (!win->m_nativeSizeEvent)
1910 {
1911 wxSizeEvent event( win->GetSize(), win->GetId() );
1912 event.SetEventObject( win );
1913 win->GetEventHandler()->ProcessEvent( event );
1914 }
8f75cb6c
RR
1915}
1916
1917
3ed2e7ce
VZ
1918#ifdef HAVE_XIM
1919 #define WXUNUSED_UNLESS_XIM(param) param
1920#else
1921 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1922#endif
1923
b79395c5
RR
1924/* Resize XIM window */
1925
3ed2e7ce 1926static
8f75cb6c
RR
1927void gtk_wxwindow_size_callback( GtkWidget* WXUNUSED_UNLESS_XIM(widget),
1928 GtkAllocation* WXUNUSED_UNLESS_XIM(alloc),
1929 wxWindow* WXUNUSED_UNLESS_XIM(win) )
b79395c5
RR
1930{
1931 if (g_isIdle)
1932 wxapp_install_idle_handler();
2daa0ce9 1933
9a8c7620 1934#ifdef HAVE_XIM
b79395c5
RR
1935 if (!win->m_ic)
1936 return;
1937
b79395c5
RR
1938 if (gdk_ic_get_style (win->m_ic) & GDK_IM_PREEDIT_POSITION)
1939 {
1940 gint width, height;
1941
3ed2e7ce 1942 gdk_window_get_size (widget->window, &width, &height);
b79395c5
RR
1943 win->m_icattr->preedit_area.width = width;
1944 win->m_icattr->preedit_area.height = height;
1945 gdk_ic_set_attr (win->m_ic, win->m_icattr, GDK_IC_PREEDIT_AREA);
1946 }
9a8c7620 1947#endif // HAVE_XIM
b79395c5
RR
1948}
1949
63081513
RR
1950//-----------------------------------------------------------------------------
1951// "realize" from m_wxwindow
1952//-----------------------------------------------------------------------------
1953
1954/* Initialize XIM support */
1955
1956static gint
3ed2e7ce
VZ
1957gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
1958 wxWindow * WXUNUSED_UNLESS_XIM(win) )
63081513
RR
1959{
1960 if (g_isIdle)
1961 wxapp_install_idle_handler();
1962
d06800f1 1963#ifdef HAVE_XIM
63081513
RR
1964 if (win->m_ic) return FALSE;
1965 if (!widget) return FALSE;
1966 if (!gdk_im_ready()) return FALSE;
1967
1968 win->m_icattr = gdk_ic_attr_new();
1969 if (!win->m_icattr) return FALSE;
2daa0ce9 1970
63081513
RR
1971 gint width, height;
1972 GdkEventMask mask;
1973 GdkColormap *colormap;
1974 GdkICAttr *attr = win->m_icattr;
b58b1dfc 1975 unsigned attrmask = GDK_IC_ALL_REQ;
63081513 1976 GdkIMStyle style;
b79395c5
RR
1977 GdkIMStyle supported_style = (GdkIMStyle)
1978 (GDK_IM_PREEDIT_NONE |
63081513
RR
1979 GDK_IM_PREEDIT_NOTHING |
1980 GDK_IM_PREEDIT_POSITION |
1981 GDK_IM_STATUS_NONE |
b79395c5 1982 GDK_IM_STATUS_NOTHING);
63081513
RR
1983
1984 if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
b79395c5 1985 supported_style = (GdkIMStyle)(supported_style & ~GDK_IM_PREEDIT_POSITION);
63081513
RR
1986
1987 attr->style = style = gdk_im_decide_style (supported_style);
1988 attr->client_window = widget->window;
1989
1990 if ((colormap = gtk_widget_get_colormap (widget)) !=
1991 gtk_widget_get_default_colormap ())
1992 {
b420fb6a
RR
1993 attrmask |= GDK_IC_PREEDIT_COLORMAP;
1994 attr->preedit_colormap = colormap;
63081513 1995 }
2daa0ce9 1996
63081513
RR
1997 attrmask |= GDK_IC_PREEDIT_FOREGROUND;
1998 attrmask |= GDK_IC_PREEDIT_BACKGROUND;
1999 attr->preedit_foreground = widget->style->fg[GTK_STATE_NORMAL];
2000 attr->preedit_background = widget->style->base[GTK_STATE_NORMAL];
2001
2002 switch (style & GDK_IM_PREEDIT_MASK)
2003 {
2004 case GDK_IM_PREEDIT_POSITION:
2005 if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
2006 {
2007 g_warning ("over-the-spot style requires fontset");
2008 break;
2009 }
2010
2011 gdk_window_get_size (widget->window, &width, &height);
2012
2013 attrmask |= GDK_IC_PREEDIT_POSITION_REQ;
2014 attr->spot_location.x = 0;
2015 attr->spot_location.y = height;
2016 attr->preedit_area.x = 0;
2017 attr->preedit_area.y = 0;
2018 attr->preedit_area.width = width;
2019 attr->preedit_area.height = height;
2020 attr->preedit_fontset = widget->style->font;
2021
2022 break;
b79395c5 2023 }
2daa0ce9 2024
b58b1dfc 2025 win->m_ic = gdk_ic_new (attr, (GdkICAttributesType)attrmask);
2daa0ce9 2026
63081513
RR
2027 if (win->m_ic == NULL)
2028 g_warning ("Can't create input context.");
2029 else
2030 {
2031 mask = gdk_window_get_events (widget->window);
b79395c5 2032 mask = (GdkEventMask)(mask | gdk_ic_get_events (win->m_ic));
63081513
RR
2033 gdk_window_set_events (widget->window, mask);
2034
2035 if (GTK_WIDGET_HAS_FOCUS(widget))
2036 gdk_im_begin (win->m_ic, widget->window);
2037 }
63081513
RR
2038#endif
2039
2040 return FALSE;
2041}
2042
6ca41e57
RR
2043//-----------------------------------------------------------------------------
2044// InsertChild for wxWindow.
2045//-----------------------------------------------------------------------------
2046
b1170810
RR
2047/* Callback for wxWindow. This very strange beast has to be used because
2048 * C++ has no virtual methods in a constructor. We have to emulate a
2049 * virtual function here as wxNotebook requires a different way to insert
2050 * a child in it. I had opted for creating a wxNotebookPage window class
2051 * which would have made this superfluous (such in the MDI window system),
2052 * but no-one was listening to me... */
6ca41e57
RR
2053
2054static void wxInsertChildInWindow( wxWindow* parent, wxWindow* child )
2055{
bf0c00c6
RR
2056 /* the window might have been scrolled already, do we
2057 have to adapt the position */
da048e3d
RR
2058 GtkPizza *pizza = GTK_PIZZA(parent->m_wxwindow);
2059 child->m_x += pizza->xoffset;
2060 child->m_y += pizza->yoffset;
148cd9b6 2061
da048e3d 2062 gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
a2053b27
RR
2063 GTK_WIDGET(child->m_widget),
2064 child->m_x,
2065 child->m_y,
2066 child->m_width,
2067 child->m_height );
6ca41e57
RR
2068}
2069
bbe0af5b
RR
2070//-----------------------------------------------------------------------------
2071// global functions
2072//-----------------------------------------------------------------------------
2073
2074wxWindow* wxGetActiveWindow()
2075{
f03fc89f 2076 return g_focusWindow;
bbe0af5b
RR
2077}
2078
c801d85f 2079//-----------------------------------------------------------------------------
2f2aa628 2080// wxWindow
c801d85f
KB
2081//-----------------------------------------------------------------------------
2082
f03fc89f 2083IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
c801d85f 2084
68995f26 2085void wxWindow::Init()
c801d85f 2086{
f03fc89f
VZ
2087 // common init
2088 InitBase();
68995f26 2089
f03fc89f 2090 // GTK specific
a2053b27 2091 m_widget = (GtkWidget *) NULL;
e380f72b 2092 m_wxwindow = (GtkWidget *) NULL;
8bbe427f 2093
f03fc89f 2094 // position/size
a2053b27
RR
2095 m_x = 0;
2096 m_y = 0;
2097 m_width = 0;
e380f72b 2098 m_height = 0;
8bbe427f 2099
e380f72b
RR
2100 m_sizeSet = FALSE;
2101 m_hasVMT = FALSE;
2102 m_needParent = TRUE;
31c6b4fc 2103 m_isBeingDeleted = FALSE;
148cd9b6 2104
147bc491 2105 m_noExpose = FALSE;
30760ce7 2106 m_nativeSizeEvent = FALSE;
148cd9b6 2107
a2053b27 2108 m_hasScrolling = FALSE;
846e1424 2109 m_isScrolling = FALSE;
f03fc89f 2110
a2053b27 2111 m_hAdjust = (GtkAdjustment*) NULL;
e380f72b 2112 m_vAdjust = (GtkAdjustment*) NULL;
a2053b27 2113 m_oldHorizontalPos = 0.0;
e380f72b 2114 m_oldVerticalPos = 0.0;
8bbe427f 2115
e380f72b 2116 m_resizing = FALSE;
e380f72b 2117 m_widgetStyle = (GtkStyle*) NULL;
8bbe427f 2118
ddb6bc71 2119 m_insertCallback = (wxInsertChildFunction) NULL;
8bbe427f 2120
1ecc4d80 2121 m_isStaticBox = FALSE;
953704c1 2122 m_isRadioButton = FALSE;
54517652 2123 m_isFrame = FALSE;
b292e2f5 2124 m_acceptsFocus = FALSE;
148cd9b6 2125
b6fa52db 2126 m_clipPaintRegion = FALSE;
b6fa52db 2127
5e014a0c 2128 m_cursor = *wxSTANDARD_CURSOR;
2daa0ce9 2129
f6bcfd97
BP
2130 m_delayedForegroundColour = FALSE;
2131 m_delayedBackgroundColour = FALSE;
2132
63081513
RR
2133#ifdef HAVE_XIM
2134 m_ic = (GdkIC*) NULL;
2135 m_icattr = (GdkICAttr*) NULL;
2136#endif
362c6693 2137}
c801d85f 2138
68995f26
VZ
2139wxWindow::wxWindow()
2140{
2141 Init();
2142}
2143
6ca41e57 2144wxWindow::wxWindow( wxWindow *parent, wxWindowID id,
e380f72b
RR
2145 const wxPoint &pos, const wxSize &size,
2146 long style, const wxString &name )
6ca41e57 2147{
68995f26
VZ
2148 Init();
2149
e380f72b 2150 Create( parent, id, pos, size, style, name );
6ca41e57 2151}
8bbe427f 2152
debe6624 2153bool wxWindow::Create( wxWindow *parent, wxWindowID id,
e380f72b
RR
2154 const wxPoint &pos, const wxSize &size,
2155 long style, const wxString &name )
c801d85f 2156{
4dcaf11a
RR
2157 if (!PreCreation( parent, pos, size ) ||
2158 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
2159 {
223d09f6 2160 wxFAIL_MSG( wxT("wxWindow creation failed") );
b02da6b1 2161 return FALSE;
4dcaf11a 2162 }
47d67540 2163
ddb6bc71 2164 m_insertCallback = wxInsertChildInWindow;
b6fa52db 2165
e380f72b 2166 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
38c7b3d3 2167 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
ff8bfdbb 2168
f03fc89f 2169 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget);
47d67540 2170
dd00f3f6 2171 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
e380f72b 2172 scroll_class->scrollbar_spacing = 0;
47d67540 2173
f03fc89f 2174 gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
47d67540 2175
f03fc89f
VZ
2176 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->hscrollbar) );
2177 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->vscrollbar) );
47d67540 2178
da048e3d 2179 m_wxwindow = gtk_pizza_new();
38c7b3d3 2180
034be888 2181 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
58dea4b0 2182
034be888 2183#if (GTK_MINOR_VERSION > 0)
da048e3d 2184 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
b292e2f5 2185
f03fc89f 2186 if (HasFlag(wxRAISED_BORDER))
034be888 2187 {
da048e3d 2188 gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_OUT );
034be888 2189 }
f03fc89f 2190 else if (HasFlag(wxSUNKEN_BORDER))
034be888 2191 {
da048e3d 2192 gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_IN );
5e014a0c
RR
2193 }
2194 else if (HasFlag(wxSIMPLE_BORDER))
2195 {
da048e3d 2196 gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_THIN );
034be888
RR
2197 }
2198 else
2199 {
da048e3d 2200 gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_NONE );
034be888 2201 }
f03fc89f
VZ
2202#else // GTK_MINOR_VERSION == 0
2203 GtkViewport *viewport = GTK_VIEWPORT(scrolledWindow->viewport);
b292e2f5 2204
f03fc89f 2205 if (HasFlag(wxRAISED_BORDER))
e380f72b
RR
2206 {
2207 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
2208 }
f03fc89f 2209 else if (HasFlag(wxSUNKEN_BORDER))
e380f72b
RR
2210 {
2211 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
2212 }
2213 else
2214 {
2215 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
2216 }
f03fc89f 2217#endif // GTK_MINOR_VERSION
47d67540 2218
3da17724
RR
2219 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
2220 m_acceptsFocus = TRUE;
ca298c88 2221
034be888 2222#if (GTK_MINOR_VERSION == 0)
e380f72b
RR
2223 // shut the viewport up
2224 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2225 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
f03fc89f 2226#endif // GTK_MINOR_VERSION == 0
e380f72b
RR
2227
2228 // I _really_ don't want scrollbars in the beginning
a2053b27
RR
2229 m_vAdjust->lower = 0.0;
2230 m_vAdjust->upper = 1.0;
2231 m_vAdjust->value = 0.0;
2232 m_vAdjust->step_increment = 1.0;
2233 m_vAdjust->page_increment = 1.0;
2234 m_vAdjust->page_size = 5.0;
2235 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
2236 m_hAdjust->lower = 0.0;
2237 m_hAdjust->upper = 1.0;
2238 m_hAdjust->value = 0.0;
2239 m_hAdjust->step_increment = 1.0;
2240 m_hAdjust->page_increment = 1.0;
2241 m_hAdjust->page_size = 5.0;
2242 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
f03fc89f
VZ
2243
2244 // these handlers block mouse events to any window during scrolling such as
2245 // motion events and prevent GTK and wxWindows from fighting over where the
2246 // slider should be
2247
2248 gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_press_event",
76ed8f8d
RR
2249 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
2250
f03fc89f 2251 gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_press_event",
76ed8f8d
RR
2252 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
2253
f03fc89f 2254 gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_release_event",
76ed8f8d
RR
2255 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
2256
f03fc89f 2257 gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_release_event",
76ed8f8d 2258 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
8bbe427f 2259
034be888 2260 // these handlers get notified when screen updates are required either when
76ed8f8d
RR
2261 // scrolling or when the window size (and therefore scrollbar configuration)
2262 // has changed
2263
2264 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
2265 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
2266 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
2267 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
2268
f03fc89f 2269 gtk_widget_show( m_wxwindow );
47d67540 2270
f03fc89f
VZ
2271 if (m_parent)
2272 m_parent->DoAddChild( this );
8bbe427f 2273
e380f72b 2274 PostCreation();
8bbe427f 2275
e380f72b 2276 Show( TRUE );
c801d85f 2277
e380f72b 2278 return TRUE;
362c6693 2279}
c801d85f 2280
68dda785 2281wxWindow::~wxWindow()
c801d85f 2282{
31c6b4fc 2283 m_isBeingDeleted = TRUE;
43a18898 2284 m_hasVMT = FALSE;
47d67540 2285
f03fc89f
VZ
2286 if (m_widget)
2287 Show( FALSE );
8bbe427f 2288
a2053b27
RR
2289 DestroyChildren();
2290
f03fc89f
VZ
2291 if (m_parent)
2292 m_parent->RemoveChild( this );
c801d85f 2293
63081513
RR
2294#ifdef HAVE_XIM
2295 if (m_ic)
2296 gdk_ic_destroy (m_ic);
2297 if (m_icattr)
2298 gdk_ic_attr_destroy (m_icattr);
2299#endif
2300
f03fc89f 2301 if (m_widgetStyle)
a2053b27 2302 {
a56fcaaf 2303#if DISABLE_STYLE_IF_BROKEN_THEME
bce1406b
RR
2304 // don't delete if it's a pixmap theme style
2305 if (!m_widgetStyle->engine_data)
2306 gtk_style_unref( m_widgetStyle );
a56fcaaf 2307#endif
c50f1fb9 2308 m_widgetStyle = (GtkStyle*) NULL;
a2053b27 2309 }
c801d85f 2310
f03fc89f 2311 if (m_wxwindow)
a2053b27 2312 {
f03fc89f 2313 gtk_widget_destroy( m_wxwindow );
c50f1fb9 2314 m_wxwindow = (GtkWidget*) NULL;
a2053b27 2315 }
8bbe427f 2316
f03fc89f 2317 if (m_widget)
a2053b27 2318 {
f03fc89f 2319 gtk_widget_destroy( m_widget );
c50f1fb9 2320 m_widget = (GtkWidget*) NULL;
a2053b27 2321 }
362c6693 2322}
c801d85f 2323
4dcaf11a 2324bool wxWindow::PreCreation( wxWindow *parent, const wxPoint &pos, const wxSize &size )
c801d85f 2325{
223d09f6 2326 wxCHECK_MSG( !m_needParent || parent, FALSE, wxT("Need complete parent.") );
8bbe427f 2327
4dcaf11a
RR
2328 /* this turns -1 into 20 so that a minimal window is
2329 visible even although -1,-1 has been given as the
2330 size of the window. the same trick is used in other
2331 ports and should make debugging easier */
f03fc89f
VZ
2332 m_width = WidthDefault(size.x);
2333 m_height = HeightDefault(size.y);
8bbe427f 2334
43a18898
RR
2335 m_x = (int)pos.x;
2336 m_y = (int)pos.y;
8bbe427f 2337
4dcaf11a 2338 /* some reasonable defaults */
148cd9b6 2339 if (!parent)
6ca41e57 2340 {
43a18898
RR
2341 if (m_x == -1)
2342 {
2343 m_x = (gdk_screen_width () - m_width) / 2;
2344 if (m_x < 10) m_x = 10;
2345 }
2346 if (m_y == -1)
2347 {
2348 m_y = (gdk_screen_height () - m_height) / 2;
2349 if (m_y < 10) m_y = 10;
2350 }
6ca41e57 2351 }
148cd9b6 2352
4dcaf11a 2353 return TRUE;
c801d85f
KB
2354}
2355
68dda785 2356void wxWindow::PostCreation()
c801d85f 2357{
223d09f6 2358 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
ca298c88 2359
43a18898
RR
2360 if (m_wxwindow)
2361 {
147bc491 2362 if (!m_noExpose)
b02da6b1 2363 {
147bc491 2364 /* these get reported to wxWindows -> wxPaintEvent */
b420fb6a
RR
2365
2366 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow), TRUE );
2367
b6fa52db
RR
2368 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "event",
2369 GTK_SIGNAL_FUNC(gtk_window_event_event_callback), (gpointer)this );
2370
147bc491
RR
2371 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
2372 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
2373
2374 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
2375 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
b02da6b1 2376 }
148cd9b6 2377
ef47f9b3 2378#if (GTK_MINOR_VERSION > 0)
ed673c6a 2379 /* these are called when the "sunken" or "raised" borders are drawn */
034be888
RR
2380 gtk_signal_connect( GTK_OBJECT(m_widget), "expose_event",
2381 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback), (gpointer)this );
2382
2383 gtk_signal_connect( GTK_OBJECT(m_widget), "draw",
2384 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback), (gpointer)this );
ef47f9b3 2385#endif
43a18898 2386 }
47d67540 2387
63081513
RR
2388 if (m_wxwindow && m_needParent)
2389 {
2390 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "focus_in_event",
2391 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
2392
2393 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "focus_out_event",
2394 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
2395 }
2396 else
2397 {
2398 // For dialogs and frames, we are interested mainly in
2399 // m_widget's focus.
2daa0ce9 2400
63081513
RR
2401 gtk_signal_connect( GTK_OBJECT(m_widget), "focus_in_event",
2402 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
2403
2404 gtk_signal_connect( GTK_OBJECT(m_widget), "focus_out_event",
2405 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
2406 }
2407
a2053b27 2408 GtkWidget *connect_widget = GetConnectWidget();
f03fc89f 2409
a2053b27 2410 ConnectWidget( connect_widget );
47d67540 2411
63081513 2412 /* We cannot set colours, fonts and cursors before the widget has
a2053b27
RR
2413 been realized, so we do this directly after realization */
2414 gtk_signal_connect( GTK_OBJECT(connect_widget), "realize",
c50f1fb9 2415 GTK_SIGNAL_FUNC(gtk_window_realized_callback), (gpointer) this );
2daa0ce9 2416
63081513
RR
2417 if (m_wxwindow)
2418 {
8f75cb6c
RR
2419 /* Catch native resize events. */
2420 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "size_allocate",
2421 GTK_SIGNAL_FUNC(gtk_window_size_callback), (gpointer)this );
2daa0ce9 2422
8f75cb6c 2423 /* Initialize XIM support. */
63081513
RR
2424 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "realize",
2425 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback), (gpointer) this );
8f75cb6c
RR
2426
2427 /* And resize XIM window. */
b79395c5
RR
2428 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "size_allocate",
2429 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback), (gpointer)this );
63081513 2430 }
2daa0ce9 2431
43a18898 2432 m_hasVMT = TRUE;
b4071e91
RR
2433}
2434
2435void wxWindow::ConnectWidget( GtkWidget *widget )
2436{
43a18898
RR
2437 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
2438 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
c801d85f 2439
b666df2c
RR
2440 gtk_signal_connect( GTK_OBJECT(widget), "key_release_event",
2441 GTK_SIGNAL_FUNC(gtk_window_key_release_callback), (gpointer)this );
2442
43a18898
RR
2443 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
2444 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
47d67540 2445
43a18898
RR
2446 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
2447 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
47d67540 2448
43a18898
RR
2449 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
2450 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
47d67540 2451
43a18898
RR
2452 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
2453 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
47d67540 2454
43a18898
RR
2455 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
2456 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
362c6693 2457}
c801d85f 2458
68dda785 2459bool wxWindow::Destroy()
c801d85f 2460{
223d09f6 2461 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
47d67540 2462
43a18898 2463 m_hasVMT = FALSE;
c801d85f 2464
f03fc89f 2465 return wxWindowBase::Destroy();
362c6693 2466}
c801d85f 2467
23efdd02
RR
2468void wxWindow::DoMoveWindow(int x, int y, int width, int height)
2469{
2470 gtk_pizza_set_size( GTK_PIZZA(m_parent->m_wxwindow), m_widget, x, y, width, height );
2471}
2daa0ce9 2472
bfc6fde4 2473void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
c801d85f 2474{
223d09f6
KB
2475 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
2476 wxASSERT_MSG( (m_parent != NULL), wxT("wxWindow::SetSize requires parent.\n") );
8bbe427f 2477
e27ce4e9 2478 if (m_resizing) return; /* I don't like recursions */
fb1585ae 2479 m_resizing = TRUE;
b6fa52db 2480
a2053b27 2481 if (m_parent->m_wxwindow == NULL) /* i.e. wxNotebook */
fb1585ae 2482 {
e27ce4e9 2483 /* don't set the size for children of wxNotebook, just take the values. */
fb1585ae
RR
2484 m_x = x;
2485 m_y = y;
2486 m_width = width;
ba4e3652 2487 m_height = height;
fb1585ae 2488 }
ba4e3652 2489 else
fb1585ae 2490 {
da048e3d 2491 GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
148cd9b6 2492
85ad5eb5 2493 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
ba4e3652 2494 {
da048e3d
RR
2495 if (x != -1) m_x = x + pizza->xoffset;
2496 if (y != -1) m_y = y + pizza->yoffset;
ba4e3652
RR
2497 if (width != -1) m_width = width;
2498 if (height != -1) m_height = height;
2499 }
2500 else
2501 {
da048e3d
RR
2502 m_x = x + pizza->xoffset;
2503 m_y = y + pizza->yoffset;
ba4e3652
RR
2504 m_width = width;
2505 m_height = height;
2506 }
47d67540 2507
ba4e3652
RR
2508 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
2509 {
2510 if (width == -1) m_width = 80;
2511 }
2512
2513 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
2514 {
2515 if (height == -1) m_height = 26;
2516 }
8bbe427f 2517
ba4e3652
RR
2518 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
2519 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
d3b4d113
RR
2520 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
2521 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
47d67540 2522
a2053b27 2523 int border = 0;
c50f1fb9 2524 int bottom_border = 0;
f03fc89f 2525
29f538ce 2526 if (GTK_WIDGET_CAN_DEFAULT(m_widget))
c50f1fb9
VZ
2527 {
2528 /* the default button has a border around it */
2529 border = 6;
2530 bottom_border = 5;
2531 }
2532
23efdd02
RR
2533 DoMoveWindow( m_x-border,
2534 m_y-border,
2535 m_width+2*border,
2536 m_height+border+bottom_border );
54517652 2537 }
148cd9b6 2538
5b8a521e
RR
2539 if (m_hasScrolling)
2540 {
b6fa52db
RR
2541 /* Sometimes the client area changes size without the
2542 whole windows's size changing, but if the whole
2543 windows's size doesn't change, no wxSizeEvent will
2544 normally be sent. Here we add an extra test if
2545 the client test has been changed and this will
2546 be used then. */
5b8a521e
RR
2547 GetClientSize( &m_oldClientWidth, &m_oldClientHeight );
2548 }
2549
54517652 2550/*
6d693bb4
RR
2551 wxPrintf( "OnSize sent from " );
2552 if (GetClassInfo() && GetClassInfo()->GetClassName())
2553 wxPrintf( GetClassInfo()->GetClassName() );
2554 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2555*/
2556
30760ce7
RR
2557 if (!m_nativeSizeEvent)
2558 {
2559 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
2560 event.SetEventObject( this );
2561 GetEventHandler()->ProcessEvent( event );
2562 }
6d693bb4 2563
fb1585ae 2564 m_resizing = FALSE;
362c6693 2565}
c801d85f 2566
9390a202
RR
2567void wxWindow::OnInternalIdle()
2568{
148cd9b6
VZ
2569 if ( g_sendActivateEvent != -1 )
2570 {
2571 bool activate = g_sendActivateEvent != 0;
2572
2573 // do it only once
2574 g_sendActivateEvent = -1;
2575
2576 wxActivateEvent event(wxEVT_ACTIVATE, activate, GetId());
2577 event.SetEventObject(this);
2578
2579 (void)GetEventHandler()->ProcessEvent(event);
2580 }
2581
9146082c
RR
2582 wxCursor cursor = m_cursor;
2583 if (g_globalCursor.Ok()) cursor = g_globalCursor;
c50f1fb9 2584
f7a11f8c 2585 if (cursor.Ok())
9146082c 2586 {
3017f78d 2587 /* I now set the cursor anew in every OnInternalIdle call
b02da6b1
VZ
2588 as setting the cursor in a parent window also effects the
2589 windows above so that checking for the current cursor is
2590 not possible. */
148cd9b6 2591
9146082c 2592 if (m_wxwindow)
6a008b33 2593 {
da048e3d 2594 GdkWindow *window = GTK_PIZZA(m_wxwindow)->bin_window;
6a008b33 2595 if (window)
c50f1fb9 2596 gdk_window_set_cursor( window, cursor.GetCursor() );
6a008b33
VZ
2597
2598 if (!g_globalCursor.Ok())
2599 cursor = *wxSTANDARD_CURSOR;
2600
2601 window = m_widget->window;
5e014a0c 2602 if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget)))
9146082c 2603 gdk_window_set_cursor( window, cursor.GetCursor() );
5e014a0c 2604
6a008b33
VZ
2605 }
2606 else
2607 {
5e014a0c 2608
9146082c 2609 GdkWindow *window = m_widget->window;
5e014a0c 2610 if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget)))
9146082c 2611 gdk_window_set_cursor( window, cursor.GetCursor() );
5e014a0c 2612
6a008b33 2613 }
9146082c 2614 }
6a008b33 2615
9390a202
RR
2616 UpdateWindowUI();
2617}
2618
f03fc89f 2619void wxWindow::DoGetSize( int *width, int *height ) const
c801d85f 2620{
223d09f6 2621 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2622
fb1585ae
RR
2623 if (width) (*width) = m_width;
2624 if (height) (*height) = m_height;
362c6693 2625}
c801d85f 2626
bfc6fde4 2627void wxWindow::DoSetClientSize( int width, int height )
c801d85f 2628{
223d09f6 2629 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2630
1ecc4d80 2631 if (!m_wxwindow)
c801d85f 2632 {
1ecc4d80 2633 SetSize( width, height );
c801d85f
KB
2634 }
2635 else
2636 {
1ecc4d80
RR
2637 int dw = 0;
2638 int dh = 0;
2639
98d3fdbe
RR
2640 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2641 {
5e014a0c 2642 /* when using GTK 1.2 we set the shadow border size to 2 */
6a008b33 2643 dw += 2 * 2;
98d3fdbe
RR
2644 dh += 2 * 2;
2645 }
5e014a0c
RR
2646 if (HasFlag(wxSIMPLE_BORDER))
2647 {
2648 /* when using GTK 1.2 we set the simple border size to 1 */
2649 dw += 1 * 2;
2650 dh += 1 * 2;
2651 }
034be888 2652
5b8a521e 2653 if (m_hasScrolling)
98d3fdbe 2654 {
324dbfec 2655 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2daa0ce9 2656
9000c624
RR
2657 GtkRequisition vscroll_req;
2658 vscroll_req.width = 2;
2659 vscroll_req.height = 2;
dd00f3f6 2660 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
9000c624 2661 (scroll_window->vscrollbar, &vscroll_req );
2daa0ce9 2662
9000c624
RR
2663 GtkRequisition hscroll_req;
2664 hscroll_req.width = 2;
2665 hscroll_req.height = 2;
dd00f3f6 2666 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
9000c624
RR
2667 (scroll_window->hscrollbar, &hscroll_req );
2668
dd00f3f6 2669 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
324dbfec 2670
1ecc4d80
RR
2671 if (scroll_window->vscrollbar_visible)
2672 {
9000c624 2673 dw += vscroll_req.width;
1ecc4d80
RR
2674 dw += scroll_class->scrollbar_spacing;
2675 }
2676
2677 if (scroll_window->hscrollbar_visible)
2678 {
9000c624 2679 dh += hscroll_req.height;
63cc5d9d 2680 dh += scroll_class->scrollbar_spacing;
1ecc4d80 2681 }
9000c624 2682 }
1ecc4d80 2683
034be888 2684 SetSize( width+dw, height+dh );
1ecc4d80 2685 }
362c6693 2686}
c801d85f 2687
f03fc89f 2688void wxWindow::DoGetClientSize( int *width, int *height ) const
c801d85f 2689{
223d09f6 2690 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2691
1ecc4d80
RR
2692 if (!m_wxwindow)
2693 {
2694 if (width) (*width) = m_width;
2695 if (height) (*height) = m_height;
c801d85f
KB
2696 }
2697 else
2698 {
1ecc4d80
RR
2699 int dw = 0;
2700 int dh = 0;
2701
98d3fdbe
RR
2702 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2703 {
5e014a0c 2704 /* when using GTK 1.2 we set the shadow border size to 2 */
6a008b33 2705 dw += 2 * 2;
98d3fdbe
RR
2706 dh += 2 * 2;
2707 }
5e014a0c
RR
2708 if (HasFlag(wxSIMPLE_BORDER))
2709 {
2710 /* when using GTK 1.2 we set the simple border size to 1 */
2711 dw += 1 * 2;
2712 dh += 1 * 2;
2713 }
9000c624 2714
5b8a521e 2715 if (m_hasScrolling)
98d3fdbe 2716 {
6a008b33 2717 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2daa0ce9 2718
9000c624
RR
2719 GtkRequisition vscroll_req;
2720 vscroll_req.width = 2;
2721 vscroll_req.height = 2;
dd00f3f6 2722 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
9000c624 2723 (scroll_window->vscrollbar, &vscroll_req );
2daa0ce9 2724
9000c624
RR
2725 GtkRequisition hscroll_req;
2726 hscroll_req.width = 2;
2727 hscroll_req.height = 2;
dd00f3f6 2728 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
9000c624
RR
2729 (scroll_window->hscrollbar, &hscroll_req );
2730
dd00f3f6 2731 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
6a008b33 2732
1ecc4d80
RR
2733 if (scroll_window->vscrollbar_visible)
2734 {
9000c624 2735 dw += vscroll_req.width;
1ecc4d80
RR
2736 dw += scroll_class->scrollbar_spacing;
2737 }
2738
2739 if (scroll_window->hscrollbar_visible)
2740 {
9000c624 2741 dh += hscroll_req.height;
1ecc4d80
RR
2742 dh += scroll_class->scrollbar_spacing;
2743 }
6a008b33 2744 }
47d67540 2745
1ecc4d80
RR
2746 if (width) (*width) = m_width - dw;
2747 if (height) (*height) = m_height - dh;
2748 }
362c6693 2749}
c801d85f 2750
f03fc89f 2751void wxWindow::DoGetPosition( int *x, int *y ) const
c801d85f 2752{
223d09f6 2753 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2754
bf0c00c6
RR
2755 int dx = 0;
2756 int dy = 0;
2757 if (m_parent && m_parent->m_wxwindow)
2758 {
da048e3d 2759 GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
b02da6b1
VZ
2760 dx = pizza->xoffset;
2761 dy = pizza->yoffset;
bf0c00c6
RR
2762 }
2763
2764 if (x) (*x) = m_x - dx;
2765 if (y) (*y) = m_y - dy;
362c6693 2766}
c801d85f 2767
dabc0cd5 2768void wxWindow::DoClientToScreen( int *x, int *y ) const
c801d85f 2769{
223d09f6 2770 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2771
a2053b27
RR
2772 if (!m_widget->window) return;
2773
43a18898
RR
2774 GdkWindow *source = (GdkWindow *) NULL;
2775 if (m_wxwindow)
da048e3d 2776 source = GTK_PIZZA(m_wxwindow)->bin_window;
43a18898
RR
2777 else
2778 source = m_widget->window;
47d67540 2779
43a18898
RR
2780 int org_x = 0;
2781 int org_y = 0;
2782 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2783
43a18898 2784 if (!m_wxwindow)
c801d85f 2785 {
43a18898
RR
2786 if (GTK_WIDGET_NO_WINDOW (m_widget))
2787 {
2788 org_x += m_widget->allocation.x;
2789 org_y += m_widget->allocation.y;
2790 }
362c6693 2791 }
47d67540 2792
43a18898
RR
2793 if (x) *x += org_x;
2794 if (y) *y += org_y;
362c6693 2795}
c801d85f 2796
dabc0cd5 2797void wxWindow::DoScreenToClient( int *x, int *y ) const
c801d85f 2798{
223d09f6 2799 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2800
a2053b27
RR
2801 if (!m_widget->window) return;
2802
1ecc4d80
RR
2803 GdkWindow *source = (GdkWindow *) NULL;
2804 if (m_wxwindow)
da048e3d 2805 source = GTK_PIZZA(m_wxwindow)->bin_window;
1ecc4d80
RR
2806 else
2807 source = m_widget->window;
47d67540 2808
1ecc4d80
RR
2809 int org_x = 0;
2810 int org_y = 0;
2811 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2812
1ecc4d80 2813 if (!m_wxwindow)
c801d85f 2814 {
1ecc4d80
RR
2815 if (GTK_WIDGET_NO_WINDOW (m_widget))
2816 {
2817 org_x += m_widget->allocation.x;
2818 org_y += m_widget->allocation.y;
2819 }
362c6693 2820 }
47d67540 2821
1ecc4d80
RR
2822 if (x) *x -= org_x;
2823 if (y) *y -= org_y;
362c6693 2824}
c801d85f 2825
f03fc89f 2826bool wxWindow::Show( bool show )
c801d85f 2827{
223d09f6 2828 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
47d67540 2829
739730ca
RR
2830 if (!wxWindowBase::Show(show))
2831 {
2832 // nothing to do
f03fc89f 2833 return FALSE;
739730ca 2834 }
8bbe427f 2835
f03fc89f
VZ
2836 if (show)
2837 gtk_widget_show( m_widget );
1ecc4d80 2838 else
f03fc89f 2839 gtk_widget_hide( m_widget );
8bbe427f 2840
f03fc89f 2841 return TRUE;
362c6693 2842}
c801d85f 2843
f03fc89f 2844bool wxWindow::Enable( bool enable )
c801d85f 2845{
223d09f6 2846 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
5e0aa05a 2847
739730ca
RR
2848 if (!wxWindowBase::Enable(enable))
2849 {
2850 // nothing to do
f03fc89f 2851 return FALSE;
739730ca 2852 }
1ecc4d80 2853
f03fc89f
VZ
2854 gtk_widget_set_sensitive( m_widget, enable );
2855 if ( m_wxwindow )
2856 gtk_widget_set_sensitive( m_wxwindow, enable );
ff8bfdbb 2857
f03fc89f 2858 return TRUE;
362c6693 2859}
c801d85f 2860
f03fc89f 2861int wxWindow::GetCharHeight() const
2f2aa628 2862{
223d09f6 2863 wxCHECK_MSG( (m_widget != NULL), 12, wxT("invalid window") );
47d67540 2864
223d09f6 2865 wxCHECK_MSG( m_font.Ok(), 12, wxT("invalid font") );
2f2aa628 2866
f03fc89f
VZ
2867 GdkFont *font = m_font.GetInternalFont( 1.0 );
2868
2869 return font->ascent + font->descent;
362c6693 2870}
c801d85f 2871
f03fc89f 2872int wxWindow::GetCharWidth() const
c33c4050 2873{
223d09f6 2874 wxCHECK_MSG( (m_widget != NULL), 8, wxT("invalid window") );
47d67540 2875
223d09f6 2876 wxCHECK_MSG( m_font.Ok(), 8, wxT("invalid font") );
47d67540 2877
463c1fa1 2878 GdkFont *font = m_font.GetInternalFont( 1.0 );
ff8bfdbb 2879
463c1fa1 2880 return gdk_string_width( font, "H" );
c33c4050
RR
2881}
2882
f03fc89f
VZ
2883void wxWindow::GetTextExtent( const wxString& string,
2884 int *x,
2885 int *y,
2886 int *descent,
2887 int *externalLeading,
2888 const wxFont *theFont ) const
c33c4050 2889{
463c1fa1
RR
2890 wxFont fontToUse = m_font;
2891 if (theFont) fontToUse = *theFont;
47d67540 2892
223d09f6 2893 wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") );
47d67540 2894
463c1fa1 2895 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
05939a81 2896 if (x) (*x) = gdk_string_width( font, string.mbc_str() );
463c1fa1
RR
2897 if (y) (*y) = font->ascent + font->descent;
2898 if (descent) (*descent) = font->descent;
2899 if (externalLeading) (*externalLeading) = 0; // ??
c33c4050
RR
2900}
2901
68dda785 2902void wxWindow::SetFocus()
c801d85f 2903{
223d09f6 2904 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
2daa0ce9 2905
354aa1e3
RR
2906 if (m_wxwindow)
2907 {
173348db
RR
2908 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow))
2909 gtk_widget_grab_focus (m_wxwindow);
354aa1e3
RR
2910 return;
2911 }
2912
2913 if (m_widget)
c801d85f 2914 {
173348db 2915 if (GTK_WIDGET_CAN_FOCUS(m_widget) && !GTK_WIDGET_HAS_FOCUS (m_widget) )
463c1fa1 2916 {
354aa1e3 2917 gtk_widget_grab_focus (m_widget);
463c1fa1 2918 }
354aa1e3 2919 else if (GTK_IS_CONTAINER(m_widget))
ff8bfdbb 2920 {
354aa1e3 2921 gtk_container_focus( GTK_CONTAINER(m_widget), GTK_DIR_TAB_FORWARD );
ff8bfdbb
VZ
2922 }
2923 else
2924 {
b02da6b1 2925 // ?
ff8bfdbb 2926 }
362c6693 2927 }
362c6693 2928}
c801d85f 2929
b292e2f5
RR
2930bool wxWindow::AcceptsFocus() const
2931{
f03fc89f 2932 return m_acceptsFocus && wxWindowBase::AcceptsFocus();
b292e2f5
RR
2933}
2934
fdb7dadb 2935bool wxWindow::Reparent( wxWindowBase *newParentBase )
463c1fa1 2936{
223d09f6 2937 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
c50f1fb9 2938
fdb7dadb
VZ
2939 wxWindow *oldParent = m_parent,
2940 *newParent = (wxWindow *)newParentBase;
a2053b27 2941
5fd11f09
RR
2942 wxASSERT( GTK_IS_WIDGET(m_widget) );
2943
f03fc89f
VZ
2944 if ( !wxWindowBase::Reparent(newParent) )
2945 return FALSE;
8bbe427f 2946
5fd11f09
RR
2947 wxASSERT( GTK_IS_WIDGET(m_widget) );
2948
2949 /* prevent GTK from deleting the widget arbitrarily */
2950 gtk_widget_ref( m_widget );
2951
8ce63e9d
RR
2952 if (oldParent)
2953 {
3017f78d 2954 gtk_container_remove( GTK_CONTAINER(m_widget->parent), m_widget );
8ce63e9d 2955 }
c50f1fb9 2956
5fd11f09
RR
2957 wxASSERT( GTK_IS_WIDGET(m_widget) );
2958
8ce63e9d
RR
2959 if (newParent)
2960 {
2961 /* insert GTK representation */
2962 (*(newParent->m_insertCallback))(newParent, this);
2963 }
c50f1fb9 2964
5fd11f09
RR
2965 /* reverse: prevent GTK from deleting the widget arbitrarily */
2966 gtk_widget_unref( m_widget );
148cd9b6 2967
f03fc89f 2968 return TRUE;
362c6693 2969}
c801d85f 2970
c50f1fb9 2971void wxWindow::DoAddChild(wxWindow *child)
ddb6bc71 2972{
223d09f6 2973 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
ddb6bc71 2974
223d09f6 2975 wxASSERT_MSG( (child != NULL), wxT("invalid child window") );
ddb6bc71 2976
223d09f6 2977 wxASSERT_MSG( (m_insertCallback != NULL), wxT("invalid child insertion function") );
c50f1fb9 2978
ddb6bc71
RR
2979 /* add to list */
2980 AddChild( child );
c50f1fb9 2981
ddb6bc71
RR
2982 /* insert GTK representation */
2983 (*m_insertCallback)(this, child);
2984}
2985
68dda785 2986void wxWindow::Raise()
362c6693 2987{
223d09f6 2988 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2989
a2053b27
RR
2990 if (!m_widget->window) return;
2991
f03fc89f 2992 gdk_window_raise( m_widget->window );
362c6693
RR
2993}
2994
68dda785 2995void wxWindow::Lower()
362c6693 2996{
223d09f6 2997 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2998
a2053b27
RR
2999 if (!m_widget->window) return;
3000
f03fc89f 3001 gdk_window_lower( m_widget->window );
362c6693 3002}
c801d85f 3003
f03fc89f 3004bool wxWindow::SetCursor( const wxCursor &cursor )
86b29a61 3005{
223d09f6 3006 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
86b29a61 3007
f6bcfd97
BP
3008 if (cursor == m_cursor)
3009 return FALSE;
3010
3011 if (g_isIdle)
3012 wxapp_install_idle_handler();
3013
3014 if (cursor == wxNullCursor)
3015 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR );
3016 else
3017 return wxWindowBase::SetCursor( cursor );
362c6693 3018}
c801d85f 3019
85eb36c2 3020void wxWindow::WarpPointer( int x, int y )
4f22cf8d 3021{
223d09f6 3022 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
85eb36c2 3023
ed673c6a
RR
3024 /* we provide this function ourselves as it is
3025 missing in GDK (top of this file) */
148cd9b6 3026
ed673c6a
RR
3027 GdkWindow *window = (GdkWindow*) NULL;
3028 if (m_wxwindow)
da048e3d 3029 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3030 else
3031 window = GetConnectWidget()->window;
148cd9b6 3032
ed673c6a
RR
3033 if (window)
3034 gdk_window_warp_pointer( window, x, y );
4f22cf8d
RR
3035}
3036
debe6624 3037void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
c801d85f 3038{
f2593d0d 3039 if (!m_widget) return;
a2053b27
RR
3040 if (!m_widget->window) return;
3041
139adb6a 3042 if (eraseBackground && m_wxwindow && m_wxwindow->window)
c801d85f 3043 {
139adb6a
RR
3044 if (rect)
3045 {
da048e3d 3046 gdk_window_clear_area( GTK_PIZZA(m_wxwindow)->bin_window,
139adb6a 3047 rect->x, rect->y,
f234c60c 3048 rect->width, rect->height );
139adb6a
RR
3049 }
3050 else
3051 {
da048e3d 3052 gdk_window_clear( GTK_PIZZA(m_wxwindow)->bin_window );
139adb6a
RR
3053 }
3054 }
ff8bfdbb 3055
1b68e0b5 3056 /* there is no GTK equivalent of "draw only, don't clear" so we
da048e3d 3057 invent our own in the GtkPizza widget */
1b68e0b5 3058
139adb6a
RR
3059 if (!rect)
3060 {
3061 if (m_wxwindow)
b02da6b1 3062 {
b6fa52db
RR
3063
3064/*
b02da6b1
VZ
3065 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3066 gboolean old_clear = pizza->clear_on_draw;
3067 gtk_pizza_set_clear( pizza, FALSE );
1b68e0b5 3068 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
b02da6b1 3069 gtk_pizza_set_clear( pizza, old_clear );
b6fa52db
RR
3070*/
3071 GdkEventExpose gdk_event;
b4bee866
RR
3072 gdk_event.type = GDK_EXPOSE;
3073 gdk_event.window = GTK_PIZZA(m_wxwindow)->bin_window;
b6fa52db
RR
3074 gdk_event.count = 0;
3075 gdk_event.area.x = 0;
3076 gdk_event.area.y = 0;
3077 gdk_event.area.width = m_wxwindow->allocation.width;
3078 gdk_event.area.height = m_wxwindow->allocation.height;
3079 gtk_window_expose_callback( m_wxwindow, &gdk_event, this );
3080
b02da6b1 3081 }
ff8bfdbb 3082 else
b6fa52db 3083 {
139adb6a 3084 gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
b6fa52db 3085 }
362c6693 3086 }
c801d85f 3087 else
139adb6a 3088 {
139adb6a
RR
3089
3090 if (m_wxwindow)
b02da6b1 3091 {
b6fa52db 3092/*
b02da6b1
VZ
3093 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3094 gboolean old_clear = pizza->clear_on_draw;
3095 gtk_pizza_set_clear( pizza, FALSE );
148cd9b6 3096
b6fa52db
RR
3097 GdkRectangle gdk_rect;
3098 gdk_rect.x = rect->x;
3099 gdk_rect.y = rect->y;
3100 gdk_rect.width = rect->width;
3101 gdk_rect.height = rect->height;
1b68e0b5 3102 gtk_widget_draw( m_wxwindow, &gdk_rect );
b6fa52db 3103 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
148cd9b6 3104
b02da6b1 3105 gtk_pizza_set_clear( pizza, old_clear );
b6fa52db
RR
3106*/
3107 GdkEventExpose gdk_event;
b4bee866
RR
3108 gdk_event.type = GDK_EXPOSE;
3109 gdk_event.window = GTK_PIZZA(m_wxwindow)->bin_window;
b6fa52db
RR
3110 gdk_event.count = 0;
3111 gdk_event.area.x = rect->x;
3112 gdk_event.area.y = rect->y;
3113 gdk_event.area.width = rect->width;
3114 gdk_event.area.height = rect->height;
3115 gtk_window_expose_callback( m_wxwindow, &gdk_event, this );
b02da6b1 3116 }
139adb6a 3117 else
b6fa52db
RR
3118 {
3119 GdkRectangle gdk_rect;
3120 gdk_rect.x = rect->x;
3121 gdk_rect.y = rect->y;
3122 gdk_rect.width = rect->width;
3123 gdk_rect.height = rect->height;
139adb6a 3124 gtk_widget_draw( m_widget, &gdk_rect );
b6fa52db 3125 }
139adb6a 3126 }
362c6693 3127}
c801d85f 3128
68dda785 3129void wxWindow::Clear()
c801d85f 3130{
223d09f6 3131 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3132
a2053b27
RR
3133 if (!m_widget->window) return;
3134
f234c60c
RR
3135 if (m_wxwindow && m_wxwindow->window)
3136 {
c916e13b 3137// gdk_window_clear( m_wxwindow->window );
f234c60c 3138 }
362c6693 3139}
c801d85f 3140
ff8bfdbb 3141#if wxUSE_TOOLTIPS
f03fc89f 3142void wxWindow::DoSetToolTip( wxToolTip *tip )
b1170810 3143{
f03fc89f 3144 wxWindowBase::DoSetToolTip(tip);
ff8bfdbb 3145
f03fc89f
VZ
3146 if (m_tooltip)
3147 m_tooltip->Apply( this );
b1170810
RR
3148}
3149
05939a81 3150void wxWindow::ApplyToolTip( GtkTooltips *tips, const wxChar *tip )
b1170810 3151{
dcf924a3 3152 gtk_tooltips_set_tip( tips, GetConnectWidget(), wxConvCurrent->cWX2MB(tip), (gchar*) NULL );
301cd871 3153}
ff8bfdbb 3154#endif // wxUSE_TOOLTIPS
b1170810 3155
f03fc89f 3156bool wxWindow::SetBackgroundColour( const wxColour &colour )
c801d85f 3157{
223d09f6 3158 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
8bbe427f 3159
739730ca
RR
3160 if (!wxWindowBase::SetBackgroundColour(colour))
3161 {
3162 // don't leave if the GTK widget has just
3163 // been realized
3164 if (!m_delayedBackgroundColour) return FALSE;
3165 }
c50f1fb9 3166
ed673c6a
RR
3167 GdkWindow *window = (GdkWindow*) NULL;
3168 if (m_wxwindow)
da048e3d 3169 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3170 else
3171 window = GetConnectWidget()->window;
148cd9b6 3172
ed673c6a 3173 if (!window)
739730ca
RR
3174 {
3175 // indicate that a new style has been set
c50f1fb9
VZ
3176 // but it couldn't get applied as the
3177 // widget hasn't been realized yet.
3178 m_delayedBackgroundColour = TRUE;
739730ca 3179 }
ca298c88 3180
0f2f4986 3181 if ((m_wxwindow) &&
103aab26 3182 (m_wxwindow->window) &&
0f2f4986 3183 (m_backgroundColour != wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE)))
3bc755fc 3184 {
a2053b27
RR
3185 /* wxMSW doesn't clear the window here. I don't do that either to
3186 provide compatibility. call Clear() to do the job. */
ca298c88 3187
ed673c6a
RR
3188 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
3189 gdk_window_set_background( window, m_backgroundColour.GetColor() );
3bc755fc 3190 }
8bbe427f 3191
0f2f4986 3192 ApplyWidgetStyle();
c801d85f 3193
f03fc89f 3194 return TRUE;
6de97a3b
RR
3195}
3196
f03fc89f 3197bool wxWindow::SetForegroundColour( const wxColour &colour )
6de97a3b 3198{
223d09f6 3199 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
8bbe427f 3200
739730ca
RR
3201 if (!wxWindowBase::SetForegroundColour(colour))
3202 {
3203 // don't leave if the GTK widget has just
3204 // been realized
3205 if (!m_delayedForegroundColour) return FALSE;
3206 }
c50f1fb9 3207
ed673c6a
RR
3208 GdkWindow *window = (GdkWindow*) NULL;
3209 if (m_wxwindow)
da048e3d 3210 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3211 else
3212 window = GetConnectWidget()->window;
148cd9b6 3213
ed673c6a 3214 if (!window)
739730ca
RR
3215 {
3216 // indicate that a new style has been set
c50f1fb9
VZ
3217 // but it couldn't get applied as the
3218 // widget hasn't been realized yet.
3219 m_delayedForegroundColour = TRUE;
739730ca 3220 }
2b07d713 3221
0f2f4986 3222 ApplyWidgetStyle();
f03fc89f
VZ
3223
3224 return TRUE;
58614078
RR
3225}
3226
3227GtkStyle *wxWindow::GetWidgetStyle()
3228{
103aab26
RR
3229 if (m_widgetStyle)
3230 {
3231 GtkStyle *remake = gtk_style_copy( m_widgetStyle );
dd00f3f6
OK
3232#ifdef __WXGTK20__
3233 /* FIXME: is this necessary? */
3234 _G_TYPE_IGC(remake, GtkObjectClass) = _G_TYPE_IGC(m_widgetStyle, GtkObjectClass);
3235#else
103aab26 3236 remake->klass = m_widgetStyle->klass;
dd00f3f6 3237#endif
2daa0ce9 3238
103aab26
RR
3239 gtk_style_unref( m_widgetStyle );
3240 m_widgetStyle = remake;
3241 }
3242 else
3243 {
3244 GtkStyle *def = gtk_rc_get_style( m_widget );
e6527f9d 3245
103aab26
RR
3246 if (!def)
3247 def = gtk_widget_get_default_style();
e6527f9d 3248
103aab26 3249 m_widgetStyle = gtk_style_copy( def );
dd00f3f6
OK
3250#ifdef __WXGTK20__
3251 /* FIXME: is this necessary? */
3252 _G_TYPE_IGC(m_widgetStyle, GtkObjectClass) = _G_TYPE_IGC(def, GtkObjectClass);
3253#else
103aab26 3254 m_widgetStyle->klass = def->klass;
dd00f3f6 3255#endif
103aab26 3256 }
8bbe427f 3257
1ecc4d80 3258 return m_widgetStyle;
58614078
RR
3259}
3260
3261void wxWindow::SetWidgetStyle()
3262{
a56fcaaf 3263#if DISABLE_STYLE_IF_BROKEN_THEM
fb65642c
RR
3264 if (m_widget->style->engine_data)
3265 {
3266 static bool s_warningPrinted = FALSE;
3267 if (!s_warningPrinted)
3268 {
3269 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3270 s_warningPrinted = TRUE;
3271 }
3272 m_widgetStyle = m_widget->style;
3273 return;
3274 }
a56fcaaf 3275#endif
fb65642c 3276
1ecc4d80
RR
3277 GtkStyle *style = GetWidgetStyle();
3278
db434467
RR
3279 if (m_font != wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT ))
3280 {
3281 gdk_font_unref( style->font );
3282 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
3283 }
1ecc4d80
RR
3284
3285 if (m_foregroundColour.Ok())
3286 {
454e2a22 3287 m_foregroundColour.CalcPixel( gtk_widget_get_colormap( m_widget ) );
db434467
RR
3288 if (m_foregroundColour != wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT))
3289 {
3290 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
3291 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
3292 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
3293 }
f6bcfd97
BP
3294 else
3295 {
3296 // Try to restore the gtk default style. This is still a little
3297 // oversimplified for what is probably really needed here for controls
3298 // other than buttons, but is better than not being able to (re)set a
3299 // control's foreground colour to *wxBLACK -- RL
3300 GtkStyle *def = gtk_rc_get_style( m_widget );
3301
3302 if (!def)
3303 def = gtk_widget_get_default_style();
3304
3305 style->fg[GTK_STATE_NORMAL] = def->fg[GTK_STATE_NORMAL];
3306 style->fg[GTK_STATE_PRELIGHT] = def->fg[GTK_STATE_PRELIGHT];
3307 style->fg[GTK_STATE_ACTIVE] = def->fg[GTK_STATE_ACTIVE];
3308 }
1ecc4d80
RR
3309 }
3310
3311 if (m_backgroundColour.Ok())
3312 {
454e2a22 3313 m_backgroundColour.CalcPixel( gtk_widget_get_colormap( m_widget ) );
db434467
RR
3314 if (m_backgroundColour != wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE))
3315 {
3316 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
3317 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
3318 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
3319 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
3320 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
3321 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
3322 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
3323 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
f6bcfd97
BP
3324 }
3325 else
3326 {
3327 // Try to restore the gtk default style. This is still a little
3328 // oversimplified for what is probably really needed here for controls
3329 // other than buttons, but is better than not being able to (re)set a
3330 // control's background colour to default grey and means resetting a
3331 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3332 // behavior -- RL
3333 GtkStyle *def = gtk_rc_get_style( m_widget );
3334
3335 if (!def)
3336 def = gtk_widget_get_default_style();
3337
3338 style->bg[GTK_STATE_NORMAL] = def->bg[GTK_STATE_NORMAL];
3339 style->base[GTK_STATE_NORMAL] = def->base[GTK_STATE_NORMAL];
3340 style->bg[GTK_STATE_PRELIGHT] = def->bg[GTK_STATE_PRELIGHT];
3341 style->base[GTK_STATE_PRELIGHT] = def->base[GTK_STATE_PRELIGHT];
3342 style->bg[GTK_STATE_ACTIVE] = def->bg[GTK_STATE_ACTIVE];
3343 style->base[GTK_STATE_ACTIVE] = def->base[GTK_STATE_ACTIVE];
3344 style->bg[GTK_STATE_INSENSITIVE] = def->bg[GTK_STATE_INSENSITIVE];
3345 style->base[GTK_STATE_INSENSITIVE] = def->base[GTK_STATE_INSENSITIVE];
3346 }
1ecc4d80 3347 }
a81258be
RR
3348}
3349
58614078 3350void wxWindow::ApplyWidgetStyle()
a81258be 3351{
6de97a3b
RR
3352}
3353
2259e007
RR
3354//-----------------------------------------------------------------------------
3355// Pop-up menu stuff
3356//-----------------------------------------------------------------------------
3357
3358static void gtk_pop_hide_callback( GtkWidget *WXUNUSED(widget), bool* is_waiting )
3359{
3360 *is_waiting = FALSE;
3361}
3362
30dea054
RR
3363static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
3364{
1ecc4d80 3365 menu->SetInvokingWindow( win );
1987af7e 3366 wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
1ecc4d80
RR
3367 while (node)
3368 {
1987af7e 3369 wxMenuItem *menuitem = node->GetData();
1ecc4d80
RR
3370 if (menuitem->IsSubMenu())
3371 {
ff8bfdbb
VZ
3372 SetInvokingWindow( menuitem->GetSubMenu(), win );
3373 }
1987af7e
VZ
3374
3375 node = node->GetNext();
1ecc4d80 3376 }
362c6693 3377}
30dea054 3378
0c77152e
RR
3379static gint gs_pop_x = 0;
3380static gint gs_pop_y = 0;
3381
a234a61a
VZ
3382static void pop_pos_callback( GtkMenu * WXUNUSED(menu),
3383 gint *x, gint *y,
3384 wxWindow *win )
0c77152e
RR
3385{
3386 win->ClientToScreen( &gs_pop_x, &gs_pop_y );
3387 *x = gs_pop_x;
3388 *y = gs_pop_y;
3389}
3390
a1665b22 3391bool wxWindow::DoPopupMenu( wxMenu *menu, int x, int y )
30dea054 3392{
223d09f6 3393 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
47d67540 3394
223d09f6 3395 wxCHECK_MSG( menu != NULL, FALSE, wxT("invalid popup-menu") );
8bbe427f 3396
1ecc4d80 3397 SetInvokingWindow( menu, this );
ff8bfdbb 3398
631f1bfe
JS
3399 menu->UpdateUI();
3400
0c77152e
RR
3401 gs_pop_x = x;
3402 gs_pop_y = y;
ff8bfdbb 3403
2259e007 3404 bool is_waiting = TRUE;
148cd9b6 3405
2259e007
RR
3406 gtk_signal_connect( GTK_OBJECT(menu->m_menu), "hide",
3407 GTK_SIGNAL_FUNC(gtk_pop_hide_callback), (gpointer)&is_waiting );
3408
1ecc4d80 3409 gtk_menu_popup(
47d67540 3410 GTK_MENU(menu->m_menu),
0c77152e
RR
3411 (GtkWidget *) NULL, // parent menu shell
3412 (GtkWidget *) NULL, // parent menu item
3413 (GtkMenuPositionFunc) pop_pos_callback,
3414 (gpointer) this, // client data
3415 0, // button used to activate it
54517652 3416 gs_timeLastClick // the time of activation
47d67540 3417 );
148cd9b6 3418
956dbab1
RR
3419 while (is_waiting)
3420 {
3421 while (gtk_events_pending())
3422 gtk_main_iteration();
3423 }
2259e007 3424
1ecc4d80 3425 return TRUE;
30dea054
RR
3426}
3427
06cfab17 3428#if wxUSE_DRAG_AND_DROP
ac57418f 3429
c801d85f
KB
3430void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
3431{
223d09f6 3432 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3433
1ecc4d80 3434 GtkWidget *dnd_widget = GetConnectWidget();
47d67540 3435
1ecc4d80 3436 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
47d67540 3437
1ecc4d80
RR
3438 if (m_dropTarget) delete m_dropTarget;
3439 m_dropTarget = dropTarget;
47d67540 3440
1ecc4d80 3441 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
362c6693 3442}
c801d85f 3443
f03fc89f 3444#endif // wxUSE_DRAG_AND_DROP
ac57418f 3445
68dda785 3446GtkWidget* wxWindow::GetConnectWidget()
e3e65dac 3447{
1ecc4d80
RR
3448 GtkWidget *connect_widget = m_widget;
3449 if (m_wxwindow) connect_widget = m_wxwindow;
47d67540 3450
1ecc4d80 3451 return connect_widget;
e3e65dac 3452}
47d67540 3453
903f689b
RR
3454bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
3455{
148cd9b6 3456 if (m_wxwindow)
da048e3d 3457 return (window == GTK_PIZZA(m_wxwindow)->bin_window);
148cd9b6 3458
1ecc4d80 3459 return (window == m_widget->window);
903f689b
RR
3460}
3461
f03fc89f 3462bool wxWindow::SetFont( const wxFont &font )
c801d85f 3463{
223d09f6 3464 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
c801d85f 3465
739730ca
RR
3466 if (!wxWindowBase::SetFont(font))
3467 {
454e2a22 3468 return FALSE;
739730ca 3469 }
9c288e4d 3470
ae0bdb01 3471 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
f03fc89f 3472 if ( sysbg == m_backgroundColour )
ae0bdb01
RR
3473 {
3474 m_backgroundColour = wxNullColour;
3475 ApplyWidgetStyle();
ff8bfdbb
VZ
3476 m_backgroundColour = sysbg;
3477 }
ae0bdb01
RR
3478 else
3479 {
3480 ApplyWidgetStyle();
3481 }
c801d85f 3482
f03fc89f 3483 return TRUE;
362c6693 3484}
c801d85f 3485
68dda785 3486void wxWindow::CaptureMouse()
c801d85f 3487{
223d09f6 3488 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3489
223d09f6 3490 wxCHECK_RET( g_captureWindow == NULL, wxT("CaptureMouse called twice") );
47d67540 3491
ed673c6a
RR
3492 GdkWindow *window = (GdkWindow*) NULL;
3493 if (m_wxwindow)
da048e3d 3494 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3495 else
3496 window = GetConnectWidget()->window;
148cd9b6 3497
ed673c6a 3498 if (!window) return;
c50f1fb9 3499
cca602ac
JS
3500 wxCursor* cursor = & m_cursor;
3501 if (!cursor->Ok())
3502 cursor = wxSTANDARD_CURSOR;
3503
ed673c6a 3504 gdk_pointer_grab( window, FALSE,
1ecc4d80
RR
3505 (GdkEventMask)
3506 (GDK_BUTTON_PRESS_MASK |
3507 GDK_BUTTON_RELEASE_MASK |
148cd9b6 3508 GDK_POINTER_MOTION_HINT_MASK |
1ecc4d80 3509 GDK_POINTER_MOTION_MASK),
ff8bfdbb 3510 (GdkWindow *) NULL,
cca602ac 3511 cursor->GetCursor(),
b02da6b1 3512 (guint32)GDK_CURRENT_TIME );
72195a0f 3513 g_captureWindow = this;
362c6693 3514}
c801d85f 3515
68dda785 3516void wxWindow::ReleaseMouse()
c801d85f 3517{
223d09f6 3518 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3519
223d09f6 3520 wxCHECK_RET( g_captureWindow, wxT("ReleaseMouse called twice") );
47d67540 3521
ed673c6a
RR
3522 GdkWindow *window = (GdkWindow*) NULL;
3523 if (m_wxwindow)
da048e3d 3524 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3525 else
3526 window = GetConnectWidget()->window;
148cd9b6 3527
b02da6b1
VZ
3528 if (!window)
3529 return;
c50f1fb9 3530
b02da6b1 3531 gdk_pointer_ungrab ( (guint32)GDK_CURRENT_TIME );
72195a0f 3532 g_captureWindow = (wxWindow*) NULL;
362c6693 3533}
c801d85f 3534
f03fc89f 3535bool wxWindow::IsRetained() const
c801d85f 3536{
1ecc4d80 3537 return FALSE;
362c6693 3538}
c801d85f 3539
debe6624 3540void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
cb43b372 3541 int range, bool refresh )
c801d85f 3542{
223d09f6 3543 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
8bbe427f 3544
223d09f6 3545 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
c801d85f 3546
1ecc4d80 3547 m_hasScrolling = TRUE;
47d67540 3548
1ecc4d80 3549 if (orient == wxHORIZONTAL)
cb43b372 3550 {
1ecc4d80
RR
3551 float fpos = (float)pos;
3552 float frange = (float)range;
3553 float fthumb = (float)thumbVisible;
3554 if (fpos > frange-fthumb) fpos = frange-fthumb;
3555 if (fpos < 0.0) fpos = 0.0;
3556
3557 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
3558 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
3559 {
3560 SetScrollPos( orient, pos, refresh );
3561 return;
3562 }
47d67540 3563
1ecc4d80 3564 m_oldHorizontalPos = fpos;
47d67540 3565
1ecc4d80
RR
3566 m_hAdjust->lower = 0.0;
3567 m_hAdjust->upper = frange;
3568 m_hAdjust->value = fpos;
3569 m_hAdjust->step_increment = 1.0;
3570 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
3571 m_hAdjust->page_size = fthumb;
cb43b372 3572 }
1ecc4d80
RR
3573 else
3574 {
3575 float fpos = (float)pos;
3576 float frange = (float)range;
3577 float fthumb = (float)thumbVisible;
3578 if (fpos > frange-fthumb) fpos = frange-fthumb;
3579 if (fpos < 0.0) fpos = 0.0;
3580
3581 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
3582 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
3583 {
3584 SetScrollPos( orient, pos, refresh );
3585 return;
3586 }
47d67540 3587
1ecc4d80 3588 m_oldVerticalPos = fpos;
47d67540 3589
1ecc4d80
RR
3590 m_vAdjust->lower = 0.0;
3591 m_vAdjust->upper = frange;
3592 m_vAdjust->value = fpos;
3593 m_vAdjust->step_increment = 1.0;
3594 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
3595 m_vAdjust->page_size = fthumb;
3596 }
47d67540 3597
eb082a08
RR
3598 if (orient == wxHORIZONTAL)
3599 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
3600 else
3601 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
362c6693 3602}
c801d85f 3603
debe6624 3604void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
c801d85f 3605{
223d09f6 3606 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
1ecc4d80 3607
223d09f6 3608 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
1ecc4d80
RR
3609
3610 if (orient == wxHORIZONTAL)
3611 {
3612 float fpos = (float)pos;
3613 if (fpos > m_hAdjust->upper - m_hAdjust->page_size) fpos = m_hAdjust->upper - m_hAdjust->page_size;
3614 if (fpos < 0.0) fpos = 0.0;
3615 m_oldHorizontalPos = fpos;
3616
3617 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
3618 m_hAdjust->value = fpos;
3619 }
3620 else
3621 {
3622 float fpos = (float)pos;
3623 if (fpos > m_vAdjust->upper - m_vAdjust->page_size) fpos = m_vAdjust->upper - m_vAdjust->page_size;
3624 if (fpos < 0.0) fpos = 0.0;
3625 m_oldVerticalPos = fpos;
ff8bfdbb 3626
1ecc4d80
RR
3627 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
3628 m_vAdjust->value = fpos;
3629 }
47d67540 3630
5b8a521e 3631 if (m_wxwindow->window)
47d67540 3632 {
5b8a521e 3633 if (orient == wxHORIZONTAL)
473d087e
RR
3634 {
3635 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust),
3636 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
2daa0ce9 3637
5b8a521e 3638 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
2daa0ce9 3639
473d087e
RR
3640 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
3641 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
3642 }
5b8a521e 3643 else
473d087e
RR
3644 {
3645 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust),
3646 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
2daa0ce9 3647
5b8a521e 3648 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
473d087e
RR
3649
3650 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
3651 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
3652 }
cb43b372 3653 }
362c6693 3654}
c801d85f 3655
debe6624 3656int wxWindow::GetScrollThumb( int orient ) const
c801d85f 3657{
223d09f6 3658 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
47d67540 3659
223d09f6 3660 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
47d67540 3661
1ecc4d80
RR
3662 if (orient == wxHORIZONTAL)
3663 return (int)(m_hAdjust->page_size+0.5);
3664 else
3665 return (int)(m_vAdjust->page_size+0.5);
362c6693 3666}
c801d85f 3667
debe6624 3668int wxWindow::GetScrollPos( int orient ) const
c801d85f 3669{
223d09f6 3670 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
47d67540 3671
223d09f6 3672 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
c801d85f 3673
1ecc4d80
RR
3674 if (orient == wxHORIZONTAL)
3675 return (int)(m_hAdjust->value+0.5);
3676 else
3677 return (int)(m_vAdjust->value+0.5);
362c6693 3678}
c801d85f 3679
debe6624 3680int wxWindow::GetScrollRange( int orient ) const
c801d85f 3681{
223d09f6 3682 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
47d67540 3683
223d09f6 3684 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
c801d85f 3685
1ecc4d80
RR
3686 if (orient == wxHORIZONTAL)
3687 return (int)(m_hAdjust->upper+0.5);
3688 else
3689 return (int)(m_vAdjust->upper+0.5);
362c6693 3690}
c801d85f 3691
debe6624 3692void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
c801d85f 3693{
223d09f6 3694 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3695
223d09f6 3696 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
8e217128
RR
3697
3698 if ((dx == 0) && (dy == 0)) return;
c801d85f 3699
b6fa52db 3700 m_clipPaintRegion = TRUE;
da048e3d 3701 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
b6fa52db 3702 m_clipPaintRegion = FALSE;
8e217128
RR
3703
3704/*
3705 if (m_children.GetCount() > 0)
3706 {
3707 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3708 }
3709 else
3710 {
3711 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3712
3713 pizza->xoffset -= dx;
3714 pizza->yoffset -= dy;
3715
3716 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3717 gdk_gc_set_exposures( m_scrollGC, TRUE );
3718
3719 int cw = 0;
3720 int ch = 0;
3721 GetClientSize( &cw, &ch );
3722 int w = cw - abs(dx);
3723 int h = ch - abs(dy);
3724
3725 if ((h < 0) || (w < 0))
3726 {
3727 Refresh();
3728 }
3729 else
3730 {
3731 int s_x = 0;
3732 int s_y = 0;
3733 if (dx < 0) s_x = -dx;
3734 if (dy < 0) s_y = -dy;
3735 int d_x = 0;
3736 int d_y = 0;
3737 if (dx > 0) d_x = dx;
3738 if (dy > 0) d_y = dy;
3739
3740 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3741 pizza->bin_window, s_x, s_y, w, h );
3742
3743 wxRect rect;
3744 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3745 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3746 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3747 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3748
3749 Refresh( TRUE, &rect );
3750 }
3751
3752 gdk_gc_unref( m_scrollGC );
3753 }
3754*/
c801d85f 3755}