]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/window.cpp
Use wxClientDC in header window so we don't clip (because of gtk_paint_box not
[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
47c93b63
RR
658//-----------------------------------------------------------------------------
659// "size_request" of m_widget
660//-----------------------------------------------------------------------------
661
662static void gtk_window_size_request_callback( GtkWidget *widget, GtkRequisition *requisition, wxWindow *win )
663{
664 int w,h;
665 win->GetSize( &w, &h );
666 if (w < 2) w = 2;
667 if (h < 2) h = 2;
668
669 requisition->height = h;
670 requisition->width = w;
671}
672
c801d85f 673//-----------------------------------------------------------------------------
034be888 674// "expose_event" of m_wxwindow
c801d85f
KB
675//-----------------------------------------------------------------------------
676
b6fa52db 677static int gtk_window_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindow *win )
47d67540 678{
3ac8d3bc
RR
679 DEBUG_MAIN_THREAD
680
b6fa52db
RR
681 if (g_isIdle)
682 wxapp_install_idle_handler();
683
40c70187 684/*
8cb9f0d0 685 if (win->GetName() == wxT("panel"))
3d2d8da1
RR
686 {
687 wxPrintf( wxT("OnExpose from ") );
688 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
689 wxPrintf( win->GetClassInfo()->GetClassName() );
690 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
691 (int)gdk_event->area.y,
692 (int)gdk_event->area.width,
693 (int)gdk_event->area.height );
694 }
40c70187 695*/
3d2d8da1 696
2bc6945a 697 GtkPizza *pizza = GTK_PIZZA (widget);
a2d93e73 698
a2d93e73
JS
699 if (win->GetThemeEnabled())
700 {
701 wxWindow *parent = win->GetParent();
702 while (parent && !parent->IsTopLevel())
703 parent = parent->GetParent();
704 if (!parent)
705 parent = win;
706
789dbcd4
RR
707 gtk_paint_flat_box (parent->m_widget->style, pizza->bin_window, GTK_STATE_NORMAL,
708 GTK_SHADOW_NONE, &gdk_event->area, parent->m_widget, "base", 0, 0, -1, -1);
2bc6945a
RR
709 }
710
711 win->GetUpdateRegion().Union( gdk_event->area.x,
712 gdk_event->area.y,
713 gdk_event->area.width,
714 gdk_event->area.height );
0e09f76e 715
9cc7121f
RR
716 if (gdk_event->count == 0)
717 {
e22454be
RR
718 win->m_clipPaintRegion = TRUE;
719
9cc7121f
RR
720 wxEraseEvent eevent( win->GetId() );
721 eevent.SetEventObject( win );
722 win->GetEventHandler()->ProcessEvent(eevent);
f7a11f8c 723
9cc7121f
RR
724 wxPaintEvent event( win->GetId() );
725 event.SetEventObject( win );
726 win->GetEventHandler()->ProcessEvent( event );
727
728 win->GetUpdateRegion().Clear();
e22454be
RR
729
730 win->m_clipPaintRegion = FALSE;
9cc7121f 731 }
b6fa52db 732
b420fb6a
RR
733 /* The following code will result in all window-less widgets
734 being redrawn if the wxWindows class is given a chance to
735 paint *anything* because it will then be allowed to paint
736 over the window-less widgets */
b6fa52db 737
b420fb6a
RR
738 GList *children = pizza->children;
739 while (children)
740 {
741 GtkPizzaChild *child = (GtkPizzaChild*) children->data;
742 children = children->next;
b6fa52db 743
b420fb6a 744 GdkEventExpose child_event = *gdk_event;
b6fa52db 745
b420fb6a
RR
746 if (GTK_WIDGET_NO_WINDOW (child->widget) &&
747 GTK_WIDGET_DRAWABLE (child->widget) /* &&
748 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
749 {
750 child_event.area.x = child->widget->allocation.x;
751 child_event.area.y = child->widget->allocation.y;
752 child_event.area.width = child->widget->allocation.width;
753 child_event.area.height = child->widget->allocation.height;
754 gtk_widget_event (child->widget, (GdkEvent*) &child_event);
755 }
b6fa52db 756 }
b6fa52db
RR
757
758 return TRUE;
759}
760
761//-----------------------------------------------------------------------------
762// "event" of m_wxwindow
763//-----------------------------------------------------------------------------
764
765/* GTK thinks it is clever and filters out a certain amount of "unneeded"
766 expose events. We need them, of course, so we override the main event
b420fb6a
RR
767 procedure in GtkWidget by giving our own handler for all system events.
768 There, we look for expose events ourselves whereas all other events are
769 handled normally. */
b6fa52db
RR
770
771gint gtk_window_event_event_callback( GtkWidget *widget, GdkEventExpose *event, wxWindow *win )
772{
773 if (event->type == GDK_EXPOSE)
774 {
775 gint ret = gtk_window_expose_callback( widget, event, win );
776 return ret;
777 }
778
b6fa52db 779 return FALSE;
362c6693 780}
c801d85f
KB
781
782//-----------------------------------------------------------------------------
034be888 783// "draw" of m_wxwindow
2f2aa628 784//-----------------------------------------------------------------------------
c801d85f 785
b6fa52db
RR
786/* This callback is a complete replacement of the gtk_pizza_draw() function,
787 which disabled. */
788
789static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxWindow *win )
47d67540 790{
3ac8d3bc
RR
791 DEBUG_MAIN_THREAD
792
c50f1fb9 793 if (g_isIdle)
a2053b27 794 wxapp_install_idle_handler();
2d19ad25 795
e22454be
RR
796 if ((win->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE)) &&
797 (win->GetChildren().GetCount() == 0))
798 {
799 return;
800 }
2d19ad25 801
40c70187 802/*
8cb9f0d0 803 if (win->GetName() == wxT("panel"))
3d2d8da1
RR
804 {
805 wxPrintf( wxT("OnDraw from ") );
806 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
807 wxPrintf( win->GetClassInfo()->GetClassName() );
808 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
809 (int)rect->y,
810 (int)rect->width,
811 (int)rect->height );
812 }
40c70187 813*/
b6fa52db 814
b420fb6a 815 GtkPizza *pizza = GTK_PIZZA (widget);
2bc6945a 816
9cc7121f 817 if (win->GetThemeEnabled())
789dbcd4 818 {
9cc7121f
RR
819 wxWindow *parent = win->GetParent();
820 while (parent && !parent->IsTopLevel())
789dbcd4 821 parent = parent->GetParent();
9cc7121f
RR
822 if (!parent)
823 parent = win;
824
789dbcd4
RR
825 gtk_paint_flat_box (parent->m_widget->style, pizza->bin_window, GTK_STATE_NORMAL,
826 GTK_SHADOW_NONE, rect, parent->m_widget, "base", 0, 0, -1, -1);
827 }
828
9cc7121f
RR
829
830 if (!(GTK_WIDGET_APP_PAINTABLE (widget)) &&
831 (pizza->clear_on_draw))
832 {
833 gdk_window_clear_area( pizza->bin_window,
b420fb6a 834 rect->x, rect->y, rect->width, rect->height);
9cc7121f 835 }
b420fb6a 836
9cc7121f 837 win->GetUpdateRegion().Union( rect->x, rect->y, rect->width, rect->height );
148cd9b6 838
9cc7121f 839 win->m_clipPaintRegion = TRUE;
304e5625 840
e22454be
RR
841 wxEraseEvent eevent( win->GetId() );
842 eevent.SetEventObject( win );
843 win->GetEventHandler()->ProcessEvent(eevent);
148cd9b6 844
e22454be
RR
845 wxPaintEvent event( win->GetId() );
846 event.SetEventObject( win );
847 win->GetEventHandler()->ProcessEvent( event );
47d67540 848
e22454be 849 win->GetUpdateRegion().Clear();
b6fa52db 850
e22454be 851 win->m_clipPaintRegion = FALSE;
304e5625 852
b420fb6a 853
e22454be
RR
854 GList *children = pizza->children;
855 while (children)
856 {
b420fb6a
RR
857 GtkPizzaChild *child = (GtkPizzaChild*) children->data;
858 children = children->next;
859
860 GdkRectangle child_area;
861 if (gtk_widget_intersect (child->widget, rect, &child_area))
862 {
863 gtk_widget_draw (child->widget, &child_area /* (GdkRectangle*) NULL*/ );
864 }
e22454be 865 }
362c6693 866}
c801d85f
KB
867
868//-----------------------------------------------------------------------------
b292e2f5 869// "key_press_event" from any window
c801d85f 870//-----------------------------------------------------------------------------
c801d85f 871
2f2aa628 872static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
47d67540 873{
3ac8d3bc
RR
874 DEBUG_MAIN_THREAD
875
c50f1fb9 876 if (g_isIdle)
a2053b27
RR
877 wxapp_install_idle_handler();
878
879 if (!win->m_hasVMT) return FALSE;
f5e27805 880 if (g_blockEventsOnDrag) return FALSE;
c801d85f 881
3d6f7261 882
7be4c594 883/*
b79395c5
RR
884 wxString tmp;
885 tmp += (char)gdk_event->keyval;
886 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
d1367c3d 887 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
7be4c594 888*/
2daa0ce9 889
b0e813a0
RR
890 int x = 0;
891 int y = 0;
892 GdkModifierType state;
893 if (gdk_event->window) gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
47d67540 894
3017f78d 895 bool ret = FALSE;
148cd9b6 896
74505862 897 long key_code = map_to_unmodified_wx_keysym( gdk_event->keyval );
f0492f7d
RR
898 /* sending unknown key events doesn't really make sense */
899 if (key_code == 0) return FALSE;
900
c50f1fb9 901 wxKeyEvent event( wxEVT_KEY_DOWN );
d1367c3d 902 event.SetTimestamp( gdk_event->time );
f5e27805
RR
903 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
904 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
905 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
906 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
907 event.m_keyCode = key_code;
b0e813a0
RR
908 event.m_scanCode = gdk_event->keyval;
909 event.m_x = x;
910 event.m_y = y;
f5e27805 911 event.SetEventObject( win );
c5b42c87 912 ret = win->GetEventHandler()->ProcessEvent( event );
c50f1fb9 913
88ac883a 914#if wxUSE_ACCEL
f5e27805 915 if (!ret)
47d67540 916 {
f5e27805
RR
917 wxWindow *ancestor = win;
918 while (ancestor)
919 {
920 int command = ancestor->GetAcceleratorTable()->GetCommand( event );
921 if (command != -1)
922 {
923 wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
924 ret = ancestor->GetEventHandler()->ProcessEvent( command_event );
925 break;
926 }
f6bcfd97 927 if (ancestor->IsTopLevel())
b02da6b1 928 break;
f5e27805
RR
929 ancestor = ancestor->GetParent();
930 }
bcf1fa6b 931 }
88ac883a 932#endif // wxUSE_ACCEL
3017f78d 933
d728dd40
KB
934 /* wxMSW doesn't send char events with Alt pressed */
935 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
3017f78d
RR
936 will only be sent if it is not in an accelerator table. */
937 key_code = map_to_wx_keysym( gdk_event->keyval );
148cd9b6 938
3017f78d
RR
939 if ( (!ret) &&
940 (key_code != 0))
d728dd40 941 {
c50f1fb9 942 wxKeyEvent event2( wxEVT_CHAR );
d728dd40
KB
943 event2.SetTimestamp( gdk_event->time );
944 event2.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
945 event2.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
946 event2.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
947 event2.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
948 event2.m_keyCode = key_code;
949 event2.m_scanCode = gdk_event->keyval;
950 event2.m_x = x;
951 event2.m_y = y;
952 event2.SetEventObject( win );
3017f78d 953 ret = win->GetEventHandler()->ProcessEvent( event2 );
d728dd40
KB
954 }
955
053f9cc1 956 /* win is a control: tab can be propagated up */
ca298c88 957 if ( (!ret) &&
5664fc32 958 ((gdk_event->keyval == GDK_Tab) || (gdk_event->keyval == GDK_ISO_Left_Tab)) &&
f6bcfd97
BP
959// VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
960// have this style, yet choose not to process this particular TAB in which
961// case TAB must still work as a navigational character
962#if 0
3da17724 963 (!win->HasFlag(wxTE_PROCESS_TAB)) &&
f6bcfd97 964#endif // 0
b02da6b1
VZ
965 (win->GetParent()) &&
966 (win->GetParent()->HasFlag( wxTAB_TRAVERSAL)) )
b292e2f5
RR
967 {
968 wxNavigationKeyEvent new_event;
8253c7fd 969 new_event.SetEventObject( win->GetParent() );
f03fc89f 970 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
5664fc32 971 new_event.SetDirection( (gdk_event->keyval == GDK_Tab) );
f03fc89f 972 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
b98d804b 973 new_event.SetWindowChange( (gdk_event->state & GDK_CONTROL_MASK) );
b292e2f5 974 new_event.SetCurrentFocus( win );
8253c7fd 975 ret = win->GetParent()->GetEventHandler()->ProcessEvent( new_event );
b292e2f5 976 }
ff8bfdbb 977
801aa178 978 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
ca298c88 979 if ( (!ret) &&
b98d804b
RR
980 (gdk_event->keyval == GDK_Escape) )
981 {
982 wxCommandEvent new_event(wxEVT_COMMAND_BUTTON_CLICKED,wxID_CANCEL);
983 new_event.SetEventObject( win );
984 ret = win->GetEventHandler()->ProcessEvent( new_event );
985 }
c50f1fb9 986
6bc8a1c8 987#if (GTK_MINOR_VERSION > 0)
da048e3d
RR
988 /* Pressing F10 will activate the menu bar of the top frame. */
989 /* Doesn't work. */
3017f78d 990/*
801aa178
RR
991 if ( (!ret) &&
992 (gdk_event->keyval == GDK_F10) )
993 {
994 wxWindow *ancestor = win;
995 while (ancestor)
996 {
997 if (wxIsKindOf(ancestor,wxFrame))
c50f1fb9
VZ
998 {
999 wxFrame *frame = (wxFrame*) ancestor;
801aa178 1000 wxMenuBar *menubar = frame->GetMenuBar();
c50f1fb9
VZ
1001 if (menubar)
1002 {
801aa178 1003 wxNode *node = menubar->GetMenus().First();
c50f1fb9
VZ
1004 if (node)
1005 {
3017f78d
RR
1006 wxMenu *firstMenu = (wxMenu*) node->Data();
1007 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
1008 ret = TRUE;
c50f1fb9
VZ
1009 break;
1010 }
1011 }
1012 }
801aa178
RR
1013 ancestor = ancestor->GetParent();
1014 }
1015 }
3017f78d 1016*/
6bc8a1c8 1017#endif
ca298c88 1018
f5e27805
RR
1019 if (ret)
1020 {
b292e2f5 1021 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
f03fc89f 1022 return TRUE;
f5e27805 1023 }
47d67540 1024
034be888 1025 return FALSE;
362c6693 1026}
c801d85f 1027
b666df2c
RR
1028//-----------------------------------------------------------------------------
1029// "key_release_event" from any window
1030//-----------------------------------------------------------------------------
1031
1032static gint gtk_window_key_release_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
1033{
3ac8d3bc
RR
1034 DEBUG_MAIN_THREAD
1035
c50f1fb9 1036 if (g_isIdle)
a2053b27
RR
1037 wxapp_install_idle_handler();
1038
1039 if (!win->m_hasVMT) return FALSE;
b666df2c
RR
1040 if (g_blockEventsOnDrag) return FALSE;
1041
1042/*
d1367c3d
RR
1043 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
1044 if (gdk_event->state & GDK_SHIFT_MASK)
1045 printf( "ShiftDown.\n" );
1046 else
1047 printf( "ShiftUp.\n" );
1048 if (gdk_event->state & GDK_CONTROL_MASK)
1049 printf( "ControlDown.\n" );
1050 else
1051 printf( "ControlUp.\n" );
1052 printf( "\n" );
b666df2c
RR
1053*/
1054
74505862 1055 long key_code = map_to_unmodified_wx_keysym( gdk_event->keyval );
c50f1fb9 1056
f0492f7d
RR
1057 /* sending unknown key events doesn't really make sense */
1058 if (key_code == 0) return FALSE;
b666df2c 1059
b0e813a0
RR
1060 int x = 0;
1061 int y = 0;
1062 GdkModifierType state;
1063 if (gdk_event->window) gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
b666df2c
RR
1064
1065 wxKeyEvent event( wxEVT_KEY_UP );
d1367c3d 1066 event.SetTimestamp( gdk_event->time );
b666df2c
RR
1067 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
1068 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
1069 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
1070 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
1071 event.m_keyCode = key_code;
b0e813a0
RR
1072 event.m_scanCode = gdk_event->keyval;
1073 event.m_x = x;
1074 event.m_y = y;
b666df2c
RR
1075 event.SetEventObject( win );
1076
034be888 1077 if (win->GetEventHandler()->ProcessEvent( event ))
b666df2c 1078 {
b98d804b 1079 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_release_event" );
f03fc89f 1080 return TRUE;
b666df2c
RR
1081 }
1082
034be888 1083 return FALSE;
b666df2c
RR
1084}
1085
2daa0ce9
VZ
1086// ----------------------------------------------------------------------------
1087// mouse event processing helper
1088// ----------------------------------------------------------------------------
1089
1090static void AdjustEventButtonState(wxMouseEvent& event)
1091{
1092 // GDK reports the old state of the button for a button press event, but
1093 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1094 // for a LEFT_DOWN event, not FALSE, so we will invert
1095 // left/right/middleDown for the corresponding click events
1096 switch ( event.GetEventType() )
1097 {
1098 case wxEVT_LEFT_DOWN:
1099 case wxEVT_LEFT_DCLICK:
1100 case wxEVT_LEFT_UP:
1101 event.m_leftDown = !event.m_leftDown;
1102 break;
1103
1104 case wxEVT_MIDDLE_DOWN:
1105 case wxEVT_MIDDLE_DCLICK:
1106 case wxEVT_MIDDLE_UP:
1107 event.m_middleDown = !event.m_middleDown;
1108 break;
1109
1110 case wxEVT_RIGHT_DOWN:
1111 case wxEVT_RIGHT_DCLICK:
1112 case wxEVT_RIGHT_UP:
1113 event.m_rightDown = !event.m_rightDown;
1114 break;
1115 }
1116}
1117
c801d85f 1118//-----------------------------------------------------------------------------
2f2aa628
RR
1119// "button_press_event"
1120//-----------------------------------------------------------------------------
c801d85f 1121
2f2aa628 1122static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
903f689b 1123{
3ac8d3bc
RR
1124 DEBUG_MAIN_THREAD
1125
c50f1fb9 1126 if (g_isIdle)
a2053b27
RR
1127 wxapp_install_idle_handler();
1128
1129/*
223d09f6 1130 wxPrintf( wxT("1) OnButtonPress from ") );
a2053b27
RR
1131 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1132 wxPrintf( win->GetClassInfo()->GetClassName() );
223d09f6 1133 wxPrintf( wxT(".\n") );
a2053b27 1134*/
a2053b27 1135 if (!win->m_hasVMT) return FALSE;
f5e27805 1136 if (g_blockEventsOnDrag) return TRUE;
76ed8f8d 1137 if (g_blockEventsOnScroll) return TRUE;
c801d85f 1138
034be888
RR
1139 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
1140
a2053b27 1141 if (win->m_wxwindow)
c801d85f 1142 {
a2053b27 1143 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow) && !GTK_WIDGET_HAS_FOCUS (win->m_wxwindow) )
f5e27805 1144 {
a2053b27 1145 gtk_widget_grab_focus (win->m_wxwindow);
47d67540 1146
c801d85f 1147/*
223d09f6 1148 wxPrintf( wxT("GrabFocus from ") );
f5e27805 1149 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
a2053b27 1150 wxPrintf( win->GetClassInfo()->GetClassName() );
223d09f6 1151 wxPrintf( wxT(".\n") );
c801d85f 1152*/
47d67540 1153
f5e27805 1154 }
362c6693 1155 }
47d67540 1156
2daa0ce9 1157 wxEventType event_type = wxEVT_NULL;
47d67540 1158
f5e27805 1159 if (gdk_event->button == 1)
c801d85f 1160 {
f5e27805
RR
1161 switch (gdk_event->type)
1162 {
1163 case GDK_BUTTON_PRESS: event_type = wxEVT_LEFT_DOWN; break;
1164 case GDK_2BUTTON_PRESS: event_type = wxEVT_LEFT_DCLICK; break;
1165 default: break;
1166 }
362c6693 1167 }
f5e27805 1168 else if (gdk_event->button == 2)
c801d85f 1169 {
f5e27805
RR
1170 switch (gdk_event->type)
1171 {
1172 case GDK_BUTTON_PRESS: event_type = wxEVT_MIDDLE_DOWN; break;
1173 case GDK_2BUTTON_PRESS: event_type = wxEVT_MIDDLE_DCLICK; break;
1174 default: break;
1175 }
362c6693 1176 }
f5e27805 1177 else if (gdk_event->button == 3)
c801d85f 1178 {
f5e27805
RR
1179 switch (gdk_event->type)
1180 {
1181 case GDK_BUTTON_PRESS: event_type = wxEVT_RIGHT_DOWN; break;
1182 case GDK_2BUTTON_PRESS: event_type = wxEVT_RIGHT_DCLICK; break;
1183 default: break;
1184 }
362c6693 1185 }
47d67540 1186
2daa0ce9
VZ
1187 if ( event_type == wxEVT_NULL )
1188 {
1189 // unknown mouse button or click type
1190 return FALSE;
1191 }
1192
f5e27805 1193 wxMouseEvent event( event_type );
d1367c3d 1194 event.SetTimestamp( gdk_event->time );
f5e27805
RR
1195 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
1196 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
1197 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
1198 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
1199 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
1200 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
1201 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
47d67540 1202
13111b2a
VZ
1203 event.m_x = (wxCoord)gdk_event->x;
1204 event.m_y = (wxCoord)gdk_event->y;
47d67540 1205
2daa0ce9
VZ
1206 AdjustEventButtonState(event);
1207
f5e27805
RR
1208 // Some control don't have their own X window and thus cannot get
1209 // any events.
47d67540 1210
72195a0f 1211 if (!g_captureWindow)
2f2aa628 1212 {
b02da6b1
VZ
1213 wxCoord x = event.m_x;
1214 wxCoord y = event.m_y;
2f073eb2
RR
1215 if (win->m_wxwindow)
1216 {
da048e3d 1217 GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
b02da6b1
VZ
1218 x += pizza->xoffset;
1219 y += pizza->yoffset;
2f073eb2
RR
1220 }
1221
db1b4961 1222 wxNode *node = win->GetChildren().First();
f5e27805
RR
1223 while (node)
1224 {
1225 wxWindow *child = (wxWindow*)node->Data();
148cd9b6 1226
f96ac56a 1227 node = node->Next();
b02da6b1
VZ
1228 if (!child->IsShown())
1229 continue;
ff8bfdbb 1230
a2053b27 1231 if (child->m_isStaticBox)
ff8bfdbb
VZ
1232 {
1233 // wxStaticBox is transparent in the box itself
a2053b27
RR
1234 int xx1 = child->m_x;
1235 int yy1 = child->m_y;
1236 int xx2 = child->m_x + child->m_width;
1237 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
1238
1239 // left
1240 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
1241 // right
1242 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1243 // top
1244 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1245 // bottom
1246 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1247 {
1ecc4d80 1248 win = child;
a2053b27
RR
1249 event.m_x -= child->m_x;
1250 event.m_y -= child->m_y;
1ecc4d80 1251 break;
ff8bfdbb
VZ
1252 }
1253
1254 }
1255 else
1256 {
a2053b27 1257 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
2f073eb2
RR
1258 (child->m_x <= x) &&
1259 (child->m_y <= y) &&
1260 (child->m_x+child->m_width >= x) &&
1261 (child->m_y+child->m_height >= y))
1ecc4d80
RR
1262 {
1263 win = child;
a2053b27
RR
1264 event.m_x -= child->m_x;
1265 event.m_y -= child->m_y;
1ecc4d80 1266 break;
ff8bfdbb 1267 }
f5e27805 1268 }
f5e27805 1269 }
2f2aa628 1270 }
ff8bfdbb 1271
f5e27805 1272 event.SetEventObject( win );
47d67540 1273
f5e27805 1274 gs_timeLastClick = gdk_event->time;
47d67540 1275
2f073eb2
RR
1276/*
1277 wxPrintf( wxT("2) OnButtonPress from ") );
1278 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1279 wxPrintf( win->GetClassInfo()->GetClassName() );
1280 wxPrintf( wxT(".\n") );
1281*/
1282
f5e27805 1283 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1284 {
f5e27805 1285 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_press_event" );
f03fc89f 1286 return TRUE;
034be888 1287 }
47d67540 1288
034be888 1289 return FALSE;
362c6693 1290}
c801d85f
KB
1291
1292//-----------------------------------------------------------------------------
97b3455a 1293// "button_release_event"
2f2aa628 1294//-----------------------------------------------------------------------------
c801d85f 1295
2f2aa628 1296static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
47d67540 1297{
3ac8d3bc
RR
1298 DEBUG_MAIN_THREAD
1299
c50f1fb9 1300 if (g_isIdle)
a2053b27
RR
1301 wxapp_install_idle_handler();
1302
1303 if (!win->m_hasVMT) return FALSE;
034be888
RR
1304 if (g_blockEventsOnDrag) return FALSE;
1305 if (g_blockEventsOnScroll) return FALSE;
c801d85f 1306
034be888 1307 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
47d67540 1308
c801d85f 1309/*
f5e27805
RR
1310 printf( "OnButtonRelease from " );
1311 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1312 printf( win->GetClassInfo()->GetClassName() );
1313 printf( ".\n" );
c801d85f 1314*/
47d67540 1315
f5e27805 1316 wxEventType event_type = wxEVT_NULL;
47d67540 1317
f5e27805
RR
1318 switch (gdk_event->button)
1319 {
1320 case 1: event_type = wxEVT_LEFT_UP; break;
1321 case 2: event_type = wxEVT_MIDDLE_UP; break;
1322 case 3: event_type = wxEVT_RIGHT_UP; break;
2daa0ce9 1323 default: return FALSE;
f5e27805 1324 }
47d67540 1325
f5e27805 1326 wxMouseEvent event( event_type );
d1367c3d 1327 event.SetTimestamp( gdk_event->time );
f5e27805
RR
1328 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
1329 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
1330 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
1331 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
1332 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
1333 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
1334 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
13111b2a
VZ
1335 event.m_x = (wxCoord)gdk_event->x;
1336 event.m_y = (wxCoord)gdk_event->y;
f5e27805 1337
2daa0ce9
VZ
1338 AdjustEventButtonState(event);
1339
f5e27805
RR
1340 // Some control don't have their own X window and thus cannot get
1341 // any events.
1342
72195a0f 1343 if (!g_captureWindow)
2f2aa628 1344 {
b02da6b1
VZ
1345 wxCoord x = event.m_x;
1346 wxCoord y = event.m_y;
2f073eb2
RR
1347 if (win->m_wxwindow)
1348 {
da048e3d 1349 GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
b02da6b1
VZ
1350 x += pizza->xoffset;
1351 y += pizza->yoffset;
2f073eb2
RR
1352 }
1353
db1b4961 1354 wxNode *node = win->GetChildren().First();
f5e27805
RR
1355 while (node)
1356 {
1357 wxWindow *child = (wxWindow*)node->Data();
ff8bfdbb 1358
f96ac56a 1359 node = node->Next();
b02da6b1
VZ
1360 if (!child->IsShown())
1361 continue;
f96ac56a 1362
a2053b27 1363 if (child->m_isStaticBox)
ff8bfdbb
VZ
1364 {
1365 // wxStaticBox is transparent in the box itself
a2053b27
RR
1366 int xx1 = child->m_x;
1367 int yy1 = child->m_y;
1368 int xx2 = child->m_x + child->m_width;
1369 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
1370
1371 // left
1372 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
1373 // right
1374 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1375 // top
1376 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1377 // bottom
1378 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1379 {
1ecc4d80 1380 win = child;
a2053b27
RR
1381 event.m_x -= child->m_x;
1382 event.m_y -= child->m_y;
1ecc4d80 1383 break;
ff8bfdbb
VZ
1384 }
1385
1386 }
1387 else
1388 {
a2053b27 1389 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
2f073eb2
RR
1390 (child->m_x <= x) &&
1391 (child->m_y <= y) &&
1392 (child->m_x+child->m_width >= x) &&
1393 (child->m_y+child->m_height >= y))
1ecc4d80
RR
1394 {
1395 win = child;
a2053b27
RR
1396 event.m_x -= child->m_x;
1397 event.m_y -= child->m_y;
1ecc4d80 1398 break;
ff8bfdbb 1399 }
f5e27805 1400 }
f5e27805 1401 }
2f2aa628 1402 }
47d67540 1403
f5e27805 1404 event.SetEventObject( win );
47d67540 1405
f5e27805 1406 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1407 {
f5e27805 1408 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_release_event" );
f03fc89f 1409 return TRUE;
034be888 1410 }
47d67540 1411
034be888 1412 return FALSE;
362c6693 1413}
c801d85f
KB
1414
1415//-----------------------------------------------------------------------------
2f2aa628
RR
1416// "motion_notify_event"
1417//-----------------------------------------------------------------------------
c801d85f 1418
2f2aa628 1419static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win )
47d67540 1420{
3ac8d3bc
RR
1421 DEBUG_MAIN_THREAD
1422
c50f1fb9 1423 if (g_isIdle)
a2053b27
RR
1424 wxapp_install_idle_handler();
1425
1426 if (!win->m_hasVMT) return FALSE;
034be888
RR
1427 if (g_blockEventsOnDrag) return FALSE;
1428 if (g_blockEventsOnScroll) return FALSE;
148cd9b6 1429
034be888
RR
1430 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
1431
ff8bfdbb 1432 if (gdk_event->is_hint)
aae24d21 1433 {
f7a11f8c
RR
1434 int x = 0;
1435 int y = 0;
1436 GdkModifierType state;
1437 gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
1438 gdk_event->x = x;
1439 gdk_event->y = y;
aae24d21 1440 }
ff8bfdbb 1441
c801d85f 1442/*
e380f72b
RR
1443 printf( "OnMotion from " );
1444 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1445 printf( win->GetClassInfo()->GetClassName() );
1446 printf( ".\n" );
aae24d21 1447*/
47d67540 1448
e380f72b 1449 wxMouseEvent event( wxEVT_MOTION );
d1367c3d 1450 event.SetTimestamp( gdk_event->time );
e380f72b
RR
1451 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
1452 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
1453 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
1454 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
1455 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
1456 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
1457 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
1458
13111b2a
VZ
1459 event.m_x = (wxCoord)gdk_event->x;
1460 event.m_y = (wxCoord)gdk_event->y;
e380f72b
RR
1461
1462 // Some control don't have their own X window and thus cannot get
1463 // any events.
1464
72195a0f 1465 if (!g_captureWindow)
2f2aa628 1466 {
b02da6b1
VZ
1467 wxCoord x = event.m_x;
1468 wxCoord y = event.m_y;
2f073eb2
RR
1469 if (win->m_wxwindow)
1470 {
da048e3d 1471 GtkPizza *pizza = GTK_PIZZA(win->m_wxwindow);
b02da6b1
VZ
1472 x += pizza->xoffset;
1473 y += pizza->yoffset;
2f073eb2
RR
1474 }
1475
db1b4961 1476 wxNode *node = win->GetChildren().First();
e380f72b
RR
1477 while (node)
1478 {
1479 wxWindow *child = (wxWindow*)node->Data();
ff8bfdbb 1480
f96ac56a 1481 node = node->Next();
b02da6b1
VZ
1482 if (!child->IsShown())
1483 continue;
f96ac56a 1484
a2053b27 1485 if (child->m_isStaticBox)
ff8bfdbb
VZ
1486 {
1487 // wxStaticBox is transparent in the box itself
a2053b27
RR
1488 int xx1 = child->m_x;
1489 int yy1 = child->m_y;
1490 int xx2 = child->m_x + child->m_width;
1491 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
1492
1493 // left
1494 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
1495 // right
1496 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
1497 // top
1498 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
1499 // bottom
1500 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
1501 {
1ecc4d80 1502 win = child;
a2053b27
RR
1503 event.m_x -= child->m_x;
1504 event.m_y -= child->m_y;
1ecc4d80 1505 break;
ff8bfdbb
VZ
1506 }
1507
1508 }
1509 else
1510 {
a2053b27 1511 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
2f073eb2
RR
1512 (child->m_x <= x) &&
1513 (child->m_y <= y) &&
1514 (child->m_x+child->m_width >= x) &&
1515 (child->m_y+child->m_height >= y))
1ecc4d80
RR
1516 {
1517 win = child;
a2053b27
RR
1518 event.m_x -= child->m_x;
1519 event.m_y -= child->m_y;
1ecc4d80 1520 break;
ff8bfdbb 1521 }
e380f72b 1522 }
e380f72b 1523 }
2f2aa628 1524 }
47d67540 1525
e380f72b 1526 event.SetEventObject( win );
47d67540 1527
e380f72b 1528 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1529 {
e380f72b 1530 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "motion_notify_event" );
f03fc89f 1531 return TRUE;
034be888 1532 }
47d67540 1533
034be888 1534 return FALSE;
362c6693 1535}
c801d85f
KB
1536
1537//-----------------------------------------------------------------------------
2f2aa628
RR
1538// "focus_in_event"
1539//-----------------------------------------------------------------------------
c801d85f 1540
2f2aa628 1541static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
c801d85f 1542{
3ac8d3bc
RR
1543 DEBUG_MAIN_THREAD
1544
c50f1fb9 1545 if (g_isIdle)
a2053b27
RR
1546 wxapp_install_idle_handler();
1547
1548 if (!win->m_hasVMT) return FALSE;
034be888 1549 if (g_blockEventsOnDrag) return FALSE;
ff8bfdbb 1550
148cd9b6
VZ
1551 switch ( g_sendActivateEvent )
1552 {
1553 case -1:
1554 // we've got focus from outside, synthtize wxActivateEvent
1555 g_sendActivateEvent = 1;
1556 break;
1557
1558 case 0:
1559 // another our window just lost focus, it was already ours before
1560 // - don't send any wxActivateEvent
1561 g_sendActivateEvent = -1;
1562 break;
1563 }
1564
b292e2f5 1565 g_focusWindow = win;
ff8bfdbb 1566
c801d85f 1567/*
f03fc89f 1568 printf( "OnSetFocus from " );
e380f72b 1569 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
f03fc89f
VZ
1570 printf( win->GetClassInfo()->GetClassName() );
1571 printf( " " );
1572 printf( WXSTRINGCAST win->GetLabel() );
1573 printf( ".\n" );
c801d85f 1574*/
47d67540 1575
3da17724
RR
1576 wxPanel *panel = wxDynamicCast(win->GetParent(), wxPanel);
1577 if (panel)
1578 {
1579 panel->SetLastFocus(win);
1580 }
148cd9b6 1581
b79395c5
RR
1582#ifdef HAVE_XIM
1583 if (win->m_ic)
1584 gdk_im_begin(win->m_ic, win->m_wxwindow->window);
1585#endif
1586
f6bcfd97
BP
1587#ifdef wxUSE_CARET
1588 // caret needs to be informed about focus change
1589 wxCaret *caret = win->GetCaret();
1590 if ( caret )
1591 {
1592 caret->OnSetFocus();
1593 }
1594#endif // wxUSE_CARET
1595
e380f72b
RR
1596 wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
1597 event.SetEventObject( win );
47d67540 1598
e380f72b 1599 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1600 {
e380f72b 1601 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
034be888
RR
1602 return TRUE;
1603 }
ca298c88 1604
034be888 1605 return FALSE;
362c6693 1606}
c801d85f
KB
1607
1608//-----------------------------------------------------------------------------
2f2aa628
RR
1609// "focus_out_event"
1610//-----------------------------------------------------------------------------
c801d85f 1611
2f2aa628 1612static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
c801d85f 1613{
3ac8d3bc
RR
1614 DEBUG_MAIN_THREAD
1615
c50f1fb9 1616 if (g_isIdle)
a2053b27
RR
1617 wxapp_install_idle_handler();
1618
1619 if (!win->m_hasVMT) return FALSE;
034be888 1620 if (g_blockEventsOnDrag) return FALSE;
ca298c88 1621
148cd9b6
VZ
1622 // if the focus goes out of our app alltogether, OnIdle() will send
1623 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1624 // g_sendActivateEvent to -1
1625 g_sendActivateEvent = 0;
1626
f6bcfd97
BP
1627 wxWindow *winFocus = FindFocusedChild(win);
1628 if ( winFocus )
1629 win = winFocus;
1630
148cd9b6
VZ
1631 g_focusWindow = (wxWindow *)NULL;
1632
c801d85f 1633/*
f03fc89f 1634 printf( "OnKillFocus from " );
e380f72b 1635 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
f03fc89f
VZ
1636 printf( win->GetClassInfo()->GetClassName() );
1637 printf( ".\n" );
c801d85f 1638*/
47d67540 1639
b79395c5
RR
1640#ifdef HAVE_XIM
1641 if (win->m_ic)
1642 gdk_im_end();
1643#endif
1644
f6bcfd97
BP
1645#ifdef wxUSE_CARET
1646 // caret needs to be informed about focus change
1647 wxCaret *caret = win->GetCaret();
1648 if ( caret )
1649 {
1650 caret->OnKillFocus();
1651 }
1652#endif // wxUSE_CARET
1653
e380f72b
RR
1654 wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
1655 event.SetEventObject( win );
47d67540 1656
e380f72b 1657 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1658 {
e380f72b 1659 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
034be888
RR
1660 return TRUE;
1661 }
ca298c88 1662
034be888 1663 return FALSE;
362c6693 1664}
c801d85f 1665
b4071e91
RR
1666//-----------------------------------------------------------------------------
1667// "enter_notify_event"
1668//-----------------------------------------------------------------------------
1669
1670static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
1671{
3ac8d3bc
RR
1672 DEBUG_MAIN_THREAD
1673
c50f1fb9 1674 if (g_isIdle)
a2053b27 1675 wxapp_install_idle_handler();
ca298c88 1676
a2053b27
RR
1677 if (!win->m_hasVMT) return FALSE;
1678 if (g_blockEventsOnDrag) return FALSE;
47d67540 1679
a2053b27 1680 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
b292e2f5 1681
e380f72b 1682 wxMouseEvent event( wxEVT_ENTER_WINDOW );
6bc8a1c8 1683#if (GTK_MINOR_VERSION > 0)
d1367c3d 1684 event.SetTimestamp( gdk_event->time );
6bc8a1c8 1685#endif
e380f72b 1686 event.SetEventObject( win );
ff8bfdbb 1687
4a33eba6
RR
1688 int x = 0;
1689 int y = 0;
1690 GdkModifierType state = (GdkModifierType)0;
ff8bfdbb 1691
a2053b27 1692 gdk_window_get_pointer( widget->window, &x, &y, &state );
ff8bfdbb 1693
4a33eba6
RR
1694 event.m_shiftDown = (state & GDK_SHIFT_MASK);
1695 event.m_controlDown = (state & GDK_CONTROL_MASK);
1696 event.m_altDown = (state & GDK_MOD1_MASK);
1697 event.m_metaDown = (state & GDK_MOD2_MASK);
1698 event.m_leftDown = (state & GDK_BUTTON1_MASK);
1699 event.m_middleDown = (state & GDK_BUTTON2_MASK);
1700 event.m_rightDown = (state & GDK_BUTTON3_MASK);
1701
13111b2a
VZ
1702 event.m_x = x;
1703 event.m_y = y;
ff8bfdbb 1704
e380f72b 1705 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1706 {
e380f72b 1707 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "enter_notify_event" );
034be888
RR
1708 return TRUE;
1709 }
ca298c88 1710
034be888 1711 return FALSE;
b4071e91 1712}
47d67540 1713
b4071e91
RR
1714//-----------------------------------------------------------------------------
1715// "leave_notify_event"
1716//-----------------------------------------------------------------------------
1717
1718static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
1719{
3ac8d3bc
RR
1720 DEBUG_MAIN_THREAD
1721
c50f1fb9 1722 if (g_isIdle)
a2053b27 1723 wxapp_install_idle_handler();
acfd422a 1724
a2053b27
RR
1725 if (!win->m_hasVMT) return FALSE;
1726 if (g_blockEventsOnDrag) return FALSE;
b292e2f5 1727
a2053b27 1728 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
c50f1fb9 1729
e380f72b 1730 wxMouseEvent event( wxEVT_LEAVE_WINDOW );
6bc8a1c8 1731#if (GTK_MINOR_VERSION > 0)
d1367c3d 1732 event.SetTimestamp( gdk_event->time );
6bc8a1c8 1733#endif
e380f72b 1734 event.SetEventObject( win );
47d67540 1735
4a33eba6
RR
1736 int x = 0;
1737 int y = 0;
1738 GdkModifierType state = (GdkModifierType)0;
ff8bfdbb 1739
4a33eba6 1740 gdk_window_get_pointer( widget->window, &x, &y, &state );
ff8bfdbb 1741
4a33eba6
RR
1742 event.m_shiftDown = (state & GDK_SHIFT_MASK);
1743 event.m_controlDown = (state & GDK_CONTROL_MASK);
1744 event.m_altDown = (state & GDK_MOD1_MASK);
1745 event.m_metaDown = (state & GDK_MOD2_MASK);
1746 event.m_leftDown = (state & GDK_BUTTON1_MASK);
1747 event.m_middleDown = (state & GDK_BUTTON2_MASK);
1748 event.m_rightDown = (state & GDK_BUTTON3_MASK);
1749
13111b2a
VZ
1750 event.m_x = x;
1751 event.m_y = y;
ff8bfdbb 1752
e380f72b 1753 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1754 {
e380f72b 1755 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "leave_notify_event" );
034be888
RR
1756 return TRUE;
1757 }
ca298c88 1758
034be888 1759 return FALSE;
b4071e91 1760}
47d67540 1761
c801d85f 1762//-----------------------------------------------------------------------------
2f2aa628
RR
1763// "value_changed" from m_vAdjust
1764//-----------------------------------------------------------------------------
c801d85f 1765
5e014a0c 1766static void gtk_window_vscroll_callback( GtkAdjustment *adjust, wxWindow *win )
c801d85f 1767{
3ac8d3bc
RR
1768 DEBUG_MAIN_THREAD
1769
c50f1fb9 1770 if (g_isIdle)
a2053b27 1771 wxapp_install_idle_handler();
c801d85f 1772
a2053b27 1773 if (g_blockEventsOnDrag) return;
47d67540 1774
a2053b27 1775 if (!win->m_hasVMT) return;
148cd9b6 1776
5e014a0c 1777 float diff = adjust->value - win->m_oldVerticalPos;
e380f72b 1778 if (fabs(diff) < 0.2) return;
148cd9b6 1779
5e014a0c 1780 win->m_oldVerticalPos = adjust->value;
47d67540 1781
5e014a0c
RR
1782 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
1783 GtkRange *range = GTK_RANGE( scrolledWindow->vscrollbar );
148cd9b6 1784
5e014a0c
RR
1785 wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
1786 if (range->scroll_type == GTK_SCROLL_STEP_BACKWARD) command = wxEVT_SCROLLWIN_LINEUP;
1787 else if (range->scroll_type == GTK_SCROLL_STEP_FORWARD) command = wxEVT_SCROLLWIN_LINEDOWN;
1788 else if (range->scroll_type == GTK_SCROLL_PAGE_BACKWARD) command = wxEVT_SCROLLWIN_PAGEUP;
1789 else if (range->scroll_type == GTK_SCROLL_PAGE_FORWARD) command = wxEVT_SCROLLWIN_PAGEDOWN;
148cd9b6 1790
5e014a0c 1791 int value = (int)(adjust->value+0.5);
c801d85f 1792
c5b42c87 1793 wxScrollWinEvent event( command, value, wxVERTICAL );
e380f72b
RR
1794 event.SetEventObject( win );
1795 win->GetEventHandler()->ProcessEvent( event );
362c6693 1796}
c801d85f
KB
1797
1798//-----------------------------------------------------------------------------
2f2aa628
RR
1799// "value_changed" from m_hAdjust
1800//-----------------------------------------------------------------------------
c801d85f 1801
5e014a0c 1802static void gtk_window_hscroll_callback( GtkAdjustment *adjust, wxWindow *win )
47d67540 1803{
3ac8d3bc
RR
1804 DEBUG_MAIN_THREAD
1805
c50f1fb9 1806 if (g_isIdle)
a2053b27 1807 wxapp_install_idle_handler();
47d67540 1808
a2053b27
RR
1809 if (g_blockEventsOnDrag) return;
1810 if (!win->m_hasVMT) return;
47d67540 1811
5e014a0c 1812 float diff = adjust->value - win->m_oldHorizontalPos;
e380f72b 1813 if (fabs(diff) < 0.2) return;
148cd9b6 1814
5e014a0c 1815 win->m_oldHorizontalPos = adjust->value;
8bbe427f 1816
5e014a0c
RR
1817 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
1818 GtkRange *range = GTK_RANGE( scrolledWindow->hscrollbar );
148cd9b6 1819
5e014a0c
RR
1820 wxEventType command = wxEVT_SCROLLWIN_THUMBTRACK;
1821 if (range->scroll_type == GTK_SCROLL_STEP_BACKWARD) command = wxEVT_SCROLLWIN_LINEUP;
1822 else if (range->scroll_type == GTK_SCROLL_STEP_FORWARD) command = wxEVT_SCROLLWIN_LINEDOWN;
1823 else if (range->scroll_type == GTK_SCROLL_PAGE_BACKWARD) command = wxEVT_SCROLLWIN_PAGEUP;
1824 else if (range->scroll_type == GTK_SCROLL_PAGE_FORWARD) command = wxEVT_SCROLLWIN_PAGEDOWN;
148cd9b6 1825
5e014a0c 1826 int value = (int)(adjust->value+0.5);
47d67540 1827
c5b42c87 1828 wxScrollWinEvent event( command, value, wxHORIZONTAL );
e380f72b
RR
1829 event.SetEventObject( win );
1830 win->GetEventHandler()->ProcessEvent( event );
362c6693 1831}
c801d85f 1832
cb43b372
RR
1833//-----------------------------------------------------------------------------
1834// "button_press_event" from scrollbar
1835//-----------------------------------------------------------------------------
1836
2a23d363
RR
1837static gint gtk_scrollbar_button_press_callback( GtkRange *widget,
1838 GdkEventButton *gdk_event,
846e1424 1839 wxWindow *win)
cb43b372 1840{
3ac8d3bc
RR
1841 DEBUG_MAIN_THREAD
1842
c50f1fb9 1843 if (g_isIdle)
a2053b27
RR
1844 wxapp_install_idle_handler();
1845
d6d26e04 1846
5b8a521e 1847 g_blockEventsOnScroll = TRUE;
2a23d363 1848 win->m_isScrolling = (gdk_event->window == widget->slider);
47d67540 1849
e380f72b 1850 return FALSE;
cb43b372
RR
1851}
1852
1853//-----------------------------------------------------------------------------
1854// "button_release_event" from scrollbar
1855//-----------------------------------------------------------------------------
1856
88413fec 1857static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
8bbe427f 1858 GdkEventButton *WXUNUSED(gdk_event),
846e1424 1859 wxWindow *win)
cb43b372 1860{
3ac8d3bc
RR
1861 DEBUG_MAIN_THREAD
1862
1ecc4d80 1863// don't test here as we can release the mouse while being over
5e014a0c 1864// a different window than the slider
76ed8f8d
RR
1865//
1866// if (gdk_event->window != widget->slider) return FALSE;
cb43b372 1867
5b8a521e 1868 g_blockEventsOnScroll = FALSE;
47d67540 1869
2a23d363 1870 if (win->m_isScrolling)
88413fec 1871 {
d6d26e04 1872 wxEventType command = wxEVT_SCROLLWIN_THUMBRELEASE;
2a23d363
RR
1873 int value = -1;
1874 int dir = -1;
2daa0ce9 1875
2a23d363
RR
1876 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
1877 if (widget == GTK_RANGE(scrolledWindow->hscrollbar))
1878 {
1879 value = (int)(win->m_hAdjust->value+0.5);
1880 dir = wxHORIZONTAL;
1881 }
1882 if (widget == GTK_RANGE(scrolledWindow->vscrollbar))
1883 {
1884 value = (int)(win->m_vAdjust->value+0.5);
1885 dir = wxVERTICAL;
1886 }
2daa0ce9 1887
2a23d363 1888 wxScrollWinEvent event( command, value, dir );
2a23d363
RR
1889 event.SetEventObject( win );
1890 win->GetEventHandler()->ProcessEvent( event );
88413fec
RR
1891 }
1892
2a23d363 1893 win->m_isScrolling = FALSE;
2daa0ce9 1894
e380f72b 1895 return FALSE;
cb43b372
RR
1896}
1897
f03fc89f
VZ
1898// ----------------------------------------------------------------------------
1899// this wxWindowBase function is implemented here (in platform-specific file)
1900// because it is static and so couldn't be made virtual
1901// ----------------------------------------------------------------------------
2b07d713 1902
f03fc89f 1903wxWindow *wxWindowBase::FindFocus()
2b07d713 1904{
f03fc89f 1905 return g_focusWindow;
2b07d713 1906}
ca298c88 1907
a2053b27
RR
1908//-----------------------------------------------------------------------------
1909// "realize" from m_widget
1910//-----------------------------------------------------------------------------
1911
b79395c5
RR
1912/* We cannot set colours and fonts before the widget has
1913 been realized, so we do this directly after realization. */
a2053b27
RR
1914
1915static gint
63081513 1916gtk_window_realized_callback( GtkWidget *WXUNUSED(m_widget), wxWindow *win )
a2053b27 1917{
3ac8d3bc
RR
1918 DEBUG_MAIN_THREAD
1919
c50f1fb9 1920 if (g_isIdle)
a2053b27
RR
1921 wxapp_install_idle_handler();
1922
739730ca
RR
1923 if (win->m_delayedBackgroundColour)
1924 win->SetBackgroundColour( win->GetBackgroundColour() );
a2053b27 1925
739730ca
RR
1926 if (win->m_delayedForegroundColour)
1927 win->SetForegroundColour( win->GetForegroundColour() );
a2053b27 1928
3c679789
RR
1929 wxWindowCreateEvent event( win );
1930 event.SetEventObject( win );
1931 win->GetEventHandler()->ProcessEvent( event );
3d2d8da1 1932
a2053b27
RR
1933 return FALSE;
1934}
1935
b79395c5
RR
1936//-----------------------------------------------------------------------------
1937// "size_allocate"
1938//-----------------------------------------------------------------------------
1939
8f75cb6c 1940static
adc1999b
RR
1941void gtk_window_size_callback( GtkWidget *WXUNUSED(widget),
1942 GtkAllocation *WXUNUSED(alloc),
8f75cb6c
RR
1943 wxWindow *win )
1944{
1945 if (g_isIdle)
1946 wxapp_install_idle_handler();
2daa0ce9 1947
5b8a521e 1948 if (!win->m_hasScrolling) return;
2daa0ce9 1949
5b8a521e
RR
1950 int client_width = 0;
1951 int client_height = 0;
1952 win->GetClientSize( &client_width, &client_height );
1953 if ((client_width == win->m_oldClientWidth) && (client_height == win->m_oldClientHeight))
1954 return;
2daa0ce9 1955
5b8a521e
RR
1956 win->m_oldClientWidth = client_width;
1957 win->m_oldClientHeight = client_height;
2daa0ce9 1958
5b8a521e
RR
1959 if (!win->m_nativeSizeEvent)
1960 {
1961 wxSizeEvent event( win->GetSize(), win->GetId() );
1962 event.SetEventObject( win );
1963 win->GetEventHandler()->ProcessEvent( event );
1964 }
8f75cb6c
RR
1965}
1966
1967
3ed2e7ce
VZ
1968#ifdef HAVE_XIM
1969 #define WXUNUSED_UNLESS_XIM(param) param
1970#else
1971 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1972#endif
1973
b79395c5
RR
1974/* Resize XIM window */
1975
3ed2e7ce 1976static
8f75cb6c
RR
1977void gtk_wxwindow_size_callback( GtkWidget* WXUNUSED_UNLESS_XIM(widget),
1978 GtkAllocation* WXUNUSED_UNLESS_XIM(alloc),
1979 wxWindow* WXUNUSED_UNLESS_XIM(win) )
b79395c5
RR
1980{
1981 if (g_isIdle)
1982 wxapp_install_idle_handler();
2daa0ce9 1983
9a8c7620 1984#ifdef HAVE_XIM
b79395c5
RR
1985 if (!win->m_ic)
1986 return;
1987
b79395c5
RR
1988 if (gdk_ic_get_style (win->m_ic) & GDK_IM_PREEDIT_POSITION)
1989 {
1990 gint width, height;
1991
3ed2e7ce 1992 gdk_window_get_size (widget->window, &width, &height);
b79395c5
RR
1993 win->m_icattr->preedit_area.width = width;
1994 win->m_icattr->preedit_area.height = height;
1995 gdk_ic_set_attr (win->m_ic, win->m_icattr, GDK_IC_PREEDIT_AREA);
1996 }
9a8c7620 1997#endif // HAVE_XIM
b79395c5
RR
1998}
1999
63081513
RR
2000//-----------------------------------------------------------------------------
2001// "realize" from m_wxwindow
2002//-----------------------------------------------------------------------------
2003
2004/* Initialize XIM support */
2005
2006static gint
3ed2e7ce
VZ
2007gtk_wxwindow_realized_callback( GtkWidget * WXUNUSED_UNLESS_XIM(widget),
2008 wxWindow * WXUNUSED_UNLESS_XIM(win) )
63081513
RR
2009{
2010 if (g_isIdle)
2011 wxapp_install_idle_handler();
2012
d06800f1 2013#ifdef HAVE_XIM
63081513
RR
2014 if (win->m_ic) return FALSE;
2015 if (!widget) return FALSE;
2016 if (!gdk_im_ready()) return FALSE;
2017
2018 win->m_icattr = gdk_ic_attr_new();
2019 if (!win->m_icattr) return FALSE;
2daa0ce9 2020
63081513
RR
2021 gint width, height;
2022 GdkEventMask mask;
2023 GdkColormap *colormap;
2024 GdkICAttr *attr = win->m_icattr;
b58b1dfc 2025 unsigned attrmask = GDK_IC_ALL_REQ;
63081513 2026 GdkIMStyle style;
b79395c5
RR
2027 GdkIMStyle supported_style = (GdkIMStyle)
2028 (GDK_IM_PREEDIT_NONE |
63081513
RR
2029 GDK_IM_PREEDIT_NOTHING |
2030 GDK_IM_PREEDIT_POSITION |
2031 GDK_IM_STATUS_NONE |
b79395c5 2032 GDK_IM_STATUS_NOTHING);
63081513
RR
2033
2034 if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
b79395c5 2035 supported_style = (GdkIMStyle)(supported_style & ~GDK_IM_PREEDIT_POSITION);
63081513
RR
2036
2037 attr->style = style = gdk_im_decide_style (supported_style);
2038 attr->client_window = widget->window;
2039
2040 if ((colormap = gtk_widget_get_colormap (widget)) !=
2041 gtk_widget_get_default_colormap ())
2042 {
b420fb6a
RR
2043 attrmask |= GDK_IC_PREEDIT_COLORMAP;
2044 attr->preedit_colormap = colormap;
63081513 2045 }
2daa0ce9 2046
63081513
RR
2047 attrmask |= GDK_IC_PREEDIT_FOREGROUND;
2048 attrmask |= GDK_IC_PREEDIT_BACKGROUND;
2049 attr->preedit_foreground = widget->style->fg[GTK_STATE_NORMAL];
2050 attr->preedit_background = widget->style->base[GTK_STATE_NORMAL];
2051
2052 switch (style & GDK_IM_PREEDIT_MASK)
2053 {
2054 case GDK_IM_PREEDIT_POSITION:
2055 if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
2056 {
2057 g_warning ("over-the-spot style requires fontset");
2058 break;
2059 }
2060
2061 gdk_window_get_size (widget->window, &width, &height);
2062
2063 attrmask |= GDK_IC_PREEDIT_POSITION_REQ;
2064 attr->spot_location.x = 0;
2065 attr->spot_location.y = height;
2066 attr->preedit_area.x = 0;
2067 attr->preedit_area.y = 0;
2068 attr->preedit_area.width = width;
2069 attr->preedit_area.height = height;
2070 attr->preedit_fontset = widget->style->font;
2071
2072 break;
b79395c5 2073 }
2daa0ce9 2074
b58b1dfc 2075 win->m_ic = gdk_ic_new (attr, (GdkICAttributesType)attrmask);
2daa0ce9 2076
63081513
RR
2077 if (win->m_ic == NULL)
2078 g_warning ("Can't create input context.");
2079 else
2080 {
2081 mask = gdk_window_get_events (widget->window);
b79395c5 2082 mask = (GdkEventMask)(mask | gdk_ic_get_events (win->m_ic));
63081513
RR
2083 gdk_window_set_events (widget->window, mask);
2084
2085 if (GTK_WIDGET_HAS_FOCUS(widget))
2086 gdk_im_begin (win->m_ic, widget->window);
2087 }
63081513
RR
2088#endif
2089
2090 return FALSE;
2091}
2092
6ca41e57
RR
2093//-----------------------------------------------------------------------------
2094// InsertChild for wxWindow.
2095//-----------------------------------------------------------------------------
2096
b1170810
RR
2097/* Callback for wxWindow. This very strange beast has to be used because
2098 * C++ has no virtual methods in a constructor. We have to emulate a
2099 * virtual function here as wxNotebook requires a different way to insert
2100 * a child in it. I had opted for creating a wxNotebookPage window class
2101 * which would have made this superfluous (such in the MDI window system),
2102 * but no-one was listening to me... */
6ca41e57
RR
2103
2104static void wxInsertChildInWindow( wxWindow* parent, wxWindow* child )
2105{
bf0c00c6
RR
2106 /* the window might have been scrolled already, do we
2107 have to adapt the position */
da048e3d
RR
2108 GtkPizza *pizza = GTK_PIZZA(parent->m_wxwindow);
2109 child->m_x += pizza->xoffset;
2110 child->m_y += pizza->yoffset;
148cd9b6 2111
da048e3d 2112 gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
a2053b27
RR
2113 GTK_WIDGET(child->m_widget),
2114 child->m_x,
2115 child->m_y,
2116 child->m_width,
2117 child->m_height );
6ca41e57
RR
2118}
2119
bbe0af5b
RR
2120//-----------------------------------------------------------------------------
2121// global functions
2122//-----------------------------------------------------------------------------
2123
2124wxWindow* wxGetActiveWindow()
2125{
f03fc89f 2126 return g_focusWindow;
bbe0af5b
RR
2127}
2128
c801d85f 2129//-----------------------------------------------------------------------------
2f2aa628 2130// wxWindow
c801d85f
KB
2131//-----------------------------------------------------------------------------
2132
f03fc89f 2133IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
c801d85f 2134
68995f26 2135void wxWindow::Init()
c801d85f 2136{
f03fc89f
VZ
2137 // common init
2138 InitBase();
68995f26 2139
f03fc89f 2140 // GTK specific
a2053b27 2141 m_widget = (GtkWidget *) NULL;
e380f72b 2142 m_wxwindow = (GtkWidget *) NULL;
8bbe427f 2143
f03fc89f 2144 // position/size
a2053b27
RR
2145 m_x = 0;
2146 m_y = 0;
2147 m_width = 0;
e380f72b 2148 m_height = 0;
8bbe427f 2149
e380f72b
RR
2150 m_sizeSet = FALSE;
2151 m_hasVMT = FALSE;
2152 m_needParent = TRUE;
31c6b4fc 2153 m_isBeingDeleted = FALSE;
148cd9b6 2154
147bc491 2155 m_noExpose = FALSE;
30760ce7 2156 m_nativeSizeEvent = FALSE;
148cd9b6 2157
a2053b27 2158 m_hasScrolling = FALSE;
846e1424 2159 m_isScrolling = FALSE;
f03fc89f 2160
a2053b27 2161 m_hAdjust = (GtkAdjustment*) NULL;
e380f72b 2162 m_vAdjust = (GtkAdjustment*) NULL;
a2053b27 2163 m_oldHorizontalPos = 0.0;
e380f72b 2164 m_oldVerticalPos = 0.0;
8bbe427f 2165
e380f72b 2166 m_resizing = FALSE;
e380f72b 2167 m_widgetStyle = (GtkStyle*) NULL;
8bbe427f 2168
ddb6bc71 2169 m_insertCallback = (wxInsertChildFunction) NULL;
8bbe427f 2170
1ecc4d80 2171 m_isStaticBox = FALSE;
953704c1 2172 m_isRadioButton = FALSE;
54517652 2173 m_isFrame = FALSE;
b292e2f5 2174 m_acceptsFocus = FALSE;
148cd9b6 2175
b6fa52db 2176 m_clipPaintRegion = FALSE;
b6fa52db 2177
5e014a0c 2178 m_cursor = *wxSTANDARD_CURSOR;
2daa0ce9 2179
f6bcfd97
BP
2180 m_delayedForegroundColour = FALSE;
2181 m_delayedBackgroundColour = FALSE;
2182
63081513
RR
2183#ifdef HAVE_XIM
2184 m_ic = (GdkIC*) NULL;
2185 m_icattr = (GdkICAttr*) NULL;
2186#endif
362c6693 2187}
c801d85f 2188
68995f26
VZ
2189wxWindow::wxWindow()
2190{
2191 Init();
2192}
2193
6ca41e57 2194wxWindow::wxWindow( wxWindow *parent, wxWindowID id,
e380f72b
RR
2195 const wxPoint &pos, const wxSize &size,
2196 long style, const wxString &name )
6ca41e57 2197{
68995f26
VZ
2198 Init();
2199
e380f72b 2200 Create( parent, id, pos, size, style, name );
6ca41e57 2201}
8bbe427f 2202
debe6624 2203bool wxWindow::Create( wxWindow *parent, wxWindowID id,
e380f72b
RR
2204 const wxPoint &pos, const wxSize &size,
2205 long style, const wxString &name )
c801d85f 2206{
4dcaf11a
RR
2207 if (!PreCreation( parent, pos, size ) ||
2208 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
2209 {
223d09f6 2210 wxFAIL_MSG( wxT("wxWindow creation failed") );
b02da6b1 2211 return FALSE;
4dcaf11a 2212 }
47d67540 2213
ddb6bc71 2214 m_insertCallback = wxInsertChildInWindow;
b6fa52db 2215
e380f72b 2216 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
38c7b3d3 2217 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
ff8bfdbb 2218
f03fc89f 2219 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget);
47d67540 2220
dd00f3f6 2221 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
e380f72b 2222 scroll_class->scrollbar_spacing = 0;
47d67540 2223
f03fc89f 2224 gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
47d67540 2225
f03fc89f
VZ
2226 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->hscrollbar) );
2227 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->vscrollbar) );
47d67540 2228
da048e3d 2229 m_wxwindow = gtk_pizza_new();
38c7b3d3 2230
034be888 2231 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
58dea4b0 2232
034be888 2233#if (GTK_MINOR_VERSION > 0)
da048e3d 2234 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
b292e2f5 2235
f03fc89f 2236 if (HasFlag(wxRAISED_BORDER))
034be888 2237 {
da048e3d 2238 gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_OUT );
034be888 2239 }
f03fc89f 2240 else if (HasFlag(wxSUNKEN_BORDER))
034be888 2241 {
da048e3d 2242 gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_IN );
5e014a0c
RR
2243 }
2244 else if (HasFlag(wxSIMPLE_BORDER))
2245 {
da048e3d 2246 gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_THIN );
034be888
RR
2247 }
2248 else
2249 {
da048e3d 2250 gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_NONE );
034be888 2251 }
f03fc89f
VZ
2252#else // GTK_MINOR_VERSION == 0
2253 GtkViewport *viewport = GTK_VIEWPORT(scrolledWindow->viewport);
b292e2f5 2254
f03fc89f 2255 if (HasFlag(wxRAISED_BORDER))
e380f72b
RR
2256 {
2257 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
2258 }
f03fc89f 2259 else if (HasFlag(wxSUNKEN_BORDER))
e380f72b
RR
2260 {
2261 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
2262 }
2263 else
2264 {
2265 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
2266 }
f03fc89f 2267#endif // GTK_MINOR_VERSION
47d67540 2268
3da17724
RR
2269 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
2270 m_acceptsFocus = TRUE;
ca298c88 2271
034be888 2272#if (GTK_MINOR_VERSION == 0)
e380f72b
RR
2273 // shut the viewport up
2274 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2275 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
f03fc89f 2276#endif // GTK_MINOR_VERSION == 0
e380f72b
RR
2277
2278 // I _really_ don't want scrollbars in the beginning
a2053b27
RR
2279 m_vAdjust->lower = 0.0;
2280 m_vAdjust->upper = 1.0;
2281 m_vAdjust->value = 0.0;
2282 m_vAdjust->step_increment = 1.0;
2283 m_vAdjust->page_increment = 1.0;
2284 m_vAdjust->page_size = 5.0;
2285 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
2286 m_hAdjust->lower = 0.0;
2287 m_hAdjust->upper = 1.0;
2288 m_hAdjust->value = 0.0;
2289 m_hAdjust->step_increment = 1.0;
2290 m_hAdjust->page_increment = 1.0;
2291 m_hAdjust->page_size = 5.0;
2292 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
f03fc89f
VZ
2293
2294 // these handlers block mouse events to any window during scrolling such as
2295 // motion events and prevent GTK and wxWindows from fighting over where the
2296 // slider should be
2297
2298 gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_press_event",
76ed8f8d
RR
2299 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
2300
f03fc89f 2301 gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_press_event",
76ed8f8d
RR
2302 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
2303
f03fc89f 2304 gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_release_event",
76ed8f8d
RR
2305 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
2306
f03fc89f 2307 gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_release_event",
76ed8f8d 2308 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
8bbe427f 2309
034be888 2310 // these handlers get notified when screen updates are required either when
76ed8f8d
RR
2311 // scrolling or when the window size (and therefore scrollbar configuration)
2312 // has changed
2313
2314 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
2315 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
2316 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
2317 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
2318
f03fc89f 2319 gtk_widget_show( m_wxwindow );
47d67540 2320
f03fc89f
VZ
2321 if (m_parent)
2322 m_parent->DoAddChild( this );
8bbe427f 2323
e380f72b 2324 PostCreation();
8bbe427f 2325
e380f72b 2326 Show( TRUE );
c801d85f 2327
e380f72b 2328 return TRUE;
362c6693 2329}
c801d85f 2330
68dda785 2331wxWindow::~wxWindow()
c801d85f 2332{
31c6b4fc 2333 m_isBeingDeleted = TRUE;
43a18898 2334 m_hasVMT = FALSE;
47d67540 2335
f03fc89f
VZ
2336 if (m_widget)
2337 Show( FALSE );
8bbe427f 2338
a2053b27
RR
2339 DestroyChildren();
2340
f03fc89f
VZ
2341 if (m_parent)
2342 m_parent->RemoveChild( this );
c801d85f 2343
63081513
RR
2344#ifdef HAVE_XIM
2345 if (m_ic)
2346 gdk_ic_destroy (m_ic);
2347 if (m_icattr)
2348 gdk_ic_attr_destroy (m_icattr);
2349#endif
2350
f03fc89f 2351 if (m_widgetStyle)
a2053b27 2352 {
a56fcaaf 2353#if DISABLE_STYLE_IF_BROKEN_THEME
bce1406b
RR
2354 // don't delete if it's a pixmap theme style
2355 if (!m_widgetStyle->engine_data)
2356 gtk_style_unref( m_widgetStyle );
a56fcaaf 2357#endif
c50f1fb9 2358 m_widgetStyle = (GtkStyle*) NULL;
a2053b27 2359 }
c801d85f 2360
f03fc89f 2361 if (m_wxwindow)
a2053b27 2362 {
f03fc89f 2363 gtk_widget_destroy( m_wxwindow );
c50f1fb9 2364 m_wxwindow = (GtkWidget*) NULL;
a2053b27 2365 }
8bbe427f 2366
f03fc89f 2367 if (m_widget)
a2053b27 2368 {
f03fc89f 2369 gtk_widget_destroy( m_widget );
c50f1fb9 2370 m_widget = (GtkWidget*) NULL;
a2053b27 2371 }
362c6693 2372}
c801d85f 2373
4dcaf11a 2374bool wxWindow::PreCreation( wxWindow *parent, const wxPoint &pos, const wxSize &size )
c801d85f 2375{
223d09f6 2376 wxCHECK_MSG( !m_needParent || parent, FALSE, wxT("Need complete parent.") );
8bbe427f 2377
4dcaf11a
RR
2378 /* this turns -1 into 20 so that a minimal window is
2379 visible even although -1,-1 has been given as the
2380 size of the window. the same trick is used in other
2381 ports and should make debugging easier */
f03fc89f
VZ
2382 m_width = WidthDefault(size.x);
2383 m_height = HeightDefault(size.y);
8bbe427f 2384
43a18898
RR
2385 m_x = (int)pos.x;
2386 m_y = (int)pos.y;
8bbe427f 2387
4dcaf11a 2388 /* some reasonable defaults */
148cd9b6 2389 if (!parent)
6ca41e57 2390 {
43a18898
RR
2391 if (m_x == -1)
2392 {
2393 m_x = (gdk_screen_width () - m_width) / 2;
2394 if (m_x < 10) m_x = 10;
2395 }
2396 if (m_y == -1)
2397 {
2398 m_y = (gdk_screen_height () - m_height) / 2;
2399 if (m_y < 10) m_y = 10;
2400 }
6ca41e57 2401 }
148cd9b6 2402
4dcaf11a 2403 return TRUE;
c801d85f
KB
2404}
2405
68dda785 2406void wxWindow::PostCreation()
c801d85f 2407{
223d09f6 2408 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
ca298c88 2409
43a18898
RR
2410 if (m_wxwindow)
2411 {
147bc491 2412 if (!m_noExpose)
b02da6b1 2413 {
147bc491 2414 /* these get reported to wxWindows -> wxPaintEvent */
b420fb6a
RR
2415
2416 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow), TRUE );
2417
147bc491
RR
2418 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
2419 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
2420
2421 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
2422 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
e22454be
RR
2423
2424 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE))
2425 {
2426 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "event",
2427 GTK_SIGNAL_FUNC(gtk_window_event_event_callback), (gpointer)this );
2428 }
b02da6b1 2429 }
148cd9b6 2430
ef47f9b3 2431#if (GTK_MINOR_VERSION > 0)
ed673c6a 2432 /* these are called when the "sunken" or "raised" borders are drawn */
034be888
RR
2433 gtk_signal_connect( GTK_OBJECT(m_widget), "expose_event",
2434 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback), (gpointer)this );
2435
2436 gtk_signal_connect( GTK_OBJECT(m_widget), "draw",
2437 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback), (gpointer)this );
ef47f9b3 2438#endif
43a18898 2439 }
47d67540 2440
63081513
RR
2441 if (m_wxwindow && m_needParent)
2442 {
2443 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "focus_in_event",
2444 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
2445
2446 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "focus_out_event",
2447 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
2448 }
2449 else
2450 {
2451 // For dialogs and frames, we are interested mainly in
2452 // m_widget's focus.
2daa0ce9 2453
63081513
RR
2454 gtk_signal_connect( GTK_OBJECT(m_widget), "focus_in_event",
2455 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
2456
2457 gtk_signal_connect( GTK_OBJECT(m_widget), "focus_out_event",
2458 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
2459 }
2460
a2053b27 2461 GtkWidget *connect_widget = GetConnectWidget();
f03fc89f 2462
a2053b27 2463 ConnectWidget( connect_widget );
47d67540 2464
63081513 2465 /* We cannot set colours, fonts and cursors before the widget has
a2053b27
RR
2466 been realized, so we do this directly after realization */
2467 gtk_signal_connect( GTK_OBJECT(connect_widget), "realize",
c50f1fb9 2468 GTK_SIGNAL_FUNC(gtk_window_realized_callback), (gpointer) this );
2daa0ce9 2469
63081513
RR
2470 if (m_wxwindow)
2471 {
47c93b63 2472 // Catch native resize events
8f75cb6c
RR
2473 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "size_allocate",
2474 GTK_SIGNAL_FUNC(gtk_window_size_callback), (gpointer)this );
2daa0ce9 2475
47c93b63 2476 // Initialize XIM support
63081513
RR
2477 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "realize",
2478 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback), (gpointer) this );
8f75cb6c 2479
47c93b63 2480 // And resize XIM window
b79395c5
RR
2481 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "size_allocate",
2482 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback), (gpointer)this );
63081513 2483 }
2daa0ce9 2484
47c93b63
RR
2485 if (!GTK_IS_COMBO(m_widget))
2486 {
2487 // This is needed if we want to add our windows into native
2488 // GTK control, such as the toolbar. With this callback, the
2489 // toolbar gets to know the correct size (the one set by the
2490 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2491 // when moving to GTK 2.0.
2492 gtk_signal_connect( GTK_OBJECT(m_widget), "size_request",
2493 GTK_SIGNAL_FUNC(gtk_window_size_request_callback), (gpointer) this );
2494 }
2495
43a18898 2496 m_hasVMT = TRUE;
b4071e91
RR
2497}
2498
2499void wxWindow::ConnectWidget( GtkWidget *widget )
2500{
43a18898
RR
2501 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
2502 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
c801d85f 2503
b666df2c
RR
2504 gtk_signal_connect( GTK_OBJECT(widget), "key_release_event",
2505 GTK_SIGNAL_FUNC(gtk_window_key_release_callback), (gpointer)this );
2506
43a18898
RR
2507 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
2508 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
47d67540 2509
43a18898
RR
2510 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
2511 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
47d67540 2512
43a18898
RR
2513 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
2514 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
47d67540 2515
43a18898
RR
2516 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
2517 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
47d67540 2518
43a18898
RR
2519 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
2520 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
362c6693 2521}
c801d85f 2522
68dda785 2523bool wxWindow::Destroy()
c801d85f 2524{
223d09f6 2525 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
47d67540 2526
43a18898 2527 m_hasVMT = FALSE;
c801d85f 2528
f03fc89f 2529 return wxWindowBase::Destroy();
362c6693 2530}
c801d85f 2531
23efdd02
RR
2532void wxWindow::DoMoveWindow(int x, int y, int width, int height)
2533{
2534 gtk_pizza_set_size( GTK_PIZZA(m_parent->m_wxwindow), m_widget, x, y, width, height );
2535}
2daa0ce9 2536
bfc6fde4 2537void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
c801d85f 2538{
223d09f6
KB
2539 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
2540 wxASSERT_MSG( (m_parent != NULL), wxT("wxWindow::SetSize requires parent.\n") );
8bbe427f 2541
e27ce4e9 2542 if (m_resizing) return; /* I don't like recursions */
fb1585ae 2543 m_resizing = TRUE;
b6fa52db 2544
a2053b27 2545 if (m_parent->m_wxwindow == NULL) /* i.e. wxNotebook */
fb1585ae 2546 {
e27ce4e9 2547 /* don't set the size for children of wxNotebook, just take the values. */
fb1585ae
RR
2548 m_x = x;
2549 m_y = y;
2550 m_width = width;
ba4e3652 2551 m_height = height;
fb1585ae 2552 }
ba4e3652 2553 else
fb1585ae 2554 {
da048e3d 2555 GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
148cd9b6 2556
85ad5eb5 2557 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
ba4e3652 2558 {
da048e3d
RR
2559 if (x != -1) m_x = x + pizza->xoffset;
2560 if (y != -1) m_y = y + pizza->yoffset;
ba4e3652
RR
2561 if (width != -1) m_width = width;
2562 if (height != -1) m_height = height;
2563 }
2564 else
2565 {
da048e3d
RR
2566 m_x = x + pizza->xoffset;
2567 m_y = y + pizza->yoffset;
ba4e3652
RR
2568 m_width = width;
2569 m_height = height;
2570 }
47d67540 2571
ba4e3652
RR
2572 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
2573 {
2574 if (width == -1) m_width = 80;
2575 }
2576
2577 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
2578 {
2579 if (height == -1) m_height = 26;
2580 }
8bbe427f 2581
ba4e3652
RR
2582 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
2583 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
d3b4d113
RR
2584 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
2585 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
47d67540 2586
a2053b27 2587 int border = 0;
c50f1fb9 2588 int bottom_border = 0;
f03fc89f 2589
29f538ce 2590 if (GTK_WIDGET_CAN_DEFAULT(m_widget))
c50f1fb9
VZ
2591 {
2592 /* the default button has a border around it */
2593 border = 6;
2594 bottom_border = 5;
2595 }
2596
23efdd02
RR
2597 DoMoveWindow( m_x-border,
2598 m_y-border,
2599 m_width+2*border,
2600 m_height+border+bottom_border );
54517652 2601 }
148cd9b6 2602
5b8a521e
RR
2603 if (m_hasScrolling)
2604 {
b6fa52db
RR
2605 /* Sometimes the client area changes size without the
2606 whole windows's size changing, but if the whole
2607 windows's size doesn't change, no wxSizeEvent will
2608 normally be sent. Here we add an extra test if
2609 the client test has been changed and this will
2610 be used then. */
5b8a521e
RR
2611 GetClientSize( &m_oldClientWidth, &m_oldClientHeight );
2612 }
2613
54517652 2614/*
6d693bb4
RR
2615 wxPrintf( "OnSize sent from " );
2616 if (GetClassInfo() && GetClassInfo()->GetClassName())
2617 wxPrintf( GetClassInfo()->GetClassName() );
2618 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2619*/
2620
30760ce7
RR
2621 if (!m_nativeSizeEvent)
2622 {
2623 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
2624 event.SetEventObject( this );
2625 GetEventHandler()->ProcessEvent( event );
2626 }
6d693bb4 2627
fb1585ae 2628 m_resizing = FALSE;
362c6693 2629}
c801d85f 2630
9390a202
RR
2631void wxWindow::OnInternalIdle()
2632{
148cd9b6
VZ
2633 if ( g_sendActivateEvent != -1 )
2634 {
2635 bool activate = g_sendActivateEvent != 0;
2636
2637 // do it only once
2638 g_sendActivateEvent = -1;
2639
2640 wxActivateEvent event(wxEVT_ACTIVATE, activate, GetId());
2641 event.SetEventObject(this);
2642
2643 (void)GetEventHandler()->ProcessEvent(event);
2644 }
2645
9146082c
RR
2646 wxCursor cursor = m_cursor;
2647 if (g_globalCursor.Ok()) cursor = g_globalCursor;
c50f1fb9 2648
f7a11f8c 2649 if (cursor.Ok())
9146082c 2650 {
3017f78d 2651 /* I now set the cursor anew in every OnInternalIdle call
b02da6b1
VZ
2652 as setting the cursor in a parent window also effects the
2653 windows above so that checking for the current cursor is
2654 not possible. */
148cd9b6 2655
9146082c 2656 if (m_wxwindow)
6a008b33 2657 {
da048e3d 2658 GdkWindow *window = GTK_PIZZA(m_wxwindow)->bin_window;
6a008b33 2659 if (window)
c50f1fb9 2660 gdk_window_set_cursor( window, cursor.GetCursor() );
6a008b33
VZ
2661
2662 if (!g_globalCursor.Ok())
2663 cursor = *wxSTANDARD_CURSOR;
2664
2665 window = m_widget->window;
5e014a0c 2666 if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget)))
9146082c 2667 gdk_window_set_cursor( window, cursor.GetCursor() );
5e014a0c 2668
6a008b33
VZ
2669 }
2670 else
2671 {
5e014a0c 2672
9146082c 2673 GdkWindow *window = m_widget->window;
5e014a0c 2674 if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget)))
9146082c 2675 gdk_window_set_cursor( window, cursor.GetCursor() );
5e014a0c 2676
6a008b33 2677 }
9146082c 2678 }
6a008b33 2679
9390a202
RR
2680 UpdateWindowUI();
2681}
2682
f03fc89f 2683void wxWindow::DoGetSize( int *width, int *height ) const
c801d85f 2684{
223d09f6 2685 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2686
fb1585ae
RR
2687 if (width) (*width) = m_width;
2688 if (height) (*height) = m_height;
362c6693 2689}
c801d85f 2690
bfc6fde4 2691void wxWindow::DoSetClientSize( int width, int height )
c801d85f 2692{
223d09f6 2693 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2694
1ecc4d80 2695 if (!m_wxwindow)
c801d85f 2696 {
1ecc4d80 2697 SetSize( width, height );
c801d85f
KB
2698 }
2699 else
2700 {
1ecc4d80
RR
2701 int dw = 0;
2702 int dh = 0;
2703
98d3fdbe
RR
2704 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2705 {
5e014a0c 2706 /* when using GTK 1.2 we set the shadow border size to 2 */
6a008b33 2707 dw += 2 * 2;
98d3fdbe
RR
2708 dh += 2 * 2;
2709 }
5e014a0c
RR
2710 if (HasFlag(wxSIMPLE_BORDER))
2711 {
2712 /* when using GTK 1.2 we set the simple border size to 1 */
2713 dw += 1 * 2;
2714 dh += 1 * 2;
2715 }
034be888 2716
5b8a521e 2717 if (m_hasScrolling)
98d3fdbe 2718 {
324dbfec 2719 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2daa0ce9 2720
9000c624
RR
2721 GtkRequisition vscroll_req;
2722 vscroll_req.width = 2;
2723 vscroll_req.height = 2;
dd00f3f6 2724 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
9000c624 2725 (scroll_window->vscrollbar, &vscroll_req );
2daa0ce9 2726
9000c624
RR
2727 GtkRequisition hscroll_req;
2728 hscroll_req.width = 2;
2729 hscroll_req.height = 2;
dd00f3f6 2730 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
9000c624
RR
2731 (scroll_window->hscrollbar, &hscroll_req );
2732
dd00f3f6 2733 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
324dbfec 2734
1ecc4d80
RR
2735 if (scroll_window->vscrollbar_visible)
2736 {
9000c624 2737 dw += vscroll_req.width;
1ecc4d80
RR
2738 dw += scroll_class->scrollbar_spacing;
2739 }
2740
2741 if (scroll_window->hscrollbar_visible)
2742 {
9000c624 2743 dh += hscroll_req.height;
63cc5d9d 2744 dh += scroll_class->scrollbar_spacing;
1ecc4d80 2745 }
9000c624 2746 }
1ecc4d80 2747
034be888 2748 SetSize( width+dw, height+dh );
1ecc4d80 2749 }
362c6693 2750}
c801d85f 2751
f03fc89f 2752void wxWindow::DoGetClientSize( int *width, int *height ) const
c801d85f 2753{
223d09f6 2754 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2755
1ecc4d80
RR
2756 if (!m_wxwindow)
2757 {
2758 if (width) (*width) = m_width;
2759 if (height) (*height) = m_height;
c801d85f
KB
2760 }
2761 else
2762 {
1ecc4d80
RR
2763 int dw = 0;
2764 int dh = 0;
2765
98d3fdbe
RR
2766 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2767 {
5e014a0c 2768 /* when using GTK 1.2 we set the shadow border size to 2 */
6a008b33 2769 dw += 2 * 2;
98d3fdbe
RR
2770 dh += 2 * 2;
2771 }
5e014a0c
RR
2772 if (HasFlag(wxSIMPLE_BORDER))
2773 {
2774 /* when using GTK 1.2 we set the simple border size to 1 */
2775 dw += 1 * 2;
2776 dh += 1 * 2;
2777 }
9000c624 2778
5b8a521e 2779 if (m_hasScrolling)
98d3fdbe 2780 {
6a008b33 2781 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2daa0ce9 2782
9000c624
RR
2783 GtkRequisition vscroll_req;
2784 vscroll_req.width = 2;
2785 vscroll_req.height = 2;
dd00f3f6 2786 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
9000c624 2787 (scroll_window->vscrollbar, &vscroll_req );
2daa0ce9 2788
9000c624
RR
2789 GtkRequisition hscroll_req;
2790 hscroll_req.width = 2;
2791 hscroll_req.height = 2;
dd00f3f6 2792 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
9000c624
RR
2793 (scroll_window->hscrollbar, &hscroll_req );
2794
dd00f3f6 2795 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
6a008b33 2796
1ecc4d80
RR
2797 if (scroll_window->vscrollbar_visible)
2798 {
9000c624 2799 dw += vscroll_req.width;
1ecc4d80
RR
2800 dw += scroll_class->scrollbar_spacing;
2801 }
2802
2803 if (scroll_window->hscrollbar_visible)
2804 {
9000c624 2805 dh += hscroll_req.height;
1ecc4d80
RR
2806 dh += scroll_class->scrollbar_spacing;
2807 }
6a008b33 2808 }
47d67540 2809
1ecc4d80
RR
2810 if (width) (*width) = m_width - dw;
2811 if (height) (*height) = m_height - dh;
2812 }
362c6693 2813}
c801d85f 2814
f03fc89f 2815void wxWindow::DoGetPosition( int *x, int *y ) const
c801d85f 2816{
223d09f6 2817 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2818
bf0c00c6
RR
2819 int dx = 0;
2820 int dy = 0;
2821 if (m_parent && m_parent->m_wxwindow)
2822 {
da048e3d 2823 GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
b02da6b1
VZ
2824 dx = pizza->xoffset;
2825 dy = pizza->yoffset;
bf0c00c6
RR
2826 }
2827
2828 if (x) (*x) = m_x - dx;
2829 if (y) (*y) = m_y - dy;
362c6693 2830}
c801d85f 2831
dabc0cd5 2832void wxWindow::DoClientToScreen( int *x, int *y ) const
c801d85f 2833{
223d09f6 2834 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2835
a2053b27
RR
2836 if (!m_widget->window) return;
2837
43a18898
RR
2838 GdkWindow *source = (GdkWindow *) NULL;
2839 if (m_wxwindow)
da048e3d 2840 source = GTK_PIZZA(m_wxwindow)->bin_window;
43a18898
RR
2841 else
2842 source = m_widget->window;
47d67540 2843
43a18898
RR
2844 int org_x = 0;
2845 int org_y = 0;
2846 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2847
43a18898 2848 if (!m_wxwindow)
c801d85f 2849 {
43a18898
RR
2850 if (GTK_WIDGET_NO_WINDOW (m_widget))
2851 {
2852 org_x += m_widget->allocation.x;
2853 org_y += m_widget->allocation.y;
2854 }
362c6693 2855 }
47d67540 2856
43a18898
RR
2857 if (x) *x += org_x;
2858 if (y) *y += org_y;
362c6693 2859}
c801d85f 2860
dabc0cd5 2861void wxWindow::DoScreenToClient( int *x, int *y ) const
c801d85f 2862{
223d09f6 2863 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2864
a2053b27
RR
2865 if (!m_widget->window) return;
2866
1ecc4d80
RR
2867 GdkWindow *source = (GdkWindow *) NULL;
2868 if (m_wxwindow)
da048e3d 2869 source = GTK_PIZZA(m_wxwindow)->bin_window;
1ecc4d80
RR
2870 else
2871 source = m_widget->window;
47d67540 2872
1ecc4d80
RR
2873 int org_x = 0;
2874 int org_y = 0;
2875 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2876
1ecc4d80 2877 if (!m_wxwindow)
c801d85f 2878 {
1ecc4d80
RR
2879 if (GTK_WIDGET_NO_WINDOW (m_widget))
2880 {
2881 org_x += m_widget->allocation.x;
2882 org_y += m_widget->allocation.y;
2883 }
362c6693 2884 }
47d67540 2885
1ecc4d80
RR
2886 if (x) *x -= org_x;
2887 if (y) *y -= org_y;
362c6693 2888}
c801d85f 2889
f03fc89f 2890bool wxWindow::Show( bool show )
c801d85f 2891{
223d09f6 2892 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
47d67540 2893
739730ca
RR
2894 if (!wxWindowBase::Show(show))
2895 {
2896 // nothing to do
f03fc89f 2897 return FALSE;
739730ca 2898 }
8bbe427f 2899
f03fc89f
VZ
2900 if (show)
2901 gtk_widget_show( m_widget );
1ecc4d80 2902 else
f03fc89f 2903 gtk_widget_hide( m_widget );
8bbe427f 2904
f03fc89f 2905 return TRUE;
362c6693 2906}
c801d85f 2907
f03fc89f 2908bool wxWindow::Enable( bool enable )
c801d85f 2909{
223d09f6 2910 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
5e0aa05a 2911
739730ca
RR
2912 if (!wxWindowBase::Enable(enable))
2913 {
2914 // nothing to do
f03fc89f 2915 return FALSE;
739730ca 2916 }
1ecc4d80 2917
f03fc89f
VZ
2918 gtk_widget_set_sensitive( m_widget, enable );
2919 if ( m_wxwindow )
2920 gtk_widget_set_sensitive( m_wxwindow, enable );
ff8bfdbb 2921
f03fc89f 2922 return TRUE;
362c6693 2923}
c801d85f 2924
f03fc89f 2925int wxWindow::GetCharHeight() const
2f2aa628 2926{
223d09f6 2927 wxCHECK_MSG( (m_widget != NULL), 12, wxT("invalid window") );
47d67540 2928
223d09f6 2929 wxCHECK_MSG( m_font.Ok(), 12, wxT("invalid font") );
2f2aa628 2930
f03fc89f
VZ
2931 GdkFont *font = m_font.GetInternalFont( 1.0 );
2932
2933 return font->ascent + font->descent;
362c6693 2934}
c801d85f 2935
f03fc89f 2936int wxWindow::GetCharWidth() const
c33c4050 2937{
223d09f6 2938 wxCHECK_MSG( (m_widget != NULL), 8, wxT("invalid window") );
47d67540 2939
223d09f6 2940 wxCHECK_MSG( m_font.Ok(), 8, wxT("invalid font") );
47d67540 2941
463c1fa1 2942 GdkFont *font = m_font.GetInternalFont( 1.0 );
ff8bfdbb 2943
463c1fa1 2944 return gdk_string_width( font, "H" );
c33c4050
RR
2945}
2946
f03fc89f
VZ
2947void wxWindow::GetTextExtent( const wxString& string,
2948 int *x,
2949 int *y,
2950 int *descent,
2951 int *externalLeading,
2952 const wxFont *theFont ) const
c33c4050 2953{
463c1fa1
RR
2954 wxFont fontToUse = m_font;
2955 if (theFont) fontToUse = *theFont;
47d67540 2956
223d09f6 2957 wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") );
47d67540 2958
463c1fa1 2959 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
05939a81 2960 if (x) (*x) = gdk_string_width( font, string.mbc_str() );
463c1fa1
RR
2961 if (y) (*y) = font->ascent + font->descent;
2962 if (descent) (*descent) = font->descent;
2963 if (externalLeading) (*externalLeading) = 0; // ??
c33c4050
RR
2964}
2965
68dda785 2966void wxWindow::SetFocus()
c801d85f 2967{
223d09f6 2968 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
2daa0ce9 2969
354aa1e3
RR
2970 if (m_wxwindow)
2971 {
173348db
RR
2972 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow))
2973 gtk_widget_grab_focus (m_wxwindow);
354aa1e3
RR
2974 return;
2975 }
2976
2977 if (m_widget)
c801d85f 2978 {
173348db 2979 if (GTK_WIDGET_CAN_FOCUS(m_widget) && !GTK_WIDGET_HAS_FOCUS (m_widget) )
463c1fa1 2980 {
354aa1e3 2981 gtk_widget_grab_focus (m_widget);
463c1fa1 2982 }
354aa1e3 2983 else if (GTK_IS_CONTAINER(m_widget))
ff8bfdbb 2984 {
354aa1e3 2985 gtk_container_focus( GTK_CONTAINER(m_widget), GTK_DIR_TAB_FORWARD );
ff8bfdbb
VZ
2986 }
2987 else
2988 {
b02da6b1 2989 // ?
ff8bfdbb 2990 }
362c6693 2991 }
362c6693 2992}
c801d85f 2993
b292e2f5
RR
2994bool wxWindow::AcceptsFocus() const
2995{
f03fc89f 2996 return m_acceptsFocus && wxWindowBase::AcceptsFocus();
b292e2f5
RR
2997}
2998
fdb7dadb 2999bool wxWindow::Reparent( wxWindowBase *newParentBase )
463c1fa1 3000{
223d09f6 3001 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
c50f1fb9 3002
fdb7dadb
VZ
3003 wxWindow *oldParent = m_parent,
3004 *newParent = (wxWindow *)newParentBase;
a2053b27 3005
5fd11f09
RR
3006 wxASSERT( GTK_IS_WIDGET(m_widget) );
3007
f03fc89f
VZ
3008 if ( !wxWindowBase::Reparent(newParent) )
3009 return FALSE;
8bbe427f 3010
5fd11f09
RR
3011 wxASSERT( GTK_IS_WIDGET(m_widget) );
3012
3013 /* prevent GTK from deleting the widget arbitrarily */
3014 gtk_widget_ref( m_widget );
3015
8ce63e9d
RR
3016 if (oldParent)
3017 {
3017f78d 3018 gtk_container_remove( GTK_CONTAINER(m_widget->parent), m_widget );
8ce63e9d 3019 }
c50f1fb9 3020
5fd11f09
RR
3021 wxASSERT( GTK_IS_WIDGET(m_widget) );
3022
8ce63e9d
RR
3023 if (newParent)
3024 {
3025 /* insert GTK representation */
3026 (*(newParent->m_insertCallback))(newParent, this);
3027 }
c50f1fb9 3028
5fd11f09
RR
3029 /* reverse: prevent GTK from deleting the widget arbitrarily */
3030 gtk_widget_unref( m_widget );
148cd9b6 3031
f03fc89f 3032 return TRUE;
362c6693 3033}
c801d85f 3034
c50f1fb9 3035void wxWindow::DoAddChild(wxWindow *child)
ddb6bc71 3036{
223d09f6 3037 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
ddb6bc71 3038
223d09f6 3039 wxASSERT_MSG( (child != NULL), wxT("invalid child window") );
ddb6bc71 3040
223d09f6 3041 wxASSERT_MSG( (m_insertCallback != NULL), wxT("invalid child insertion function") );
c50f1fb9 3042
ddb6bc71
RR
3043 /* add to list */
3044 AddChild( child );
c50f1fb9 3045
ddb6bc71
RR
3046 /* insert GTK representation */
3047 (*m_insertCallback)(this, child);
3048}
3049
68dda785 3050void wxWindow::Raise()
362c6693 3051{
223d09f6 3052 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 3053
a2053b27
RR
3054 if (!m_widget->window) return;
3055
f03fc89f 3056 gdk_window_raise( m_widget->window );
362c6693
RR
3057}
3058
68dda785 3059void wxWindow::Lower()
362c6693 3060{
223d09f6 3061 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 3062
a2053b27
RR
3063 if (!m_widget->window) return;
3064
f03fc89f 3065 gdk_window_lower( m_widget->window );
362c6693 3066}
c801d85f 3067
f03fc89f 3068bool wxWindow::SetCursor( const wxCursor &cursor )
86b29a61 3069{
223d09f6 3070 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
86b29a61 3071
f6bcfd97
BP
3072 if (cursor == m_cursor)
3073 return FALSE;
3074
3075 if (g_isIdle)
3076 wxapp_install_idle_handler();
3077
3078 if (cursor == wxNullCursor)
3079 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR );
3080 else
3081 return wxWindowBase::SetCursor( cursor );
362c6693 3082}
c801d85f 3083
85eb36c2 3084void wxWindow::WarpPointer( int x, int y )
4f22cf8d 3085{
223d09f6 3086 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
85eb36c2 3087
ed673c6a
RR
3088 /* we provide this function ourselves as it is
3089 missing in GDK (top of this file) */
148cd9b6 3090
ed673c6a
RR
3091 GdkWindow *window = (GdkWindow*) NULL;
3092 if (m_wxwindow)
da048e3d 3093 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3094 else
3095 window = GetConnectWidget()->window;
148cd9b6 3096
ed673c6a
RR
3097 if (window)
3098 gdk_window_warp_pointer( window, x, y );
4f22cf8d
RR
3099}
3100
debe6624 3101void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
c801d85f 3102{
f2593d0d 3103 if (!m_widget) return;
a2053b27
RR
3104 if (!m_widget->window) return;
3105
139adb6a 3106 if (eraseBackground && m_wxwindow && m_wxwindow->window)
c801d85f 3107 {
139adb6a
RR
3108 if (rect)
3109 {
da048e3d 3110 gdk_window_clear_area( GTK_PIZZA(m_wxwindow)->bin_window,
139adb6a 3111 rect->x, rect->y,
f234c60c 3112 rect->width, rect->height );
139adb6a
RR
3113 }
3114 else
3115 {
da048e3d 3116 gdk_window_clear( GTK_PIZZA(m_wxwindow)->bin_window );
139adb6a
RR
3117 }
3118 }
ff8bfdbb 3119
1b68e0b5 3120 /* there is no GTK equivalent of "draw only, don't clear" so we
da048e3d 3121 invent our own in the GtkPizza widget */
1b68e0b5 3122
139adb6a
RR
3123 if (!rect)
3124 {
3125 if (m_wxwindow)
b02da6b1 3126 {
b6fa52db
RR
3127
3128/*
b02da6b1
VZ
3129 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3130 gboolean old_clear = pizza->clear_on_draw;
3131 gtk_pizza_set_clear( pizza, FALSE );
1b68e0b5 3132 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
b02da6b1 3133 gtk_pizza_set_clear( pizza, old_clear );
b6fa52db
RR
3134*/
3135 GdkEventExpose gdk_event;
b4bee866
RR
3136 gdk_event.type = GDK_EXPOSE;
3137 gdk_event.window = GTK_PIZZA(m_wxwindow)->bin_window;
b6fa52db
RR
3138 gdk_event.count = 0;
3139 gdk_event.area.x = 0;
3140 gdk_event.area.y = 0;
3141 gdk_event.area.width = m_wxwindow->allocation.width;
3142 gdk_event.area.height = m_wxwindow->allocation.height;
3143 gtk_window_expose_callback( m_wxwindow, &gdk_event, this );
3144
b02da6b1 3145 }
ff8bfdbb 3146 else
b6fa52db 3147 {
139adb6a 3148 gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
b6fa52db 3149 }
362c6693 3150 }
c801d85f 3151 else
139adb6a 3152 {
139adb6a
RR
3153
3154 if (m_wxwindow)
b02da6b1 3155 {
b6fa52db 3156/*
b02da6b1
VZ
3157 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3158 gboolean old_clear = pizza->clear_on_draw;
3159 gtk_pizza_set_clear( pizza, FALSE );
148cd9b6 3160
b6fa52db
RR
3161 GdkRectangle gdk_rect;
3162 gdk_rect.x = rect->x;
3163 gdk_rect.y = rect->y;
3164 gdk_rect.width = rect->width;
3165 gdk_rect.height = rect->height;
1b68e0b5 3166 gtk_widget_draw( m_wxwindow, &gdk_rect );
b6fa52db 3167 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
148cd9b6 3168
b02da6b1 3169 gtk_pizza_set_clear( pizza, old_clear );
b6fa52db
RR
3170*/
3171 GdkEventExpose gdk_event;
b4bee866
RR
3172 gdk_event.type = GDK_EXPOSE;
3173 gdk_event.window = GTK_PIZZA(m_wxwindow)->bin_window;
b6fa52db
RR
3174 gdk_event.count = 0;
3175 gdk_event.area.x = rect->x;
3176 gdk_event.area.y = rect->y;
3177 gdk_event.area.width = rect->width;
3178 gdk_event.area.height = rect->height;
3179 gtk_window_expose_callback( m_wxwindow, &gdk_event, this );
b02da6b1 3180 }
139adb6a 3181 else
b6fa52db
RR
3182 {
3183 GdkRectangle gdk_rect;
3184 gdk_rect.x = rect->x;
3185 gdk_rect.y = rect->y;
3186 gdk_rect.width = rect->width;
3187 gdk_rect.height = rect->height;
139adb6a 3188 gtk_widget_draw( m_widget, &gdk_rect );
b6fa52db 3189 }
139adb6a 3190 }
362c6693 3191}
c801d85f 3192
68dda785 3193void wxWindow::Clear()
c801d85f 3194{
223d09f6 3195 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3196
a2053b27
RR
3197 if (!m_widget->window) return;
3198
f234c60c
RR
3199 if (m_wxwindow && m_wxwindow->window)
3200 {
c916e13b 3201// gdk_window_clear( m_wxwindow->window );
f234c60c 3202 }
362c6693 3203}
c801d85f 3204
ff8bfdbb 3205#if wxUSE_TOOLTIPS
f03fc89f 3206void wxWindow::DoSetToolTip( wxToolTip *tip )
b1170810 3207{
f03fc89f 3208 wxWindowBase::DoSetToolTip(tip);
ff8bfdbb 3209
f03fc89f
VZ
3210 if (m_tooltip)
3211 m_tooltip->Apply( this );
b1170810
RR
3212}
3213
05939a81 3214void wxWindow::ApplyToolTip( GtkTooltips *tips, const wxChar *tip )
b1170810 3215{
dcf924a3 3216 gtk_tooltips_set_tip( tips, GetConnectWidget(), wxConvCurrent->cWX2MB(tip), (gchar*) NULL );
301cd871 3217}
ff8bfdbb 3218#endif // wxUSE_TOOLTIPS
b1170810 3219
f03fc89f 3220bool wxWindow::SetBackgroundColour( const wxColour &colour )
c801d85f 3221{
223d09f6 3222 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
8bbe427f 3223
739730ca
RR
3224 if (!wxWindowBase::SetBackgroundColour(colour))
3225 {
3226 // don't leave if the GTK widget has just
3227 // been realized
3228 if (!m_delayedBackgroundColour) return FALSE;
3229 }
c50f1fb9 3230
ed673c6a
RR
3231 GdkWindow *window = (GdkWindow*) NULL;
3232 if (m_wxwindow)
da048e3d 3233 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3234 else
3235 window = GetConnectWidget()->window;
148cd9b6 3236
ed673c6a 3237 if (!window)
739730ca
RR
3238 {
3239 // indicate that a new style has been set
c50f1fb9
VZ
3240 // but it couldn't get applied as the
3241 // widget hasn't been realized yet.
3242 m_delayedBackgroundColour = TRUE;
739730ca 3243 }
ca298c88 3244
0f2f4986 3245 if ((m_wxwindow) &&
103aab26 3246 (m_wxwindow->window) &&
0f2f4986 3247 (m_backgroundColour != wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE)))
3bc755fc 3248 {
a2053b27
RR
3249 /* wxMSW doesn't clear the window here. I don't do that either to
3250 provide compatibility. call Clear() to do the job. */
ca298c88 3251
ed673c6a
RR
3252 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
3253 gdk_window_set_background( window, m_backgroundColour.GetColor() );
3bc755fc 3254 }
8bbe427f 3255
0f2f4986 3256 ApplyWidgetStyle();
c801d85f 3257
f03fc89f 3258 return TRUE;
6de97a3b
RR
3259}
3260
f03fc89f 3261bool wxWindow::SetForegroundColour( const wxColour &colour )
6de97a3b 3262{
223d09f6 3263 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
8bbe427f 3264
739730ca
RR
3265 if (!wxWindowBase::SetForegroundColour(colour))
3266 {
3267 // don't leave if the GTK widget has just
3268 // been realized
3269 if (!m_delayedForegroundColour) return FALSE;
3270 }
c50f1fb9 3271
ed673c6a
RR
3272 GdkWindow *window = (GdkWindow*) NULL;
3273 if (m_wxwindow)
da048e3d 3274 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3275 else
3276 window = GetConnectWidget()->window;
148cd9b6 3277
ed673c6a 3278 if (!window)
739730ca
RR
3279 {
3280 // indicate that a new style has been set
c50f1fb9
VZ
3281 // but it couldn't get applied as the
3282 // widget hasn't been realized yet.
3283 m_delayedForegroundColour = TRUE;
739730ca 3284 }
2b07d713 3285
0f2f4986 3286 ApplyWidgetStyle();
f03fc89f
VZ
3287
3288 return TRUE;
58614078
RR
3289}
3290
3291GtkStyle *wxWindow::GetWidgetStyle()
3292{
103aab26
RR
3293 if (m_widgetStyle)
3294 {
3295 GtkStyle *remake = gtk_style_copy( m_widgetStyle );
dd00f3f6
OK
3296#ifdef __WXGTK20__
3297 /* FIXME: is this necessary? */
3298 _G_TYPE_IGC(remake, GtkObjectClass) = _G_TYPE_IGC(m_widgetStyle, GtkObjectClass);
3299#else
103aab26 3300 remake->klass = m_widgetStyle->klass;
dd00f3f6 3301#endif
2daa0ce9 3302
103aab26
RR
3303 gtk_style_unref( m_widgetStyle );
3304 m_widgetStyle = remake;
3305 }
3306 else
3307 {
3308 GtkStyle *def = gtk_rc_get_style( m_widget );
e6527f9d 3309
103aab26
RR
3310 if (!def)
3311 def = gtk_widget_get_default_style();
e6527f9d 3312
103aab26 3313 m_widgetStyle = gtk_style_copy( def );
dd00f3f6
OK
3314#ifdef __WXGTK20__
3315 /* FIXME: is this necessary? */
3316 _G_TYPE_IGC(m_widgetStyle, GtkObjectClass) = _G_TYPE_IGC(def, GtkObjectClass);
3317#else
103aab26 3318 m_widgetStyle->klass = def->klass;
dd00f3f6 3319#endif
103aab26 3320 }
8bbe427f 3321
1ecc4d80 3322 return m_widgetStyle;
58614078
RR
3323}
3324
3325void wxWindow::SetWidgetStyle()
3326{
a56fcaaf 3327#if DISABLE_STYLE_IF_BROKEN_THEM
fb65642c
RR
3328 if (m_widget->style->engine_data)
3329 {
3330 static bool s_warningPrinted = FALSE;
3331 if (!s_warningPrinted)
3332 {
3333 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3334 s_warningPrinted = TRUE;
3335 }
3336 m_widgetStyle = m_widget->style;
3337 return;
3338 }
a56fcaaf 3339#endif
fb65642c 3340
1ecc4d80
RR
3341 GtkStyle *style = GetWidgetStyle();
3342
db434467
RR
3343 if (m_font != wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT ))
3344 {
3345 gdk_font_unref( style->font );
3346 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
3347 }
1ecc4d80
RR
3348
3349 if (m_foregroundColour.Ok())
3350 {
454e2a22 3351 m_foregroundColour.CalcPixel( gtk_widget_get_colormap( m_widget ) );
db434467
RR
3352 if (m_foregroundColour != wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT))
3353 {
3354 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
3355 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
3356 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
3357 }
f6bcfd97
BP
3358 else
3359 {
3360 // Try to restore the gtk default style. This is still a little
3361 // oversimplified for what is probably really needed here for controls
3362 // other than buttons, but is better than not being able to (re)set a
3363 // control's foreground colour to *wxBLACK -- RL
3364 GtkStyle *def = gtk_rc_get_style( m_widget );
3365
3366 if (!def)
3367 def = gtk_widget_get_default_style();
3368
3369 style->fg[GTK_STATE_NORMAL] = def->fg[GTK_STATE_NORMAL];
3370 style->fg[GTK_STATE_PRELIGHT] = def->fg[GTK_STATE_PRELIGHT];
3371 style->fg[GTK_STATE_ACTIVE] = def->fg[GTK_STATE_ACTIVE];
3372 }
1ecc4d80
RR
3373 }
3374
3375 if (m_backgroundColour.Ok())
3376 {
454e2a22 3377 m_backgroundColour.CalcPixel( gtk_widget_get_colormap( m_widget ) );
db434467
RR
3378 if (m_backgroundColour != wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE))
3379 {
3380 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
3381 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
3382 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
3383 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
3384 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
3385 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
3386 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
3387 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
f6bcfd97
BP
3388 }
3389 else
3390 {
3391 // Try to restore the gtk default style. This is still a little
3392 // oversimplified for what is probably really needed here for controls
3393 // other than buttons, but is better than not being able to (re)set a
3394 // control's background colour to default grey and means resetting a
3395 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3396 // behavior -- RL
3397 GtkStyle *def = gtk_rc_get_style( m_widget );
3398
3399 if (!def)
3400 def = gtk_widget_get_default_style();
3401
3402 style->bg[GTK_STATE_NORMAL] = def->bg[GTK_STATE_NORMAL];
3403 style->base[GTK_STATE_NORMAL] = def->base[GTK_STATE_NORMAL];
3404 style->bg[GTK_STATE_PRELIGHT] = def->bg[GTK_STATE_PRELIGHT];
3405 style->base[GTK_STATE_PRELIGHT] = def->base[GTK_STATE_PRELIGHT];
3406 style->bg[GTK_STATE_ACTIVE] = def->bg[GTK_STATE_ACTIVE];
3407 style->base[GTK_STATE_ACTIVE] = def->base[GTK_STATE_ACTIVE];
3408 style->bg[GTK_STATE_INSENSITIVE] = def->bg[GTK_STATE_INSENSITIVE];
3409 style->base[GTK_STATE_INSENSITIVE] = def->base[GTK_STATE_INSENSITIVE];
3410 }
1ecc4d80 3411 }
a81258be
RR
3412}
3413
58614078 3414void wxWindow::ApplyWidgetStyle()
a81258be 3415{
6de97a3b
RR
3416}
3417
2259e007
RR
3418//-----------------------------------------------------------------------------
3419// Pop-up menu stuff
3420//-----------------------------------------------------------------------------
3421
3422static void gtk_pop_hide_callback( GtkWidget *WXUNUSED(widget), bool* is_waiting )
3423{
3424 *is_waiting = FALSE;
3425}
3426
30dea054
RR
3427static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
3428{
1ecc4d80 3429 menu->SetInvokingWindow( win );
1987af7e 3430 wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
1ecc4d80
RR
3431 while (node)
3432 {
1987af7e 3433 wxMenuItem *menuitem = node->GetData();
1ecc4d80
RR
3434 if (menuitem->IsSubMenu())
3435 {
ff8bfdbb
VZ
3436 SetInvokingWindow( menuitem->GetSubMenu(), win );
3437 }
1987af7e
VZ
3438
3439 node = node->GetNext();
1ecc4d80 3440 }
362c6693 3441}
30dea054 3442
0c77152e
RR
3443static gint gs_pop_x = 0;
3444static gint gs_pop_y = 0;
3445
a234a61a
VZ
3446static void pop_pos_callback( GtkMenu * WXUNUSED(menu),
3447 gint *x, gint *y,
3448 wxWindow *win )
0c77152e
RR
3449{
3450 win->ClientToScreen( &gs_pop_x, &gs_pop_y );
3451 *x = gs_pop_x;
3452 *y = gs_pop_y;
3453}
3454
a1665b22 3455bool wxWindow::DoPopupMenu( wxMenu *menu, int x, int y )
30dea054 3456{
223d09f6 3457 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
47d67540 3458
223d09f6 3459 wxCHECK_MSG( menu != NULL, FALSE, wxT("invalid popup-menu") );
8bbe427f 3460
1ecc4d80 3461 SetInvokingWindow( menu, this );
ff8bfdbb 3462
631f1bfe
JS
3463 menu->UpdateUI();
3464
0c77152e
RR
3465 gs_pop_x = x;
3466 gs_pop_y = y;
ff8bfdbb 3467
2259e007 3468 bool is_waiting = TRUE;
148cd9b6 3469
2259e007
RR
3470 gtk_signal_connect( GTK_OBJECT(menu->m_menu), "hide",
3471 GTK_SIGNAL_FUNC(gtk_pop_hide_callback), (gpointer)&is_waiting );
3472
1ecc4d80 3473 gtk_menu_popup(
47d67540 3474 GTK_MENU(menu->m_menu),
0c77152e
RR
3475 (GtkWidget *) NULL, // parent menu shell
3476 (GtkWidget *) NULL, // parent menu item
3477 (GtkMenuPositionFunc) pop_pos_callback,
3478 (gpointer) this, // client data
3479 0, // button used to activate it
54517652 3480 gs_timeLastClick // the time of activation
47d67540 3481 );
148cd9b6 3482
956dbab1
RR
3483 while (is_waiting)
3484 {
3485 while (gtk_events_pending())
3486 gtk_main_iteration();
3487 }
2259e007 3488
1ecc4d80 3489 return TRUE;
30dea054
RR
3490}
3491
06cfab17 3492#if wxUSE_DRAG_AND_DROP
ac57418f 3493
c801d85f
KB
3494void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
3495{
223d09f6 3496 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3497
1ecc4d80 3498 GtkWidget *dnd_widget = GetConnectWidget();
47d67540 3499
1ecc4d80 3500 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
47d67540 3501
1ecc4d80
RR
3502 if (m_dropTarget) delete m_dropTarget;
3503 m_dropTarget = dropTarget;
47d67540 3504
1ecc4d80 3505 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
362c6693 3506}
c801d85f 3507
f03fc89f 3508#endif // wxUSE_DRAG_AND_DROP
ac57418f 3509
68dda785 3510GtkWidget* wxWindow::GetConnectWidget()
e3e65dac 3511{
1ecc4d80
RR
3512 GtkWidget *connect_widget = m_widget;
3513 if (m_wxwindow) connect_widget = m_wxwindow;
47d67540 3514
1ecc4d80 3515 return connect_widget;
e3e65dac 3516}
47d67540 3517
903f689b
RR
3518bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
3519{
148cd9b6 3520 if (m_wxwindow)
da048e3d 3521 return (window == GTK_PIZZA(m_wxwindow)->bin_window);
148cd9b6 3522
1ecc4d80 3523 return (window == m_widget->window);
903f689b
RR
3524}
3525
f03fc89f 3526bool wxWindow::SetFont( const wxFont &font )
c801d85f 3527{
223d09f6 3528 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
c801d85f 3529
739730ca
RR
3530 if (!wxWindowBase::SetFont(font))
3531 {
454e2a22 3532 return FALSE;
739730ca 3533 }
9c288e4d 3534
ae0bdb01 3535 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
f03fc89f 3536 if ( sysbg == m_backgroundColour )
ae0bdb01
RR
3537 {
3538 m_backgroundColour = wxNullColour;
3539 ApplyWidgetStyle();
ff8bfdbb
VZ
3540 m_backgroundColour = sysbg;
3541 }
ae0bdb01
RR
3542 else
3543 {
3544 ApplyWidgetStyle();
3545 }
c801d85f 3546
f03fc89f 3547 return TRUE;
362c6693 3548}
c801d85f 3549
68dda785 3550void wxWindow::CaptureMouse()
c801d85f 3551{
223d09f6 3552 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3553
223d09f6 3554 wxCHECK_RET( g_captureWindow == NULL, wxT("CaptureMouse called twice") );
47d67540 3555
ed673c6a
RR
3556 GdkWindow *window = (GdkWindow*) NULL;
3557 if (m_wxwindow)
da048e3d 3558 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3559 else
3560 window = GetConnectWidget()->window;
148cd9b6 3561
ed673c6a 3562 if (!window) return;
c50f1fb9 3563
cca602ac
JS
3564 wxCursor* cursor = & m_cursor;
3565 if (!cursor->Ok())
3566 cursor = wxSTANDARD_CURSOR;
3567
ed673c6a 3568 gdk_pointer_grab( window, FALSE,
1ecc4d80
RR
3569 (GdkEventMask)
3570 (GDK_BUTTON_PRESS_MASK |
3571 GDK_BUTTON_RELEASE_MASK |
148cd9b6 3572 GDK_POINTER_MOTION_HINT_MASK |
1ecc4d80 3573 GDK_POINTER_MOTION_MASK),
ff8bfdbb 3574 (GdkWindow *) NULL,
cca602ac 3575 cursor->GetCursor(),
b02da6b1 3576 (guint32)GDK_CURRENT_TIME );
72195a0f 3577 g_captureWindow = this;
362c6693 3578}
c801d85f 3579
68dda785 3580void wxWindow::ReleaseMouse()
c801d85f 3581{
223d09f6 3582 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3583
223d09f6 3584 wxCHECK_RET( g_captureWindow, wxT("ReleaseMouse called twice") );
47d67540 3585
ed673c6a
RR
3586 GdkWindow *window = (GdkWindow*) NULL;
3587 if (m_wxwindow)
da048e3d 3588 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3589 else
3590 window = GetConnectWidget()->window;
148cd9b6 3591
b02da6b1
VZ
3592 if (!window)
3593 return;
c50f1fb9 3594
b02da6b1 3595 gdk_pointer_ungrab ( (guint32)GDK_CURRENT_TIME );
72195a0f 3596 g_captureWindow = (wxWindow*) NULL;
362c6693 3597}
c801d85f 3598
f03fc89f 3599bool wxWindow::IsRetained() const
c801d85f 3600{
1ecc4d80 3601 return FALSE;
362c6693 3602}
c801d85f 3603
debe6624 3604void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
cb43b372 3605 int range, bool refresh )
c801d85f 3606{
223d09f6 3607 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
8bbe427f 3608
223d09f6 3609 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
c801d85f 3610
1ecc4d80 3611 m_hasScrolling = TRUE;
47d67540 3612
1ecc4d80 3613 if (orient == wxHORIZONTAL)
cb43b372 3614 {
1ecc4d80
RR
3615 float fpos = (float)pos;
3616 float frange = (float)range;
3617 float fthumb = (float)thumbVisible;
3618 if (fpos > frange-fthumb) fpos = frange-fthumb;
3619 if (fpos < 0.0) fpos = 0.0;
3620
3621 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
3622 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
3623 {
3624 SetScrollPos( orient, pos, refresh );
3625 return;
3626 }
47d67540 3627
1ecc4d80 3628 m_oldHorizontalPos = fpos;
47d67540 3629
1ecc4d80
RR
3630 m_hAdjust->lower = 0.0;
3631 m_hAdjust->upper = frange;
3632 m_hAdjust->value = fpos;
3633 m_hAdjust->step_increment = 1.0;
3634 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
3635 m_hAdjust->page_size = fthumb;
cb43b372 3636 }
1ecc4d80
RR
3637 else
3638 {
3639 float fpos = (float)pos;
3640 float frange = (float)range;
3641 float fthumb = (float)thumbVisible;
3642 if (fpos > frange-fthumb) fpos = frange-fthumb;
3643 if (fpos < 0.0) fpos = 0.0;
3644
3645 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
3646 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
3647 {
3648 SetScrollPos( orient, pos, refresh );
3649 return;
3650 }
47d67540 3651
1ecc4d80 3652 m_oldVerticalPos = fpos;
47d67540 3653
1ecc4d80
RR
3654 m_vAdjust->lower = 0.0;
3655 m_vAdjust->upper = frange;
3656 m_vAdjust->value = fpos;
3657 m_vAdjust->step_increment = 1.0;
3658 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
3659 m_vAdjust->page_size = fthumb;
3660 }
47d67540 3661
eb082a08
RR
3662 if (orient == wxHORIZONTAL)
3663 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
3664 else
3665 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
362c6693 3666}
c801d85f 3667
debe6624 3668void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
c801d85f 3669{
223d09f6 3670 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
1ecc4d80 3671
223d09f6 3672 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
1ecc4d80
RR
3673
3674 if (orient == wxHORIZONTAL)
3675 {
3676 float fpos = (float)pos;
3677 if (fpos > m_hAdjust->upper - m_hAdjust->page_size) fpos = m_hAdjust->upper - m_hAdjust->page_size;
3678 if (fpos < 0.0) fpos = 0.0;
3679 m_oldHorizontalPos = fpos;
3680
3681 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
3682 m_hAdjust->value = fpos;
3683 }
3684 else
3685 {
3686 float fpos = (float)pos;
3687 if (fpos > m_vAdjust->upper - m_vAdjust->page_size) fpos = m_vAdjust->upper - m_vAdjust->page_size;
3688 if (fpos < 0.0) fpos = 0.0;
3689 m_oldVerticalPos = fpos;
ff8bfdbb 3690
1ecc4d80
RR
3691 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
3692 m_vAdjust->value = fpos;
3693 }
47d67540 3694
5b8a521e 3695 if (m_wxwindow->window)
47d67540 3696 {
5b8a521e 3697 if (orient == wxHORIZONTAL)
473d087e
RR
3698 {
3699 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust),
3700 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
2daa0ce9 3701
5b8a521e 3702 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
2daa0ce9 3703
473d087e
RR
3704 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
3705 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
3706 }
5b8a521e 3707 else
473d087e
RR
3708 {
3709 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust),
3710 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
2daa0ce9 3711
5b8a521e 3712 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
473d087e
RR
3713
3714 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
3715 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
3716 }
cb43b372 3717 }
362c6693 3718}
c801d85f 3719
debe6624 3720int wxWindow::GetScrollThumb( int orient ) const
c801d85f 3721{
223d09f6 3722 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
47d67540 3723
223d09f6 3724 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
47d67540 3725
1ecc4d80
RR
3726 if (orient == wxHORIZONTAL)
3727 return (int)(m_hAdjust->page_size+0.5);
3728 else
3729 return (int)(m_vAdjust->page_size+0.5);
362c6693 3730}
c801d85f 3731
debe6624 3732int wxWindow::GetScrollPos( int orient ) const
c801d85f 3733{
223d09f6 3734 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
47d67540 3735
223d09f6 3736 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
c801d85f 3737
1ecc4d80
RR
3738 if (orient == wxHORIZONTAL)
3739 return (int)(m_hAdjust->value+0.5);
3740 else
3741 return (int)(m_vAdjust->value+0.5);
362c6693 3742}
c801d85f 3743
debe6624 3744int wxWindow::GetScrollRange( int orient ) const
c801d85f 3745{
223d09f6 3746 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
47d67540 3747
223d09f6 3748 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
c801d85f 3749
1ecc4d80
RR
3750 if (orient == wxHORIZONTAL)
3751 return (int)(m_hAdjust->upper+0.5);
3752 else
3753 return (int)(m_vAdjust->upper+0.5);
362c6693 3754}
c801d85f 3755
debe6624 3756void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
c801d85f 3757{
223d09f6 3758 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3759
223d09f6 3760 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
8e217128
RR
3761
3762 if ((dx == 0) && (dy == 0)) return;
c801d85f 3763
b6fa52db 3764 m_clipPaintRegion = TRUE;
da048e3d 3765 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
b6fa52db 3766 m_clipPaintRegion = FALSE;
8e217128
RR
3767
3768/*
3769 if (m_children.GetCount() > 0)
3770 {
3771 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3772 }
3773 else
3774 {
3775 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3776
3777 pizza->xoffset -= dx;
3778 pizza->yoffset -= dy;
3779
3780 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3781 gdk_gc_set_exposures( m_scrollGC, TRUE );
3782
3783 int cw = 0;
3784 int ch = 0;
3785 GetClientSize( &cw, &ch );
3786 int w = cw - abs(dx);
3787 int h = ch - abs(dy);
3788
3789 if ((h < 0) || (w < 0))
3790 {
3791 Refresh();
3792 }
3793 else
3794 {
3795 int s_x = 0;
3796 int s_y = 0;
3797 if (dx < 0) s_x = -dx;
3798 if (dy < 0) s_y = -dy;
3799 int d_x = 0;
3800 int d_y = 0;
3801 if (dx > 0) d_x = dx;
3802 if (dy > 0) d_y = dy;
3803
3804 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3805 pizza->bin_window, s_x, s_y, w, h );
3806
3807 wxRect rect;
3808 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3809 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3810 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3811 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3812
3813 Refresh( TRUE, &rect );
3814 }
3815
3816 gdk_gc_unref( m_scrollGC );
3817 }
3818*/
c801d85f 3819}
3723b7b1 3820
3723b7b1
JS
3821// Find the wxWindow at the current mouse position, also returning the mouse
3822// position.
3823wxWindow* wxFindWindowAtPointer(wxPoint& pt)
3824{
59a12e90
JS
3825 pt = wxGetMousePosition();
3826 wxWindow* found = wxFindWindowAtPoint(pt);
3827 return found;
3723b7b1
JS
3828}
3829
3830// Get the current mouse position.
3831wxPoint wxGetMousePosition()
3832{
59a12e90
JS
3833 /* This crashes when used within wxHelpContext,
3834 so we have to use the X-specific implementation below.
3835 gint x, y;
3836 GdkModifierType *mask;
3837 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
3838
3839 return wxPoint(x, y);
3840 */
3841
3723b7b1
JS
3842 int x, y;
3843 GdkWindow* windowAtPtr = gdk_window_at_pointer(& x, & y);
57591e0e
JS
3844 if (!windowAtPtr)
3845 return wxPoint(-999, -999);
59a12e90
JS
3846
3847 Display *display = GDK_WINDOW_XDISPLAY(windowAtPtr);
3848 Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display));
3849 Window rootReturn, childReturn;
3850 int rootX, rootY, winX, winY;
3851 unsigned int maskReturn;
3852
3853 XQueryPointer (display,
3854 rootWindow,
3855 &rootReturn,
3856 &childReturn,
3857 &rootX, &rootY, &winX, &winY, &maskReturn);
3858 return wxPoint(rootX, rootY);
3859
3723b7b1
JS
3860}
3861