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