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