]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/window.cpp
* fix in wcslen()
[wxWidgets.git] / src / gtk1 / window.cpp
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: window.cpp
3// Purpose:
4// Author: Robert Roebling
c67d8618 5// Id: $Id$
01111366 6// Copyright: (c) 1998 Robert Roebling, Julian Smart
5e0aa05a 7// Licence: wxWindows licence
c801d85f
KB
8/////////////////////////////////////////////////////////////////////////////
9
10
11#ifdef __GNUG__
bfc6fde4 12 #pragma implementation "window.h"
c801d85f
KB
13#endif
14
15#include "wx/defs.h"
16#include "wx/window.h"
17#include "wx/dc.h"
18#include "wx/frame.h"
19#include "wx/app.h"
20#include "wx/layout.h"
21#include "wx/utils.h"
22#include "wx/dialog.h"
23#include "wx/msgdlg.h"
bfc6fde4 24
06cfab17 25#if wxUSE_DRAG_AND_DROP
bfc6fde4 26 #include "wx/dnd.h"
ac57418f 27#endif
bfc6fde4 28
cad880f5 29#if wxUSE_TOOLTIPS
bfc6fde4 30 #include "wx/tooltip.h"
cad880f5 31#endif
bfc6fde4 32
30dea054 33#include "wx/menu.h"
d4c99d6f 34#include "wx/statusbr.h"
b4071e91 35#include "wx/intl.h"
3bc755fc 36#include "wx/settings.h"
3069ac4e 37#include "wx/log.h"
b4071e91
RR
38
39#include <math.h>
c801d85f 40
83624f79
RR
41#include "gdk/gdk.h"
42#include "gtk/gtk.h"
43#include "gdk/gdkprivate.h"
44#include "gdk/gdkkeysyms.h"
45#include "wx/gtk/win_gtk.h"
46
868a2826
RR
47//-----------------------------------------------------------------------------
48// documentation on internals
49//-----------------------------------------------------------------------------
50
51/*
52 I have been asked several times about writing some documentation about
53 the GTK port of wxWindows, especially its internal structures. Obviously,
54 you cannot understand wxGTK without knowing a little about the GTK, but
47d67540 55 some more information about what the wxWindow, which is the base class
868a2826 56 for all other window classes, does seems required as well.
47d67540 57
868a2826 58 What does wxWindow do? It contains the common interface for the following
e380f72b 59 jobs of its descendants:
47d67540 60
868a2826 61 1) Define the rudimentary behaviour common to all window classes, such as
e380f72b
RR
62 resizing, intercepting user input (so as to make it possible to use these
63 events for special purposes in a derived class), window names etc.
868a2826
RR
64
65 2) Provide the possibility to contain and manage children, if the derived
66 class is allowed to contain children, which holds true for those window
e380f72b 67 classes which do not display a native GTK widget. To name them, these
868a2826 68 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
47d67540 69 work classes are a special case and are handled a bit differently from
e380f72b 70 the rest. The same holds true for the wxNotebook class.
47d67540 71
868a2826
RR
72 3) Provide the possibility to draw into a client area of a window. This,
73 too, only holds true for classes that do not display a native GTK widget
74 as above.
47d67540 75
e380f72b
RR
76 4) Provide the entire mechanism for scrolling widgets. This actual inter-
77 face for this is usually in wxScrolledWindow, but the GTK implementation
868a2826 78 is in this class.
47d67540 79
868a2826
RR
80 5) A multitude of helper or extra methods for special purposes, such as
81 Drag'n'Drop, managing validators etc.
47d67540 82
e380f72b
RR
83 Normally one might expect, that one wxWindows window would always correspond
84 to one GTK widget. Under GTK, there is no such allround widget that has all
868a2826
RR
85 the functionality. Moreover, the GTK defines a client area as a different
86 widget from the actual widget you are handling. Last but not least some
87 special classes (e.g. wxFrame) handle different categories of widgets and
88 still have the possibility to draw something in the client area.
89 It was therefore required to write a special purpose GTK widget, that would
90 represent a client area in the sense of wxWindows capable to do the jobs
91 2), 3) and 4). I have written this class and it resides in win_gtk.c of
92 this directory.
47d67540 93
868a2826 94 All windows must have a widget, with which they interact with other under-
e380f72b 95 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
868a2826 96 thw wxWindow class has a member variable called m_widget which holds a
e380f72b
RR
97 pointer to this widget. When the window class represents a GTK native widget,
98 this is (in most cases) the only GTK widget the class manages. E.g. the
99 wxStatitText class handles only a GtkLabel widget a pointer to which you
100 can find in m_widget (defined in wxWindow)
8bbe427f 101
e380f72b 102 When the class has a client area for drawing into and for containing children
8bbe427f
VZ
103 it has to handle the client area widget (of the type GtkMyFixed, defined in
104 win_gtk.c), but there could be any number of widgets, handled by a class
105 The common rule for all windows is only, that the widget that interacts with
106 the rest of GTK must be referenced in m_widget and all other widgets must be
107 children of this widget on the GTK level. The top-most widget, which also
108 represents the client area, must be in the m_wxwindow field and must be of
e380f72b 109 the type GtkMyFixed.
47d67540 110
868a2826
RR
111 As I said, the window classes that display a GTK native widget only have
112 one widget, so in the case of e.g. the wxButton class m_widget holds a
113 pointer to a GtkButton widget. But windows with client areas (for drawing
114 and children) have a m_widget field that is a pointer to a GtkScrolled-
115 Window and a m_wxwindow field that is pointer to a GtkMyFixed and this
116 one is (in the GTK sense) a child of the GtkScrolledWindow.
47d67540 117
868a2826
RR
118 If the m_wxwindow field is set, then all input to this widget is inter-
119 cepted and sent to the wxWindows class. If not, all input to the widget
120 that gets pointed to by m_widget gets intercepted and sent to the class.
121
122*/
123
f03fc89f
VZ
124//-----------------------------------------------------------------------------
125// data
126//-----------------------------------------------------------------------------
127
128extern wxList wxPendingDelete;
129extern bool g_blockEventsOnDrag;
130extern bool g_blockEventsOnScroll;
131static bool g_capturing = FALSE;
132static wxWindow *g_focusWindow = (wxWindow*) NULL;
133
134/* hack: we need something to pass to gtk_menu_popup, so we store the time of
135 the last click here */
136static guint32 gs_timeLastClick = 0;
137
2e563988
RR
138//-----------------------------------------------------------------------------
139// debug
140//-----------------------------------------------------------------------------
141
142#ifdef __WXDEBUG__
143
144static gint gtk_debug_focus_in_callback( GtkWidget *WXUNUSED(widget),
145 GdkEvent *WXUNUSED(event),
146 const wxChar *name )
147{
053dcf1a 148/*
167e3718
VZ
149 static bool s_done = FALSE;
150 if ( !s_done )
151 {
152 wxLog::AddTraceMask("focus");
153 s_done = TRUE;
154 }
167e3718 155 wxLogTrace(_T("FOCUS NOW AT: %s"), name);
053dcf1a 156*/
2e563988
RR
157
158 return FALSE;
159}
160
161void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window )
162{
163 wxString tmp = name;
164 tmp += _T(" FROM ");
165 tmp += window;
166
167 wxChar *s = new wxChar[tmp.Length()+1];
168
169 wxStrcpy( s, tmp );
170
171 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
172 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback), (gpointer)s );
173}
174
f03fc89f 175#endif // Debug
ff8bfdbb 176
acfd422a 177//-----------------------------------------------------------------------------
a2053b27 178// idle system
acfd422a
RR
179//-----------------------------------------------------------------------------
180
a2053b27
RR
181extern void wxapp_install_idle_handler();
182extern bool g_isIdle;
183
184//-----------------------------------------------------------------------------
185// local code (see below)
186//-----------------------------------------------------------------------------
acfd422a 187
ef47f9b3
RR
188#if (GTK_MINOR_VERSION > 0)
189
034be888 190static void draw_frame( GtkWidget *widget, wxWindow *win )
b292e2f5 191{
a2053b27 192 if (!win->m_hasVMT)
f03fc89f 193 return;
b292e2f5 194
034be888
RR
195 int dw = 0;
196 int dh = 0;
ca298c88 197
f03fc89f 198 if (win->HasScrolling())
034be888
RR
199 {
200 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(widget);
201 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget)->klass );
ff8bfdbb 202
034be888
RR
203/*
204 GtkWidget *hscrollbar = scroll_window->hscrollbar;
205 GtkWidget *vscrollbar = scroll_window->vscrollbar;
ca298c88 206
f03fc89f 207 we use this instead: range.slider_width = 11 + 2*2pts edge
034be888 208*/
ff8bfdbb 209
034be888
RR
210 if (scroll_window->vscrollbar_visible)
211 {
212 dw += 15; /* dw += vscrollbar->allocation.width; */
213 dw += scroll_class->scrollbar_spacing;
214 }
b292e2f5 215
034be888
RR
216 if (scroll_window->hscrollbar_visible)
217 {
218 dh += 15; /* dh += hscrollbar->allocation.height; */
219 dw += scroll_class->scrollbar_spacing;
220 }
221 }
ca298c88 222
034be888
RR
223 int dx = 0;
224 int dy = 0;
225 if (GTK_WIDGET_NO_WINDOW (widget))
226 {
227 dx += widget->allocation.x;
228 dy += widget->allocation.y;
229 }
ca298c88 230
f03fc89f 231 if (win->HasFlag(wxRAISED_BORDER))
034be888 232 {
ca298c88 233 gtk_draw_shadow( widget->style,
034be888 234 widget->window,
f03fc89f
VZ
235 GTK_STATE_NORMAL,
236 GTK_SHADOW_OUT,
237 dx, dy,
a2053b27 238 win->m_width-dw, win->m_height-dh );
f03fc89f 239 return;
ca298c88
RD
240 }
241
f03fc89f 242 if (win->HasFlag(wxSUNKEN_BORDER))
034be888 243 {
ca298c88 244 gtk_draw_shadow( widget->style,
034be888 245 widget->window,
f03fc89f
VZ
246 GTK_STATE_NORMAL,
247 GTK_SHADOW_IN,
248 dx, dy,
a2053b27 249 win->m_width-dw, win->m_height-dh );
f03fc89f 250 return;
034be888 251 }
b292e2f5
RR
252}
253
c801d85f 254//-----------------------------------------------------------------------------
034be888 255// "expose_event" of m_widget
c801d85f
KB
256//-----------------------------------------------------------------------------
257
034be888
RR
258static void gtk_window_own_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxWindow *win )
259{
260 if (gdk_event->count > 0) return;
261 draw_frame( widget, win );
262}
47d67540 263
034be888
RR
264//-----------------------------------------------------------------------------
265// "draw" of m_wxwindow
266//-----------------------------------------------------------------------------
267
268static void gtk_window_own_draw_callback( GtkWidget *widget, GdkRectangle *WXUNUSED(rect), wxWindow *win )
269{
270 draw_frame( widget, win );
271}
c801d85f 272
f03fc89f 273#endif // GTK_MINOR_VERSION > 0
ef47f9b3 274
c801d85f 275//-----------------------------------------------------------------------------
034be888 276// "expose_event" of m_wxwindow
c801d85f
KB
277//-----------------------------------------------------------------------------
278
2f2aa628 279static void gtk_window_expose_callback( GtkWidget *WXUNUSED(widget), GdkEventExpose *gdk_event, wxWindow *win )
47d67540 280{
a2053b27 281 if ( !win->m_hasVMT )
f03fc89f 282 return;
47d67540 283
f03fc89f
VZ
284 win->GetUpdateRegion().Union( gdk_event->area.x,
285 gdk_event->area.y,
286 gdk_event->area.width,
287 gdk_event->area.height );
47d67540 288
f03fc89f
VZ
289 if ( gdk_event->count > 0 )
290 return;
c801d85f 291
d8c83875 292/*
f5e27805
RR
293 printf( "OnExpose from " );
294 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
295 printf( win->GetClassInfo()->GetClassName() );
296 printf( ".\n" );
d8c83875
RR
297*/
298
f5e27805
RR
299 wxPaintEvent event( win->GetId() );
300 event.SetEventObject( win );
301 win->GetEventHandler()->ProcessEvent( event );
47d67540 302
f03fc89f 303 win->GetUpdateRegion().Clear();
362c6693 304}
c801d85f
KB
305
306//-----------------------------------------------------------------------------
034be888 307// "draw" of m_wxwindow
2f2aa628 308//-----------------------------------------------------------------------------
c801d85f 309
2f2aa628 310static void gtk_window_draw_callback( GtkWidget *WXUNUSED(widget), GdkRectangle *rect, wxWindow *win )
47d67540 311{
a2053b27
RR
312 if (g_isIdle)
313 wxapp_install_idle_handler();
314
315 if (!win->m_hasVMT)
f03fc89f 316 return;
47d67540 317
f03fc89f
VZ
318 win->GetUpdateRegion().Union( rect->x, rect->y,
319 rect->width, rect->height );
47d67540 320
f5e27805
RR
321 wxPaintEvent event( win->GetId() );
322 event.SetEventObject( win );
323 win->GetEventHandler()->ProcessEvent( event );
47d67540 324
f03fc89f 325 win->GetUpdateRegion().Clear();
362c6693 326}
c801d85f
KB
327
328//-----------------------------------------------------------------------------
b292e2f5 329// "key_press_event" from any window
c801d85f 330//-----------------------------------------------------------------------------
c801d85f 331
2f2aa628 332static gint gtk_window_key_press_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
47d67540 333{
a2053b27
RR
334 if (g_isIdle)
335 wxapp_install_idle_handler();
336
337 if (!win->m_hasVMT) return FALSE;
f5e27805 338 if (g_blockEventsOnDrag) return FALSE;
c801d85f 339
7be4c594 340/*
d1367c3d
RR
341 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
342 if (gdk_event->state & GDK_SHIFT_MASK)
343 printf( "ShiftDown.\n" );
344 else
345 printf( "ShiftUp.\n" );
346 if (gdk_event->state & GDK_CONTROL_MASK)
347 printf( "ControlDown.\n" );
348 else
349 printf( "ControlUp.\n" );
350 printf( "\n" );
7be4c594 351*/
ca298c88 352
f5e27805
RR
353 long key_code = 0;
354 switch (gdk_event->keyval)
c801d85f 355 {
f5e27805 356 case GDK_BackSpace: key_code = WXK_BACK; break;
f03fc89f 357 case GDK_ISO_Left_Tab:
5664fc32 358 case GDK_KP_Tab:
f5e27805
RR
359 case GDK_Tab: key_code = WXK_TAB; break;
360 case GDK_Linefeed: key_code = WXK_RETURN; break;
361 case GDK_Clear: key_code = WXK_CLEAR; break;
362 case GDK_Return: key_code = WXK_RETURN; break;
363 case GDK_Pause: key_code = WXK_PAUSE; break;
364 case GDK_Scroll_Lock: key_code = WXK_SCROLL; break;
365 case GDK_Escape: key_code = WXK_ESCAPE; break;
366 case GDK_Delete: key_code = WXK_DELETE; break;
367 case GDK_Home: key_code = WXK_HOME; break;
368 case GDK_Left: key_code = WXK_LEFT; break;
369 case GDK_Up: key_code = WXK_UP; break;
370 case GDK_Right: key_code = WXK_RIGHT; break;
371 case GDK_Down: key_code = WXK_DOWN; break;
372 case GDK_Prior: key_code = WXK_PRIOR; break;
373// case GDK_Page_Up: key_code = WXK_PAGEUP; break;
374 case GDK_Next: key_code = WXK_NEXT; break;
375// case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
376 case GDK_End: key_code = WXK_END; break;
377 case GDK_Begin: key_code = WXK_HOME; break;
378 case GDK_Select: key_code = WXK_SELECT; break;
379 case GDK_Print: key_code = WXK_PRINT; break;
380 case GDK_Execute: key_code = WXK_EXECUTE; break;
381 case GDK_Insert: key_code = WXK_INSERT; break;
382 case GDK_Num_Lock: key_code = WXK_NUMLOCK; break;
f5e27805
RR
383 case GDK_KP_Enter: key_code = WXK_RETURN; break;
384 case GDK_KP_Home: key_code = WXK_HOME; break;
385 case GDK_KP_Left: key_code = WXK_LEFT; break;
386 case GDK_KP_Up: key_code = WXK_UP; break;
387 case GDK_KP_Right: key_code = WXK_RIGHT; break;
388 case GDK_KP_Down: key_code = WXK_DOWN; break;
389 case GDK_KP_Prior: key_code = WXK_PRIOR; break;
390// case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
391 case GDK_KP_Next: key_code = WXK_NEXT; break;
392// case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
393 case GDK_KP_End: key_code = WXK_END; break;
394 case GDK_KP_Begin: key_code = WXK_HOME; break;
395 case GDK_KP_Insert: key_code = WXK_INSERT; break;
396 case GDK_KP_Delete: key_code = WXK_DELETE; break;
397 case GDK_KP_Multiply: key_code = WXK_MULTIPLY; break;
398 case GDK_KP_Add: key_code = WXK_ADD; break;
399 case GDK_KP_Separator: key_code = WXK_SEPARATOR; break;
400 case GDK_KP_Subtract: key_code = WXK_SUBTRACT; break;
401 case GDK_KP_Decimal: key_code = WXK_DECIMAL; break;
402 case GDK_KP_Divide: key_code = WXK_DIVIDE; break;
403 case GDK_KP_0: key_code = WXK_NUMPAD0; break;
404 case GDK_KP_1: key_code = WXK_NUMPAD1; break;
405 case GDK_KP_2: key_code = WXK_NUMPAD2; break;
406 case GDK_KP_3: key_code = WXK_NUMPAD3; break;
407 case GDK_KP_4: key_code = WXK_NUMPAD4; break;
408 case GDK_KP_5: key_code = WXK_NUMPAD5; break;
409 case GDK_KP_6: key_code = WXK_NUMPAD6; break;
410 case GDK_KP_7: key_code = WXK_NUMPAD7; break;
411 case GDK_KP_8: key_code = WXK_NUMPAD7; break;
412 case GDK_KP_9: key_code = WXK_NUMPAD9; break;
413 case GDK_F1: key_code = WXK_F1; break;
414 case GDK_F2: key_code = WXK_F2; break;
415 case GDK_F3: key_code = WXK_F3; break;
416 case GDK_F4: key_code = WXK_F4; break;
417 case GDK_F5: key_code = WXK_F5; break;
418 case GDK_F6: key_code = WXK_F6; break;
419 case GDK_F7: key_code = WXK_F7; break;
420 case GDK_F8: key_code = WXK_F8; break;
421 case GDK_F9: key_code = WXK_F9; break;
422 case GDK_F10: key_code = WXK_F10; break;
423 case GDK_F11: key_code = WXK_F11; break;
424 case GDK_F12: key_code = WXK_F12; break;
425 default:
426 {
427 if ((gdk_event->keyval >= 0x20) && (gdk_event->keyval <= 0xFF))
428 key_code = gdk_event->keyval;
429 }
362c6693 430 }
c801d85f 431
f5e27805 432 if (!key_code) return FALSE;
47d67540 433
b666df2c 434 wxKeyEvent event( wxEVT_KEY_DOWN );
d1367c3d 435 event.SetTimestamp( gdk_event->time );
f5e27805
RR
436 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
437 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
438 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
439 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
440 event.m_keyCode = key_code;
441 event.m_x = 0;
442 event.m_y = 0;
443 event.SetEventObject( win );
47d67540 444
f5e27805 445 bool ret = win->GetEventHandler()->ProcessEvent( event );
47d67540 446
f5e27805 447 if (!ret)
47d67540 448 {
f5e27805
RR
449 wxWindow *ancestor = win;
450 while (ancestor)
451 {
452 int command = ancestor->GetAcceleratorTable()->GetCommand( event );
453 if (command != -1)
454 {
455 wxCommandEvent command_event( wxEVT_COMMAND_MENU_SELECTED, command );
456 ret = ancestor->GetEventHandler()->ProcessEvent( command_event );
457 break;
458 }
459 ancestor = ancestor->GetParent();
460 }
bcf1fa6b 461 }
ff8bfdbb 462
b292e2f5 463 // win is a control: tab can be propagated up
ca298c88 464 if ( (!ret) &&
5664fc32 465 ((gdk_event->keyval == GDK_Tab) || (gdk_event->keyval == GDK_ISO_Left_Tab)) &&
f03fc89f 466 (win->HasFlag(wxTE_PROCESS_TAB) == 0))
b292e2f5
RR
467 {
468 wxNavigationKeyEvent new_event;
f03fc89f 469 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
5664fc32 470 new_event.SetDirection( (gdk_event->keyval == GDK_Tab) );
f03fc89f 471 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
b98d804b 472 new_event.SetWindowChange( (gdk_event->state & GDK_CONTROL_MASK) );
b292e2f5 473 new_event.SetCurrentFocus( win );
ff8bfdbb 474 ret = win->GetEventHandler()->ProcessEvent( new_event );
b292e2f5 475 }
ff8bfdbb 476
ca298c88 477 if ( (!ret) &&
b98d804b
RR
478 (gdk_event->keyval == GDK_Escape) )
479 {
480 wxCommandEvent new_event(wxEVT_COMMAND_BUTTON_CLICKED,wxID_CANCEL);
481 new_event.SetEventObject( win );
482 ret = win->GetEventHandler()->ProcessEvent( new_event );
483 }
ca298c88 484
b292e2f5 485/*
b98d804b
RR
486 Damn, I forgot why this didn't work, but it didn't work.
487
b292e2f5 488 // win is a panel: up can be propagated to the panel
a2053b27 489 if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
b292e2f5
RR
490 (gdk_event->keyval == GDK_Up))
491 {
492 win->m_parent->SetFocus();
ff8bfdbb 493 ret = TRUE;
b292e2f5 494 }
ff8bfdbb 495
b292e2f5 496 // win is a panel: left/right can be propagated to the panel
a2053b27 497 if ((!ret) && (win->m_wxwindow) &&
ff8bfdbb 498 ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
b292e2f5
RR
499 (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
500 {
501 wxNavigationKeyEvent new_event;
502 new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
503 new_event.SetCurrentFocus( win );
ff8bfdbb 504 ret = win->GetEventHandler()->ProcessEvent( new_event );
b292e2f5
RR
505 }
506*/
ff8bfdbb 507
f5e27805
RR
508 if (ret)
509 {
b292e2f5 510 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_press_event" );
f03fc89f 511 return TRUE;
f5e27805 512 }
47d67540 513
034be888 514 return FALSE;
362c6693 515}
c801d85f 516
b666df2c
RR
517//-----------------------------------------------------------------------------
518// "key_release_event" from any window
519//-----------------------------------------------------------------------------
520
521static gint gtk_window_key_release_callback( GtkWidget *widget, GdkEventKey *gdk_event, wxWindow *win )
522{
a2053b27
RR
523 if (g_isIdle)
524 wxapp_install_idle_handler();
525
526 if (!win->m_hasVMT) return FALSE;
b666df2c
RR
527 if (g_blockEventsOnDrag) return FALSE;
528
529/*
d1367c3d
RR
530 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
531 if (gdk_event->state & GDK_SHIFT_MASK)
532 printf( "ShiftDown.\n" );
533 else
534 printf( "ShiftUp.\n" );
535 if (gdk_event->state & GDK_CONTROL_MASK)
536 printf( "ControlDown.\n" );
537 else
538 printf( "ControlUp.\n" );
539 printf( "\n" );
b666df2c
RR
540*/
541
542 long key_code = 0;
543 switch (gdk_event->keyval)
544 {
545 case GDK_BackSpace: key_code = WXK_BACK; break;
f03fc89f 546 case GDK_ISO_Left_Tab:
5664fc32 547 case GDK_KP_Tab:
b666df2c
RR
548 case GDK_Tab: key_code = WXK_TAB; break;
549 case GDK_Linefeed: key_code = WXK_RETURN; break;
550 case GDK_Clear: key_code = WXK_CLEAR; break;
551 case GDK_Return: key_code = WXK_RETURN; break;
552 case GDK_Pause: key_code = WXK_PAUSE; break;
553 case GDK_Scroll_Lock: key_code = WXK_SCROLL; break;
554 case GDK_Escape: key_code = WXK_ESCAPE; break;
555 case GDK_Delete: key_code = WXK_DELETE; break;
556 case GDK_Home: key_code = WXK_HOME; break;
557 case GDK_Left: key_code = WXK_LEFT; break;
558 case GDK_Up: key_code = WXK_UP; break;
559 case GDK_Right: key_code = WXK_RIGHT; break;
560 case GDK_Down: key_code = WXK_DOWN; break;
561 case GDK_Prior: key_code = WXK_PRIOR; break;
562// case GDK_Page_Up: key_code = WXK_PAGEUP; break;
563 case GDK_Next: key_code = WXK_NEXT; break;
564// case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
565 case GDK_End: key_code = WXK_END; break;
566 case GDK_Begin: key_code = WXK_HOME; break;
567 case GDK_Select: key_code = WXK_SELECT; break;
568 case GDK_Print: key_code = WXK_PRINT; break;
569 case GDK_Execute: key_code = WXK_EXECUTE; break;
570 case GDK_Insert: key_code = WXK_INSERT; break;
571 case GDK_Num_Lock: key_code = WXK_NUMLOCK; break;
b666df2c
RR
572 case GDK_KP_Enter: key_code = WXK_RETURN; break;
573 case GDK_KP_Home: key_code = WXK_HOME; break;
574 case GDK_KP_Left: key_code = WXK_LEFT; break;
575 case GDK_KP_Up: key_code = WXK_UP; break;
576 case GDK_KP_Right: key_code = WXK_RIGHT; break;
577 case GDK_KP_Down: key_code = WXK_DOWN; break;
578 case GDK_KP_Prior: key_code = WXK_PRIOR; break;
579// case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
580 case GDK_KP_Next: key_code = WXK_NEXT; break;
581// case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
582 case GDK_KP_End: key_code = WXK_END; break;
583 case GDK_KP_Begin: key_code = WXK_HOME; break;
584 case GDK_KP_Insert: key_code = WXK_INSERT; break;
585 case GDK_KP_Delete: key_code = WXK_DELETE; break;
586 case GDK_KP_Multiply: key_code = WXK_MULTIPLY; break;
587 case GDK_KP_Add: key_code = WXK_ADD; break;
588 case GDK_KP_Separator: key_code = WXK_SEPARATOR; break;
589 case GDK_KP_Subtract: key_code = WXK_SUBTRACT; break;
590 case GDK_KP_Decimal: key_code = WXK_DECIMAL; break;
591 case GDK_KP_Divide: key_code = WXK_DIVIDE; break;
592 case GDK_KP_0: key_code = WXK_NUMPAD0; break;
593 case GDK_KP_1: key_code = WXK_NUMPAD1; break;
594 case GDK_KP_2: key_code = WXK_NUMPAD2; break;
595 case GDK_KP_3: key_code = WXK_NUMPAD3; break;
596 case GDK_KP_4: key_code = WXK_NUMPAD4; break;
597 case GDK_KP_5: key_code = WXK_NUMPAD5; break;
598 case GDK_KP_6: key_code = WXK_NUMPAD6; break;
599 case GDK_KP_7: key_code = WXK_NUMPAD7; break;
600 case GDK_KP_8: key_code = WXK_NUMPAD7; break;
601 case GDK_KP_9: key_code = WXK_NUMPAD9; break;
602 case GDK_F1: key_code = WXK_F1; break;
603 case GDK_F2: key_code = WXK_F2; break;
604 case GDK_F3: key_code = WXK_F3; break;
605 case GDK_F4: key_code = WXK_F4; break;
606 case GDK_F5: key_code = WXK_F5; break;
607 case GDK_F6: key_code = WXK_F6; break;
608 case GDK_F7: key_code = WXK_F7; break;
609 case GDK_F8: key_code = WXK_F8; break;
610 case GDK_F9: key_code = WXK_F9; break;
611 case GDK_F10: key_code = WXK_F10; break;
612 case GDK_F11: key_code = WXK_F11; break;
613 case GDK_F12: key_code = WXK_F12; break;
614 default:
615 {
616 if ((gdk_event->keyval >= 0x20) && (gdk_event->keyval <= 0xFF))
617 key_code = gdk_event->keyval;
618 }
619 }
620
621 if (!key_code) return FALSE;
622
623 wxKeyEvent event( wxEVT_KEY_UP );
d1367c3d 624 event.SetTimestamp( gdk_event->time );
b666df2c
RR
625 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
626 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
627 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
628 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
629 event.m_keyCode = key_code;
630 event.m_x = 0;
631 event.m_y = 0;
632 event.SetEventObject( win );
633
034be888 634 if (win->GetEventHandler()->ProcessEvent( event ))
b666df2c 635 {
b98d804b 636 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "key_release_event" );
f03fc89f 637 return TRUE;
b666df2c
RR
638 }
639
034be888 640 return FALSE;
b666df2c
RR
641}
642
c801d85f 643//-----------------------------------------------------------------------------
2f2aa628
RR
644// "button_press_event"
645//-----------------------------------------------------------------------------
c801d85f 646
2f2aa628 647static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
903f689b 648{
a2053b27
RR
649 if (g_isIdle)
650 wxapp_install_idle_handler();
651
652/*
653 wxPrintf( _T("1) OnButtonPress from ") );
654 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
655 wxPrintf( win->GetClassInfo()->GetClassName() );
656 wxPrintf( _T(".\n") );
657*/
a2053b27 658 if (!win->m_hasVMT) return FALSE;
f5e27805 659 if (g_blockEventsOnDrag) return TRUE;
76ed8f8d 660 if (g_blockEventsOnScroll) return TRUE;
c801d85f 661
034be888
RR
662 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
663
a2053b27 664 if (win->m_wxwindow)
c801d85f 665 {
a2053b27 666 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow) && !GTK_WIDGET_HAS_FOCUS (win->m_wxwindow) )
f5e27805 667 {
a2053b27 668 gtk_widget_grab_focus (win->m_wxwindow);
47d67540 669
c801d85f 670/*
a2053b27 671 wxPrintf( _T("GrabFocus from ") );
f5e27805 672 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
a2053b27
RR
673 wxPrintf( win->GetClassInfo()->GetClassName() );
674 wxPrintf( _T(".\n") );
c801d85f 675*/
47d67540 676
f5e27805 677 }
362c6693 678 }
47d67540 679
8429bec1 680/*
a2053b27 681 wxPrintf( _T("2) OnButtonPress from ") );
f5e27805 682 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
a2053b27
RR
683 wxPrintf( win->GetClassInfo()->GetClassName() );
684 wxPrintf( _T(".\n") );
8429bec1 685*/
30dea054 686
f5e27805 687 wxEventType event_type = wxEVT_LEFT_DOWN;
47d67540 688
f5e27805 689 if (gdk_event->button == 1)
c801d85f 690 {
f5e27805
RR
691 switch (gdk_event->type)
692 {
693 case GDK_BUTTON_PRESS: event_type = wxEVT_LEFT_DOWN; break;
694 case GDK_2BUTTON_PRESS: event_type = wxEVT_LEFT_DCLICK; break;
695 default: break;
696 }
362c6693 697 }
f5e27805 698 else if (gdk_event->button == 2)
c801d85f 699 {
f5e27805
RR
700 switch (gdk_event->type)
701 {
702 case GDK_BUTTON_PRESS: event_type = wxEVT_MIDDLE_DOWN; break;
703 case GDK_2BUTTON_PRESS: event_type = wxEVT_MIDDLE_DCLICK; break;
704 default: break;
705 }
362c6693 706 }
f5e27805 707 else if (gdk_event->button == 3)
c801d85f 708 {
f5e27805
RR
709 switch (gdk_event->type)
710 {
711 case GDK_BUTTON_PRESS: event_type = wxEVT_RIGHT_DOWN; break;
712 case GDK_2BUTTON_PRESS: event_type = wxEVT_RIGHT_DCLICK; break;
713 default: break;
714 }
362c6693 715 }
47d67540 716
f5e27805 717 wxMouseEvent event( event_type );
d1367c3d 718 event.SetTimestamp( gdk_event->time );
f5e27805
RR
719 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
720 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
721 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
722 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
723 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
724 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
725 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
47d67540 726
f5e27805
RR
727 event.m_x = (long)gdk_event->x;
728 event.m_y = (long)gdk_event->y;
47d67540 729
f5e27805
RR
730 // Some control don't have their own X window and thus cannot get
731 // any events.
47d67540 732
f5e27805 733 if (!g_capturing)
2f2aa628 734 {
db1b4961 735 wxNode *node = win->GetChildren().First();
f5e27805
RR
736 while (node)
737 {
738 wxWindow *child = (wxWindow*)node->Data();
ff8bfdbb 739
a2053b27 740 if (child->m_isStaticBox)
ff8bfdbb
VZ
741 {
742 // wxStaticBox is transparent in the box itself
a2053b27
RR
743 int x = event.m_x;
744 int y = event.m_y;
745 int xx1 = child->m_x;
746 int yy1 = child->m_y;
747 int xx2 = child->m_x + child->m_width;
748 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
749
750 // left
751 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
752 // right
753 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
754 // top
755 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
756 // bottom
757 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
758 {
1ecc4d80 759 win = child;
a2053b27
RR
760 event.m_x -= child->m_x;
761 event.m_y -= child->m_y;
1ecc4d80 762 break;
ff8bfdbb
VZ
763 }
764
765 }
766 else
767 {
a2053b27
RR
768 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
769 (child->m_x <= event.m_x) &&
770 (child->m_y <= event.m_y) &&
771 (child->m_x+child->m_width >= event.m_x) &&
772 (child->m_y+child->m_height >= event.m_y))
1ecc4d80
RR
773 {
774 win = child;
a2053b27
RR
775 event.m_x -= child->m_x;
776 event.m_y -= child->m_y;
1ecc4d80 777 break;
ff8bfdbb 778 }
f5e27805
RR
779 }
780 node = node->Next();
781 }
2f2aa628 782 }
ff8bfdbb 783
f5e27805 784 event.SetEventObject( win );
47d67540 785
f5e27805 786 gs_timeLastClick = gdk_event->time;
47d67540 787
f5e27805 788 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 789 {
f5e27805 790 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_press_event" );
f03fc89f 791 return TRUE;
034be888 792 }
47d67540 793
034be888 794 return FALSE;
362c6693 795}
c801d85f
KB
796
797//-----------------------------------------------------------------------------
97b3455a 798// "button_release_event"
2f2aa628 799//-----------------------------------------------------------------------------
c801d85f 800
2f2aa628 801static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxWindow *win )
47d67540 802{
a2053b27
RR
803 if (g_isIdle)
804 wxapp_install_idle_handler();
805
806 if (!win->m_hasVMT) return FALSE;
034be888
RR
807 if (g_blockEventsOnDrag) return FALSE;
808 if (g_blockEventsOnScroll) return FALSE;
c801d85f 809
034be888 810 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
47d67540 811
c801d85f 812/*
f5e27805
RR
813 printf( "OnButtonRelease from " );
814 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
815 printf( win->GetClassInfo()->GetClassName() );
816 printf( ".\n" );
c801d85f 817*/
47d67540 818
f5e27805 819 wxEventType event_type = wxEVT_NULL;
47d67540 820
f5e27805
RR
821 switch (gdk_event->button)
822 {
823 case 1: event_type = wxEVT_LEFT_UP; break;
824 case 2: event_type = wxEVT_MIDDLE_UP; break;
825 case 3: event_type = wxEVT_RIGHT_UP; break;
826 }
47d67540 827
f5e27805 828 wxMouseEvent event( event_type );
d1367c3d 829 event.SetTimestamp( gdk_event->time );
f5e27805
RR
830 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
831 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
832 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
833 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
834 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
835 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
836 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
837 event.m_x = (long)gdk_event->x;
838 event.m_y = (long)gdk_event->y;
839
840 // Some control don't have their own X window and thus cannot get
841 // any events.
842
843 if (!g_capturing)
2f2aa628 844 {
db1b4961 845 wxNode *node = win->GetChildren().First();
f5e27805
RR
846 while (node)
847 {
848 wxWindow *child = (wxWindow*)node->Data();
ff8bfdbb 849
a2053b27 850 if (child->m_isStaticBox)
ff8bfdbb
VZ
851 {
852 // wxStaticBox is transparent in the box itself
853 int x = event.m_x;
854 int y = event.m_y;
a2053b27
RR
855 int xx1 = child->m_x;
856 int yy1 = child->m_y;
857 int xx2 = child->m_x + child->m_width;
858 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
859
860 // left
861 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
862 // right
863 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
864 // top
865 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
866 // bottom
867 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
868 {
1ecc4d80 869 win = child;
a2053b27
RR
870 event.m_x -= child->m_x;
871 event.m_y -= child->m_y;
1ecc4d80 872 break;
ff8bfdbb
VZ
873 }
874
875 }
876 else
877 {
a2053b27
RR
878 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
879 (child->m_x <= event.m_x) &&
880 (child->m_y <= event.m_y) &&
881 (child->m_x+child->m_width >= event.m_x) &&
882 (child->m_y+child->m_height >= event.m_y))
1ecc4d80
RR
883 {
884 win = child;
a2053b27
RR
885 event.m_x -= child->m_x;
886 event.m_y -= child->m_y;
1ecc4d80 887 break;
ff8bfdbb 888 }
f5e27805
RR
889 }
890 node = node->Next();
891 }
2f2aa628 892 }
47d67540 893
f5e27805 894 event.SetEventObject( win );
47d67540 895
f5e27805 896 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 897 {
f5e27805 898 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "button_release_event" );
f03fc89f 899 return TRUE;
034be888 900 }
47d67540 901
034be888 902 return FALSE;
362c6693 903}
c801d85f
KB
904
905//-----------------------------------------------------------------------------
2f2aa628
RR
906// "motion_notify_event"
907//-----------------------------------------------------------------------------
c801d85f 908
2f2aa628 909static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxWindow *win )
47d67540 910{
a2053b27
RR
911 if (g_isIdle)
912 wxapp_install_idle_handler();
913
914 if (!win->m_hasVMT) return FALSE;
034be888
RR
915 if (g_blockEventsOnDrag) return FALSE;
916 if (g_blockEventsOnScroll) return FALSE;
917
918 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
919
ff8bfdbb 920 if (gdk_event->is_hint)
aae24d21
RR
921 {
922 int x = 0;
923 int y = 0;
924 GdkModifierType state;
925 gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
926 gdk_event->x = x;
927 gdk_event->y = y;
928 gdk_event->state = state;
929 }
ff8bfdbb 930
c801d85f 931/*
e380f72b
RR
932 printf( "OnMotion from " );
933 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
934 printf( win->GetClassInfo()->GetClassName() );
935 printf( ".\n" );
aae24d21 936*/
47d67540 937
e380f72b 938 wxMouseEvent event( wxEVT_MOTION );
d1367c3d 939 event.SetTimestamp( gdk_event->time );
e380f72b
RR
940 event.m_shiftDown = (gdk_event->state & GDK_SHIFT_MASK);
941 event.m_controlDown = (gdk_event->state & GDK_CONTROL_MASK);
942 event.m_altDown = (gdk_event->state & GDK_MOD1_MASK);
943 event.m_metaDown = (gdk_event->state & GDK_MOD2_MASK);
944 event.m_leftDown = (gdk_event->state & GDK_BUTTON1_MASK);
945 event.m_middleDown = (gdk_event->state & GDK_BUTTON2_MASK);
946 event.m_rightDown = (gdk_event->state & GDK_BUTTON3_MASK);
947
948 event.m_x = (long)gdk_event->x;
949 event.m_y = (long)gdk_event->y;
950
951 // Some control don't have their own X window and thus cannot get
952 // any events.
953
954 if (!g_capturing)
2f2aa628 955 {
db1b4961 956 wxNode *node = win->GetChildren().First();
e380f72b
RR
957 while (node)
958 {
959 wxWindow *child = (wxWindow*)node->Data();
ff8bfdbb 960
a2053b27 961 if (child->m_isStaticBox)
ff8bfdbb
VZ
962 {
963 // wxStaticBox is transparent in the box itself
964 int x = event.m_x;
965 int y = event.m_y;
a2053b27
RR
966 int xx1 = child->m_x;
967 int yy1 = child->m_y;
968 int xx2 = child->m_x + child->m_width;
969 int yy2 = child->m_x + child->m_height;
ff8bfdbb
VZ
970
971 // left
972 if (((x >= xx1) && (x <= xx1+10) && (y >= yy1) && (y <= yy2)) ||
973 // right
974 ((x >= xx2-10) && (x <= xx2) && (y >= yy1) && (y <= yy2)) ||
975 // top
976 ((x >= xx1) && (x <= xx2) && (y >= yy1) && (y <= yy1+10)) ||
977 // bottom
978 ((x >= xx1) && (x <= xx2) && (y >= yy2-1) && (y <= yy2)))
979 {
1ecc4d80 980 win = child;
a2053b27
RR
981 event.m_x -= child->m_x;
982 event.m_y -= child->m_y;
1ecc4d80 983 break;
ff8bfdbb
VZ
984 }
985
986 }
987 else
988 {
a2053b27
RR
989 if ((child->m_wxwindow == (GtkWidget*) NULL) &&
990 (child->m_x <= event.m_x) &&
991 (child->m_y <= event.m_y) &&
992 (child->m_x+child->m_width >= event.m_x) &&
993 (child->m_y+child->m_height >= event.m_y))
1ecc4d80
RR
994 {
995 win = child;
a2053b27
RR
996 event.m_x -= child->m_x;
997 event.m_y -= child->m_y;
1ecc4d80 998 break;
ff8bfdbb 999 }
e380f72b
RR
1000 }
1001 node = node->Next();
1002 }
2f2aa628 1003 }
47d67540 1004
e380f72b 1005 event.SetEventObject( win );
47d67540 1006
e380f72b 1007 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1008 {
e380f72b 1009 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "motion_notify_event" );
f03fc89f 1010 return TRUE;
034be888 1011 }
47d67540 1012
034be888 1013 return FALSE;
362c6693 1014}
c801d85f
KB
1015
1016//-----------------------------------------------------------------------------
2f2aa628
RR
1017// "focus_in_event"
1018//-----------------------------------------------------------------------------
c801d85f 1019
2f2aa628 1020static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
c801d85f 1021{
a2053b27
RR
1022 if (g_isIdle)
1023 wxapp_install_idle_handler();
1024
1025 if (!win->m_hasVMT) return FALSE;
034be888 1026 if (g_blockEventsOnDrag) return FALSE;
ff8bfdbb 1027
b292e2f5 1028 g_focusWindow = win;
ff8bfdbb 1029
a2053b27 1030 if (win->m_wxwindow)
c801d85f 1031 {
a2053b27 1032 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
e380f72b 1033 {
a2053b27 1034 GTK_WIDGET_SET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
47d67540 1035/*
e380f72b
RR
1036 printf( "SetFocus flag from " );
1037 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1038 printf( win->GetClassInfo()->GetClassName() );
1039 printf( ".\n" );
c801d85f 1040*/
e380f72b 1041 }
362c6693 1042 }
47d67540 1043
47d67540 1044
c801d85f 1045/*
f03fc89f 1046 printf( "OnSetFocus from " );
e380f72b 1047 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
f03fc89f
VZ
1048 printf( win->GetClassInfo()->GetClassName() );
1049 printf( " " );
1050 printf( WXSTRINGCAST win->GetLabel() );
1051 printf( ".\n" );
c801d85f 1052*/
47d67540 1053
e380f72b
RR
1054 wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() );
1055 event.SetEventObject( win );
47d67540 1056
e380f72b 1057 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1058 {
e380f72b 1059 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
034be888
RR
1060 return TRUE;
1061 }
ca298c88 1062
034be888 1063 return FALSE;
362c6693 1064}
c801d85f
KB
1065
1066//-----------------------------------------------------------------------------
2f2aa628
RR
1067// "focus_out_event"
1068//-----------------------------------------------------------------------------
c801d85f 1069
2f2aa628 1070static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win )
c801d85f 1071{
a2053b27
RR
1072 if (g_isIdle)
1073 wxapp_install_idle_handler();
1074
1075 if (!win->m_hasVMT) return FALSE;
034be888 1076 if (g_blockEventsOnDrag) return FALSE;
ca298c88 1077
a2053b27 1078 if (win->m_wxwindow)
e380f72b 1079 {
a2053b27
RR
1080 if (GTK_WIDGET_CAN_FOCUS(win->m_wxwindow))
1081 GTK_WIDGET_UNSET_FLAGS (win->m_wxwindow, GTK_HAS_FOCUS);
e380f72b 1082 }
47d67540 1083
c801d85f 1084/*
f03fc89f 1085 printf( "OnKillFocus from " );
e380f72b 1086 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
f03fc89f
VZ
1087 printf( win->GetClassInfo()->GetClassName() );
1088 printf( ".\n" );
c801d85f 1089*/
47d67540 1090
e380f72b
RR
1091 wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
1092 event.SetEventObject( win );
47d67540 1093
e380f72b 1094 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1095 {
e380f72b 1096 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
034be888
RR
1097 return TRUE;
1098 }
ca298c88 1099
034be888 1100 return FALSE;
362c6693 1101}
c801d85f 1102
b4071e91
RR
1103//-----------------------------------------------------------------------------
1104// "enter_notify_event"
1105//-----------------------------------------------------------------------------
1106
1107static gint gtk_window_enter_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
1108{
a2053b27
RR
1109 if (g_isIdle)
1110 wxapp_install_idle_handler();
ca298c88 1111
a2053b27
RR
1112 if (!win->m_hasVMT) return FALSE;
1113 if (g_blockEventsOnDrag) return FALSE;
47d67540 1114
a2053b27 1115 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
b292e2f5 1116
a2053b27
RR
1117 if (widget->window && win->GetCursor().Ok() )
1118 gdk_window_set_cursor( widget->window, win->GetCursor().GetCursor() );
47d67540 1119
e380f72b 1120 wxMouseEvent event( wxEVT_ENTER_WINDOW );
d1367c3d 1121 event.SetTimestamp( gdk_event->time );
e380f72b 1122 event.SetEventObject( win );
ff8bfdbb 1123
4a33eba6
RR
1124 int x = 0;
1125 int y = 0;
1126 GdkModifierType state = (GdkModifierType)0;
ff8bfdbb 1127
a2053b27 1128 gdk_window_get_pointer( widget->window, &x, &y, &state );
ff8bfdbb 1129
4a33eba6
RR
1130 event.m_shiftDown = (state & GDK_SHIFT_MASK);
1131 event.m_controlDown = (state & GDK_CONTROL_MASK);
1132 event.m_altDown = (state & GDK_MOD1_MASK);
1133 event.m_metaDown = (state & GDK_MOD2_MASK);
1134 event.m_leftDown = (state & GDK_BUTTON1_MASK);
1135 event.m_middleDown = (state & GDK_BUTTON2_MASK);
1136 event.m_rightDown = (state & GDK_BUTTON3_MASK);
1137
1138 event.m_x = (long)x;
1139 event.m_y = (long)y;
ff8bfdbb 1140
e380f72b 1141 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1142 {
e380f72b 1143 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "enter_notify_event" );
034be888
RR
1144 return TRUE;
1145 }
ca298c88 1146
034be888 1147 return FALSE;
b4071e91 1148}
47d67540 1149
b4071e91
RR
1150//-----------------------------------------------------------------------------
1151// "leave_notify_event"
1152//-----------------------------------------------------------------------------
1153
1154static gint gtk_window_leave_callback( GtkWidget *widget, GdkEventCrossing *gdk_event, wxWindow *win )
1155{
a2053b27
RR
1156 if (g_isIdle)
1157 wxapp_install_idle_handler();
acfd422a 1158
a2053b27
RR
1159 if (!win->m_hasVMT) return FALSE;
1160 if (g_blockEventsOnDrag) return FALSE;
b292e2f5 1161
a2053b27
RR
1162 if (!win->IsOwnGtkWindow( gdk_event->window )) return FALSE;
1163
1164 if (widget->window && win->GetCursor().Ok() )
1165 gdk_window_set_cursor( widget->window, wxSTANDARD_CURSOR->GetCursor() );
47d67540 1166
e380f72b 1167 wxMouseEvent event( wxEVT_LEAVE_WINDOW );
d1367c3d 1168 event.SetTimestamp( gdk_event->time );
e380f72b 1169 event.SetEventObject( win );
47d67540 1170
4a33eba6
RR
1171 int x = 0;
1172 int y = 0;
1173 GdkModifierType state = (GdkModifierType)0;
ff8bfdbb 1174
4a33eba6 1175 gdk_window_get_pointer( widget->window, &x, &y, &state );
ff8bfdbb 1176
4a33eba6
RR
1177 event.m_shiftDown = (state & GDK_SHIFT_MASK);
1178 event.m_controlDown = (state & GDK_CONTROL_MASK);
1179 event.m_altDown = (state & GDK_MOD1_MASK);
1180 event.m_metaDown = (state & GDK_MOD2_MASK);
1181 event.m_leftDown = (state & GDK_BUTTON1_MASK);
1182 event.m_middleDown = (state & GDK_BUTTON2_MASK);
1183 event.m_rightDown = (state & GDK_BUTTON3_MASK);
1184
1185 event.m_x = (long)x;
1186 event.m_y = (long)y;
ff8bfdbb 1187
e380f72b 1188 if (win->GetEventHandler()->ProcessEvent( event ))
034be888 1189 {
e380f72b 1190 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "leave_notify_event" );
034be888
RR
1191 return TRUE;
1192 }
ca298c88 1193
034be888 1194 return FALSE;
b4071e91 1195}
47d67540 1196
c801d85f 1197//-----------------------------------------------------------------------------
2f2aa628
RR
1198// "value_changed" from m_vAdjust
1199//-----------------------------------------------------------------------------
c801d85f 1200
2f2aa628 1201static void gtk_window_vscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
c801d85f 1202{
a2053b27
RR
1203 if (g_isIdle)
1204 wxapp_install_idle_handler();
c801d85f 1205
a2053b27 1206 if (g_blockEventsOnDrag) return;
47d67540 1207
a2053b27 1208 if (!win->m_hasVMT) return;
47d67540 1209
a2053b27 1210 float diff = win->m_vAdjust->value - win->m_oldVerticalPos;
e380f72b 1211 if (fabs(diff) < 0.2) return;
a2053b27 1212 win->m_oldVerticalPos = win->m_vAdjust->value;
47d67540 1213
e380f72b 1214 wxEventType command = wxEVT_NULL;
47d67540 1215
a2053b27
RR
1216 float line_step = win->m_vAdjust->step_increment;
1217 float page_step = win->m_vAdjust->page_increment;
47d67540 1218
f03fc89f 1219 if (win->IsScrolling())
76ed8f8d
RR
1220 {
1221 command = wxEVT_SCROLL_THUMBTRACK;
1222 }
1223 else
1224 {
a2053b27
RR
1225 if (fabs(win->m_vAdjust->value-win->m_vAdjust->lower) < 0.2) command = wxEVT_SCROLL_BOTTOM;
1226 else if (fabs(win->m_vAdjust->value-win->m_vAdjust->upper) < 0.2) command = wxEVT_SCROLL_TOP;
76ed8f8d
RR
1227 else if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLL_LINEDOWN;
1228 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLL_LINEUP;
1229 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLL_PAGEDOWN;
1230 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLL_PAGEUP;
1231 else command = wxEVT_SCROLL_THUMBTRACK;
1232 }
47d67540 1233
a2053b27 1234 int value = (int)(win->m_vAdjust->value+0.5);
c801d85f 1235
e380f72b
RR
1236 wxScrollEvent event( command, win->GetId(), value, wxVERTICAL );
1237 event.SetEventObject( win );
1238 win->GetEventHandler()->ProcessEvent( event );
362c6693 1239}
c801d85f
KB
1240
1241//-----------------------------------------------------------------------------
2f2aa628
RR
1242// "value_changed" from m_hAdjust
1243//-----------------------------------------------------------------------------
c801d85f 1244
2f2aa628 1245static void gtk_window_hscroll_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
47d67540 1246{
a2053b27
RR
1247 if (g_isIdle)
1248 wxapp_install_idle_handler();
47d67540 1249
a2053b27
RR
1250 if (g_blockEventsOnDrag) return;
1251 if (!win->m_hasVMT) return;
47d67540 1252
a2053b27 1253 float diff = win->m_hAdjust->value - win->m_oldHorizontalPos;
e380f72b 1254 if (fabs(diff) < 0.2) return;
a2053b27 1255 win->m_oldHorizontalPos = win->m_hAdjust->value;
47d67540 1256
e380f72b 1257 wxEventType command = wxEVT_NULL;
47d67540 1258
a2053b27
RR
1259 float line_step = win->m_hAdjust->step_increment;
1260 float page_step = win->m_hAdjust->page_increment;
8bbe427f 1261
f03fc89f 1262 if (win->IsScrolling())
76ed8f8d
RR
1263 {
1264 command = wxEVT_SCROLL_THUMBTRACK;
1265 }
1266 else
1267 {
a2053b27
RR
1268 if (fabs(win->m_hAdjust->value-win->m_hAdjust->lower) < 0.2) command = wxEVT_SCROLL_BOTTOM;
1269 else if (fabs(win->m_hAdjust->value-win->m_hAdjust->upper) < 0.2) command = wxEVT_SCROLL_TOP;
76ed8f8d
RR
1270 else if (fabs(diff-line_step) < 0.2) command = wxEVT_SCROLL_LINEDOWN;
1271 else if (fabs(diff+line_step) < 0.2) command = wxEVT_SCROLL_LINEUP;
1272 else if (fabs(diff-page_step) < 0.2) command = wxEVT_SCROLL_PAGEDOWN;
1273 else if (fabs(diff+page_step) < 0.2) command = wxEVT_SCROLL_PAGEUP;
1274 else command = wxEVT_SCROLL_THUMBTRACK;
1275 }
c801d85f 1276
a2053b27 1277 int value = (int)(win->m_hAdjust->value+0.5);
47d67540 1278
e380f72b
RR
1279 wxScrollEvent event( command, win->GetId(), value, wxHORIZONTAL );
1280 event.SetEventObject( win );
1281 win->GetEventHandler()->ProcessEvent( event );
362c6693 1282}
c801d85f
KB
1283
1284//-----------------------------------------------------------------------------
2f2aa628
RR
1285// "changed" from m_vAdjust
1286//-----------------------------------------------------------------------------
c801d85f 1287
2f2aa628 1288static void gtk_window_vscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
c801d85f 1289{
a2053b27
RR
1290 if (g_isIdle)
1291 wxapp_install_idle_handler();
c801d85f 1292
a2053b27
RR
1293 if (g_blockEventsOnDrag) return;
1294 if (!win->m_hasVMT) return;
47d67540 1295
e380f72b 1296 wxEventType command = wxEVT_SCROLL_THUMBTRACK;
a2053b27 1297 int value = (int)(win->m_vAdjust->value+0.5);
c801d85f 1298
e380f72b
RR
1299 wxScrollEvent event( command, win->GetId(), value, wxVERTICAL );
1300 event.SetEventObject( win );
1301 win->GetEventHandler()->ProcessEvent( event );
362c6693 1302}
c801d85f
KB
1303
1304//-----------------------------------------------------------------------------
2f2aa628
RR
1305// "changed" from m_hAdjust
1306//-----------------------------------------------------------------------------
c801d85f 1307
2f2aa628 1308static void gtk_window_hscroll_change_callback( GtkWidget *WXUNUSED(widget), wxWindow *win )
47d67540 1309{
a2053b27
RR
1310 if (g_isIdle)
1311 wxapp_install_idle_handler();
47d67540 1312
a2053b27
RR
1313 if (g_blockEventsOnDrag) return;
1314 if (!win->m_hasVMT) return;
47d67540 1315
e380f72b 1316 wxEventType command = wxEVT_SCROLL_THUMBTRACK;
a2053b27 1317 int value = (int)(win->m_hAdjust->value+0.5);
47d67540 1318
e380f72b
RR
1319 wxScrollEvent event( command, win->GetId(), value, wxHORIZONTAL );
1320 event.SetEventObject( win );
1321 win->GetEventHandler()->ProcessEvent( event );
362c6693 1322}
c801d85f 1323
cb43b372
RR
1324//-----------------------------------------------------------------------------
1325// "button_press_event" from scrollbar
1326//-----------------------------------------------------------------------------
1327
8bbe427f
VZ
1328static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
1329 GdkEventButton *WXUNUSED(gdk_event),
ff8bfdbb 1330 wxWindow *win )
cb43b372 1331{
a2053b27
RR
1332 if (g_isIdle)
1333 wxapp_install_idle_handler();
1334
1ecc4d80
RR
1335// don't test here as we can release the mouse while being over
1336// a different window then the slider
1337//
76ed8f8d 1338// if (gdk_event->window != widget->slider) return FALSE;
8bbe427f 1339
f03fc89f 1340 win->SetScrolling( TRUE );
47d67540 1341
e380f72b 1342 return FALSE;
cb43b372
RR
1343}
1344
1345//-----------------------------------------------------------------------------
1346// "button_release_event" from scrollbar
1347//-----------------------------------------------------------------------------
1348
8bbe427f
VZ
1349static gint gtk_scrollbar_button_release_callback( GtkRange *widget,
1350 GdkEventButton *WXUNUSED(gdk_event),
ff8bfdbb 1351 wxWindow *win )
cb43b372 1352{
76ed8f8d 1353
1ecc4d80 1354// don't test here as we can release the mouse while being over
76ed8f8d
RR
1355// a different window then the slider
1356//
1357// if (gdk_event->window != widget->slider) return FALSE;
cb43b372 1358
a2053b27 1359 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(win->m_widget);
47d67540 1360
f03fc89f 1361 if (widget == GTK_RANGE(scrolledWindow->vscrollbar))
a2053b27 1362 gtk_signal_emit_by_name( GTK_OBJECT(win->m_hAdjust), "value_changed" );
e380f72b 1363 else
a2053b27 1364 gtk_signal_emit_by_name( GTK_OBJECT(win->m_vAdjust), "value_changed" );
47d67540 1365
f03fc89f 1366 win->SetScrolling( FALSE );
47d67540 1367
e380f72b 1368 return FALSE;
cb43b372
RR
1369}
1370
f03fc89f
VZ
1371// ----------------------------------------------------------------------------
1372// this wxWindowBase function is implemented here (in platform-specific file)
1373// because it is static and so couldn't be made virtual
1374// ----------------------------------------------------------------------------
2b07d713 1375
f03fc89f 1376wxWindow *wxWindowBase::FindFocus()
2b07d713 1377{
f03fc89f 1378 return g_focusWindow;
2b07d713 1379}
ca298c88 1380
a2053b27
RR
1381//-----------------------------------------------------------------------------
1382// "realize" from m_widget
1383//-----------------------------------------------------------------------------
1384
1385/* we cannot set colours, fonts and cursors before the widget has
1386 been realized, so we do this directly after realization */
1387
1388static gint
a234a61a 1389gtk_window_realized_callback( GtkWidget * WXUNUSED(widget), wxWindow *win )
a2053b27
RR
1390{
1391 if (g_isIdle)
1392 wxapp_install_idle_handler();
1393
739730ca
RR
1394 if (win->m_delayedFont)
1395 win->SetFont( win->GetFont() );
a2053b27 1396
739730ca
RR
1397 if (win->m_delayedBackgroundColour)
1398 win->SetBackgroundColour( win->GetBackgroundColour() );
a2053b27 1399
739730ca
RR
1400 if (win->m_delayedForegroundColour)
1401 win->SetForegroundColour( win->GetForegroundColour() );
a2053b27 1402
739730ca 1403 win->SetCursor( win->GetCursor() );
a2053b27
RR
1404
1405 return FALSE;
1406}
1407
6ca41e57
RR
1408//-----------------------------------------------------------------------------
1409// InsertChild for wxWindow.
1410//-----------------------------------------------------------------------------
1411
b1170810
RR
1412/* Callback for wxWindow. This very strange beast has to be used because
1413 * C++ has no virtual methods in a constructor. We have to emulate a
1414 * virtual function here as wxNotebook requires a different way to insert
1415 * a child in it. I had opted for creating a wxNotebookPage window class
1416 * which would have made this superfluous (such in the MDI window system),
1417 * but no-one was listening to me... */
6ca41e57
RR
1418
1419static void wxInsertChildInWindow( wxWindow* parent, wxWindow* child )
1420{
a2053b27
RR
1421 gtk_myfixed_put( GTK_MYFIXED(parent->m_wxwindow),
1422 GTK_WIDGET(child->m_widget),
1423 child->m_x,
1424 child->m_y,
1425 child->m_width,
1426 child->m_height );
f03fc89f
VZ
1427
1428 if (parent->HasFlag(wxTAB_TRAVERSAL))
3e61c765
RR
1429 {
1430 /* we now allow a window to get the focus as long as it
ff8bfdbb 1431 doesn't have any children. */
a2053b27 1432 GTK_WIDGET_UNSET_FLAGS( parent->m_wxwindow, GTK_CAN_FOCUS );
3e61c765 1433 }
6ca41e57
RR
1434}
1435
bbe0af5b
RR
1436//-----------------------------------------------------------------------------
1437// global functions
1438//-----------------------------------------------------------------------------
1439
1440wxWindow* wxGetActiveWindow()
1441{
f03fc89f 1442 return g_focusWindow;
bbe0af5b
RR
1443}
1444
c801d85f 1445//-----------------------------------------------------------------------------
2f2aa628 1446// wxWindow
c801d85f
KB
1447//-----------------------------------------------------------------------------
1448
f03fc89f 1449IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
c801d85f 1450
f03fc89f 1451BEGIN_EVENT_TABLE(wxWindow, wxWindowBase)
b666df2c 1452 EVT_KEY_DOWN(wxWindow::OnKeyDown)
c801d85f
KB
1453END_EVENT_TABLE()
1454
68995f26 1455void wxWindow::Init()
c801d85f 1456{
f03fc89f
VZ
1457 // common init
1458 InitBase();
68995f26 1459
f03fc89f 1460 // GTK specific
a2053b27 1461 m_widget = (GtkWidget *) NULL;
e380f72b 1462 m_wxwindow = (GtkWidget *) NULL;
8bbe427f 1463
f03fc89f 1464 // position/size
a2053b27
RR
1465 m_x = 0;
1466 m_y = 0;
1467 m_width = 0;
e380f72b 1468 m_height = 0;
8bbe427f 1469
e380f72b
RR
1470 m_sizeSet = FALSE;
1471 m_hasVMT = FALSE;
1472 m_needParent = TRUE;
31c6b4fc 1473 m_isBeingDeleted = FALSE;
8bbe427f 1474
a2053b27 1475 m_hasScrolling = FALSE;
e380f72b 1476 m_isScrolling = FALSE;
f03fc89f 1477
a2053b27 1478 m_hAdjust = (GtkAdjustment*) NULL;
e380f72b 1479 m_vAdjust = (GtkAdjustment*) NULL;
a2053b27 1480 m_oldHorizontalPos = 0.0;
e380f72b 1481 m_oldVerticalPos = 0.0;
8bbe427f 1482
e380f72b
RR
1483 m_resizing = FALSE;
1484 m_scrollGC = (GdkGC*) NULL;
1485 m_widgetStyle = (GtkStyle*) NULL;
8bbe427f 1486
e380f72b 1487 m_insertCallback = wxInsertChildInWindow;
8bbe427f 1488
1ecc4d80 1489 m_isStaticBox = FALSE;
b292e2f5 1490 m_acceptsFocus = FALSE;
362c6693 1491}
c801d85f 1492
68995f26
VZ
1493wxWindow::wxWindow()
1494{
1495 Init();
1496}
1497
6ca41e57 1498wxWindow::wxWindow( wxWindow *parent, wxWindowID id,
e380f72b
RR
1499 const wxPoint &pos, const wxSize &size,
1500 long style, const wxString &name )
6ca41e57 1501{
68995f26
VZ
1502 Init();
1503
e380f72b 1504 Create( parent, id, pos, size, style, name );
6ca41e57 1505}
8bbe427f 1506
debe6624 1507bool wxWindow::Create( wxWindow *parent, wxWindowID id,
e380f72b
RR
1508 const wxPoint &pos, const wxSize &size,
1509 long style, const wxString &name )
c801d85f 1510{
e380f72b 1511 PreCreation( parent, id, pos, size, style, name );
47d67540 1512
e380f72b 1513 m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL );
38c7b3d3 1514 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
ff8bfdbb 1515
2e563988
RR
1516#ifdef __WXDEBUG__
1517 debug_focus_in( m_widget, _T("wxWindow::m_widget"), name );
1518#endif
1519
f03fc89f 1520 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget);
47d67540 1521
2e563988 1522#ifdef __WXDEBUG__
f03fc89f
VZ
1523 debug_focus_in( scrolledWindow->hscrollbar, _T("wxWindow::hsrcollbar"), name );
1524 debug_focus_in( scrolledWindow->vscrollbar, _T("wxWindow::vsrcollbar"), name );
2e563988
RR
1525#endif
1526
e380f72b
RR
1527 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
1528 scroll_class->scrollbar_spacing = 0;
47d67540 1529
f03fc89f 1530 gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
47d67540 1531
f03fc89f
VZ
1532 m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->hscrollbar) );
1533 m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->vscrollbar) );
47d67540 1534
38c7b3d3
RR
1535 m_wxwindow = gtk_myfixed_new();
1536
2e563988
RR
1537#ifdef __WXDEBUG__
1538 debug_focus_in( m_wxwindow, _T("wxWindow::m_wxwindow"), name );
1539#endif
1540
034be888 1541 gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow );
58dea4b0 1542
034be888
RR
1543#if (GTK_MINOR_VERSION > 0)
1544 GtkMyFixed *myfixed = GTK_MYFIXED(m_wxwindow);
b292e2f5 1545
f03fc89f 1546 if (HasFlag(wxRAISED_BORDER))
034be888
RR
1547 {
1548 gtk_myfixed_set_shadow_type( myfixed, GTK_SHADOW_OUT );
1549 }
f03fc89f 1550 else if (HasFlag(wxSUNKEN_BORDER))
034be888
RR
1551 {
1552 gtk_myfixed_set_shadow_type( myfixed, GTK_SHADOW_IN );
1553 }
1554 else
1555 {
1556 gtk_myfixed_set_shadow_type( myfixed, GTK_SHADOW_NONE );
1557 }
f03fc89f
VZ
1558#else // GTK_MINOR_VERSION == 0
1559 GtkViewport *viewport = GTK_VIEWPORT(scrolledWindow->viewport);
b292e2f5 1560
f03fc89f 1561 if (HasFlag(wxRAISED_BORDER))
e380f72b
RR
1562 {
1563 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_OUT );
1564 }
f03fc89f 1565 else if (HasFlag(wxSUNKEN_BORDER))
e380f72b
RR
1566 {
1567 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_IN );
1568 }
1569 else
1570 {
1571 gtk_viewport_set_shadow_type( viewport, GTK_SHADOW_NONE );
1572 }
f03fc89f 1573#endif // GTK_MINOR_VERSION
47d67540 1574
f03fc89f 1575 if (HasFlag(wxTAB_TRAVERSAL))
b292e2f5 1576 {
f03fc89f
VZ
1577 /* we now allow a window to get the focus as long as it
1578 doesn't have any children. */
ff8bfdbb 1579 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
b292e2f5
RR
1580 m_acceptsFocus = FALSE;
1581 }
e380f72b 1582 else
b292e2f5 1583 {
e380f72b 1584 GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
b292e2f5
RR
1585 m_acceptsFocus = TRUE;
1586 }
ca298c88 1587
034be888 1588#if (GTK_MINOR_VERSION == 0)
e380f72b
RR
1589 // shut the viewport up
1590 gtk_viewport_set_hadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1591 gtk_viewport_set_vadjustment( viewport, (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
f03fc89f 1592#endif // GTK_MINOR_VERSION == 0
e380f72b
RR
1593
1594 // I _really_ don't want scrollbars in the beginning
a2053b27
RR
1595 m_vAdjust->lower = 0.0;
1596 m_vAdjust->upper = 1.0;
1597 m_vAdjust->value = 0.0;
1598 m_vAdjust->step_increment = 1.0;
1599 m_vAdjust->page_increment = 1.0;
1600 m_vAdjust->page_size = 5.0;
1601 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
1602 m_hAdjust->lower = 0.0;
1603 m_hAdjust->upper = 1.0;
1604 m_hAdjust->value = 0.0;
1605 m_hAdjust->step_increment = 1.0;
1606 m_hAdjust->page_increment = 1.0;
1607 m_hAdjust->page_size = 5.0;
1608 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
f03fc89f
VZ
1609
1610 // these handlers block mouse events to any window during scrolling such as
1611 // motion events and prevent GTK and wxWindows from fighting over where the
1612 // slider should be
1613
1614 gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_press_event",
76ed8f8d
RR
1615 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1616
f03fc89f 1617 gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_press_event",
76ed8f8d
RR
1618 (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this );
1619
f03fc89f 1620 gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_release_event",
76ed8f8d
RR
1621 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
1622
f03fc89f 1623 gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_release_event",
76ed8f8d 1624 (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this );
8bbe427f 1625
034be888 1626 // these handlers get notified when screen updates are required either when
76ed8f8d
RR
1627 // scrolling or when the window size (and therefore scrollbar configuration)
1628 // has changed
1629
1630 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "value_changed",
1631 (GtkSignalFunc) gtk_window_hscroll_callback, (gpointer) this );
1632 gtk_signal_connect( GTK_OBJECT(m_vAdjust), "value_changed",
1633 (GtkSignalFunc) gtk_window_vscroll_callback, (gpointer) this );
1634
1635 gtk_signal_connect( GTK_OBJECT(m_hAdjust), "changed",
1636 (GtkSignalFunc) gtk_window_hscroll_change_callback, (gpointer) this );
1637 gtk_signal_connect(GTK_OBJECT(m_vAdjust), "changed",
1638 (GtkSignalFunc) gtk_window_vscroll_change_callback, (gpointer) this );
1639
f03fc89f 1640 gtk_widget_show( m_wxwindow );
47d67540 1641
f03fc89f
VZ
1642 if (m_parent)
1643 m_parent->DoAddChild( this );
8bbe427f 1644
e380f72b 1645 PostCreation();
8bbe427f 1646
e380f72b 1647 Show( TRUE );
c801d85f 1648
e380f72b 1649 return TRUE;
362c6693 1650}
c801d85f 1651
68dda785 1652wxWindow::~wxWindow()
c801d85f 1653{
31c6b4fc 1654 m_isBeingDeleted = TRUE;
43a18898 1655 m_hasVMT = FALSE;
47d67540 1656
f03fc89f
VZ
1657 if (m_widget)
1658 Show( FALSE );
8bbe427f 1659
a2053b27
RR
1660 DestroyChildren();
1661
f03fc89f
VZ
1662 if (m_parent)
1663 m_parent->RemoveChild( this );
c801d85f 1664
f03fc89f 1665 if (m_widgetStyle)
a2053b27 1666 {
f03fc89f 1667 gtk_style_unref( m_widgetStyle );
a2053b27
RR
1668 m_widgetStyle = (GtkStyle*) NULL;
1669 }
c801d85f 1670
f03fc89f 1671 if (m_scrollGC)
a2053b27 1672 {
f03fc89f 1673 gdk_gc_unref( m_scrollGC );
a2053b27
RR
1674 m_scrollGC = (GdkGC*) NULL;
1675 }
47d67540 1676
f03fc89f 1677 if (m_wxwindow)
a2053b27 1678 {
f03fc89f 1679 gtk_widget_destroy( m_wxwindow );
a2053b27
RR
1680 m_wxwindow = (GtkWidget*) NULL;
1681 }
8bbe427f 1682
f03fc89f 1683 if (m_widget)
a2053b27 1684 {
f03fc89f 1685 gtk_widget_destroy( m_widget );
a2053b27
RR
1686 m_widget = (GtkWidget*) NULL;
1687 }
362c6693 1688}
c801d85f 1689
f03fc89f
VZ
1690void wxWindow::PreCreation( wxWindow *parent,
1691 wxWindowID id,
1692 const wxPoint &pos,
1693 const wxSize &size,
1694 long style,
1695 const wxString &name )
c801d85f 1696{
f03fc89f 1697 wxASSERT_MSG( !m_needParent || parent, _T("Need complete parent.") );
8bbe427f 1698
f03fc89f
VZ
1699 if ( !CreateBase(parent, id, pos, size, style, name) )
1700 {
1701 wxFAIL_MSG(_T("window creation failed"));
1702 }
8bbe427f 1703
f03fc89f
VZ
1704 m_width = WidthDefault(size.x);
1705 m_height = HeightDefault(size.y);
8bbe427f 1706
43a18898
RR
1707 m_x = (int)pos.x;
1708 m_y = (int)pos.y;
8bbe427f 1709
f03fc89f 1710 if (!parent) /* some reasonable defaults */
6ca41e57 1711 {
43a18898
RR
1712 if (m_x == -1)
1713 {
1714 m_x = (gdk_screen_width () - m_width) / 2;
1715 if (m_x < 10) m_x = 10;
1716 }
1717 if (m_y == -1)
1718 {
1719 m_y = (gdk_screen_height () - m_height) / 2;
1720 if (m_y < 10) m_y = 10;
1721 }
6ca41e57 1722 }
c801d85f
KB
1723}
1724
68dda785 1725void wxWindow::PostCreation()
c801d85f 1726{
05939a81 1727 wxASSERT_MSG( (m_widget != NULL), _T("invalid window") );
ca298c88 1728
43a18898
RR
1729 if (m_wxwindow)
1730 {
034be888 1731 /* these get reported to wxWindows -> wxPaintEvent */
20239453
RR
1732 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "expose_event",
1733 GTK_SIGNAL_FUNC(gtk_window_expose_callback), (gpointer)this );
47d67540 1734
20239453
RR
1735 gtk_signal_connect( GTK_OBJECT(m_wxwindow), "draw",
1736 GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this );
ca298c88 1737
ef47f9b3 1738#if (GTK_MINOR_VERSION > 0)
f03fc89f 1739 /* these are called when the "sunken" or "raised" borders are drawn */
034be888
RR
1740 gtk_signal_connect( GTK_OBJECT(m_widget), "expose_event",
1741 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback), (gpointer)this );
1742
1743 gtk_signal_connect( GTK_OBJECT(m_widget), "draw",
1744 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback), (gpointer)this );
ef47f9b3 1745#endif
43a18898 1746 }
47d67540 1747
a2053b27 1748 GtkWidget *connect_widget = GetConnectWidget();
f03fc89f 1749
a2053b27 1750 ConnectWidget( connect_widget );
47d67540 1751
a2053b27
RR
1752 /* we cannot set colours, fonts and cursors before the widget has
1753 been realized, so we do this directly after realization */
1754 gtk_signal_connect( GTK_OBJECT(connect_widget), "realize",
1755 GTK_SIGNAL_FUNC(gtk_window_realized_callback), (gpointer) this );
ca298c88 1756
43a18898 1757 m_hasVMT = TRUE;
b4071e91
RR
1758}
1759
1760void wxWindow::ConnectWidget( GtkWidget *widget )
1761{
43a18898
RR
1762 gtk_signal_connect( GTK_OBJECT(widget), "key_press_event",
1763 GTK_SIGNAL_FUNC(gtk_window_key_press_callback), (gpointer)this );
c801d85f 1764
b666df2c
RR
1765 gtk_signal_connect( GTK_OBJECT(widget), "key_release_event",
1766 GTK_SIGNAL_FUNC(gtk_window_key_release_callback), (gpointer)this );
1767
43a18898
RR
1768 gtk_signal_connect( GTK_OBJECT(widget), "button_press_event",
1769 GTK_SIGNAL_FUNC(gtk_window_button_press_callback), (gpointer)this );
47d67540 1770
43a18898
RR
1771 gtk_signal_connect( GTK_OBJECT(widget), "button_release_event",
1772 GTK_SIGNAL_FUNC(gtk_window_button_release_callback), (gpointer)this );
47d67540 1773
43a18898
RR
1774 gtk_signal_connect( GTK_OBJECT(widget), "motion_notify_event",
1775 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback), (gpointer)this );
47d67540 1776
43a18898
RR
1777 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
1778 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback), (gpointer)this );
c801d85f 1779
43a18898
RR
1780 gtk_signal_connect( GTK_OBJECT(widget), "focus_out_event",
1781 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback), (gpointer)this );
c801d85f 1782
43a18898
RR
1783 gtk_signal_connect( GTK_OBJECT(widget), "enter_notify_event",
1784 GTK_SIGNAL_FUNC(gtk_window_enter_callback), (gpointer)this );
47d67540 1785
43a18898
RR
1786 gtk_signal_connect( GTK_OBJECT(widget), "leave_notify_event",
1787 GTK_SIGNAL_FUNC(gtk_window_leave_callback), (gpointer)this );
362c6693 1788}
c801d85f 1789
68dda785 1790bool wxWindow::Destroy()
c801d85f 1791{
05939a81 1792 wxASSERT_MSG( (m_widget != NULL), _T("invalid window") );
47d67540 1793
43a18898 1794 m_hasVMT = FALSE;
c801d85f 1795
f03fc89f 1796 return wxWindowBase::Destroy();
362c6693 1797}
c801d85f 1798
bfc6fde4 1799void wxWindow::DoSetSize( int x, int y, int width, int height, int sizeFlags )
c801d85f 1800{
05939a81
OK
1801 wxASSERT_MSG( (m_widget != NULL), _T("invalid window") );
1802 wxASSERT_MSG( (m_parent != NULL), _T("wxWindow::SetSize requires parent.\n") );
8bbe427f 1803
e27ce4e9 1804 if (m_resizing) return; /* I don't like recursions */
fb1585ae 1805 m_resizing = TRUE;
47d67540 1806
a2053b27 1807 if (m_parent->m_wxwindow == NULL) /* i.e. wxNotebook */
fb1585ae 1808 {
e27ce4e9 1809 /* don't set the size for children of wxNotebook, just take the values. */
fb1585ae
RR
1810 m_x = x;
1811 m_y = y;
1812 m_width = width;
ba4e3652 1813 m_height = height;
fb1585ae 1814 }
ba4e3652 1815 else
fb1585ae 1816 {
ba4e3652
RR
1817 if ((sizeFlags & wxSIZE_USE_EXISTING) == wxSIZE_USE_EXISTING)
1818 {
1819 if (x != -1) m_x = x;
1820 if (y != -1) m_y = y;
1821 if (width != -1) m_width = width;
1822 if (height != -1) m_height = height;
1823 }
1824 else
1825 {
1826 m_x = x;
1827 m_y = y;
1828 m_width = width;
1829 m_height = height;
1830 }
47d67540 1831
ba4e3652
RR
1832 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
1833 {
1834 if (width == -1) m_width = 80;
1835 }
1836
1837 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
1838 {
1839 if (height == -1) m_height = 26;
1840 }
8bbe427f 1841
ba4e3652
RR
1842 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
1843 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
d3b4d113
RR
1844 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
1845 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
47d67540 1846
a2053b27 1847 int border = 0;
f03fc89f 1848
a2053b27
RR
1849 if (GTK_WIDGET_HAS_DEFAULT(m_widget))
1850 {
1851 /* the default button has a border around it */
1852 border = 5;
1853 }
1854
1855 /* this is the result of hours of debugging: the following code
1856 means that if we have a m_wxwindow and we set the size of
1857 m_widget, m_widget (which is a GtkScrolledWindow) does NOT
1858 automatically propagate its size down to its m_wxwindow,
1859 which is its client area. therefore, we have to tell the
1860 client area directly that it has to resize itself.
1861 this will lead to that m_widget (GtkScrolledWindow) will
1862 calculate how much size it needs for scrollbars etc and
1863 it will then call XXX_size_allocate of its child, which
1864 is m_wxwindow. m_wxwindow in turn will do the same with its
1865 children and so on. problems can arise if this happens
1866 before all the children have been realized as some widgets
1867 stupidy need to be realized during XXX_size_allocate (e.g.
1868 GtkNotebook) and they will segv if called otherwise. this
1869 emergency is tested in gtk_myfixed_size_allocate. Normally
1870 this shouldn't be needed and only gtk_widget_queue_resize()
1871 should be enough to provoke a resize at the next appropriate
1872 moment, but this seems to fail, e.g. when a wxNotebook contains
1873 a wxSplitterWindow: the splitter window's children won't
1874 show up properly resized then. */
1875
1876 gtk_myfixed_set_size( GTK_MYFIXED(m_parent->m_wxwindow),
1877 m_widget,
1878 m_x-border,
1879 m_y-border,
1880 m_width+2*border,
1881 m_height+2*border );
ba4e3652 1882 }
8bbe427f 1883
fb1585ae 1884 m_sizeSet = TRUE;
47d67540 1885
fb1585ae
RR
1886 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
1887 event.SetEventObject( this );
ba4e3652 1888 GetEventHandler()->ProcessEvent( event );
47d67540 1889
fb1585ae 1890 m_resizing = FALSE;
362c6693 1891}
c801d85f 1892
9390a202
RR
1893void wxWindow::OnInternalIdle()
1894{
1895 UpdateWindowUI();
1896}
1897
f03fc89f 1898void wxWindow::DoGetSize( int *width, int *height ) const
c801d85f 1899{
05939a81 1900 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 1901
fb1585ae
RR
1902 if (width) (*width) = m_width;
1903 if (height) (*height) = m_height;
362c6693 1904}
c801d85f 1905
bfc6fde4 1906void wxWindow::DoSetClientSize( int width, int height )
c801d85f 1907{
05939a81 1908 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 1909
1ecc4d80 1910 if (!m_wxwindow)
c801d85f 1911 {
1ecc4d80 1912 SetSize( width, height );
c801d85f
KB
1913 }
1914 else
1915 {
1ecc4d80
RR
1916 int dw = 0;
1917 int dh = 0;
1918
1919 if (!m_hasScrolling)
1920 {
1921 GtkStyleClass *window_class = m_wxwindow->style->klass;
1922
f03fc89f 1923 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
1ecc4d80
RR
1924 {
1925 dw += 2 * window_class->xthickness;
1926 dh += 2 * window_class->ythickness;
1927 }
1928 }
1929 else
1930 {
1931 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1932 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
47d67540 1933
034be888 1934#if (GTK_MINOR_VERSION == 0)
1ecc4d80 1935 GtkWidget *viewport = scroll_window->viewport;
1ecc4d80
RR
1936 GtkStyleClass *viewport_class = viewport->style->klass;
1937
f03fc89f 1938 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
1ecc4d80
RR
1939 {
1940 dw += 2 * viewport_class->xthickness;
1941 dh += 2 * viewport_class->ythickness;
1942 }
034be888
RR
1943#endif
1944
1945/*
1946 GtkWidget *hscrollbar = scroll_window->hscrollbar;
1947 GtkWidget *vscrollbar = scroll_window->vscrollbar;
ca298c88 1948
f03fc89f 1949 we use this instead: range.slider_width = 11 + 2*2pts edge
034be888 1950*/
47d67540 1951
1ecc4d80
RR
1952 if (scroll_window->vscrollbar_visible)
1953 {
034be888 1954 dw += 15; /* dw += vscrollbar->allocation.width; */
1ecc4d80
RR
1955 dw += scroll_class->scrollbar_spacing;
1956 }
1957
1958 if (scroll_window->hscrollbar_visible)
1959 {
034be888 1960 dh += 15; /* dh += hscrollbar->allocation.height; */
1ecc4d80
RR
1961 dw += scroll_class->scrollbar_spacing;
1962 }
1963 }
1964
034be888 1965 SetSize( width+dw, height+dh );
1ecc4d80 1966 }
362c6693 1967}
c801d85f 1968
f03fc89f 1969void wxWindow::DoGetClientSize( int *width, int *height ) const
c801d85f 1970{
05939a81 1971 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 1972
1ecc4d80
RR
1973 if (!m_wxwindow)
1974 {
1975 if (width) (*width) = m_width;
1976 if (height) (*height) = m_height;
c801d85f
KB
1977 }
1978 else
1979 {
1ecc4d80
RR
1980 int dw = 0;
1981 int dh = 0;
1982
1983 if (!m_hasScrolling)
1984 {
1985 GtkStyleClass *window_class = m_wxwindow->style->klass;
1986
f03fc89f 1987 if (HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER))
1ecc4d80
RR
1988 {
1989 dw += 2 * window_class->xthickness;
1990 dh += 2 * window_class->ythickness;
1991 }
1992 }
1993 else
1994 {
1995 GtkScrolledWindow *scroll_window = GTK_SCROLLED_WINDOW(m_widget);
1996 GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget)->klass );
47d67540 1997
034be888 1998#if (GTK_MINOR_VERSION == 0)
1ecc4d80 1999 GtkWidget *viewport = scroll_window->viewport;
1ecc4d80
RR
2000 GtkStyleClass *viewport_class = viewport->style->klass;
2001
f03fc89f 2002 if ( HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER) )
1ecc4d80
RR
2003 {
2004 dw += 2 * viewport_class->xthickness;
2005 dh += 2 * viewport_class->ythickness;
2006 }
034be888
RR
2007#endif
2008/*
2009 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2010 GtkWidget *vscrollbar = scroll_window->vscrollbar;
ca298c88 2011
f03fc89f 2012 we use this instead: range.slider_width = 11 + 2*2pts edge
034be888 2013*/
1ecc4d80
RR
2014
2015 if (scroll_window->vscrollbar_visible)
2016 {
034be888 2017 dw += 15; /* dw += vscrollbar->allocation.width; */
1ecc4d80
RR
2018 dw += scroll_class->scrollbar_spacing;
2019 }
2020
2021 if (scroll_window->hscrollbar_visible)
2022 {
034be888 2023 dh += 15; /* dh += hscrollbar->allocation.height; */
1ecc4d80
RR
2024 dh += scroll_class->scrollbar_spacing;
2025 }
2026 }
47d67540 2027
1ecc4d80
RR
2028 if (width) (*width) = m_width - dw;
2029 if (height) (*height) = m_height - dh;
2030 }
362c6693 2031}
c801d85f 2032
f03fc89f 2033void wxWindow::DoGetPosition( int *x, int *y ) const
c801d85f 2034{
05939a81 2035 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2036
43a18898
RR
2037 if (x) (*x) = m_x;
2038 if (y) (*y) = m_y;
362c6693 2039}
c801d85f 2040
f03fc89f 2041void wxWindow::ClientToScreen( int *x, int *y ) const
c801d85f 2042{
05939a81 2043 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2044
a2053b27
RR
2045 if (!m_widget->window) return;
2046
43a18898
RR
2047 GdkWindow *source = (GdkWindow *) NULL;
2048 if (m_wxwindow)
2049 source = m_wxwindow->window;
2050 else
2051 source = m_widget->window;
47d67540 2052
43a18898
RR
2053 int org_x = 0;
2054 int org_y = 0;
2055 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2056
43a18898 2057 if (!m_wxwindow)
c801d85f 2058 {
43a18898
RR
2059 if (GTK_WIDGET_NO_WINDOW (m_widget))
2060 {
2061 org_x += m_widget->allocation.x;
2062 org_y += m_widget->allocation.y;
2063 }
362c6693 2064 }
47d67540 2065
43a18898
RR
2066 if (x) *x += org_x;
2067 if (y) *y += org_y;
362c6693 2068}
c801d85f 2069
f03fc89f 2070void wxWindow::ScreenToClient( int *x, int *y ) const
c801d85f 2071{
05939a81 2072 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2073
a2053b27
RR
2074 if (!m_widget->window) return;
2075
1ecc4d80
RR
2076 GdkWindow *source = (GdkWindow *) NULL;
2077 if (m_wxwindow)
2078 source = m_wxwindow->window;
2079 else
2080 source = m_widget->window;
47d67540 2081
1ecc4d80
RR
2082 int org_x = 0;
2083 int org_y = 0;
2084 gdk_window_get_origin( source, &org_x, &org_y );
c801d85f 2085
1ecc4d80 2086 if (!m_wxwindow)
c801d85f 2087 {
1ecc4d80
RR
2088 if (GTK_WIDGET_NO_WINDOW (m_widget))
2089 {
2090 org_x += m_widget->allocation.x;
2091 org_y += m_widget->allocation.y;
2092 }
362c6693 2093 }
47d67540 2094
1ecc4d80
RR
2095 if (x) *x -= org_x;
2096 if (y) *y -= org_y;
362c6693 2097}
c801d85f 2098
f03fc89f 2099bool wxWindow::Show( bool show )
c801d85f 2100{
f03fc89f 2101 wxCHECK_MSG( (m_widget != NULL), FALSE, _T("invalid window") );
47d67540 2102
739730ca
RR
2103 if (!wxWindowBase::Show(show))
2104 {
2105 // nothing to do
f03fc89f 2106 return FALSE;
739730ca 2107 }
8bbe427f 2108
f03fc89f
VZ
2109 if (show)
2110 gtk_widget_show( m_widget );
1ecc4d80 2111 else
f03fc89f 2112 gtk_widget_hide( m_widget );
8bbe427f 2113
f03fc89f 2114 return TRUE;
362c6693 2115}
c801d85f 2116
f03fc89f 2117bool wxWindow::Enable( bool enable )
c801d85f 2118{
f03fc89f 2119 wxCHECK_MSG( (m_widget != NULL), FALSE, _T("invalid window") );
5e0aa05a 2120
739730ca
RR
2121 if (!wxWindowBase::Enable(enable))
2122 {
2123 // nothing to do
f03fc89f 2124 return FALSE;
739730ca 2125 }
1ecc4d80 2126
f03fc89f
VZ
2127 gtk_widget_set_sensitive( m_widget, enable );
2128 if ( m_wxwindow )
2129 gtk_widget_set_sensitive( m_wxwindow, enable );
ff8bfdbb 2130
f03fc89f 2131 return TRUE;
362c6693 2132}
c801d85f 2133
f03fc89f 2134int wxWindow::GetCharHeight() const
2f2aa628 2135{
f03fc89f 2136 wxCHECK_MSG( (m_widget != NULL), 12, _T("invalid window") );
47d67540 2137
f03fc89f 2138 wxCHECK_MSG( m_font.Ok(), 12, _T("invalid font") );
2f2aa628 2139
f03fc89f
VZ
2140 GdkFont *font = m_font.GetInternalFont( 1.0 );
2141
2142 return font->ascent + font->descent;
362c6693 2143}
c801d85f 2144
f03fc89f 2145int wxWindow::GetCharWidth() const
c33c4050 2146{
05939a81 2147 wxCHECK_MSG( (m_widget != NULL), 8, _T("invalid window") );
47d67540 2148
05939a81 2149 wxCHECK_MSG( m_font.Ok(), 8, _T("invalid font") );
47d67540 2150
463c1fa1 2151 GdkFont *font = m_font.GetInternalFont( 1.0 );
ff8bfdbb 2152
463c1fa1 2153 return gdk_string_width( font, "H" );
c33c4050
RR
2154}
2155
f03fc89f
VZ
2156void wxWindow::GetTextExtent( const wxString& string,
2157 int *x,
2158 int *y,
2159 int *descent,
2160 int *externalLeading,
2161 const wxFont *theFont ) const
c33c4050 2162{
463c1fa1
RR
2163 wxFont fontToUse = m_font;
2164 if (theFont) fontToUse = *theFont;
47d67540 2165
05939a81 2166 wxCHECK_RET( fontToUse.Ok(), _T("invalid font") );
47d67540 2167
463c1fa1 2168 GdkFont *font = fontToUse.GetInternalFont( 1.0 );
05939a81 2169 if (x) (*x) = gdk_string_width( font, string.mbc_str() );
463c1fa1
RR
2170 if (y) (*y) = font->ascent + font->descent;
2171 if (descent) (*descent) = font->descent;
2172 if (externalLeading) (*externalLeading) = 0; // ??
c33c4050
RR
2173}
2174
b666df2c
RR
2175void wxWindow::OnKeyDown( wxKeyEvent &event )
2176{
2177 event.SetEventType( wxEVT_CHAR );
ff8bfdbb 2178
b666df2c
RR
2179 if (!GetEventHandler()->ProcessEvent( event ))
2180 {
2181 event.Skip();
2182 }
2183}
2184
68dda785 2185void wxWindow::SetFocus()
c801d85f 2186{
05939a81 2187 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
ff8bfdbb 2188
463c1fa1
RR
2189 GtkWidget *connect_widget = GetConnectWidget();
2190 if (connect_widget)
c801d85f 2191 {
b292e2f5 2192 if (GTK_WIDGET_CAN_FOCUS(connect_widget) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
463c1fa1
RR
2193 {
2194 gtk_widget_grab_focus (connect_widget);
2195 }
ff8bfdbb
VZ
2196 else if (GTK_IS_CONTAINER(connect_widget))
2197 {
2198 gtk_container_focus( GTK_CONTAINER(connect_widget), GTK_DIR_TAB_FORWARD );
2199 }
2200 else
2201 {
2202 }
362c6693 2203 }
362c6693 2204}
c801d85f 2205
b292e2f5
RR
2206bool wxWindow::AcceptsFocus() const
2207{
f03fc89f 2208 return m_acceptsFocus && wxWindowBase::AcceptsFocus();
b292e2f5
RR
2209}
2210
f03fc89f 2211bool wxWindow::Reparent( wxWindow *newParent )
463c1fa1 2212{
05939a81 2213 wxCHECK_MSG( (m_widget != NULL), (wxWindow*) NULL, _T("invalid window") );
ff8bfdbb 2214
a2053b27
RR
2215 gtk_widget_unparent( m_widget );
2216
f03fc89f
VZ
2217 if ( !wxWindowBase::Reparent(newParent) )
2218 return FALSE;
8bbe427f 2219
f03fc89f 2220 return TRUE;
362c6693 2221}
c801d85f 2222
68dda785 2223void wxWindow::Raise()
362c6693 2224{
05939a81 2225 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2226
a2053b27
RR
2227 if (!m_widget->window) return;
2228
f03fc89f 2229 gdk_window_raise( m_widget->window );
362c6693
RR
2230}
2231
68dda785 2232void wxWindow::Lower()
362c6693 2233{
05939a81 2234 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2235
a2053b27
RR
2236 if (!m_widget->window) return;
2237
f03fc89f 2238 gdk_window_lower( m_widget->window );
362c6693 2239}
c801d85f 2240
f03fc89f 2241bool wxWindow::SetCursor( const wxCursor &cursor )
86b29a61 2242{
f03fc89f 2243 wxCHECK_MSG( (m_widget != NULL), FALSE, _T("invalid window") );
86b29a61 2244
739730ca 2245 if (!wxWindowBase::SetCursor(cursor))
e55ad60e 2246 {
739730ca
RR
2247 // don't leave if the GTK widget has just
2248 // been realized
2249 if (!m_delayedCursor) return FALSE;
2250 }
2251
2252 GtkWidget *connect_widget = GetConnectWidget();
2253 if (!connect_widget->window)
2254 {
2255 // indicate that a new style has been set
2256 // but it couldn't get applied as the
2257 // widget hasn't been realized yet.
2258 m_delayedCursor = TRUE;
2259
2260 // pretend we have done something
2261 return TRUE;
2262 }
a2053b27 2263
f03fc89f
VZ
2264 if ((m_widget) && (m_widget->window))
2265 gdk_window_set_cursor( m_widget->window, GetCursor().GetCursor() );
fd0eed64 2266
f03fc89f
VZ
2267 if ((m_wxwindow) && (m_wxwindow->window))
2268 gdk_window_set_cursor( m_wxwindow->window, GetCursor().GetCursor() );
fd0eed64 2269
739730ca
RR
2270 // cursor was set
2271 return TRUE;
362c6693 2272}
c801d85f 2273
4f22cf8d
RR
2274void wxWindow::WarpPointer( int WXUNUSED(x), int WXUNUSED(y) )
2275{
f03fc89f 2276 // TODO
4f22cf8d
RR
2277}
2278
debe6624 2279void wxWindow::Refresh( bool eraseBackground, const wxRect *rect )
c801d85f 2280{
05939a81 2281 wxCHECK_RET( (m_widget != NULL), _T("invalid window") );
47d67540 2282
a2053b27
RR
2283 if (!m_widget->window) return;
2284
139adb6a 2285 if (eraseBackground && m_wxwindow && m_wxwindow->window)
c801d85f 2286 {
139adb6a
RR
2287 if (rect)
2288 {
2289 gdk_window_clear_area( m_wxwindow->window,
2290 rect->x, rect->y,
f234c60c 2291 rect->width, rect->height );
139adb6a
RR
2292 }
2293 else
2294 {
f234c60c 2295 gdk_window_clear( m_wxwindow->window );
139adb6a
RR
2296 }
2297 }
ff8bfdbb 2298
139adb6a
RR
2299 if (!rect)
2300 {
2301 if (m_wxwindow)
2302 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
ff8bfdbb 2303 else
139adb6a 2304 gtk_widget_draw( m_widget, (GdkRectangle*) NULL );
362c6693 2305 }
c801d85f 2306 else
139adb6a
RR
2307 {
2308 GdkRectangle gdk_rect;
2309 gdk_rect.x = rect->x;
2310 gdk_rect.y = rect->y;
2311 gdk_rect.width = rect->width;
2312 gdk_rect.height = rect->height;
2313
2314 if (m_wxwindow)
2315 gtk_widget_draw( m_wxwindow, &gdk_rect );
2316 else
2317 gtk_widget_draw( m_widget, &gdk_rect );
2318 }
362c6693 2319}
c801d85f 2320
68dda785 2321void wxWindow::Clear()
c801d85f 2322{
05939a81 2323 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
47d67540 2324
a2053b27
RR
2325 if (!m_widget->window) return;
2326
f234c60c
RR
2327 if (m_wxwindow && m_wxwindow->window)
2328 {
2329 gdk_window_clear( m_wxwindow->window );
2330 }
362c6693 2331}
c801d85f 2332
ff8bfdbb 2333#if wxUSE_TOOLTIPS
f03fc89f 2334void wxWindow::DoSetToolTip( wxToolTip *tip )
b1170810 2335{
f03fc89f 2336 wxWindowBase::DoSetToolTip(tip);
ff8bfdbb 2337
f03fc89f
VZ
2338 if (m_tooltip)
2339 m_tooltip->Apply( this );
b1170810
RR
2340}
2341
05939a81 2342void wxWindow::ApplyToolTip( GtkTooltips *tips, const wxChar *tip )
b1170810 2343{
05939a81 2344 gtk_tooltips_set_tip( tips, GetConnectWidget(), wxConv_current->cWX2MB(tip), (gchar*) NULL );
301cd871 2345}
ff8bfdbb 2346#endif // wxUSE_TOOLTIPS
b1170810 2347
f03fc89f 2348bool wxWindow::SetBackgroundColour( const wxColour &colour )
c801d85f 2349{
f03fc89f 2350 wxCHECK_MSG( m_widget != NULL, FALSE, _T("invalid window") );
8bbe427f 2351
739730ca
RR
2352 if (!wxWindowBase::SetBackgroundColour(colour))
2353 {
2354 // don't leave if the GTK widget has just
2355 // been realized
2356 if (!m_delayedBackgroundColour) return FALSE;
2357 }
2358
a2053b27 2359 GtkWidget *connect_widget = GetConnectWidget();
739730ca
RR
2360 if (!connect_widget->window)
2361 {
2362 // indicate that a new style has been set
2363 // but it couldn't get applied as the
2364 // widget hasn't been realized yet.
2365 m_delayedBackgroundColour = TRUE;
2366
2367 // pretend we have done something
2368 return TRUE;
2369 }
ca298c88 2370
f234c60c 2371 if (m_wxwindow && m_wxwindow->window)
3bc755fc 2372 {
a2053b27
RR
2373 /* wxMSW doesn't clear the window here. I don't do that either to
2374 provide compatibility. call Clear() to do the job. */
ca298c88 2375
f234c60c
RR
2376 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_wxwindow->window ) );
2377 gdk_window_set_background( m_wxwindow->window, m_backgroundColour.GetColor() );
3bc755fc 2378 }
8bbe427f 2379
ae0bdb01 2380 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
ca298c88 2381
121a3581 2382 if (sysbg == m_backgroundColour)
ae0bdb01
RR
2383 {
2384 m_backgroundColour = wxNullColour;
2385 ApplyWidgetStyle();
ff8bfdbb
VZ
2386 m_backgroundColour = sysbg;
2387 }
ae0bdb01
RR
2388 else
2389 {
2390 ApplyWidgetStyle();
2391 }
c801d85f 2392
f03fc89f 2393 return TRUE;
6de97a3b
RR
2394}
2395
f03fc89f 2396bool wxWindow::SetForegroundColour( const wxColour &colour )
6de97a3b 2397{
f03fc89f 2398 wxCHECK_MSG( m_widget != NULL, FALSE, _T("invalid window") );
8bbe427f 2399
739730ca
RR
2400 if (!wxWindowBase::SetForegroundColour(colour))
2401 {
2402 // don't leave if the GTK widget has just
2403 // been realized
2404 if (!m_delayedForegroundColour) return FALSE;
2405 }
2406
a2053b27 2407 GtkWidget *connect_widget = GetConnectWidget();
739730ca
RR
2408 if (!connect_widget->window)
2409 {
2410 // indicate that a new style has been set
2411 // but it couldn't get applied as the
2412 // widget hasn't been realized yet.
2413 m_delayedForegroundColour = TRUE;
2414
2415 // pretend we have done something
2416 return TRUE;
2417 }
2b07d713 2418
ae0bdb01 2419 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
121a3581 2420 if (sysbg == m_foregroundColour)
ae0bdb01
RR
2421 {
2422 m_backgroundColour = wxNullColour;
2423 ApplyWidgetStyle();
ff8bfdbb
VZ
2424 m_backgroundColour = sysbg;
2425 }
ae0bdb01
RR
2426 else
2427 {
2428 ApplyWidgetStyle();
2429 }
f03fc89f
VZ
2430
2431 return TRUE;
58614078
RR
2432}
2433
2434GtkStyle *wxWindow::GetWidgetStyle()
2435{
1ecc4d80 2436 if (m_widgetStyle) gtk_style_unref( m_widgetStyle );
8bbe427f 2437
f03fc89f 2438 m_widgetStyle = gtk_style_copy( gtk_widget_get_style( m_widget ) );
8bbe427f 2439
1ecc4d80 2440 return m_widgetStyle;
58614078
RR
2441}
2442
2443void wxWindow::SetWidgetStyle()
2444{
1ecc4d80
RR
2445 GtkStyle *style = GetWidgetStyle();
2446
2447 gdk_font_unref( style->font );
2448 style->font = gdk_font_ref( m_font.GetInternalFont( 1.0 ) );
2449
2450 if (m_foregroundColour.Ok())
2451 {
2452 m_foregroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2453 style->fg[GTK_STATE_NORMAL] = *m_foregroundColour.GetColor();
2454 style->fg[GTK_STATE_PRELIGHT] = *m_foregroundColour.GetColor();
2455 style->fg[GTK_STATE_ACTIVE] = *m_foregroundColour.GetColor();
2456 }
2457
2458 if (m_backgroundColour.Ok())
2459 {
2460 m_backgroundColour.CalcPixel( gdk_window_get_colormap( m_widget->window ) );
2461 style->bg[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2462 style->base[GTK_STATE_NORMAL] = *m_backgroundColour.GetColor();
2463 style->bg[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2464 style->base[GTK_STATE_PRELIGHT] = *m_backgroundColour.GetColor();
2465 style->bg[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2466 style->base[GTK_STATE_ACTIVE] = *m_backgroundColour.GetColor();
2467 style->bg[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2468 style->base[GTK_STATE_INSENSITIVE] = *m_backgroundColour.GetColor();
2469 }
a81258be
RR
2470}
2471
58614078 2472void wxWindow::ApplyWidgetStyle()
a81258be 2473{
6de97a3b
RR
2474}
2475
30dea054
RR
2476static void SetInvokingWindow( wxMenu *menu, wxWindow *win )
2477{
1ecc4d80 2478 menu->SetInvokingWindow( win );
c626a8b7 2479 wxNode *node = menu->GetItems().First();
1ecc4d80
RR
2480 while (node)
2481 {
2482 wxMenuItem *menuitem = (wxMenuItem*)node->Data();
2483 if (menuitem->IsSubMenu())
2484 {
ff8bfdbb
VZ
2485 SetInvokingWindow( menuitem->GetSubMenu(), win );
2486 }
1ecc4d80
RR
2487 node = node->Next();
2488 }
362c6693 2489}
30dea054 2490
0c77152e
RR
2491static gint gs_pop_x = 0;
2492static gint gs_pop_y = 0;
2493
a234a61a
VZ
2494static void pop_pos_callback( GtkMenu * WXUNUSED(menu),
2495 gint *x, gint *y,
2496 wxWindow *win )
0c77152e
RR
2497{
2498 win->ClientToScreen( &gs_pop_x, &gs_pop_y );
2499 *x = gs_pop_x;
2500 *y = gs_pop_y;
2501}
2502
2503bool wxWindow::PopupMenu( wxMenu *menu, int x, int y )
30dea054 2504{
05939a81 2505 wxCHECK_MSG( m_widget != NULL, FALSE, _T("invalid window") );
47d67540 2506
05939a81 2507 wxCHECK_MSG( menu != NULL, FALSE, _T("invalid popup-menu") );
8bbe427f 2508
1ecc4d80 2509 SetInvokingWindow( menu, this );
ff8bfdbb 2510
631f1bfe
JS
2511 menu->UpdateUI();
2512
0c77152e
RR
2513 gs_pop_x = x;
2514 gs_pop_y = y;
ff8bfdbb 2515
1ecc4d80 2516 gtk_menu_popup(
47d67540 2517 GTK_MENU(menu->m_menu),
0c77152e
RR
2518 (GtkWidget *) NULL, // parent menu shell
2519 (GtkWidget *) NULL, // parent menu item
2520 (GtkMenuPositionFunc) pop_pos_callback,
2521 (gpointer) this, // client data
2522 0, // button used to activate it
2523 0 //gs_timeLastClick // the time of activation
47d67540 2524 );
1ecc4d80 2525 return TRUE;
30dea054
RR
2526}
2527
06cfab17 2528#if wxUSE_DRAG_AND_DROP
ac57418f 2529
c801d85f
KB
2530void wxWindow::SetDropTarget( wxDropTarget *dropTarget )
2531{
05939a81 2532 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
47d67540 2533
1ecc4d80 2534 GtkWidget *dnd_widget = GetConnectWidget();
47d67540 2535
1ecc4d80 2536 if (m_dropTarget) m_dropTarget->UnregisterWidget( dnd_widget );
47d67540 2537
1ecc4d80
RR
2538 if (m_dropTarget) delete m_dropTarget;
2539 m_dropTarget = dropTarget;
47d67540 2540
1ecc4d80 2541 if (m_dropTarget) m_dropTarget->RegisterWidget( dnd_widget );
362c6693 2542}
c801d85f 2543
f03fc89f 2544#endif // wxUSE_DRAG_AND_DROP
ac57418f 2545
68dda785 2546GtkWidget* wxWindow::GetConnectWidget()
e3e65dac 2547{
1ecc4d80
RR
2548 GtkWidget *connect_widget = m_widget;
2549 if (m_wxwindow) connect_widget = m_wxwindow;
47d67540 2550
1ecc4d80 2551 return connect_widget;
e3e65dac 2552}
47d67540 2553
903f689b
RR
2554bool wxWindow::IsOwnGtkWindow( GdkWindow *window )
2555{
1ecc4d80
RR
2556 if (m_wxwindow) return (window == m_wxwindow->window);
2557 return (window == m_widget->window);
903f689b
RR
2558}
2559
f03fc89f 2560bool wxWindow::SetFont( const wxFont &font )
c801d85f 2561{
a2053b27 2562 wxCHECK_MSG( m_widget != NULL, FALSE, _T( "invalid window") );
c801d85f 2563
739730ca
RR
2564 if (!wxWindowBase::SetFont(font))
2565 {
2566 // don't leave if the GTK widget has just
2567 // been realized
2568 if (!m_delayedFont) return FALSE;
2569 }
121a3581 2570
a2053b27 2571 GtkWidget *connect_widget = GetConnectWidget();
739730ca
RR
2572 if (!connect_widget->window)
2573 {
2574 // indicate that a new style has been set
2575 // but it couldn't get applied as the
2576 // widget hasn't been realized yet.
2577 m_delayedFont = TRUE;
2578
2579 // pretend we have done something
2580 return TRUE;
2581 }
9c288e4d 2582
ae0bdb01 2583 wxColour sysbg = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE );
f03fc89f 2584 if ( sysbg == m_backgroundColour )
ae0bdb01
RR
2585 {
2586 m_backgroundColour = wxNullColour;
2587 ApplyWidgetStyle();
ff8bfdbb
VZ
2588 m_backgroundColour = sysbg;
2589 }
ae0bdb01
RR
2590 else
2591 {
2592 ApplyWidgetStyle();
2593 }
c801d85f 2594
f03fc89f 2595 return TRUE;
362c6693 2596}
c801d85f 2597
68dda785 2598void wxWindow::CaptureMouse()
c801d85f 2599{
05939a81 2600 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
47d67540 2601
05939a81 2602 wxCHECK_RET( g_capturing == FALSE, _T("CaptureMouse called twice") );
47d67540 2603
1ecc4d80 2604 GtkWidget *connect_widget = GetConnectWidget();
a2053b27
RR
2605 if (!connect_widget->window) return;
2606
1ecc4d80
RR
2607 gtk_grab_add( connect_widget );
2608 gdk_pointer_grab( connect_widget->window, FALSE,
2609 (GdkEventMask)
2610 (GDK_BUTTON_PRESS_MASK |
2611 GDK_BUTTON_RELEASE_MASK |
2612 GDK_POINTER_MOTION_MASK),
ff8bfdbb
VZ
2613 (GdkWindow *) NULL,
2614 (GdkCursor *) NULL,
2615 GDK_CURRENT_TIME );
1ecc4d80 2616 g_capturing = TRUE;
362c6693 2617}
c801d85f 2618
68dda785 2619void wxWindow::ReleaseMouse()
c801d85f 2620{
05939a81 2621 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
47d67540 2622
05939a81 2623 wxCHECK_RET( g_capturing == TRUE, _T("ReleaseMouse called twice") );
47d67540 2624
1ecc4d80 2625 GtkWidget *connect_widget = GetConnectWidget();
a2053b27
RR
2626 if (!connect_widget->window) return;
2627
1ecc4d80
RR
2628 gtk_grab_remove( connect_widget );
2629 gdk_pointer_ungrab ( GDK_CURRENT_TIME );
2630 g_capturing = FALSE;
362c6693 2631}
c801d85f 2632
f03fc89f 2633bool wxWindow::IsRetained() const
c801d85f 2634{
1ecc4d80 2635 return FALSE;
362c6693 2636}
c801d85f 2637
debe6624 2638void wxWindow::SetScrollbar( int orient, int pos, int thumbVisible,
cb43b372 2639 int range, bool refresh )
c801d85f 2640{
05939a81 2641 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
8bbe427f 2642
05939a81 2643 wxCHECK_RET( m_wxwindow != NULL, _T("window needs client area for scrolling") );
c801d85f 2644
1ecc4d80 2645 m_hasScrolling = TRUE;
47d67540 2646
1ecc4d80 2647 if (orient == wxHORIZONTAL)
cb43b372 2648 {
1ecc4d80
RR
2649 float fpos = (float)pos;
2650 float frange = (float)range;
2651 float fthumb = (float)thumbVisible;
2652 if (fpos > frange-fthumb) fpos = frange-fthumb;
2653 if (fpos < 0.0) fpos = 0.0;
2654
2655 if ((fabs(frange-m_hAdjust->upper) < 0.2) &&
2656 (fabs(fthumb-m_hAdjust->page_size) < 0.2))
2657 {
2658 SetScrollPos( orient, pos, refresh );
2659 return;
2660 }
47d67540 2661
1ecc4d80 2662 m_oldHorizontalPos = fpos;
47d67540 2663
1ecc4d80
RR
2664 m_hAdjust->lower = 0.0;
2665 m_hAdjust->upper = frange;
2666 m_hAdjust->value = fpos;
2667 m_hAdjust->step_increment = 1.0;
2668 m_hAdjust->page_increment = (float)(wxMax(fthumb,0));
2669 m_hAdjust->page_size = fthumb;
cb43b372 2670 }
1ecc4d80
RR
2671 else
2672 {
2673 float fpos = (float)pos;
2674 float frange = (float)range;
2675 float fthumb = (float)thumbVisible;
2676 if (fpos > frange-fthumb) fpos = frange-fthumb;
2677 if (fpos < 0.0) fpos = 0.0;
2678
2679 if ((fabs(frange-m_vAdjust->upper) < 0.2) &&
2680 (fabs(fthumb-m_vAdjust->page_size) < 0.2))
2681 {
2682 SetScrollPos( orient, pos, refresh );
2683 return;
2684 }
47d67540 2685
1ecc4d80 2686 m_oldVerticalPos = fpos;
47d67540 2687
1ecc4d80
RR
2688 m_vAdjust->lower = 0.0;
2689 m_vAdjust->upper = frange;
2690 m_vAdjust->value = fpos;
2691 m_vAdjust->step_increment = 1.0;
2692 m_vAdjust->page_increment = (float)(wxMax(fthumb,0));
2693 m_vAdjust->page_size = fthumb;
2694 }
47d67540 2695
eb082a08
RR
2696 if (orient == wxHORIZONTAL)
2697 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" );
2698 else
2699 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" );
362c6693 2700}
c801d85f 2701
debe6624 2702void wxWindow::SetScrollPos( int orient, int pos, bool WXUNUSED(refresh) )
c801d85f 2703{
05939a81 2704 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
1ecc4d80 2705
05939a81 2706 wxCHECK_RET( m_wxwindow != NULL, _T("window needs client area for scrolling") );
1ecc4d80
RR
2707
2708 if (orient == wxHORIZONTAL)
2709 {
2710 float fpos = (float)pos;
2711 if (fpos > m_hAdjust->upper - m_hAdjust->page_size) fpos = m_hAdjust->upper - m_hAdjust->page_size;
2712 if (fpos < 0.0) fpos = 0.0;
2713 m_oldHorizontalPos = fpos;
2714
2715 if (fabs(fpos-m_hAdjust->value) < 0.2) return;
2716 m_hAdjust->value = fpos;
2717 }
2718 else
2719 {
2720 float fpos = (float)pos;
2721 if (fpos > m_vAdjust->upper - m_vAdjust->page_size) fpos = m_vAdjust->upper - m_vAdjust->page_size;
2722 if (fpos < 0.0) fpos = 0.0;
2723 m_oldVerticalPos = fpos;
ff8bfdbb 2724
1ecc4d80
RR
2725 if (fabs(fpos-m_vAdjust->value) < 0.2) return;
2726 m_vAdjust->value = fpos;
2727 }
47d67540 2728
eb082a08 2729 if (!m_isScrolling) /* prevent recursion */
47d67540 2730 {
1ecc4d80
RR
2731 if (m_wxwindow->window)
2732 {
2733 if (orient == wxHORIZONTAL)
2734 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "value_changed" );
2735 else
2736 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "value_changed" );
2737 }
cb43b372 2738 }
362c6693 2739}
c801d85f 2740
debe6624 2741int wxWindow::GetScrollThumb( int orient ) const
c801d85f 2742{
05939a81 2743 wxCHECK_MSG( m_widget != NULL, 0, _T("invalid window") );
47d67540 2744
05939a81 2745 wxCHECK_MSG( m_wxwindow != NULL, 0, _T("window needs client area for scrolling") );
47d67540 2746
1ecc4d80
RR
2747 if (orient == wxHORIZONTAL)
2748 return (int)(m_hAdjust->page_size+0.5);
2749 else
2750 return (int)(m_vAdjust->page_size+0.5);
362c6693 2751}
c801d85f 2752
debe6624 2753int wxWindow::GetScrollPos( int orient ) const
c801d85f 2754{
05939a81 2755 wxCHECK_MSG( m_widget != NULL, 0, _T("invalid window") );
47d67540 2756
05939a81 2757 wxCHECK_MSG( m_wxwindow != NULL, 0, _T("window needs client area for scrolling") );
c801d85f 2758
1ecc4d80
RR
2759 if (orient == wxHORIZONTAL)
2760 return (int)(m_hAdjust->value+0.5);
2761 else
2762 return (int)(m_vAdjust->value+0.5);
362c6693 2763}
c801d85f 2764
debe6624 2765int wxWindow::GetScrollRange( int orient ) const
c801d85f 2766{
05939a81 2767 wxCHECK_MSG( m_widget != NULL, 0, _T("invalid window") );
47d67540 2768
05939a81 2769 wxCHECK_MSG( m_wxwindow != NULL, 0, _T("window needs client area for scrolling") );
c801d85f 2770
1ecc4d80
RR
2771 if (orient == wxHORIZONTAL)
2772 return (int)(m_hAdjust->upper+0.5);
2773 else
2774 return (int)(m_vAdjust->upper+0.5);
362c6693 2775}
c801d85f 2776
debe6624 2777void wxWindow::ScrollWindow( int dx, int dy, const wxRect* WXUNUSED(rect) )
c801d85f 2778{
05939a81 2779 wxCHECK_RET( m_widget != NULL, _T("invalid window") );
47d67540 2780
05939a81 2781 wxCHECK_RET( m_wxwindow != NULL, _T("window needs client area for scrolling") );
c801d85f 2782
a2053b27 2783 if (!m_scrollGC)
96d5ab4d 2784 {
a2053b27
RR
2785 m_scrollGC = gdk_gc_new( m_wxwindow->window );
2786 gdk_gc_set_exposures( m_scrollGC, TRUE );
96d5ab4d
RR
2787 }
2788
c801d85f
KB
2789 int cw = 0;
2790 int ch = 0;
2791 GetClientSize( &cw, &ch );
c801d85f
KB
2792 int w = cw - abs(dx);
2793 int h = ch - abs(dy);
a2053b27 2794
c801d85f
KB
2795 if ((h < 0) || (w < 0))
2796 {
1ecc4d80 2797 Refresh();
362c6693 2798 }
a2053b27 2799 else
c801d85f 2800 {
a2053b27
RR
2801 int s_x = 0;
2802 int s_y = 0;
2803 if (dx < 0) s_x = -dx;
2804 if (dy < 0) s_y = -dy;
2805 int d_x = 0;
2806 int d_y = 0;
2807 if (dx > 0) d_x = dx;
2808 if (dy > 0) d_y = dy;
c801d85f 2809
a2053b27
RR
2810 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
2811 m_wxwindow->window, s_x, s_y, w, h );
c801d85f 2812
a2053b27
RR
2813 wxRect rect;
2814 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
2815 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
2816 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
2817 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
c801d85f 2818
a2053b27
RR
2819 Refresh( TRUE, &rect );
2820 }
2821
2822 wxNode *node = m_children.First();
2823 while (node)
2824 {
2825 wxWindow *child = (wxWindow*) node->Data();
2826 child->Move( child->m_x + dx, child->m_y + dy );
2827 node = node->Next();
2828 }
c801d85f
KB
2829}
2830
f03fc89f 2831void wxWindow::SetScrolling(bool scroll)
c801d85f 2832{
f03fc89f 2833 m_isScrolling = g_blockEventsOnScroll = scroll;
c801d85f 2834}