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