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