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