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