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