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