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