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