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