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