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