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