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