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