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