]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/window.cpp
1. made compilation with WXWIN_COMPATIBILITY_EVENT_TYPES really work
[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{
31c6b4fc 2337 m_isBeingDeleted = TRUE;
43a18898 2338 m_hasVMT = FALSE;
47d67540 2339
f03fc89f
VZ
2340 if (m_widget)
2341 Show( FALSE );
8bbe427f 2342
a2053b27
RR
2343 DestroyChildren();
2344
f03fc89f
VZ
2345 if (m_parent)
2346 m_parent->RemoveChild( this );
c801d85f 2347
63081513
RR
2348#ifdef HAVE_XIM
2349 if (m_ic)
2350 gdk_ic_destroy (m_ic);
2351 if (m_icattr)
2352 gdk_ic_attr_destroy (m_icattr);
2353#endif
2354
f03fc89f 2355 if (m_widgetStyle)
a2053b27 2356 {
a56fcaaf 2357#if DISABLE_STYLE_IF_BROKEN_THEME
bce1406b
RR
2358 // don't delete if it's a pixmap theme style
2359 if (!m_widgetStyle->engine_data)
2360 gtk_style_unref( m_widgetStyle );
a56fcaaf 2361#endif
c50f1fb9 2362 m_widgetStyle = (GtkStyle*) NULL;
a2053b27 2363 }
c801d85f 2364
f03fc89f 2365 if (m_wxwindow)
a2053b27 2366 {
f03fc89f 2367 gtk_widget_destroy( m_wxwindow );
c50f1fb9 2368 m_wxwindow = (GtkWidget*) NULL;
a2053b27 2369 }
8bbe427f 2370
f03fc89f 2371 if (m_widget)
a2053b27 2372 {
f03fc89f 2373 gtk_widget_destroy( m_widget );
c50f1fb9 2374 m_widget = (GtkWidget*) NULL;
a2053b27 2375 }
362c6693 2376}
c801d85f 2377
4dcaf11a 2378bool wxWindow::PreCreation( wxWindow *parent, const wxPoint &pos, const wxSize &size )
c801d85f 2379{
223d09f6 2380 wxCHECK_MSG( !m_needParent || parent, FALSE, wxT("Need complete parent.") );
8bbe427f 2381
4dcaf11a
RR
2382 /* this turns -1 into 20 so that a minimal window is
2383 visible even although -1,-1 has been given as the
2384 size of the window. the same trick is used in other
2385 ports and should make debugging easier */
f03fc89f
VZ
2386 m_width = WidthDefault(size.x);
2387 m_height = HeightDefault(size.y);
8bbe427f 2388
43a18898
RR
2389 m_x = (int)pos.x;
2390 m_y = (int)pos.y;
8bbe427f 2391
4dcaf11a 2392 /* some reasonable defaults */
148cd9b6 2393 if (!parent)
6ca41e57 2394 {
43a18898
RR
2395 if (m_x == -1)
2396 {
2397 m_x = (gdk_screen_width () - m_width) / 2;
2398 if (m_x < 10) m_x = 10;
2399 }
2400 if (m_y == -1)
2401 {
2402 m_y = (gdk_screen_height () - m_height) / 2;
2403 if (m_y < 10) m_y = 10;
2404 }
6ca41e57 2405 }
148cd9b6 2406
4dcaf11a 2407 return TRUE;
c801d85f
KB
2408}
2409
68dda785 2410void wxWindow::PostCreation()
c801d85f 2411{
223d09f6 2412 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
ca298c88 2413
43a18898
RR
2414 if (m_wxwindow)
2415 {
147bc491 2416 if (!m_noExpose)
b02da6b1 2417 {
147bc491 2418 /* these get reported to wxWindows -> wxPaintEvent */
b420fb6a
RR
2419
2420 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow), TRUE );
2421
147bc491
RR
2422 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
2423 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
2424
2425 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
2426 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
e22454be
RR
2427
2428 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE))
2429 {
2430 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "event",
2431 GTK_SIGNAL_FUNC(gtk_window_event_event_callback), (gpointer)this );
2432 }
b02da6b1 2433 }
148cd9b6 2434
ef47f9b3 2435#if (GTK_MINOR_VERSION > 0)
ed673c6a 2436 /* these are called when the "sunken" or "raised" borders are drawn */
034be888
RR
2437 gtk_signal_connect( GTK_OBJECT(m_widget), "expose_event",
2438 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback), (gpointer)this );
2439
2440 gtk_signal_connect( GTK_OBJECT(m_widget), "draw",
2441 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback), (gpointer)this );
ef47f9b3 2442#endif
43a18898 2443 }
47d67540 2444
63081513
RR
2445 if (m_wxwindow && m_needParent)
2446 {
2447 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "focus_in_event",
2448 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
2449
2450 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "focus_out_event",
2451 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
2452 }
2453 else
2454 {
2455 // For dialogs and frames, we are interested mainly in
2456 // m_widget's focus.
2daa0ce9 2457
63081513
RR
2458 gtk_signal_connect( GTK_OBJECT(m_widget), "focus_in_event",
2459 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
2460
2461 gtk_signal_connect( GTK_OBJECT(m_widget), "focus_out_event",
2462 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
2463 }
2464
a2053b27 2465 GtkWidget *connect_widget = GetConnectWidget();
f03fc89f 2466
a2053b27 2467 ConnectWidget( connect_widget );
47d67540 2468
63081513 2469 /* We cannot set colours, fonts and cursors before the widget has
a2053b27
RR
2470 been realized, so we do this directly after realization */
2471 gtk_signal_connect( GTK_OBJECT(connect_widget), "realize",
c50f1fb9 2472 GTK_SIGNAL_FUNC(gtk_window_realized_callback), (gpointer) this );
2daa0ce9 2473
63081513
RR
2474 if (m_wxwindow)
2475 {
47c93b63 2476 // Catch native resize events
8f75cb6c
RR
2477 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "size_allocate",
2478 GTK_SIGNAL_FUNC(gtk_window_size_callback), (gpointer)this );
2daa0ce9 2479
47c93b63 2480 // Initialize XIM support
63081513
RR
2481 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "realize",
2482 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback), (gpointer) this );
8f75cb6c 2483
47c93b63 2484 // And resize XIM window
b79395c5
RR
2485 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "size_allocate",
2486 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback), (gpointer)this );
63081513 2487 }
2daa0ce9 2488
47c93b63
RR
2489 if (!GTK_IS_COMBO(m_widget))
2490 {
2491 // This is needed if we want to add our windows into native
2492 // GTK control, such as the toolbar. With this callback, the
2493 // toolbar gets to know the correct size (the one set by the
2494 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2495 // when moving to GTK 2.0.
2496 gtk_signal_connect( GTK_OBJECT(m_widget), "size_request",
2497 GTK_SIGNAL_FUNC(gtk_window_size_request_callback), (gpointer) this );
2498 }
2499
43a18898 2500 m_hasVMT = TRUE;
b4071e91
RR
2501}
2502
2503void wxWindow::ConnectWidget( GtkWidget *widget )
2504{
43a18898
RR
2505 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
2506 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
c801d85f 2507
b666df2c
RR
2508 gtk_signal_connect( GTK_OBJECT(widget), "key_release_event",
2509 GTK_SIGNAL_FUNC(gtk_window_key_release_callback), (gpointer)this );
2510
43a18898
RR
2511 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
2512 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
47d67540 2513
43a18898
RR
2514 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
2515 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
47d67540 2516
43a18898
RR
2517 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
2518 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
47d67540 2519
43a18898
RR
2520 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
2521 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
47d67540 2522
43a18898
RR
2523 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
2524 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
362c6693 2525}
c801d85f 2526
68dda785 2527bool wxWindow::Destroy()
c801d85f 2528{
223d09f6 2529 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
47d67540 2530
43a18898 2531 m_hasVMT = FALSE;
c801d85f 2532
f03fc89f 2533 return wxWindowBase::Destroy();
362c6693 2534}
c801d85f 2535
23efdd02
RR
2536void wxWindow::DoMoveWindow(int x, int y, int width, int height)
2537{
2538 gtk_pizza_set_size( GTK_PIZZA(m_parent->m_wxwindow), m_widget, x, y, width, height );
2539}
2daa0ce9 2540
bfc6fde4 2541void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
c801d85f 2542{
223d09f6
KB
2543 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
2544 wxASSERT_MSG( (m_parent != NULL), wxT("wxWindow::SetSize requires parent.\n") );
8bbe427f 2545
e27ce4e9 2546 if (m_resizing) return; /* I don't like recursions */
fb1585ae 2547 m_resizing = TRUE;
b6fa52db 2548
a2053b27 2549 if (m_parent->m_wxwindow == NULL) /* i.e. wxNotebook */
fb1585ae 2550 {
e27ce4e9 2551 /* don't set the size for children of wxNotebook, just take the values. */
fb1585ae
RR
2552 m_x = x;
2553 m_y = y;
2554 m_width = width;
ba4e3652 2555 m_height = height;
fb1585ae 2556 }
ba4e3652 2557 else
fb1585ae 2558 {
da048e3d 2559 GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
148cd9b6 2560
85ad5eb5 2561 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
ba4e3652 2562 {
da048e3d
RR
2563 if (x != -1) m_x = x + pizza->xoffset;
2564 if (y != -1) m_y = y + pizza->yoffset;
ba4e3652
RR
2565 if (width != -1) m_width = width;
2566 if (height != -1) m_height = height;
2567 }
2568 else
2569 {
da048e3d
RR
2570 m_x = x + pizza->xoffset;
2571 m_y = y + pizza->yoffset;
ba4e3652
RR
2572 m_width = width;
2573 m_height = height;
2574 }
47d67540 2575
ba4e3652
RR
2576 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
2577 {
2578 if (width == -1) m_width = 80;
2579 }
2580
2581 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
2582 {
2583 if (height == -1) m_height = 26;
2584 }
8bbe427f 2585
ba4e3652
RR
2586 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
2587 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
d3b4d113
RR
2588 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
2589 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
47d67540 2590
a2053b27 2591 int border = 0;
c50f1fb9 2592 int bottom_border = 0;
f03fc89f 2593
29f538ce 2594 if (GTK_WIDGET_CAN_DEFAULT(m_widget))
c50f1fb9
VZ
2595 {
2596 /* the default button has a border around it */
2597 border = 6;
2598 bottom_border = 5;
2599 }
2600
23efdd02
RR
2601 DoMoveWindow( m_x-border,
2602 m_y-border,
2603 m_width+2*border,
2604 m_height+border+bottom_border );
54517652 2605 }
148cd9b6 2606
5b8a521e
RR
2607 if (m_hasScrolling)
2608 {
b6fa52db
RR
2609 /* Sometimes the client area changes size without the
2610 whole windows's size changing, but if the whole
2611 windows's size doesn't change, no wxSizeEvent will
2612 normally be sent. Here we add an extra test if
2613 the client test has been changed and this will
2614 be used then. */
5b8a521e
RR
2615 GetClientSize( &m_oldClientWidth, &m_oldClientHeight );
2616 }
2617
54517652 2618/*
6d693bb4
RR
2619 wxPrintf( "OnSize sent from " );
2620 if (GetClassInfo() && GetClassInfo()->GetClassName())
2621 wxPrintf( GetClassInfo()->GetClassName() );
2622 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2623*/
2624
30760ce7
RR
2625 if (!m_nativeSizeEvent)
2626 {
2627 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
2628 event.SetEventObject( this );
2629 GetEventHandler()->ProcessEvent( event );
2630 }
6d693bb4 2631
fb1585ae 2632 m_resizing = FALSE;
362c6693 2633}
c801d85f 2634
9390a202
RR
2635void wxWindow::OnInternalIdle()
2636{
148cd9b6
VZ
2637 if ( g_sendActivateEvent != -1 )
2638 {
2639 bool activate = g_sendActivateEvent != 0;
2640
2641 // do it only once
2642 g_sendActivateEvent = -1;
2643
2644 wxActivateEvent event(wxEVT_ACTIVATE, activate, GetId());
2645 event.SetEventObject(this);
2646
2647 (void)GetEventHandler()->ProcessEvent(event);
2648 }
2649
9146082c
RR
2650 wxCursor cursor = m_cursor;
2651 if (g_globalCursor.Ok()) cursor = g_globalCursor;
c50f1fb9 2652
f7a11f8c 2653 if (cursor.Ok())
9146082c 2654 {
3017f78d 2655 /* I now set the cursor anew in every OnInternalIdle call
b02da6b1
VZ
2656 as setting the cursor in a parent window also effects the
2657 windows above so that checking for the current cursor is
2658 not possible. */
148cd9b6 2659
9146082c 2660 if (m_wxwindow)
6a008b33 2661 {
da048e3d 2662 GdkWindow *window = GTK_PIZZA(m_wxwindow)->bin_window;
6a008b33 2663 if (window)
c50f1fb9 2664 gdk_window_set_cursor( window, cursor.GetCursor() );
6a008b33
VZ
2665
2666 if (!g_globalCursor.Ok())
2667 cursor = *wxSTANDARD_CURSOR;
2668
2669 window = m_widget->window;
5e014a0c 2670 if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget)))
9146082c 2671 gdk_window_set_cursor( window, cursor.GetCursor() );
5e014a0c 2672
6a008b33
VZ
2673 }
2674 else
2675 {
5e014a0c 2676
9146082c 2677 GdkWindow *window = m_widget->window;
5e014a0c 2678 if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget)))
9146082c 2679 gdk_window_set_cursor( window, cursor.GetCursor() );
5e014a0c 2680
6a008b33 2681 }
9146082c 2682 }
6a008b33 2683
9390a202
RR
2684 UpdateWindowUI();
2685}
2686
f03fc89f 2687void wxWindow::DoGetSize( int *width, int *height ) const
c801d85f 2688{
223d09f6 2689 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2690
fb1585ae
RR
2691 if (width) (*width) = m_width;
2692 if (height) (*height) = m_height;
362c6693 2693}
c801d85f 2694
bfc6fde4 2695void wxWindow::DoSetClientSize( int width, int height )
c801d85f 2696{
223d09f6 2697 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2698
1ecc4d80 2699 if (!m_wxwindow)
c801d85f 2700 {
1ecc4d80 2701 SetSize( width, height );
c801d85f
KB
2702 }
2703 else
2704 {
1ecc4d80
RR
2705 int dw = 0;
2706 int dh = 0;
2707
98d3fdbe
RR
2708 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2709 {
5e014a0c 2710 /* when using GTK 1.2 we set the shadow border size to 2 */
6a008b33 2711 dw += 2 * 2;
98d3fdbe
RR
2712 dh += 2 * 2;
2713 }
5e014a0c
RR
2714 if (HasFlag(wxSIMPLE_BORDER))
2715 {
2716 /* when using GTK 1.2 we set the simple border size to 1 */
2717 dw += 1 * 2;
2718 dh += 1 * 2;
2719 }
034be888 2720
5b8a521e 2721 if (m_hasScrolling)
98d3fdbe 2722 {
324dbfec 2723 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2daa0ce9 2724
9000c624
RR
2725 GtkRequisition vscroll_req;
2726 vscroll_req.width = 2;
2727 vscroll_req.height = 2;
dd00f3f6 2728 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
9000c624 2729 (scroll_window->vscrollbar, &vscroll_req );
2daa0ce9 2730
9000c624
RR
2731 GtkRequisition hscroll_req;
2732 hscroll_req.width = 2;
2733 hscroll_req.height = 2;
dd00f3f6 2734 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
9000c624
RR
2735 (scroll_window->hscrollbar, &hscroll_req );
2736
dd00f3f6 2737 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
324dbfec 2738
1ecc4d80
RR
2739 if (scroll_window->vscrollbar_visible)
2740 {
9000c624 2741 dw += vscroll_req.width;
1ecc4d80
RR
2742 dw += scroll_class->scrollbar_spacing;
2743 }
2744
2745 if (scroll_window->hscrollbar_visible)
2746 {
9000c624 2747 dh += hscroll_req.height;
63cc5d9d 2748 dh += scroll_class->scrollbar_spacing;
1ecc4d80 2749 }
9000c624 2750 }
1ecc4d80 2751
034be888 2752 SetSize( width+dw, height+dh );
1ecc4d80 2753 }
362c6693 2754}
c801d85f 2755
f03fc89f 2756void wxWindow::DoGetClientSize( int *width, int *height ) const
c801d85f 2757{
223d09f6 2758 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2759
1ecc4d80
RR
2760 if (!m_wxwindow)
2761 {
2762 if (width) (*width) = m_width;
2763 if (height) (*height) = m_height;
c801d85f
KB
2764 }
2765 else
2766 {
1ecc4d80
RR
2767 int dw = 0;
2768 int dh = 0;
2769
98d3fdbe
RR
2770 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2771 {
5e014a0c 2772 /* when using GTK 1.2 we set the shadow border size to 2 */
6a008b33 2773 dw += 2 * 2;
98d3fdbe
RR
2774 dh += 2 * 2;
2775 }
5e014a0c
RR
2776 if (HasFlag(wxSIMPLE_BORDER))
2777 {
2778 /* when using GTK 1.2 we set the simple border size to 1 */
2779 dw += 1 * 2;
2780 dh += 1 * 2;
2781 }
9000c624 2782
5b8a521e 2783 if (m_hasScrolling)
98d3fdbe 2784 {
6a008b33 2785 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2daa0ce9 2786
9000c624
RR
2787 GtkRequisition vscroll_req;
2788 vscroll_req.width = 2;
2789 vscroll_req.height = 2;
dd00f3f6 2790 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->vscrollbar) )->size_request )
9000c624 2791 (scroll_window->vscrollbar, &vscroll_req );
2daa0ce9 2792
9000c624
RR
2793 GtkRequisition hscroll_req;
2794 hscroll_req.width = 2;
2795 hscroll_req.height = 2;
dd00f3f6 2796 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window->hscrollbar) )->size_request )
9000c624
RR
2797 (scroll_window->hscrollbar, &hscroll_req );
2798
dd00f3f6 2799 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) );
6a008b33 2800
1ecc4d80
RR
2801 if (scroll_window->vscrollbar_visible)
2802 {
9000c624 2803 dw += vscroll_req.width;
1ecc4d80
RR
2804 dw += scroll_class->scrollbar_spacing;
2805 }
2806
2807 if (scroll_window->hscrollbar_visible)
2808 {
9000c624 2809 dh += hscroll_req.height;
1ecc4d80
RR
2810 dh += scroll_class->scrollbar_spacing;
2811 }
6a008b33 2812 }
47d67540 2813
1ecc4d80
RR
2814 if (width) (*width) = m_width - dw;
2815 if (height) (*height) = m_height - dh;
2816 }
362c6693 2817}
c801d85f 2818
f03fc89f 2819void wxWindow::DoGetPosition( int *x, int *y ) const
c801d85f 2820{
223d09f6 2821 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2822
bf0c00c6
RR
2823 int dx = 0;
2824 int dy = 0;
2825 if (m_parent && m_parent->m_wxwindow)
2826 {
da048e3d 2827 GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
b02da6b1
VZ
2828 dx = pizza->xoffset;
2829 dy = pizza->yoffset;
bf0c00c6
RR
2830 }
2831
2832 if (x) (*x) = m_x - dx;
2833 if (y) (*y) = m_y - dy;
362c6693 2834}
c801d85f 2835
dabc0cd5 2836void wxWindow::DoClientToScreen( int *x, int *y ) const
c801d85f 2837{
223d09f6 2838 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2839
a2053b27
RR
2840 if (!m_widget->window) return;
2841
43a18898
RR
2842 GdkWindow *source = (GdkWindow *) NULL;
2843 if (m_wxwindow)
da048e3d 2844 source = GTK_PIZZA(m_wxwindow)->bin_window;
43a18898
RR
2845 else
2846 source = m_widget->window;
47d67540 2847
43a18898
RR
2848 int org_x = 0;
2849 int org_y = 0;
2850 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2851
43a18898 2852 if (!m_wxwindow)
c801d85f 2853 {
43a18898
RR
2854 if (GTK_WIDGET_NO_WINDOW (m_widget))
2855 {
2856 org_x += m_widget->allocation.x;
2857 org_y += m_widget->allocation.y;
2858 }
362c6693 2859 }
47d67540 2860
43a18898
RR
2861 if (x) *x += org_x;
2862 if (y) *y += org_y;
362c6693 2863}
c801d85f 2864
dabc0cd5 2865void wxWindow::DoScreenToClient( int *x, int *y ) const
c801d85f 2866{
223d09f6 2867 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2868
a2053b27
RR
2869 if (!m_widget->window) return;
2870
1ecc4d80
RR
2871 GdkWindow *source = (GdkWindow *) NULL;
2872 if (m_wxwindow)
da048e3d 2873 source = GTK_PIZZA(m_wxwindow)->bin_window;
1ecc4d80
RR
2874 else
2875 source = m_widget->window;
47d67540 2876
1ecc4d80
RR
2877 int org_x = 0;
2878 int org_y = 0;
2879 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2880
1ecc4d80 2881 if (!m_wxwindow)
c801d85f 2882 {
1ecc4d80
RR
2883 if (GTK_WIDGET_NO_WINDOW (m_widget))
2884 {
2885 org_x += m_widget->allocation.x;
2886 org_y += m_widget->allocation.y;
2887 }
362c6693 2888 }
47d67540 2889
1ecc4d80
RR
2890 if (x) *x -= org_x;
2891 if (y) *y -= org_y;
362c6693 2892}
c801d85f 2893
f03fc89f 2894bool wxWindow::Show( bool show )
c801d85f 2895{
223d09f6 2896 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
47d67540 2897
739730ca
RR
2898 if (!wxWindowBase::Show(show))
2899 {
2900 // nothing to do
f03fc89f 2901 return FALSE;
739730ca 2902 }
8bbe427f 2903
f03fc89f
VZ
2904 if (show)
2905 gtk_widget_show( m_widget );
1ecc4d80 2906 else
f03fc89f 2907 gtk_widget_hide( m_widget );
8bbe427f 2908
f03fc89f 2909 return TRUE;
362c6693 2910}
c801d85f 2911
f03fc89f 2912bool wxWindow::Enable( bool enable )
c801d85f 2913{
223d09f6 2914 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
5e0aa05a 2915
739730ca
RR
2916 if (!wxWindowBase::Enable(enable))
2917 {
2918 // nothing to do
f03fc89f 2919 return FALSE;
739730ca 2920 }
1ecc4d80 2921
f03fc89f
VZ
2922 gtk_widget_set_sensitive( m_widget, enable );
2923 if ( m_wxwindow )
2924 gtk_widget_set_sensitive( m_wxwindow, enable );
ff8bfdbb 2925
f03fc89f 2926 return TRUE;
362c6693 2927}
c801d85f 2928
f03fc89f 2929int wxWindow::GetCharHeight() const
2f2aa628 2930{
223d09f6 2931 wxCHECK_MSG( (m_widget != NULL), 12, wxT("invalid window") );
47d67540 2932
223d09f6 2933 wxCHECK_MSG( m_font.Ok(), 12, wxT("invalid font") );
2f2aa628 2934
f03fc89f
VZ
2935 GdkFont *font = m_font.GetInternalFont( 1.0 );
2936
2937 return font->ascent + font->descent;
362c6693 2938}
c801d85f 2939
f03fc89f 2940int wxWindow::GetCharWidth() const
c33c4050 2941{
223d09f6 2942 wxCHECK_MSG( (m_widget != NULL), 8, wxT("invalid window") );
47d67540 2943
223d09f6 2944 wxCHECK_MSG( m_font.Ok(), 8, wxT("invalid font") );
47d67540 2945
463c1fa1 2946 GdkFont *font = m_font.GetInternalFont( 1.0 );
ff8bfdbb 2947
463c1fa1 2948 return gdk_string_width( font, "H" );
c33c4050
RR
2949}
2950
f03fc89f
VZ
2951void wxWindow::GetTextExtent( const wxString& string,
2952 int *x,
2953 int *y,
2954 int *descent,
2955 int *externalLeading,
2956 const wxFont *theFont ) const
c33c4050 2957{
463c1fa1
RR
2958 wxFont fontToUse = m_font;
2959 if (theFont) fontToUse = *theFont;
47d67540 2960
223d09f6 2961 wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") );
47d67540 2962
463c1fa1 2963 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
05939a81 2964 if (x) (*x) = gdk_string_width( font, string.mbc_str() );
463c1fa1
RR
2965 if (y) (*y) = font->ascent + font->descent;
2966 if (descent) (*descent) = font->descent;
2967 if (externalLeading) (*externalLeading) = 0; // ??
c33c4050
RR
2968}
2969
68dda785 2970void wxWindow::SetFocus()
c801d85f 2971{
223d09f6 2972 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
2daa0ce9 2973
354aa1e3
RR
2974 if (m_wxwindow)
2975 {
173348db
RR
2976 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow))
2977 gtk_widget_grab_focus (m_wxwindow);
354aa1e3
RR
2978 return;
2979 }
2980
2981 if (m_widget)
c801d85f 2982 {
173348db 2983 if (GTK_WIDGET_CAN_FOCUS(m_widget) && !GTK_WIDGET_HAS_FOCUS (m_widget) )
463c1fa1 2984 {
354aa1e3 2985 gtk_widget_grab_focus (m_widget);
463c1fa1 2986 }
354aa1e3 2987 else if (GTK_IS_CONTAINER(m_widget))
ff8bfdbb 2988 {
354aa1e3 2989 gtk_container_focus( GTK_CONTAINER(m_widget), GTK_DIR_TAB_FORWARD );
ff8bfdbb
VZ
2990 }
2991 else
2992 {
b02da6b1 2993 // ?
ff8bfdbb 2994 }
362c6693 2995 }
362c6693 2996}
c801d85f 2997
b292e2f5
RR
2998bool wxWindow::AcceptsFocus() const
2999{
f03fc89f 3000 return m_acceptsFocus && wxWindowBase::AcceptsFocus();
b292e2f5
RR
3001}
3002
fdb7dadb 3003bool wxWindow::Reparent( wxWindowBase *newParentBase )
463c1fa1 3004{
223d09f6 3005 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
c50f1fb9 3006
fdb7dadb
VZ
3007 wxWindow *oldParent = m_parent,
3008 *newParent = (wxWindow *)newParentBase;
a2053b27 3009
5fd11f09
RR
3010 wxASSERT( GTK_IS_WIDGET(m_widget) );
3011
f03fc89f
VZ
3012 if ( !wxWindowBase::Reparent(newParent) )
3013 return FALSE;
8bbe427f 3014
5fd11f09
RR
3015 wxASSERT( GTK_IS_WIDGET(m_widget) );
3016
3017 /* prevent GTK from deleting the widget arbitrarily */
3018 gtk_widget_ref( m_widget );
3019
8ce63e9d
RR
3020 if (oldParent)
3021 {
3017f78d 3022 gtk_container_remove( GTK_CONTAINER(m_widget->parent), m_widget );
8ce63e9d 3023 }
c50f1fb9 3024
5fd11f09
RR
3025 wxASSERT( GTK_IS_WIDGET(m_widget) );
3026
8ce63e9d
RR
3027 if (newParent)
3028 {
3029 /* insert GTK representation */
3030 (*(newParent->m_insertCallback))(newParent, this);
3031 }
c50f1fb9 3032
5fd11f09
RR
3033 /* reverse: prevent GTK from deleting the widget arbitrarily */
3034 gtk_widget_unref( m_widget );
148cd9b6 3035
f03fc89f 3036 return TRUE;
362c6693 3037}
c801d85f 3038
c50f1fb9 3039void wxWindow::DoAddChild(wxWindow *child)
ddb6bc71 3040{
223d09f6 3041 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
ddb6bc71 3042
223d09f6 3043 wxASSERT_MSG( (child != NULL), wxT("invalid child window") );
ddb6bc71 3044
223d09f6 3045 wxASSERT_MSG( (m_insertCallback != NULL), wxT("invalid child insertion function") );
c50f1fb9 3046
ddb6bc71
RR
3047 /* add to list */
3048 AddChild( child );
c50f1fb9 3049
ddb6bc71
RR
3050 /* insert GTK representation */
3051 (*m_insertCallback)(this, child);
3052}
3053
68dda785 3054void wxWindow::Raise()
362c6693 3055{
223d09f6 3056 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 3057
a2053b27
RR
3058 if (!m_widget->window) return;
3059
f03fc89f 3060 gdk_window_raise( m_widget->window );
362c6693
RR
3061}
3062
68dda785 3063void wxWindow::Lower()
362c6693 3064{
223d09f6 3065 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 3066
a2053b27
RR
3067 if (!m_widget->window) return;
3068
f03fc89f 3069 gdk_window_lower( m_widget->window );
362c6693 3070}
c801d85f 3071
f03fc89f 3072bool wxWindow::SetCursor( const wxCursor &cursor )
86b29a61 3073{
223d09f6 3074 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
86b29a61 3075
f6bcfd97
BP
3076 if (cursor == m_cursor)
3077 return FALSE;
3078
3079 if (g_isIdle)
3080 wxapp_install_idle_handler();
3081
3082 if (cursor == wxNullCursor)
3083 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR );
3084 else
3085 return wxWindowBase::SetCursor( cursor );
362c6693 3086}
c801d85f 3087
85eb36c2 3088void wxWindow::WarpPointer( int x, int y )
4f22cf8d 3089{
223d09f6 3090 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
85eb36c2 3091
ed673c6a
RR
3092 /* we provide this function ourselves as it is
3093 missing in GDK (top of this file) */
148cd9b6 3094
ed673c6a
RR
3095 GdkWindow *window = (GdkWindow*) NULL;
3096 if (m_wxwindow)
da048e3d 3097 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3098 else
3099 window = GetConnectWidget()->window;
148cd9b6 3100
ed673c6a
RR
3101 if (window)
3102 gdk_window_warp_pointer( window, x, y );
4f22cf8d
RR
3103}
3104
debe6624 3105void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
c801d85f 3106{
f2593d0d 3107 if (!m_widget) return;
a2053b27
RR
3108 if (!m_widget->window) return;
3109
139adb6a 3110 if (eraseBackground && m_wxwindow && m_wxwindow->window)
c801d85f 3111 {
139adb6a
RR
3112 if (rect)
3113 {
da048e3d 3114 gdk_window_clear_area( GTK_PIZZA(m_wxwindow)->bin_window,
139adb6a 3115 rect->x, rect->y,
f234c60c 3116 rect->width, rect->height );
139adb6a
RR
3117 }
3118 else
3119 {
da048e3d 3120 gdk_window_clear( GTK_PIZZA(m_wxwindow)->bin_window );
139adb6a
RR
3121 }
3122 }
ff8bfdbb 3123
1b68e0b5 3124 /* there is no GTK equivalent of "draw only, don't clear" so we
da048e3d 3125 invent our own in the GtkPizza widget */
1b68e0b5 3126
139adb6a
RR
3127 if (!rect)
3128 {
3129 if (m_wxwindow)
b02da6b1 3130 {
b6fa52db
RR
3131
3132/*
b02da6b1
VZ
3133 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3134 gboolean old_clear = pizza->clear_on_draw;
3135 gtk_pizza_set_clear( pizza, FALSE );
1b68e0b5 3136 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
b02da6b1 3137 gtk_pizza_set_clear( pizza, old_clear );
b6fa52db
RR
3138*/
3139 GdkEventExpose gdk_event;
b4bee866
RR
3140 gdk_event.type = GDK_EXPOSE;
3141 gdk_event.window = GTK_PIZZA(m_wxwindow)->bin_window;
b6fa52db
RR
3142 gdk_event.count = 0;
3143 gdk_event.area.x = 0;
3144 gdk_event.area.y = 0;
3145 gdk_event.area.width = m_wxwindow->allocation.width;
3146 gdk_event.area.height = m_wxwindow->allocation.height;
3147 gtk_window_expose_callback( m_wxwindow, &gdk_event, this );
3148
b02da6b1 3149 }
ff8bfdbb 3150 else
b6fa52db 3151 {
139adb6a 3152 gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
b6fa52db 3153 }
362c6693 3154 }
c801d85f 3155 else
139adb6a 3156 {
139adb6a
RR
3157
3158 if (m_wxwindow)
b02da6b1 3159 {
b6fa52db 3160/*
b02da6b1
VZ
3161 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3162 gboolean old_clear = pizza->clear_on_draw;
3163 gtk_pizza_set_clear( pizza, FALSE );
148cd9b6 3164
b6fa52db
RR
3165 GdkRectangle gdk_rect;
3166 gdk_rect.x = rect->x;
3167 gdk_rect.y = rect->y;
3168 gdk_rect.width = rect->width;
3169 gdk_rect.height = rect->height;
1b68e0b5 3170 gtk_widget_draw( m_wxwindow, &gdk_rect );
b6fa52db 3171 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
148cd9b6 3172
b02da6b1 3173 gtk_pizza_set_clear( pizza, old_clear );
b6fa52db
RR
3174*/
3175 GdkEventExpose gdk_event;
b4bee866
RR
3176 gdk_event.type = GDK_EXPOSE;
3177 gdk_event.window = GTK_PIZZA(m_wxwindow)->bin_window;
b6fa52db
RR
3178 gdk_event.count = 0;
3179 gdk_event.area.x = rect->x;
3180 gdk_event.area.y = rect->y;
3181 gdk_event.area.width = rect->width;
3182 gdk_event.area.height = rect->height;
3183 gtk_window_expose_callback( m_wxwindow, &gdk_event, this );
b02da6b1 3184 }
139adb6a 3185 else
b6fa52db
RR
3186 {
3187 GdkRectangle gdk_rect;
3188 gdk_rect.x = rect->x;
3189 gdk_rect.y = rect->y;
3190 gdk_rect.width = rect->width;
3191 gdk_rect.height = rect->height;
139adb6a 3192 gtk_widget_draw( m_widget, &gdk_rect );
b6fa52db 3193 }
139adb6a 3194 }
362c6693 3195}
c801d85f 3196
68dda785 3197void wxWindow::Clear()
c801d85f 3198{
223d09f6 3199 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3200
a2053b27
RR
3201 if (!m_widget->window) return;
3202
f234c60c
RR
3203 if (m_wxwindow && m_wxwindow->window)
3204 {
c916e13b 3205// gdk_window_clear( m_wxwindow->window );
f234c60c 3206 }
362c6693 3207}
c801d85f 3208
ff8bfdbb 3209#if wxUSE_TOOLTIPS
f03fc89f 3210void wxWindow::DoSetToolTip( wxToolTip *tip )
b1170810 3211{
f03fc89f 3212 wxWindowBase::DoSetToolTip(tip);
ff8bfdbb 3213
f03fc89f
VZ
3214 if (m_tooltip)
3215 m_tooltip->Apply( this );
b1170810
RR
3216}
3217
05939a81 3218void wxWindow::ApplyToolTip( GtkTooltips *tips, const wxChar *tip )
b1170810 3219{
dcf924a3 3220 gtk_tooltips_set_tip( tips, GetConnectWidget(), wxConvCurrent->cWX2MB(tip), (gchar*) NULL );
301cd871 3221}
ff8bfdbb 3222#endif // wxUSE_TOOLTIPS
b1170810 3223
f03fc89f 3224bool wxWindow::SetBackgroundColour( const wxColour &colour )
c801d85f 3225{
223d09f6 3226 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
8bbe427f 3227
739730ca
RR
3228 if (!wxWindowBase::SetBackgroundColour(colour))
3229 {
3230 // don't leave if the GTK widget has just
3231 // been realized
3232 if (!m_delayedBackgroundColour) return FALSE;
3233 }
c50f1fb9 3234
ed673c6a
RR
3235 GdkWindow *window = (GdkWindow*) NULL;
3236 if (m_wxwindow)
da048e3d 3237 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3238 else
3239 window = GetConnectWidget()->window;
148cd9b6 3240
ed673c6a 3241 if (!window)
739730ca
RR
3242 {
3243 // indicate that a new style has been set
c50f1fb9
VZ
3244 // but it couldn't get applied as the
3245 // widget hasn't been realized yet.
3246 m_delayedBackgroundColour = TRUE;
739730ca 3247 }
ca298c88 3248
0f2f4986 3249 if ((m_wxwindow) &&
103aab26 3250 (m_wxwindow->window) &&
0f2f4986 3251 (m_backgroundColour != wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE)))
3bc755fc 3252 {
a2053b27
RR
3253 /* wxMSW doesn't clear the window here. I don't do that either to
3254 provide compatibility. call Clear() to do the job. */
ca298c88 3255
ed673c6a
RR
3256 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
3257 gdk_window_set_background( window, m_backgroundColour.GetColor() );
3bc755fc 3258 }
8bbe427f 3259
0f2f4986 3260 ApplyWidgetStyle();
c801d85f 3261
f03fc89f 3262 return TRUE;
6de97a3b
RR
3263}
3264
f03fc89f 3265bool wxWindow::SetForegroundColour( const wxColour &colour )
6de97a3b 3266{
223d09f6 3267 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
8bbe427f 3268
739730ca
RR
3269 if (!wxWindowBase::SetForegroundColour(colour))
3270 {
3271 // don't leave if the GTK widget has just
3272 // been realized
3273 if (!m_delayedForegroundColour) return FALSE;
3274 }
c50f1fb9 3275
ed673c6a
RR
3276 GdkWindow *window = (GdkWindow*) NULL;
3277 if (m_wxwindow)
da048e3d 3278 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3279 else
3280 window = GetConnectWidget()->window;
148cd9b6 3281
ed673c6a 3282 if (!window)
739730ca
RR
3283 {
3284 // indicate that a new style has been set
c50f1fb9
VZ
3285 // but it couldn't get applied as the
3286 // widget hasn't been realized yet.
3287 m_delayedForegroundColour = TRUE;
739730ca 3288 }
2b07d713 3289
0f2f4986 3290 ApplyWidgetStyle();
f03fc89f
VZ
3291
3292 return TRUE;
58614078
RR
3293}
3294
3295GtkStyle *wxWindow::GetWidgetStyle()
3296{
103aab26
RR
3297 if (m_widgetStyle)
3298 {
3299 GtkStyle *remake = gtk_style_copy( m_widgetStyle );
dd00f3f6
OK
3300#ifdef __WXGTK20__
3301 /* FIXME: is this necessary? */
3302 _G_TYPE_IGC(remake, GtkObjectClass) = _G_TYPE_IGC(m_widgetStyle, GtkObjectClass);
3303#else
103aab26 3304 remake->klass = m_widgetStyle->klass;
dd00f3f6 3305#endif
2daa0ce9 3306
103aab26
RR
3307 gtk_style_unref( m_widgetStyle );
3308 m_widgetStyle = remake;
3309 }
3310 else
3311 {
3312 GtkStyle *def = gtk_rc_get_style( m_widget );
e6527f9d 3313
103aab26
RR
3314 if (!def)
3315 def = gtk_widget_get_default_style();
e6527f9d 3316
103aab26 3317 m_widgetStyle = gtk_style_copy( def );
dd00f3f6
OK
3318#ifdef __WXGTK20__
3319 /* FIXME: is this necessary? */
3320 _G_TYPE_IGC(m_widgetStyle, GtkObjectClass) = _G_TYPE_IGC(def, GtkObjectClass);
3321#else
103aab26 3322 m_widgetStyle->klass = def->klass;
dd00f3f6 3323#endif
103aab26 3324 }
8bbe427f 3325
1ecc4d80 3326 return m_widgetStyle;
58614078
RR
3327}
3328
3329void wxWindow::SetWidgetStyle()
3330{
a56fcaaf 3331#if DISABLE_STYLE_IF_BROKEN_THEM
fb65642c
RR
3332 if (m_widget->style->engine_data)
3333 {
3334 static bool s_warningPrinted = FALSE;
3335 if (!s_warningPrinted)
3336 {
3337 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3338 s_warningPrinted = TRUE;
3339 }
3340 m_widgetStyle = m_widget->style;
3341 return;
3342 }
a56fcaaf 3343#endif
fb65642c 3344
1ecc4d80
RR
3345 GtkStyle *style = GetWidgetStyle();
3346
db434467
RR
3347 if (m_font != wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT ))
3348 {
3349 gdk_font_unref( style->font );
3350 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
3351 }
1ecc4d80
RR
3352
3353 if (m_foregroundColour.Ok())
3354 {
454e2a22 3355 m_foregroundColour.CalcPixel( gtk_widget_get_colormap( m_widget ) );
db434467
RR
3356 if (m_foregroundColour != wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT))
3357 {
3358 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
3359 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
3360 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
3361 }
f6bcfd97
BP
3362 else
3363 {
3364 // Try to restore the gtk default style. This is still a little
3365 // oversimplified for what is probably really needed here for controls
3366 // other than buttons, but is better than not being able to (re)set a
3367 // control's foreground colour to *wxBLACK -- RL
3368 GtkStyle *def = gtk_rc_get_style( m_widget );
3369
3370 if (!def)
3371 def = gtk_widget_get_default_style();
3372
3373 style->fg[GTK_STATE_NORMAL] = def->fg[GTK_STATE_NORMAL];
3374 style->fg[GTK_STATE_PRELIGHT] = def->fg[GTK_STATE_PRELIGHT];
3375 style->fg[GTK_STATE_ACTIVE] = def->fg[GTK_STATE_ACTIVE];
3376 }
1ecc4d80
RR
3377 }
3378
3379 if (m_backgroundColour.Ok())
3380 {
454e2a22 3381 m_backgroundColour.CalcPixel( gtk_widget_get_colormap( m_widget ) );
db434467
RR
3382 if (m_backgroundColour != wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE))
3383 {
3384 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
3385 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
3386 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
3387 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
3388 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
3389 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
3390 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
3391 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
f6bcfd97
BP
3392 }
3393 else
3394 {
3395 // Try to restore the gtk default style. This is still a little
3396 // oversimplified for what is probably really needed here for controls
3397 // other than buttons, but is better than not being able to (re)set a
3398 // control's background colour to default grey and means resetting a
3399 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3400 // behavior -- RL
3401 GtkStyle *def = gtk_rc_get_style( m_widget );
3402
3403 if (!def)
3404 def = gtk_widget_get_default_style();
3405
3406 style->bg[GTK_STATE_NORMAL] = def->bg[GTK_STATE_NORMAL];
3407 style->base[GTK_STATE_NORMAL] = def->base[GTK_STATE_NORMAL];
3408 style->bg[GTK_STATE_PRELIGHT] = def->bg[GTK_STATE_PRELIGHT];
3409 style->base[GTK_STATE_PRELIGHT] = def->base[GTK_STATE_PRELIGHT];
3410 style->bg[GTK_STATE_ACTIVE] = def->bg[GTK_STATE_ACTIVE];
3411 style->base[GTK_STATE_ACTIVE] = def->base[GTK_STATE_ACTIVE];
3412 style->bg[GTK_STATE_INSENSITIVE] = def->bg[GTK_STATE_INSENSITIVE];
3413 style->base[GTK_STATE_INSENSITIVE] = def->base[GTK_STATE_INSENSITIVE];
3414 }
1ecc4d80 3415 }
a81258be
RR
3416}
3417
58614078 3418void wxWindow::ApplyWidgetStyle()
a81258be 3419{
6de97a3b
RR
3420}
3421
2259e007
RR
3422//-----------------------------------------------------------------------------
3423// Pop-up menu stuff
3424//-----------------------------------------------------------------------------
3425
3426static void gtk_pop_hide_callback( GtkWidget *WXUNUSED(widget), bool* is_waiting )
3427{
3428 *is_waiting = FALSE;
3429}
3430
30dea054
RR
3431static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
3432{
1ecc4d80 3433 menu->SetInvokingWindow( win );
1987af7e 3434 wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
1ecc4d80
RR
3435 while (node)
3436 {
1987af7e 3437 wxMenuItem *menuitem = node->GetData();
1ecc4d80
RR
3438 if (menuitem->IsSubMenu())
3439 {
ff8bfdbb
VZ
3440 SetInvokingWindow( menuitem->GetSubMenu(), win );
3441 }
1987af7e
VZ
3442
3443 node = node->GetNext();
1ecc4d80 3444 }
362c6693 3445}
30dea054 3446
0c77152e
RR
3447static gint gs_pop_x = 0;
3448static gint gs_pop_y = 0;
3449
a234a61a
VZ
3450static void pop_pos_callback( GtkMenu * WXUNUSED(menu),
3451 gint *x, gint *y,
3452 wxWindow *win )
0c77152e
RR
3453{
3454 win->ClientToScreen( &gs_pop_x, &gs_pop_y );
3455 *x = gs_pop_x;
3456 *y = gs_pop_y;
3457}
3458
a1665b22 3459bool wxWindow::DoPopupMenu( wxMenu *menu, int x, int y )
30dea054 3460{
223d09f6 3461 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
47d67540 3462
223d09f6 3463 wxCHECK_MSG( menu != NULL, FALSE, wxT("invalid popup-menu") );
8bbe427f 3464
1ecc4d80 3465 SetInvokingWindow( menu, this );
ff8bfdbb 3466
631f1bfe
JS
3467 menu->UpdateUI();
3468
0c77152e
RR
3469 gs_pop_x = x;
3470 gs_pop_y = y;
ff8bfdbb 3471
2259e007 3472 bool is_waiting = TRUE;
148cd9b6 3473
2259e007
RR
3474 gtk_signal_connect( GTK_OBJECT(menu->m_menu), "hide",
3475 GTK_SIGNAL_FUNC(gtk_pop_hide_callback), (gpointer)&is_waiting );
3476
1ecc4d80 3477 gtk_menu_popup(
47d67540 3478 GTK_MENU(menu->m_menu),
0c77152e
RR
3479 (GtkWidget *) NULL, // parent menu shell
3480 (GtkWidget *) NULL, // parent menu item
3481 (GtkMenuPositionFunc) pop_pos_callback,
3482 (gpointer) this, // client data
3483 0, // button used to activate it
54517652 3484 gs_timeLastClick // the time of activation
47d67540 3485 );
148cd9b6 3486
956dbab1
RR
3487 while (is_waiting)
3488 {
3489 while (gtk_events_pending())
3490 gtk_main_iteration();
3491 }
2259e007 3492
1ecc4d80 3493 return TRUE;
30dea054
RR
3494}
3495
06cfab17 3496#if wxUSE_DRAG_AND_DROP
ac57418f 3497
c801d85f
KB
3498void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
3499{
223d09f6 3500 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3501
1ecc4d80 3502 GtkWidget *dnd_widget = GetConnectWidget();
47d67540 3503
1ecc4d80 3504 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
47d67540 3505
1ecc4d80
RR
3506 if (m_dropTarget) delete m_dropTarget;
3507 m_dropTarget = dropTarget;
47d67540 3508
1ecc4d80 3509 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
362c6693 3510}
c801d85f 3511
f03fc89f 3512#endif // wxUSE_DRAG_AND_DROP
ac57418f 3513
68dda785 3514GtkWidget* wxWindow::GetConnectWidget()
e3e65dac 3515{
1ecc4d80
RR
3516 GtkWidget *connect_widget = m_widget;
3517 if (m_wxwindow) connect_widget = m_wxwindow;
47d67540 3518
1ecc4d80 3519 return connect_widget;
e3e65dac 3520}
47d67540 3521
903f689b
RR
3522bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
3523{
148cd9b6 3524 if (m_wxwindow)
da048e3d 3525 return (window == GTK_PIZZA(m_wxwindow)->bin_window);
148cd9b6 3526
1ecc4d80 3527 return (window == m_widget->window);
903f689b
RR
3528}
3529
f03fc89f 3530bool wxWindow::SetFont( const wxFont &font )
c801d85f 3531{
223d09f6 3532 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
c801d85f 3533
739730ca
RR
3534 if (!wxWindowBase::SetFont(font))
3535 {
454e2a22 3536 return FALSE;
739730ca 3537 }
9c288e4d 3538
ae0bdb01 3539 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
f03fc89f 3540 if ( sysbg == m_backgroundColour )
ae0bdb01
RR
3541 {
3542 m_backgroundColour = wxNullColour;
3543 ApplyWidgetStyle();
ff8bfdbb
VZ
3544 m_backgroundColour = sysbg;
3545 }
ae0bdb01
RR
3546 else
3547 {
3548 ApplyWidgetStyle();
3549 }
c801d85f 3550
f03fc89f 3551 return TRUE;
362c6693 3552}
c801d85f 3553
68dda785 3554void wxWindow::CaptureMouse()
c801d85f 3555{
223d09f6 3556 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3557
223d09f6 3558 wxCHECK_RET( g_captureWindow == NULL, wxT("CaptureMouse called twice") );
47d67540 3559
ed673c6a
RR
3560 GdkWindow *window = (GdkWindow*) NULL;
3561 if (m_wxwindow)
da048e3d 3562 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3563 else
3564 window = GetConnectWidget()->window;
148cd9b6 3565
ed673c6a 3566 if (!window) return;
c50f1fb9 3567
cca602ac
JS
3568 wxCursor* cursor = & m_cursor;
3569 if (!cursor->Ok())
3570 cursor = wxSTANDARD_CURSOR;
3571
ed673c6a 3572 gdk_pointer_grab( window, FALSE,
1ecc4d80
RR
3573 (GdkEventMask)
3574 (GDK_BUTTON_PRESS_MASK |
3575 GDK_BUTTON_RELEASE_MASK |
148cd9b6 3576 GDK_POINTER_MOTION_HINT_MASK |
1ecc4d80 3577 GDK_POINTER_MOTION_MASK),
ff8bfdbb 3578 (GdkWindow *) NULL,
cca602ac 3579 cursor->GetCursor(),
b02da6b1 3580 (guint32)GDK_CURRENT_TIME );
72195a0f 3581 g_captureWindow = this;
362c6693 3582}
c801d85f 3583
68dda785 3584void wxWindow::ReleaseMouse()
c801d85f 3585{
223d09f6 3586 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3587
223d09f6 3588 wxCHECK_RET( g_captureWindow, wxT("ReleaseMouse called twice") );
47d67540 3589
ed673c6a
RR
3590 GdkWindow *window = (GdkWindow*) NULL;
3591 if (m_wxwindow)
da048e3d 3592 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3593 else
3594 window = GetConnectWidget()->window;
148cd9b6 3595
b02da6b1
VZ
3596 if (!window)
3597 return;
c50f1fb9 3598
b02da6b1 3599 gdk_pointer_ungrab ( (guint32)GDK_CURRENT_TIME );
72195a0f 3600 g_captureWindow = (wxWindow*) NULL;
362c6693 3601}
c801d85f 3602
f03fc89f 3603bool wxWindow::IsRetained() const
c801d85f 3604{
1ecc4d80 3605 return FALSE;
362c6693 3606}
c801d85f 3607
debe6624 3608void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
cb43b372 3609 int range, bool refresh )
c801d85f 3610{
223d09f6 3611 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
8bbe427f 3612
223d09f6 3613 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
c801d85f 3614
1ecc4d80 3615 m_hasScrolling = TRUE;
47d67540 3616
1ecc4d80 3617 if (orient == wxHORIZONTAL)
cb43b372 3618 {
1ecc4d80
RR
3619 float fpos = (float)pos;
3620 float frange = (float)range;
3621 float fthumb = (float)thumbVisible;
3622 if (fpos > frange-fthumb) fpos = frange-fthumb;
3623 if (fpos < 0.0) fpos = 0.0;
3624
3625 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
3626 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
3627 {
3628 SetScrollPos( orient, pos, refresh );
3629 return;
3630 }
47d67540 3631
1ecc4d80 3632 m_oldHorizontalPos = fpos;
47d67540 3633
1ecc4d80
RR
3634 m_hAdjust->lower = 0.0;
3635 m_hAdjust->upper = frange;
3636 m_hAdjust->value = fpos;
3637 m_hAdjust->step_increment = 1.0;
3638 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
3639 m_hAdjust->page_size = fthumb;
cb43b372 3640 }
1ecc4d80
RR
3641 else
3642 {
3643 float fpos = (float)pos;
3644 float frange = (float)range;
3645 float fthumb = (float)thumbVisible;
3646 if (fpos > frange-fthumb) fpos = frange-fthumb;
3647 if (fpos < 0.0) fpos = 0.0;
3648
3649 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
3650 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
3651 {
3652 SetScrollPos( orient, pos, refresh );
3653 return;
3654 }
47d67540 3655
1ecc4d80 3656 m_oldVerticalPos = fpos;
47d67540 3657
1ecc4d80
RR
3658 m_vAdjust->lower = 0.0;
3659 m_vAdjust->upper = frange;
3660 m_vAdjust->value = fpos;
3661 m_vAdjust->step_increment = 1.0;
3662 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
3663 m_vAdjust->page_size = fthumb;
3664 }
47d67540 3665
eb082a08
RR
3666 if (orient == wxHORIZONTAL)
3667 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
3668 else
3669 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
362c6693 3670}
c801d85f 3671
debe6624 3672void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
c801d85f 3673{
223d09f6 3674 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
1ecc4d80 3675
223d09f6 3676 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
1ecc4d80
RR
3677
3678 if (orient == wxHORIZONTAL)
3679 {
3680 float fpos = (float)pos;
3681 if (fpos > m_hAdjust->upper - m_hAdjust->page_size) fpos = m_hAdjust->upper - m_hAdjust->page_size;
3682 if (fpos < 0.0) fpos = 0.0;
3683 m_oldHorizontalPos = fpos;
3684
3685 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
3686 m_hAdjust->value = fpos;
3687 }
3688 else
3689 {
3690 float fpos = (float)pos;
3691 if (fpos > m_vAdjust->upper - m_vAdjust->page_size) fpos = m_vAdjust->upper - m_vAdjust->page_size;
3692 if (fpos < 0.0) fpos = 0.0;
3693 m_oldVerticalPos = fpos;
ff8bfdbb 3694
1ecc4d80
RR
3695 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
3696 m_vAdjust->value = fpos;
3697 }
47d67540 3698
5b8a521e 3699 if (m_wxwindow->window)
47d67540 3700 {
5b8a521e 3701 if (orient == wxHORIZONTAL)
473d087e
RR
3702 {
3703 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust),
3704 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
2daa0ce9 3705
5b8a521e 3706 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
2daa0ce9 3707
473d087e
RR
3708 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
3709 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
3710 }
5b8a521e 3711 else
473d087e
RR
3712 {
3713 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust),
3714 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
2daa0ce9 3715
5b8a521e 3716 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
473d087e
RR
3717
3718 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
3719 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
3720 }
cb43b372 3721 }
362c6693 3722}
c801d85f 3723
debe6624 3724int wxWindow::GetScrollThumb( int orient ) const
c801d85f 3725{
223d09f6 3726 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
47d67540 3727
223d09f6 3728 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
47d67540 3729
1ecc4d80
RR
3730 if (orient == wxHORIZONTAL)
3731 return (int)(m_hAdjust->page_size+0.5);
3732 else
3733 return (int)(m_vAdjust->page_size+0.5);
362c6693 3734}
c801d85f 3735
debe6624 3736int wxWindow::GetScrollPos( int orient ) const
c801d85f 3737{
223d09f6 3738 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
47d67540 3739
223d09f6 3740 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
c801d85f 3741
1ecc4d80
RR
3742 if (orient == wxHORIZONTAL)
3743 return (int)(m_hAdjust->value+0.5);
3744 else
3745 return (int)(m_vAdjust->value+0.5);
362c6693 3746}
c801d85f 3747
debe6624 3748int wxWindow::GetScrollRange( int orient ) const
c801d85f 3749{
223d09f6 3750 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
47d67540 3751
223d09f6 3752 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
c801d85f 3753
1ecc4d80
RR
3754 if (orient == wxHORIZONTAL)
3755 return (int)(m_hAdjust->upper+0.5);
3756 else
3757 return (int)(m_vAdjust->upper+0.5);
362c6693 3758}
c801d85f 3759
debe6624 3760void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
c801d85f 3761{
223d09f6 3762 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3763
223d09f6 3764 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
8e217128
RR
3765
3766 if ((dx == 0) && (dy == 0)) return;
c801d85f 3767
b6fa52db 3768 m_clipPaintRegion = TRUE;
da048e3d 3769 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
b6fa52db 3770 m_clipPaintRegion = FALSE;
8e217128
RR
3771
3772/*
3773 if (m_children.GetCount() > 0)
3774 {
3775 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3776 }
3777 else
3778 {
3779 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3780
3781 pizza->xoffset -= dx;
3782 pizza->yoffset -= dy;
3783
3784 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3785 gdk_gc_set_exposures( m_scrollGC, TRUE );
3786
3787 int cw = 0;
3788 int ch = 0;
3789 GetClientSize( &cw, &ch );
3790 int w = cw - abs(dx);
3791 int h = ch - abs(dy);
3792
3793 if ((h < 0) || (w < 0))
3794 {
3795 Refresh();
3796 }
3797 else
3798 {
3799 int s_x = 0;
3800 int s_y = 0;
3801 if (dx < 0) s_x = -dx;
3802 if (dy < 0) s_y = -dy;
3803 int d_x = 0;
3804 int d_y = 0;
3805 if (dx > 0) d_x = dx;
3806 if (dy > 0) d_y = dy;
3807
3808 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3809 pizza->bin_window, s_x, s_y, w, h );
3810
3811 wxRect rect;
3812 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3813 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3814 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3815 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3816
3817 Refresh( TRUE, &rect );
3818 }
3819
3820 gdk_gc_unref( m_scrollGC );
3821 }
3822*/
c801d85f 3823}
3723b7b1 3824
3723b7b1
JS
3825// Find the wxWindow at the current mouse position, also returning the mouse
3826// position.
3827wxWindow* wxFindWindowAtPointer(wxPoint& pt)
3828{
59a12e90
JS
3829 pt = wxGetMousePosition();
3830 wxWindow* found = wxFindWindowAtPoint(pt);
3831 return found;
3723b7b1
JS
3832}
3833
3834// Get the current mouse position.
3835wxPoint wxGetMousePosition()
3836{
59a12e90
JS
3837 /* This crashes when used within wxHelpContext,
3838 so we have to use the X-specific implementation below.
3839 gint x, y;
3840 GdkModifierType *mask;
3841 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
3842
3843 return wxPoint(x, y);
3844 */
3845
3723b7b1
JS
3846 int x, y;
3847 GdkWindow* windowAtPtr = gdk_window_at_pointer(& x, & y);
57591e0e
JS
3848 if (!windowAtPtr)
3849 return wxPoint(-999, -999);
59a12e90
JS
3850
3851 Display *display = GDK_WINDOW_XDISPLAY(windowAtPtr);
3852 Window rootWindow = RootWindowOfScreen (DefaultScreenOfDisplay(display));
3853 Window rootReturn, childReturn;
3854 int rootX, rootY, winX, winY;
3855 unsigned int maskReturn;
3856
3857 XQueryPointer (display,
3858 rootWindow,
3859 &rootReturn,
3860 &childReturn,
3861 &rootX, &rootY, &winX, &winY, &maskReturn);
3862 return wxPoint(rootX, rootY);
3863
3723b7b1
JS
3864}
3865