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