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