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