]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/window.cpp
wxListCtrl sends event directly again. Also fixed problem
[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
1657#ifdef USE_XIM
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 }
1717
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 }
1731 }
1732#endif
1733
1734 return FALSE;
1735}
1736
6ca41e57
RR
1737//-----------------------------------------------------------------------------
1738// InsertChild for wxWindow.
1739//-----------------------------------------------------------------------------
1740
b1170810
RR
1741/* Callback for wxWindow. This very strange beast has to be used because
1742 * C++ has no virtual methods in a constructor. We have to emulate a
1743 * virtual function here as wxNotebook requires a different way to insert
1744 * a child in it. I had opted for creating a wxNotebookPage window class
1745 * which would have made this superfluous (such in the MDI window system),
1746 * but no-one was listening to me... */
6ca41e57
RR
1747
1748static void wxInsertChildInWindow( wxWindow* parent, wxWindow* child )
1749{
bf0c00c6
RR
1750 /* the window might have been scrolled already, do we
1751 have to adapt the position */
da048e3d
RR
1752 GtkPizza *pizza = GTK_PIZZA(parent->m_wxwindow);
1753 child->m_x += pizza->xoffset;
1754 child->m_y += pizza->yoffset;
148cd9b6 1755
da048e3d 1756 gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
a2053b27
RR
1757 GTK_WIDGET(child->m_widget),
1758 child->m_x,
1759 child->m_y,
1760 child->m_width,
1761 child->m_height );
6ca41e57
RR
1762}
1763
bbe0af5b
RR
1764//-----------------------------------------------------------------------------
1765// global functions
1766//-----------------------------------------------------------------------------
1767
1768wxWindow* wxGetActiveWindow()
1769{
f03fc89f 1770 return g_focusWindow;
bbe0af5b
RR
1771}
1772
c801d85f 1773//-----------------------------------------------------------------------------
2f2aa628 1774// wxWindow
c801d85f
KB
1775//-----------------------------------------------------------------------------
1776
f03fc89f 1777IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
c801d85f 1778
68995f26 1779void wxWindow::Init()
c801d85f 1780{
f03fc89f
VZ
1781 // common init
1782 InitBase();
68995f26 1783
f03fc89f 1784 // GTK specific
a2053b27 1785 m_widget = (GtkWidget *) NULL;
e380f72b 1786 m_wxwindow = (GtkWidget *) NULL;
8bbe427f 1787
f03fc89f 1788 // position/size
a2053b27
RR
1789 m_x = 0;
1790 m_y = 0;
1791 m_width = 0;
e380f72b 1792 m_height = 0;
8bbe427f 1793
e380f72b
RR
1794 m_sizeSet = FALSE;
1795 m_hasVMT = FALSE;
1796 m_needParent = TRUE;
31c6b4fc 1797 m_isBeingDeleted = FALSE;
148cd9b6 1798
147bc491 1799 m_noExpose = FALSE;
30760ce7 1800 m_nativeSizeEvent = FALSE;
148cd9b6 1801
a2053b27 1802 m_hasScrolling = FALSE;
e380f72b 1803 m_isScrolling = FALSE;
f03fc89f 1804
a2053b27 1805 m_hAdjust = (GtkAdjustment*) NULL;
e380f72b 1806 m_vAdjust = (GtkAdjustment*) NULL;
a2053b27 1807 m_oldHorizontalPos = 0.0;
e380f72b 1808 m_oldVerticalPos = 0.0;
8bbe427f 1809
e380f72b 1810 m_resizing = FALSE;
e380f72b 1811 m_widgetStyle = (GtkStyle*) NULL;
8bbe427f 1812
ddb6bc71 1813 m_insertCallback = (wxInsertChildFunction) NULL;
8bbe427f 1814
1ecc4d80 1815 m_isStaticBox = FALSE;
953704c1 1816 m_isRadioButton = FALSE;
54517652 1817 m_isFrame = FALSE;
b292e2f5 1818 m_acceptsFocus = FALSE;
148cd9b6 1819
5e014a0c 1820 m_cursor = *wxSTANDARD_CURSOR;
63081513
RR
1821
1822#ifdef HAVE_XIM
1823 m_ic = (GdkIC*) NULL;
1824 m_icattr = (GdkICAttr*) NULL;
1825#endif
362c6693 1826}
c801d85f 1827
68995f26
VZ
1828wxWindow::wxWindow()
1829{
1830 Init();
1831}
1832
6ca41e57 1833wxWindow::wxWindow( wxWindow *parent, wxWindowID id,
e380f72b
RR
1834 const wxPoint &pos, const wxSize &size,
1835 long style, const wxString &name )
6ca41e57 1836{
68995f26
VZ
1837 Init();
1838
e380f72b 1839 Create( parent, id, pos, size, style, name );
6ca41e57 1840}
8bbe427f 1841
debe6624 1842bool wxWindow::Create( wxWindow *parent, wxWindowID id,
e380f72b
RR
1843 const wxPoint &pos, const wxSize &size,
1844 long style, const wxString &name )
c801d85f 1845{
4dcaf11a
RR
1846 if (!PreCreation( parent, pos, size ) ||
1847 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
1848 {
223d09f6 1849 wxFAIL_MSG( wxT("wxWindow creation failed") );
b02da6b1 1850 return FALSE;
4dcaf11a 1851 }
47d67540 1852
ddb6bc71
RR
1853 m_insertCallback = wxInsertChildInWindow;
1854
e380f72b 1855 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
38c7b3d3 1856 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
ff8bfdbb 1857
2e563988 1858#ifdef __WXDEBUG__
223d09f6 1859 debug_focus_in( m_widget, wxT("wxWindow::m_widget"), name );
2e563988
RR
1860#endif
1861
f03fc89f 1862 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget);
47d67540 1863
2e563988 1864#ifdef __WXDEBUG__
223d09f6
KB
1865 debug_focus_in( scrolledWindow->hscrollbar, wxT("wxWindow::hsrcollbar"), name );
1866 debug_focus_in( scrolledWindow->vscrollbar, wxT("wxWindow::vsrcollbar"), name );
2e563988
RR
1867#endif
1868
e380f72b
RR
1869 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1870 scroll_class->scrollbar_spacing = 0;
47d67540 1871
f03fc89f 1872 gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
47d67540 1873
f03fc89f
VZ
1874 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->hscrollbar) );
1875 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->vscrollbar) );
47d67540 1876
da048e3d 1877 m_wxwindow = gtk_pizza_new();
38c7b3d3 1878
2e563988 1879#ifdef __WXDEBUG__
223d09f6 1880 debug_focus_in( m_wxwindow, wxT("wxWindow::m_wxwindow"), name );
2e563988
RR
1881#endif
1882
034be888 1883 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
58dea4b0 1884
034be888 1885#if (GTK_MINOR_VERSION > 0)
da048e3d 1886 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
b292e2f5 1887
f03fc89f 1888 if (HasFlag(wxRAISED_BORDER))
034be888 1889 {
da048e3d 1890 gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_OUT );
034be888 1891 }
f03fc89f 1892 else if (HasFlag(wxSUNKEN_BORDER))
034be888 1893 {
da048e3d 1894 gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_IN );
5e014a0c
RR
1895 }
1896 else if (HasFlag(wxSIMPLE_BORDER))
1897 {
da048e3d 1898 gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_THIN );
034be888
RR
1899 }
1900 else
1901 {
da048e3d 1902 gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_NONE );
034be888 1903 }
f03fc89f
VZ
1904#else // GTK_MINOR_VERSION == 0
1905 GtkViewport *viewport = GTK_VIEWPORT(scrolledWindow->viewport);
b292e2f5 1906
f03fc89f 1907 if (HasFlag(wxRAISED_BORDER))
e380f72b
RR
1908 {
1909 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
1910 }
f03fc89f 1911 else if (HasFlag(wxSUNKEN_BORDER))
e380f72b
RR
1912 {
1913 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
1914 }
1915 else
1916 {
1917 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
1918 }
f03fc89f 1919#endif // GTK_MINOR_VERSION
47d67540 1920
3da17724
RR
1921 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
1922 m_acceptsFocus = TRUE;
ca298c88 1923
034be888 1924#if (GTK_MINOR_VERSION == 0)
e380f72b
RR
1925 // shut the viewport up
1926 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1927 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
f03fc89f 1928#endif // GTK_MINOR_VERSION == 0
e380f72b
RR
1929
1930 // I _really_ don't want scrollbars in the beginning
a2053b27
RR
1931 m_vAdjust->lower = 0.0;
1932 m_vAdjust->upper = 1.0;
1933 m_vAdjust->value = 0.0;
1934 m_vAdjust->step_increment = 1.0;
1935 m_vAdjust->page_increment = 1.0;
1936 m_vAdjust->page_size = 5.0;
1937 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
1938 m_hAdjust->lower = 0.0;
1939 m_hAdjust->upper = 1.0;
1940 m_hAdjust->value = 0.0;
1941 m_hAdjust->step_increment = 1.0;
1942 m_hAdjust->page_increment = 1.0;
1943 m_hAdjust->page_size = 5.0;
1944 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
f03fc89f
VZ
1945
1946 // these handlers block mouse events to any window during scrolling such as
1947 // motion events and prevent GTK and wxWindows from fighting over where the
1948 // slider should be
1949
1950 gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_press_event",
76ed8f8d
RR
1951 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1952
f03fc89f 1953 gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_press_event",
76ed8f8d
RR
1954 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1955
f03fc89f 1956 gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_release_event",
76ed8f8d
RR
1957 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
1958
f03fc89f 1959 gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_release_event",
76ed8f8d 1960 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
8bbe427f 1961
034be888 1962 // these handlers get notified when screen updates are required either when
76ed8f8d
RR
1963 // scrolling or when the window size (and therefore scrollbar configuration)
1964 // has changed
1965
1966 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
1967 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
1968 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
1969 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
1970
1971 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "changed",
1972 (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
1973 gtk_signal_connect(GTK_OBJECT(m_vAdjust), "changed",
1974 (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
1975
f03fc89f 1976 gtk_widget_show( m_wxwindow );
47d67540 1977
f03fc89f
VZ
1978 if (m_parent)
1979 m_parent->DoAddChild( this );
8bbe427f 1980
e380f72b 1981 PostCreation();
8bbe427f 1982
e380f72b 1983 Show( TRUE );
c801d85f 1984
e380f72b 1985 return TRUE;
362c6693 1986}
c801d85f 1987
68dda785 1988wxWindow::~wxWindow()
c801d85f 1989{
31c6b4fc 1990 m_isBeingDeleted = TRUE;
43a18898 1991 m_hasVMT = FALSE;
47d67540 1992
f03fc89f
VZ
1993 if (m_widget)
1994 Show( FALSE );
8bbe427f 1995
a2053b27
RR
1996 DestroyChildren();
1997
f03fc89f
VZ
1998 if (m_parent)
1999 m_parent->RemoveChild( this );
c801d85f 2000
63081513
RR
2001#ifdef HAVE_XIM
2002 if (m_ic)
2003 gdk_ic_destroy (m_ic);
2004 if (m_icattr)
2005 gdk_ic_attr_destroy (m_icattr);
2006#endif
2007
f03fc89f 2008 if (m_widgetStyle)
a2053b27 2009 {
f03fc89f 2010 gtk_style_unref( m_widgetStyle );
c50f1fb9 2011 m_widgetStyle = (GtkStyle*) NULL;
a2053b27 2012 }
c801d85f 2013
f03fc89f 2014 if (m_wxwindow)
a2053b27 2015 {
f03fc89f 2016 gtk_widget_destroy( m_wxwindow );
c50f1fb9 2017 m_wxwindow = (GtkWidget*) NULL;
a2053b27 2018 }
8bbe427f 2019
f03fc89f 2020 if (m_widget)
a2053b27 2021 {
f03fc89f 2022 gtk_widget_destroy( m_widget );
c50f1fb9 2023 m_widget = (GtkWidget*) NULL;
a2053b27 2024 }
362c6693 2025}
c801d85f 2026
4dcaf11a 2027bool wxWindow::PreCreation( wxWindow *parent, const wxPoint &pos, const wxSize &size )
c801d85f 2028{
223d09f6 2029 wxCHECK_MSG( !m_needParent || parent, FALSE, wxT("Need complete parent.") );
8bbe427f 2030
4dcaf11a
RR
2031 /* this turns -1 into 20 so that a minimal window is
2032 visible even although -1,-1 has been given as the
2033 size of the window. the same trick is used in other
2034 ports and should make debugging easier */
f03fc89f
VZ
2035 m_width = WidthDefault(size.x);
2036 m_height = HeightDefault(size.y);
8bbe427f 2037
43a18898
RR
2038 m_x = (int)pos.x;
2039 m_y = (int)pos.y;
8bbe427f 2040
4dcaf11a 2041 /* some reasonable defaults */
148cd9b6 2042 if (!parent)
6ca41e57 2043 {
43a18898
RR
2044 if (m_x == -1)
2045 {
2046 m_x = (gdk_screen_width () - m_width) / 2;
2047 if (m_x < 10) m_x = 10;
2048 }
2049 if (m_y == -1)
2050 {
2051 m_y = (gdk_screen_height () - m_height) / 2;
2052 if (m_y < 10) m_y = 10;
2053 }
6ca41e57 2054 }
148cd9b6 2055
4dcaf11a 2056 return TRUE;
c801d85f
KB
2057}
2058
68dda785 2059void wxWindow::PostCreation()
c801d85f 2060{
223d09f6 2061 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
ca298c88 2062
43a18898
RR
2063 if (m_wxwindow)
2064 {
147bc491 2065 if (!m_noExpose)
b02da6b1 2066 {
147bc491
RR
2067 /* these get reported to wxWindows -> wxPaintEvent */
2068 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
2069 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
2070
2071 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
2072 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
b02da6b1 2073 }
148cd9b6 2074
ef47f9b3 2075#if (GTK_MINOR_VERSION > 0)
ed673c6a 2076 /* these are called when the "sunken" or "raised" borders are drawn */
034be888
RR
2077 gtk_signal_connect( GTK_OBJECT(m_widget), "expose_event",
2078 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback), (gpointer)this );
2079
2080 gtk_signal_connect( GTK_OBJECT(m_widget), "draw",
2081 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback), (gpointer)this );
ef47f9b3 2082#endif
43a18898 2083 }
47d67540 2084
63081513
RR
2085 if (m_wxwindow && m_needParent)
2086 {
2087 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "focus_in_event",
2088 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
2089
2090 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "focus_out_event",
2091 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
2092 }
2093 else
2094 {
2095 // For dialogs and frames, we are interested mainly in
2096 // m_widget's focus.
2097
2098 gtk_signal_connect( GTK_OBJECT(m_widget), "focus_in_event",
2099 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
2100
2101 gtk_signal_connect( GTK_OBJECT(m_widget), "focus_out_event",
2102 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
2103 }
2104
a2053b27 2105 GtkWidget *connect_widget = GetConnectWidget();
f03fc89f 2106
a2053b27 2107 ConnectWidget( connect_widget );
47d67540 2108
63081513 2109 /* We cannot set colours, fonts and cursors before the widget has
a2053b27
RR
2110 been realized, so we do this directly after realization */
2111 gtk_signal_connect( GTK_OBJECT(connect_widget), "realize",
c50f1fb9 2112 GTK_SIGNAL_FUNC(gtk_window_realized_callback), (gpointer) this );
63081513
RR
2113
2114 /* Initialize XIM support. */
2115 if (m_wxwindow)
2116 {
2117 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "realize",
2118 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback), (gpointer) this );
2119 }
2120
43a18898 2121 m_hasVMT = TRUE;
b4071e91
RR
2122}
2123
2124void wxWindow::ConnectWidget( GtkWidget *widget )
2125{
43a18898
RR
2126 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
2127 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
c801d85f 2128
b666df2c
RR
2129 gtk_signal_connect( GTK_OBJECT(widget), "key_release_event",
2130 GTK_SIGNAL_FUNC(gtk_window_key_release_callback), (gpointer)this );
2131
43a18898
RR
2132 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
2133 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
47d67540 2134
43a18898
RR
2135 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
2136 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
47d67540 2137
43a18898
RR
2138 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
2139 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
47d67540 2140
43a18898
RR
2141 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
2142 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
47d67540 2143
43a18898
RR
2144 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
2145 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
362c6693 2146}
c801d85f 2147
68dda785 2148bool wxWindow::Destroy()
c801d85f 2149{
223d09f6 2150 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
47d67540 2151
43a18898 2152 m_hasVMT = FALSE;
c801d85f 2153
f03fc89f 2154 return wxWindowBase::Destroy();
362c6693 2155}
c801d85f 2156
bfc6fde4 2157void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
c801d85f 2158{
223d09f6
KB
2159 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
2160 wxASSERT_MSG( (m_parent != NULL), wxT("wxWindow::SetSize requires parent.\n") );
8bbe427f 2161
e27ce4e9 2162 if (m_resizing) return; /* I don't like recursions */
fb1585ae 2163 m_resizing = TRUE;
47d67540 2164
a2053b27 2165 if (m_parent->m_wxwindow == NULL) /* i.e. wxNotebook */
fb1585ae 2166 {
e27ce4e9 2167 /* don't set the size for children of wxNotebook, just take the values. */
fb1585ae
RR
2168 m_x = x;
2169 m_y = y;
2170 m_width = width;
ba4e3652 2171 m_height = height;
fb1585ae 2172 }
ba4e3652 2173 else
fb1585ae 2174 {
da048e3d 2175 GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
148cd9b6 2176
85ad5eb5 2177 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
ba4e3652 2178 {
da048e3d
RR
2179 if (x != -1) m_x = x + pizza->xoffset;
2180 if (y != -1) m_y = y + pizza->yoffset;
ba4e3652
RR
2181 if (width != -1) m_width = width;
2182 if (height != -1) m_height = height;
2183 }
2184 else
2185 {
da048e3d
RR
2186 m_x = x + pizza->xoffset;
2187 m_y = y + pizza->yoffset;
ba4e3652
RR
2188 m_width = width;
2189 m_height = height;
2190 }
47d67540 2191
ba4e3652
RR
2192 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
2193 {
2194 if (width == -1) m_width = 80;
2195 }
2196
2197 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
2198 {
2199 if (height == -1) m_height = 26;
2200 }
8bbe427f 2201
ba4e3652
RR
2202 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
2203 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
d3b4d113
RR
2204 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
2205 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
47d67540 2206
a2053b27 2207 int border = 0;
c50f1fb9 2208 int bottom_border = 0;
f03fc89f 2209
29f538ce 2210 if (GTK_WIDGET_CAN_DEFAULT(m_widget))
c50f1fb9
VZ
2211 {
2212 /* the default button has a border around it */
2213 border = 6;
2214 bottom_border = 5;
2215 }
2216
da048e3d 2217 gtk_pizza_set_size( GTK_PIZZA(m_parent->m_wxwindow),
c50f1fb9
VZ
2218 m_widget,
2219 m_x-border,
2220 m_y-border,
2221 m_width+2*border,
2222 m_height+border+bottom_border );
54517652 2223 }
148cd9b6 2224
54517652 2225/*
6d693bb4
RR
2226 wxPrintf( "OnSize sent from " );
2227 if (GetClassInfo() && GetClassInfo()->GetClassName())
2228 wxPrintf( GetClassInfo()->GetClassName() );
2229 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2230*/
2231
30760ce7
RR
2232 if (!m_nativeSizeEvent)
2233 {
2234 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
2235 event.SetEventObject( this );
2236 GetEventHandler()->ProcessEvent( event );
2237 }
6d693bb4 2238
fb1585ae 2239 m_resizing = FALSE;
362c6693 2240}
c801d85f 2241
9390a202
RR
2242void wxWindow::OnInternalIdle()
2243{
148cd9b6
VZ
2244 if ( g_sendActivateEvent != -1 )
2245 {
2246 bool activate = g_sendActivateEvent != 0;
2247
2248 // do it only once
2249 g_sendActivateEvent = -1;
2250
2251 wxActivateEvent event(wxEVT_ACTIVATE, activate, GetId());
2252 event.SetEventObject(this);
2253
2254 (void)GetEventHandler()->ProcessEvent(event);
2255 }
2256
9146082c
RR
2257 wxCursor cursor = m_cursor;
2258 if (g_globalCursor.Ok()) cursor = g_globalCursor;
c50f1fb9 2259
f7a11f8c 2260 if (cursor.Ok())
9146082c 2261 {
3017f78d 2262 /* I now set the cursor anew in every OnInternalIdle call
b02da6b1
VZ
2263 as setting the cursor in a parent window also effects the
2264 windows above so that checking for the current cursor is
2265 not possible. */
148cd9b6 2266
9146082c 2267 if (m_wxwindow)
6a008b33 2268 {
da048e3d 2269 GdkWindow *window = GTK_PIZZA(m_wxwindow)->bin_window;
6a008b33 2270 if (window)
c50f1fb9 2271 gdk_window_set_cursor( window, cursor.GetCursor() );
6a008b33
VZ
2272
2273 if (!g_globalCursor.Ok())
2274 cursor = *wxSTANDARD_CURSOR;
2275
2276 window = m_widget->window;
5e014a0c 2277 if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget)))
9146082c 2278 gdk_window_set_cursor( window, cursor.GetCursor() );
5e014a0c 2279
6a008b33
VZ
2280 }
2281 else
2282 {
5e014a0c 2283
9146082c 2284 GdkWindow *window = m_widget->window;
5e014a0c 2285 if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget)))
9146082c 2286 gdk_window_set_cursor( window, cursor.GetCursor() );
5e014a0c 2287
6a008b33 2288 }
9146082c 2289 }
6a008b33 2290
9390a202
RR
2291 UpdateWindowUI();
2292}
2293
f03fc89f 2294void wxWindow::DoGetSize( int *width, int *height ) const
c801d85f 2295{
223d09f6 2296 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2297
fb1585ae
RR
2298 if (width) (*width) = m_width;
2299 if (height) (*height) = m_height;
362c6693 2300}
c801d85f 2301
bfc6fde4 2302void wxWindow::DoSetClientSize( int width, int height )
c801d85f 2303{
223d09f6 2304 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2305
1ecc4d80 2306 if (!m_wxwindow)
c801d85f 2307 {
1ecc4d80 2308 SetSize( width, height );
c801d85f
KB
2309 }
2310 else
2311 {
1ecc4d80
RR
2312 int dw = 0;
2313 int dh = 0;
2314
034be888 2315#if (GTK_MINOR_VERSION == 0)
98d3fdbe
RR
2316 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2317 {
324dbfec
RR
2318 if (HasScrolling())
2319 {
2320 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
014b0d06 2321#if 0 // unused - if this is ok, just remove this line (VZ)
324dbfec 2322 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
014b0d06 2323#endif // 0
324dbfec
RR
2324
2325 GtkWidget *viewport = scroll_window->viewport;
2326 GtkStyleClass *viewport_class = viewport->style->klass;
2327
2328 dw += 2 * viewport_class->xthickness;
2329 dh += 2 * viewport_class->ythickness;
2330 }
98d3fdbe
RR
2331 }
2332#else
2333 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2334 {
5e014a0c 2335 /* when using GTK 1.2 we set the shadow border size to 2 */
6a008b33 2336 dw += 2 * 2;
98d3fdbe
RR
2337 dh += 2 * 2;
2338 }
5e014a0c
RR
2339 if (HasFlag(wxSIMPLE_BORDER))
2340 {
2341 /* when using GTK 1.2 we set the simple border size to 1 */
2342 dw += 1 * 2;
2343 dh += 1 * 2;
2344 }
034be888
RR
2345#endif
2346
98d3fdbe
RR
2347 if (HasScrolling())
2348 {
034be888
RR
2349/*
2350 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2351 GtkWidget *vscrollbar = scroll_window->vscrollbar;
ca298c88 2352
f03fc89f 2353 we use this instead: range.slider_width = 11 + 2*2pts edge
034be888 2354*/
47d67540 2355
324dbfec
RR
2356 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2357 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
2358
1ecc4d80
RR
2359 if (scroll_window->vscrollbar_visible)
2360 {
034be888 2361 dw += 15; /* dw += vscrollbar->allocation.width; */
1ecc4d80
RR
2362 dw += scroll_class->scrollbar_spacing;
2363 }
2364
2365 if (scroll_window->hscrollbar_visible)
2366 {
034be888 2367 dh += 15; /* dh += hscrollbar->allocation.height; */
63cc5d9d 2368 dh += scroll_class->scrollbar_spacing;
1ecc4d80
RR
2369 }
2370 }
2371
034be888 2372 SetSize( width+dw, height+dh );
1ecc4d80 2373 }
362c6693 2374}
c801d85f 2375
f03fc89f 2376void wxWindow::DoGetClientSize( int *width, int *height ) const
c801d85f 2377{
223d09f6 2378 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2379
1ecc4d80
RR
2380 if (!m_wxwindow)
2381 {
2382 if (width) (*width) = m_width;
2383 if (height) (*height) = m_height;
c801d85f
KB
2384 }
2385 else
2386 {
1ecc4d80
RR
2387 int dw = 0;
2388 int dh = 0;
2389
034be888 2390#if (GTK_MINOR_VERSION == 0)
98d3fdbe
RR
2391 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2392 {
6a008b33
VZ
2393 if (HasScrolling())
2394 {
2395 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
ec6e0a19 2396#if 0 // unused - if this is ok, just remove this line (VZ)
6a008b33 2397 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
ec6e0a19 2398#endif // 0
6a008b33
VZ
2399
2400 GtkWidget *viewport = scroll_window->viewport;
2401 GtkStyleClass *viewport_class = viewport->style->klass;
2402
2403 dw += 2 * viewport_class->xthickness;
2404 dh += 2 * viewport_class->ythickness;
2405 }
98d3fdbe
RR
2406 }
2407#else
2408 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
2409 {
5e014a0c 2410 /* when using GTK 1.2 we set the shadow border size to 2 */
6a008b33 2411 dw += 2 * 2;
98d3fdbe
RR
2412 dh += 2 * 2;
2413 }
5e014a0c
RR
2414 if (HasFlag(wxSIMPLE_BORDER))
2415 {
2416 /* when using GTK 1.2 we set the simple border size to 1 */
2417 dw += 1 * 2;
2418 dh += 1 * 2;
2419 }
034be888 2420#endif
98d3fdbe
RR
2421 if (HasScrolling())
2422 {
034be888
RR
2423/*
2424 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2425 GtkWidget *vscrollbar = scroll_window->vscrollbar;
ca298c88 2426
f03fc89f 2427 we use this instead: range.slider_width = 11 + 2*2pts edge
034be888 2428*/
1ecc4d80 2429
6a008b33
VZ
2430 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
2431 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
2432
1ecc4d80
RR
2433 if (scroll_window->vscrollbar_visible)
2434 {
034be888 2435 dw += 15; /* dw += vscrollbar->allocation.width; */
1ecc4d80
RR
2436 dw += scroll_class->scrollbar_spacing;
2437 }
2438
2439 if (scroll_window->hscrollbar_visible)
2440 {
034be888 2441 dh += 15; /* dh += hscrollbar->allocation.height; */
1ecc4d80
RR
2442 dh += scroll_class->scrollbar_spacing;
2443 }
6a008b33 2444 }
47d67540 2445
1ecc4d80
RR
2446 if (width) (*width) = m_width - dw;
2447 if (height) (*height) = m_height - dh;
2448 }
362c6693 2449}
c801d85f 2450
f03fc89f 2451void wxWindow::DoGetPosition( int *x, int *y ) const
c801d85f 2452{
223d09f6 2453 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2454
bf0c00c6
RR
2455 int dx = 0;
2456 int dy = 0;
2457 if (m_parent && m_parent->m_wxwindow)
2458 {
da048e3d 2459 GtkPizza *pizza = GTK_PIZZA(m_parent->m_wxwindow);
b02da6b1
VZ
2460 dx = pizza->xoffset;
2461 dy = pizza->yoffset;
bf0c00c6
RR
2462 }
2463
2464 if (x) (*x) = m_x - dx;
2465 if (y) (*y) = m_y - dy;
362c6693 2466}
c801d85f 2467
dabc0cd5 2468void wxWindow::DoClientToScreen( int *x, int *y ) const
c801d85f 2469{
223d09f6 2470 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2471
a2053b27
RR
2472 if (!m_widget->window) return;
2473
43a18898
RR
2474 GdkWindow *source = (GdkWindow *) NULL;
2475 if (m_wxwindow)
da048e3d 2476 source = GTK_PIZZA(m_wxwindow)->bin_window;
43a18898
RR
2477 else
2478 source = m_widget->window;
47d67540 2479
43a18898
RR
2480 int org_x = 0;
2481 int org_y = 0;
2482 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2483
43a18898 2484 if (!m_wxwindow)
c801d85f 2485 {
43a18898
RR
2486 if (GTK_WIDGET_NO_WINDOW (m_widget))
2487 {
2488 org_x += m_widget->allocation.x;
2489 org_y += m_widget->allocation.y;
2490 }
362c6693 2491 }
47d67540 2492
43a18898
RR
2493 if (x) *x += org_x;
2494 if (y) *y += org_y;
362c6693 2495}
c801d85f 2496
dabc0cd5 2497void wxWindow::DoScreenToClient( int *x, int *y ) const
c801d85f 2498{
223d09f6 2499 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2500
a2053b27
RR
2501 if (!m_widget->window) return;
2502
1ecc4d80
RR
2503 GdkWindow *source = (GdkWindow *) NULL;
2504 if (m_wxwindow)
da048e3d 2505 source = GTK_PIZZA(m_wxwindow)->bin_window;
1ecc4d80
RR
2506 else
2507 source = m_widget->window;
47d67540 2508
1ecc4d80
RR
2509 int org_x = 0;
2510 int org_y = 0;
2511 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2512
1ecc4d80 2513 if (!m_wxwindow)
c801d85f 2514 {
1ecc4d80
RR
2515 if (GTK_WIDGET_NO_WINDOW (m_widget))
2516 {
2517 org_x += m_widget->allocation.x;
2518 org_y += m_widget->allocation.y;
2519 }
362c6693 2520 }
47d67540 2521
1ecc4d80
RR
2522 if (x) *x -= org_x;
2523 if (y) *y -= org_y;
362c6693 2524}
c801d85f 2525
f03fc89f 2526bool wxWindow::Show( bool show )
c801d85f 2527{
223d09f6 2528 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
47d67540 2529
739730ca
RR
2530 if (!wxWindowBase::Show(show))
2531 {
2532 // nothing to do
f03fc89f 2533 return FALSE;
739730ca 2534 }
8bbe427f 2535
f03fc89f
VZ
2536 if (show)
2537 gtk_widget_show( m_widget );
1ecc4d80 2538 else
f03fc89f 2539 gtk_widget_hide( m_widget );
8bbe427f 2540
f03fc89f 2541 return TRUE;
362c6693 2542}
c801d85f 2543
f03fc89f 2544bool wxWindow::Enable( bool enable )
c801d85f 2545{
223d09f6 2546 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
5e0aa05a 2547
739730ca
RR
2548 if (!wxWindowBase::Enable(enable))
2549 {
2550 // nothing to do
f03fc89f 2551 return FALSE;
739730ca 2552 }
1ecc4d80 2553
f03fc89f
VZ
2554 gtk_widget_set_sensitive( m_widget, enable );
2555 if ( m_wxwindow )
2556 gtk_widget_set_sensitive( m_wxwindow, enable );
ff8bfdbb 2557
f03fc89f 2558 return TRUE;
362c6693 2559}
c801d85f 2560
f03fc89f 2561int wxWindow::GetCharHeight() const
2f2aa628 2562{
223d09f6 2563 wxCHECK_MSG( (m_widget != NULL), 12, wxT("invalid window") );
47d67540 2564
223d09f6 2565 wxCHECK_MSG( m_font.Ok(), 12, wxT("invalid font") );
2f2aa628 2566
f03fc89f
VZ
2567 GdkFont *font = m_font.GetInternalFont( 1.0 );
2568
2569 return font->ascent + font->descent;
362c6693 2570}
c801d85f 2571
f03fc89f 2572int wxWindow::GetCharWidth() const
c33c4050 2573{
223d09f6 2574 wxCHECK_MSG( (m_widget != NULL), 8, wxT("invalid window") );
47d67540 2575
223d09f6 2576 wxCHECK_MSG( m_font.Ok(), 8, wxT("invalid font") );
47d67540 2577
463c1fa1 2578 GdkFont *font = m_font.GetInternalFont( 1.0 );
ff8bfdbb 2579
463c1fa1 2580 return gdk_string_width( font, "H" );
c33c4050
RR
2581}
2582
f03fc89f
VZ
2583void wxWindow::GetTextExtent( const wxString& string,
2584 int *x,
2585 int *y,
2586 int *descent,
2587 int *externalLeading,
2588 const wxFont *theFont ) const
c33c4050 2589{
463c1fa1
RR
2590 wxFont fontToUse = m_font;
2591 if (theFont) fontToUse = *theFont;
47d67540 2592
223d09f6 2593 wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") );
47d67540 2594
463c1fa1 2595 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
05939a81 2596 if (x) (*x) = gdk_string_width( font, string.mbc_str() );
463c1fa1
RR
2597 if (y) (*y) = font->ascent + font->descent;
2598 if (descent) (*descent) = font->descent;
2599 if (externalLeading) (*externalLeading) = 0; // ??
c33c4050
RR
2600}
2601
68dda785 2602void wxWindow::SetFocus()
c801d85f 2603{
223d09f6 2604 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
c0d6c58b 2605
354aa1e3
RR
2606 if (m_wxwindow)
2607 {
173348db
RR
2608 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow))
2609 gtk_widget_grab_focus (m_wxwindow);
354aa1e3
RR
2610 return;
2611 }
2612
2613 if (m_widget)
c801d85f 2614 {
173348db 2615 if (GTK_WIDGET_CAN_FOCUS(m_widget) && !GTK_WIDGET_HAS_FOCUS (m_widget) )
463c1fa1 2616 {
354aa1e3 2617 gtk_widget_grab_focus (m_widget);
463c1fa1 2618 }
354aa1e3 2619 else if (GTK_IS_CONTAINER(m_widget))
ff8bfdbb 2620 {
354aa1e3 2621 gtk_container_focus( GTK_CONTAINER(m_widget), GTK_DIR_TAB_FORWARD );
ff8bfdbb
VZ
2622 }
2623 else
2624 {
b02da6b1 2625 // ?
ff8bfdbb 2626 }
362c6693 2627 }
362c6693 2628}
c801d85f 2629
b292e2f5
RR
2630bool wxWindow::AcceptsFocus() const
2631{
f03fc89f 2632 return m_acceptsFocus && wxWindowBase::AcceptsFocus();
b292e2f5
RR
2633}
2634
fdb7dadb 2635bool wxWindow::Reparent( wxWindowBase *newParentBase )
463c1fa1 2636{
223d09f6 2637 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
c50f1fb9 2638
fdb7dadb
VZ
2639 wxWindow *oldParent = m_parent,
2640 *newParent = (wxWindow *)newParentBase;
a2053b27 2641
5fd11f09
RR
2642 wxASSERT( GTK_IS_WIDGET(m_widget) );
2643
f03fc89f
VZ
2644 if ( !wxWindowBase::Reparent(newParent) )
2645 return FALSE;
8bbe427f 2646
5fd11f09
RR
2647 wxASSERT( GTK_IS_WIDGET(m_widget) );
2648
2649 /* prevent GTK from deleting the widget arbitrarily */
2650 gtk_widget_ref( m_widget );
2651
8ce63e9d
RR
2652 if (oldParent)
2653 {
3017f78d 2654 gtk_container_remove( GTK_CONTAINER(m_widget->parent), m_widget );
8ce63e9d 2655 }
c50f1fb9 2656
5fd11f09
RR
2657 wxASSERT( GTK_IS_WIDGET(m_widget) );
2658
8ce63e9d
RR
2659 if (newParent)
2660 {
2661 /* insert GTK representation */
2662 (*(newParent->m_insertCallback))(newParent, this);
2663 }
c50f1fb9 2664
5fd11f09
RR
2665 /* reverse: prevent GTK from deleting the widget arbitrarily */
2666 gtk_widget_unref( m_widget );
148cd9b6 2667
f03fc89f 2668 return TRUE;
362c6693 2669}
c801d85f 2670
c50f1fb9 2671void wxWindow::DoAddChild(wxWindow *child)
ddb6bc71 2672{
223d09f6 2673 wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
ddb6bc71 2674
223d09f6 2675 wxASSERT_MSG( (child != NULL), wxT("invalid child window") );
ddb6bc71 2676
223d09f6 2677 wxASSERT_MSG( (m_insertCallback != NULL), wxT("invalid child insertion function") );
c50f1fb9 2678
ddb6bc71
RR
2679 /* add to list */
2680 AddChild( child );
c50f1fb9 2681
ddb6bc71
RR
2682 /* insert GTK representation */
2683 (*m_insertCallback)(this, child);
2684}
2685
68dda785 2686void wxWindow::Raise()
362c6693 2687{
223d09f6 2688 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2689
a2053b27
RR
2690 if (!m_widget->window) return;
2691
f03fc89f 2692 gdk_window_raise( m_widget->window );
362c6693
RR
2693}
2694
68dda785 2695void wxWindow::Lower()
362c6693 2696{
223d09f6 2697 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2698
a2053b27
RR
2699 if (!m_widget->window) return;
2700
f03fc89f 2701 gdk_window_lower( m_widget->window );
362c6693 2702}
c801d85f 2703
f03fc89f 2704bool wxWindow::SetCursor( const wxCursor &cursor )
86b29a61 2705{
223d09f6 2706 wxCHECK_MSG( (m_widget != NULL), FALSE, wxT("invalid window") );
86b29a61 2707
5e014a0c 2708 return wxWindowBase::SetCursor( cursor );
362c6693 2709}
c801d85f 2710
85eb36c2 2711void wxWindow::WarpPointer( int x, int y )
4f22cf8d 2712{
223d09f6 2713 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
85eb36c2 2714
ed673c6a
RR
2715 /* we provide this function ourselves as it is
2716 missing in GDK (top of this file) */
148cd9b6 2717
ed673c6a
RR
2718 GdkWindow *window = (GdkWindow*) NULL;
2719 if (m_wxwindow)
da048e3d 2720 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
2721 else
2722 window = GetConnectWidget()->window;
148cd9b6 2723
ed673c6a
RR
2724 if (window)
2725 gdk_window_warp_pointer( window, x, y );
4f22cf8d
RR
2726}
2727
debe6624 2728void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
c801d85f 2729{
223d09f6 2730 wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
47d67540 2731
a2053b27
RR
2732 if (!m_widget->window) return;
2733
139adb6a 2734 if (eraseBackground && m_wxwindow && m_wxwindow->window)
c801d85f 2735 {
139adb6a
RR
2736 if (rect)
2737 {
da048e3d 2738 gdk_window_clear_area( GTK_PIZZA(m_wxwindow)->bin_window,
139adb6a 2739 rect->x, rect->y,
f234c60c 2740 rect->width, rect->height );
139adb6a
RR
2741 }
2742 else
2743 {
da048e3d 2744 gdk_window_clear( GTK_PIZZA(m_wxwindow)->bin_window );
139adb6a
RR
2745 }
2746 }
ff8bfdbb 2747
1b68e0b5 2748 /* there is no GTK equivalent of "draw only, don't clear" so we
da048e3d 2749 invent our own in the GtkPizza widget */
1b68e0b5 2750
139adb6a
RR
2751 if (!rect)
2752 {
2753 if (m_wxwindow)
b02da6b1
VZ
2754 {
2755 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
2756 gboolean old_clear = pizza->clear_on_draw;
2757 gtk_pizza_set_clear( pizza, FALSE );
148cd9b6 2758
1b68e0b5 2759 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
148cd9b6 2760
b02da6b1
VZ
2761 gtk_pizza_set_clear( pizza, old_clear );
2762 }
ff8bfdbb 2763 else
139adb6a 2764 gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
362c6693 2765 }
c801d85f 2766 else
139adb6a 2767 {
1b68e0b5
RR
2768 GdkRectangle gdk_rect;
2769 gdk_rect.x = rect->x;
2770 gdk_rect.y = rect->y;
2771 gdk_rect.width = rect->width;
2772 gdk_rect.height = rect->height;
139adb6a
RR
2773
2774 if (m_wxwindow)
b02da6b1
VZ
2775 {
2776 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
2777 gboolean old_clear = pizza->clear_on_draw;
2778 gtk_pizza_set_clear( pizza, FALSE );
148cd9b6 2779
1b68e0b5 2780 gtk_widget_draw( m_wxwindow, &gdk_rect );
148cd9b6 2781
b02da6b1
VZ
2782 gtk_pizza_set_clear( pizza, old_clear );
2783 }
139adb6a
RR
2784 else
2785 gtk_widget_draw( m_widget, &gdk_rect );
2786 }
362c6693 2787}
c801d85f 2788
68dda785 2789void wxWindow::Clear()
c801d85f 2790{
223d09f6 2791 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 2792
a2053b27
RR
2793 if (!m_widget->window) return;
2794
f234c60c
RR
2795 if (m_wxwindow && m_wxwindow->window)
2796 {
2797 gdk_window_clear( m_wxwindow->window );
2798 }
362c6693 2799}
c801d85f 2800
ff8bfdbb 2801#if wxUSE_TOOLTIPS
f03fc89f 2802void wxWindow::DoSetToolTip( wxToolTip *tip )
b1170810 2803{
f03fc89f 2804 wxWindowBase::DoSetToolTip(tip);
ff8bfdbb 2805
f03fc89f
VZ
2806 if (m_tooltip)
2807 m_tooltip->Apply( this );
b1170810
RR
2808}
2809
05939a81 2810void wxWindow::ApplyToolTip( GtkTooltips *tips, const wxChar *tip )
b1170810 2811{
dcf924a3 2812 gtk_tooltips_set_tip( tips, GetConnectWidget(), wxConvCurrent->cWX2MB(tip), (gchar*) NULL );
301cd871 2813}
ff8bfdbb 2814#endif // wxUSE_TOOLTIPS
b1170810 2815
f03fc89f 2816bool wxWindow::SetBackgroundColour( const wxColour &colour )
c801d85f 2817{
223d09f6 2818 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
8bbe427f 2819
739730ca
RR
2820 if (!wxWindowBase::SetBackgroundColour(colour))
2821 {
2822 // don't leave if the GTK widget has just
2823 // been realized
2824 if (!m_delayedBackgroundColour) return FALSE;
2825 }
c50f1fb9 2826
ed673c6a
RR
2827 GdkWindow *window = (GdkWindow*) NULL;
2828 if (m_wxwindow)
da048e3d 2829 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
2830 else
2831 window = GetConnectWidget()->window;
148cd9b6 2832
ed673c6a 2833 if (!window)
739730ca
RR
2834 {
2835 // indicate that a new style has been set
c50f1fb9
VZ
2836 // but it couldn't get applied as the
2837 // widget hasn't been realized yet.
2838 m_delayedBackgroundColour = TRUE;
2839
2840 // pretend we have done something
739730ca
RR
2841 return TRUE;
2842 }
ca298c88 2843
ed673c6a 2844 if (m_wxwindow)
3bc755fc 2845 {
a2053b27
RR
2846 /* wxMSW doesn't clear the window here. I don't do that either to
2847 provide compatibility. call Clear() to do the job. */
ca298c88 2848
ed673c6a
RR
2849 m_backgroundColour.CalcPixel( gdk_window_get_colormap( window ) );
2850 gdk_window_set_background( window, m_backgroundColour.GetColor() );
3bc755fc 2851 }
8bbe427f 2852
ae0bdb01 2853 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
121a3581 2854 if (sysbg == m_backgroundColour)
ae0bdb01
RR
2855 {
2856 m_backgroundColour = wxNullColour;
2857 ApplyWidgetStyle();
ff8bfdbb
VZ
2858 m_backgroundColour = sysbg;
2859 }
ae0bdb01
RR
2860 else
2861 {
2862 ApplyWidgetStyle();
2863 }
c801d85f 2864
f03fc89f 2865 return TRUE;
6de97a3b
RR
2866}
2867
f03fc89f 2868bool wxWindow::SetForegroundColour( const wxColour &colour )
6de97a3b 2869{
223d09f6 2870 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
8bbe427f 2871
739730ca
RR
2872 if (!wxWindowBase::SetForegroundColour(colour))
2873 {
2874 // don't leave if the GTK widget has just
2875 // been realized
2876 if (!m_delayedForegroundColour) return FALSE;
2877 }
c50f1fb9 2878
ed673c6a
RR
2879 GdkWindow *window = (GdkWindow*) NULL;
2880 if (m_wxwindow)
da048e3d 2881 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
2882 else
2883 window = GetConnectWidget()->window;
148cd9b6 2884
ed673c6a 2885 if (!window)
739730ca
RR
2886 {
2887 // indicate that a new style has been set
c50f1fb9
VZ
2888 // but it couldn't get applied as the
2889 // widget hasn't been realized yet.
2890 m_delayedForegroundColour = TRUE;
2891
2892 // pretend we have done something
739730ca
RR
2893 return TRUE;
2894 }
2b07d713 2895
ae0bdb01 2896 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
2b62ab35 2897 if ( sysbg == m_backgroundColour )
ae0bdb01
RR
2898 {
2899 m_backgroundColour = wxNullColour;
2900 ApplyWidgetStyle();
ff8bfdbb
VZ
2901 m_backgroundColour = sysbg;
2902 }
ae0bdb01
RR
2903 else
2904 {
2905 ApplyWidgetStyle();
2906 }
f03fc89f
VZ
2907
2908 return TRUE;
58614078
RR
2909}
2910
2911GtkStyle *wxWindow::GetWidgetStyle()
2912{
1ecc4d80 2913 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
8bbe427f 2914
f03fc89f 2915 m_widgetStyle = gtk_style_copy( gtk_widget_get_style( m_widget ) );
8bbe427f 2916
1ecc4d80 2917 return m_widgetStyle;
58614078
RR
2918}
2919
2920void wxWindow::SetWidgetStyle()
2921{
1ecc4d80
RR
2922 GtkStyle *style = GetWidgetStyle();
2923
2924 gdk_font_unref( style->font );
2925 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2926
2927 if (m_foregroundColour.Ok())
2928 {
454e2a22 2929 m_foregroundColour.CalcPixel( gtk_widget_get_colormap( m_widget ) );
1ecc4d80
RR
2930 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
2931 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
2932 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
2933 }
2934
2935 if (m_backgroundColour.Ok())
2936 {
454e2a22 2937 m_backgroundColour.CalcPixel( gtk_widget_get_colormap( m_widget ) );
1ecc4d80
RR
2938 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2939 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2940 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2941 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2942 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2943 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2944 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2945 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2946 }
a81258be
RR
2947}
2948
58614078 2949void wxWindow::ApplyWidgetStyle()
a81258be 2950{
6de97a3b
RR
2951}
2952
2259e007
RR
2953//-----------------------------------------------------------------------------
2954// Pop-up menu stuff
2955//-----------------------------------------------------------------------------
2956
2957static void gtk_pop_hide_callback( GtkWidget *WXUNUSED(widget), bool* is_waiting )
2958{
2959 *is_waiting = FALSE;
2960}
2961
30dea054
RR
2962static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2963{
1ecc4d80 2964 menu->SetInvokingWindow( win );
1987af7e 2965 wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
1ecc4d80
RR
2966 while (node)
2967 {
1987af7e 2968 wxMenuItem *menuitem = node->GetData();
1ecc4d80
RR
2969 if (menuitem->IsSubMenu())
2970 {
ff8bfdbb
VZ
2971 SetInvokingWindow( menuitem->GetSubMenu(), win );
2972 }
1987af7e
VZ
2973
2974 node = node->GetNext();
1ecc4d80 2975 }
362c6693 2976}
30dea054 2977
0c77152e
RR
2978static gint gs_pop_x = 0;
2979static gint gs_pop_y = 0;
2980
a234a61a
VZ
2981static void pop_pos_callback( GtkMenu * WXUNUSED(menu),
2982 gint *x, gint *y,
2983 wxWindow *win )
0c77152e
RR
2984{
2985 win->ClientToScreen( &gs_pop_x, &gs_pop_y );
2986 *x = gs_pop_x;
2987 *y = gs_pop_y;
2988}
2989
a1665b22 2990bool wxWindow::DoPopupMenu( wxMenu *menu, int x, int y )
30dea054 2991{
223d09f6 2992 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
47d67540 2993
223d09f6 2994 wxCHECK_MSG( menu != NULL, FALSE, wxT("invalid popup-menu") );
8bbe427f 2995
1ecc4d80 2996 SetInvokingWindow( menu, this );
ff8bfdbb 2997
631f1bfe
JS
2998 menu->UpdateUI();
2999
0c77152e
RR
3000 gs_pop_x = x;
3001 gs_pop_y = y;
ff8bfdbb 3002
2259e007 3003 bool is_waiting = TRUE;
148cd9b6 3004
2259e007
RR
3005 gtk_signal_connect( GTK_OBJECT(menu->m_menu), "hide",
3006 GTK_SIGNAL_FUNC(gtk_pop_hide_callback), (gpointer)&is_waiting );
3007
1ecc4d80 3008 gtk_menu_popup(
47d67540 3009 GTK_MENU(menu->m_menu),
0c77152e
RR
3010 (GtkWidget *) NULL, // parent menu shell
3011 (GtkWidget *) NULL, // parent menu item
3012 (GtkMenuPositionFunc) pop_pos_callback,
3013 (gpointer) this, // client data
3014 0, // button used to activate it
54517652 3015 gs_timeLastClick // the time of activation
47d67540 3016 );
148cd9b6 3017
956dbab1
RR
3018 while (is_waiting)
3019 {
3020 while (gtk_events_pending())
3021 gtk_main_iteration();
3022 }
2259e007 3023
1ecc4d80 3024 return TRUE;
30dea054
RR
3025}
3026
06cfab17 3027#if wxUSE_DRAG_AND_DROP
ac57418f 3028
c801d85f
KB
3029void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
3030{
223d09f6 3031 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3032
1ecc4d80 3033 GtkWidget *dnd_widget = GetConnectWidget();
47d67540 3034
1ecc4d80 3035 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
47d67540 3036
1ecc4d80
RR
3037 if (m_dropTarget) delete m_dropTarget;
3038 m_dropTarget = dropTarget;
47d67540 3039
1ecc4d80 3040 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
362c6693 3041}
c801d85f 3042
f03fc89f 3043#endif // wxUSE_DRAG_AND_DROP
ac57418f 3044
68dda785 3045GtkWidget* wxWindow::GetConnectWidget()
e3e65dac 3046{
1ecc4d80
RR
3047 GtkWidget *connect_widget = m_widget;
3048 if (m_wxwindow) connect_widget = m_wxwindow;
47d67540 3049
1ecc4d80 3050 return connect_widget;
e3e65dac 3051}
47d67540 3052
903f689b
RR
3053bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
3054{
148cd9b6 3055 if (m_wxwindow)
da048e3d 3056 return (window == GTK_PIZZA(m_wxwindow)->bin_window);
148cd9b6 3057
1ecc4d80 3058 return (window == m_widget->window);
903f689b
RR
3059}
3060
f03fc89f 3061bool wxWindow::SetFont( const wxFont &font )
c801d85f 3062{
223d09f6 3063 wxCHECK_MSG( m_widget != NULL, FALSE, wxT("invalid window") );
c801d85f 3064
739730ca
RR
3065 if (!wxWindowBase::SetFont(font))
3066 {
454e2a22 3067 return FALSE;
739730ca 3068 }
9c288e4d 3069
ae0bdb01 3070 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
f03fc89f 3071 if ( sysbg == m_backgroundColour )
ae0bdb01
RR
3072 {
3073 m_backgroundColour = wxNullColour;
3074 ApplyWidgetStyle();
ff8bfdbb
VZ
3075 m_backgroundColour = sysbg;
3076 }
ae0bdb01
RR
3077 else
3078 {
3079 ApplyWidgetStyle();
3080 }
c801d85f 3081
f03fc89f 3082 return TRUE;
362c6693 3083}
c801d85f 3084
68dda785 3085void wxWindow::CaptureMouse()
c801d85f 3086{
223d09f6 3087 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3088
223d09f6 3089 wxCHECK_RET( g_captureWindow == NULL, wxT("CaptureMouse called twice") );
47d67540 3090
ed673c6a
RR
3091 GdkWindow *window = (GdkWindow*) NULL;
3092 if (m_wxwindow)
da048e3d 3093 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3094 else
3095 window = GetConnectWidget()->window;
148cd9b6 3096
ed673c6a 3097 if (!window) return;
c50f1fb9 3098
ed673c6a 3099 gdk_pointer_grab( window, FALSE,
1ecc4d80
RR
3100 (GdkEventMask)
3101 (GDK_BUTTON_PRESS_MASK |
3102 GDK_BUTTON_RELEASE_MASK |
148cd9b6 3103 GDK_POINTER_MOTION_HINT_MASK |
1ecc4d80 3104 GDK_POINTER_MOTION_MASK),
ff8bfdbb 3105 (GdkWindow *) NULL,
72195a0f 3106 m_cursor.GetCursor(),
b02da6b1 3107 (guint32)GDK_CURRENT_TIME );
72195a0f 3108 g_captureWindow = this;
362c6693 3109}
c801d85f 3110
68dda785 3111void wxWindow::ReleaseMouse()
c801d85f 3112{
223d09f6 3113 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3114
223d09f6 3115 wxCHECK_RET( g_captureWindow, wxT("ReleaseMouse called twice") );
47d67540 3116
ed673c6a
RR
3117 GdkWindow *window = (GdkWindow*) NULL;
3118 if (m_wxwindow)
da048e3d 3119 window = GTK_PIZZA(m_wxwindow)->bin_window;
ed673c6a
RR
3120 else
3121 window = GetConnectWidget()->window;
148cd9b6 3122
b02da6b1
VZ
3123 if (!window)
3124 return;
c50f1fb9 3125
b02da6b1 3126 gdk_pointer_ungrab ( (guint32)GDK_CURRENT_TIME );
72195a0f 3127 g_captureWindow = (wxWindow*) NULL;
362c6693 3128}
c801d85f 3129
f03fc89f 3130bool wxWindow::IsRetained() const
c801d85f 3131{
1ecc4d80 3132 return FALSE;
362c6693 3133}
c801d85f 3134
debe6624 3135void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
cb43b372 3136 int range, bool refresh )
c801d85f 3137{
223d09f6 3138 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
8bbe427f 3139
223d09f6 3140 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
c801d85f 3141
1ecc4d80 3142 m_hasScrolling = TRUE;
47d67540 3143
1ecc4d80 3144 if (orient == wxHORIZONTAL)
cb43b372 3145 {
1ecc4d80
RR
3146 float fpos = (float)pos;
3147 float frange = (float)range;
3148 float fthumb = (float)thumbVisible;
3149 if (fpos > frange-fthumb) fpos = frange-fthumb;
3150 if (fpos < 0.0) fpos = 0.0;
3151
3152 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
3153 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
3154 {
3155 SetScrollPos( orient, pos, refresh );
3156 return;
3157 }
47d67540 3158
1ecc4d80 3159 m_oldHorizontalPos = fpos;
47d67540 3160
1ecc4d80
RR
3161 m_hAdjust->lower = 0.0;
3162 m_hAdjust->upper = frange;
3163 m_hAdjust->value = fpos;
3164 m_hAdjust->step_increment = 1.0;
3165 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
3166 m_hAdjust->page_size = fthumb;
cb43b372 3167 }
1ecc4d80
RR
3168 else
3169 {
3170 float fpos = (float)pos;
3171 float frange = (float)range;
3172 float fthumb = (float)thumbVisible;
3173 if (fpos > frange-fthumb) fpos = frange-fthumb;
3174 if (fpos < 0.0) fpos = 0.0;
3175
3176 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
3177 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
3178 {
3179 SetScrollPos( orient, pos, refresh );
3180 return;
3181 }
47d67540 3182
1ecc4d80 3183 m_oldVerticalPos = fpos;
47d67540 3184
1ecc4d80
RR
3185 m_vAdjust->lower = 0.0;
3186 m_vAdjust->upper = frange;
3187 m_vAdjust->value = fpos;
3188 m_vAdjust->step_increment = 1.0;
3189 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
3190 m_vAdjust->page_size = fthumb;
3191 }
47d67540 3192
eb082a08
RR
3193 if (orient == wxHORIZONTAL)
3194 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
3195 else
3196 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
362c6693 3197}
c801d85f 3198
debe6624 3199void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
c801d85f 3200{
223d09f6 3201 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
1ecc4d80 3202
223d09f6 3203 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
1ecc4d80
RR
3204
3205 if (orient == wxHORIZONTAL)
3206 {
3207 float fpos = (float)pos;
3208 if (fpos > m_hAdjust->upper - m_hAdjust->page_size) fpos = m_hAdjust->upper - m_hAdjust->page_size;
3209 if (fpos < 0.0) fpos = 0.0;
3210 m_oldHorizontalPos = fpos;
3211
3212 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
3213 m_hAdjust->value = fpos;
3214 }
3215 else
3216 {
3217 float fpos = (float)pos;
3218 if (fpos > m_vAdjust->upper - m_vAdjust->page_size) fpos = m_vAdjust->upper - m_vAdjust->page_size;
3219 if (fpos < 0.0) fpos = 0.0;
3220 m_oldVerticalPos = fpos;
ff8bfdbb 3221
1ecc4d80
RR
3222 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
3223 m_vAdjust->value = fpos;
3224 }
47d67540 3225
5e014a0c
RR
3226/*
3227 if (!m_isScrolling)
47d67540 3228 {
5e014a0c 3229*/
1ecc4d80
RR
3230 if (m_wxwindow->window)
3231 {
3232 if (orient == wxHORIZONTAL)
3233 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
3234 else
3235 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
3236 }
5e014a0c 3237/*
cb43b372 3238 }
5e014a0c 3239*/
362c6693 3240}
c801d85f 3241
debe6624 3242int wxWindow::GetScrollThumb( int orient ) const
c801d85f 3243{
223d09f6 3244 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
47d67540 3245
223d09f6 3246 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
47d67540 3247
1ecc4d80
RR
3248 if (orient == wxHORIZONTAL)
3249 return (int)(m_hAdjust->page_size+0.5);
3250 else
3251 return (int)(m_vAdjust->page_size+0.5);
362c6693 3252}
c801d85f 3253
debe6624 3254int wxWindow::GetScrollPos( int orient ) const
c801d85f 3255{
223d09f6 3256 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
47d67540 3257
223d09f6 3258 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
c801d85f 3259
1ecc4d80
RR
3260 if (orient == wxHORIZONTAL)
3261 return (int)(m_hAdjust->value+0.5);
3262 else
3263 return (int)(m_vAdjust->value+0.5);
362c6693 3264}
c801d85f 3265
debe6624 3266int wxWindow::GetScrollRange( int orient ) const
c801d85f 3267{
223d09f6 3268 wxCHECK_MSG( m_widget != NULL, 0, wxT("invalid window") );
47d67540 3269
223d09f6 3270 wxCHECK_MSG( m_wxwindow != NULL, 0, wxT("window needs client area for scrolling") );
c801d85f 3271
1ecc4d80
RR
3272 if (orient == wxHORIZONTAL)
3273 return (int)(m_hAdjust->upper+0.5);
3274 else
3275 return (int)(m_vAdjust->upper+0.5);
362c6693 3276}
c801d85f 3277
debe6624 3278void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
c801d85f 3279{
223d09f6 3280 wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
47d67540 3281
223d09f6 3282 wxCHECK_RET( m_wxwindow != NULL, wxT("window needs client area for scrolling") );
c801d85f 3283
da048e3d 3284 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
ed673c6a
RR
3285
3286/*
a2053b27 3287 if (!m_scrollGC)
96d5ab4d 3288 {
a2053b27
RR
3289 m_scrollGC = gdk_gc_new( m_wxwindow->window );
3290 gdk_gc_set_exposures( m_scrollGC, TRUE );
96d5ab4d 3291 }
c50f1fb9 3292
ea5c6ca7
RR
3293 wxNode *node = m_children.First();
3294 while (node)
3295 {
3296 wxWindow *child = (wxWindow*) node->Data();
c50f1fb9
VZ
3297 int sx = 0;
3298 int sy = 0;
3299 child->GetSize( &sx, &sy );
3300 child->SetSize( child->m_x + dx, child->m_y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
3301 node = node->Next();
ea5c6ca7 3302 }
96d5ab4d 3303
c801d85f
KB
3304 int cw = 0;
3305 int ch = 0;
3306 GetClientSize( &cw, &ch );
c801d85f
KB
3307 int w = cw - abs(dx);
3308 int h = ch - abs(dy);
c50f1fb9 3309
c801d85f
KB
3310 if ((h < 0) || (w < 0))
3311 {
1ecc4d80 3312 Refresh();
362c6693 3313 }
a2053b27 3314 else
c801d85f 3315 {
a2053b27
RR
3316 int s_x = 0;
3317 int s_y = 0;
3318 if (dx < 0) s_x = -dx;
3319 if (dy < 0) s_y = -dy;
3320 int d_x = 0;
3321 int d_y = 0;
3322 if (dx > 0) d_x = dx;
3323 if (dy > 0) d_y = dy;
c801d85f 3324
a2053b27
RR
3325 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
3326 m_wxwindow->window, s_x, s_y, w, h );
c801d85f 3327
a2053b27
RR
3328 wxRect rect;
3329 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3330 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3331 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3332 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
c801d85f 3333
a2053b27
RR
3334 Refresh( TRUE, &rect );
3335 }
ed673c6a 3336*/
c801d85f
KB
3337}
3338
f03fc89f 3339void wxWindow::SetScrolling(bool scroll)
c801d85f 3340{
f03fc89f 3341 m_isScrolling = g_blockEventsOnScroll = scroll;
c801d85f 3342}