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