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