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