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