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