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