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