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