1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #include "wx/window.h"
20 #include "wx/layout.h"
22 #include "wx/dialog.h"
23 #include "wx/msgdlg.h"
25 #if wxUSE_DRAG_AND_DROP
30 #include "wx/tooltip.h"
34 #include "wx/statusbr.h"
36 #include "wx/settings.h"
43 #include "gdk/gdkprivate.h"
44 #include "gdk/gdkkeysyms.h"
45 #include "wx/gtk/win_gtk.h"
49 //-----------------------------------------------------------------------------
50 // documentation on internals
51 //-----------------------------------------------------------------------------
54 I have been asked several times about writing some documentation about
55 the GTK port of wxWindows, especially its internal structures. Obviously,
56 you cannot understand wxGTK without knowing a little about the GTK, but
57 some more information about what the wxWindow, which is the base class
58 for all other window classes, does seems required as well.
60 What does wxWindow do? It contains the common interface for the following
61 jobs of its descendants:
63 1) Define the rudimentary behaviour common to all window classes, such as
64 resizing, intercepting user input (so as to make it possible to use these
65 events for special purposes in a derived class), window names etc.
67 2) Provide the possibility to contain and manage children, if the derived
68 class is allowed to contain children, which holds true for those window
69 classes which do not display a native GTK widget. To name them, these
70 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
71 work classes are a special case and are handled a bit differently from
72 the rest. The same holds true for the wxNotebook class.
74 3) Provide the possibility to draw into a client area of a window. This,
75 too, only holds true for classes that do not display a native GTK widget
78 4) Provide the entire mechanism for scrolling widgets. This actual inter-
79 face for this is usually in wxScrolledWindow, but the GTK implementation
82 5) A multitude of helper or extra methods for special purposes, such as
83 Drag'n'Drop, managing validators etc.
85 Normally one might expect, that one wxWindows window would always correspond
86 to one GTK widget. Under GTK, there is no such allround widget that has all
87 the functionality. Moreover, the GTK defines a client area as a different
88 widget from the actual widget you are handling. Last but not least some
89 special classes (e.g. wxFrame) handle different categories of widgets and
90 still have the possibility to draw something in the client area.
91 It was therefore required to write a special purpose GTK widget, that would
92 represent a client area in the sense of wxWindows capable to do the jobs
93 2), 3) and 4). I have written this class and it resides in win_gtk.c of
96 All windows must have a widget, with which they interact with other under-
97 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
98 thw wxWindow class has a member variable called m_widget which holds a
99 pointer to this widget. When the window class represents a GTK native widget,
100 this is (in most cases) the only GTK widget the class manages. E.g. the
101 wxStatitText class handles only a GtkLabel widget a pointer to which you
102 can find in m_widget (defined in wxWindow)
104 When the class has a client area for drawing into and for containing children
105 it has to handle the client area widget (of the type GtkMyFixed, defined in
106 win_gtk.c), but there could be any number of widgets, handled by a class
107 The common rule for all windows is only, that the widget that interacts with
108 the rest of GTK must be referenced in m_widget and all other widgets must be
109 children of this widget on the GTK level. The top-most widget, which also
110 represents the client area, must be in the m_wxwindow field and must be of
113 As I said, the window classes that display a GTK native widget only have
114 one widget, so in the case of e.g. the wxButton class m_widget holds a
115 pointer to a GtkButton widget. But windows with client areas (for drawing
116 and children) have a m_widget field that is a pointer to a GtkScrolled-
117 Window and a m_wxwindow field that is pointer to a GtkMyFixed and this
118 one is (in the GTK sense) a child of the GtkScrolledWindow.
120 If the m_wxwindow field is set, then all input to this widget is inter-
121 cepted and sent to the wxWindows class. If not, all input to the widget
122 that gets pointed to by m_widget gets intercepted and sent to the class.
126 //-----------------------------------------------------------------------------
128 //-----------------------------------------------------------------------------
130 extern wxList wxPendingDelete
;
131 extern bool g_blockEventsOnDrag
;
132 extern bool g_blockEventsOnScroll
;
133 extern wxCursor g_globalCursor
;
134 static wxWindow
*g_captureWindow
= (wxWindow
*) NULL
;
135 wxWindow
*g_focusWindow
= (wxWindow
*) NULL
;
137 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
138 the last click here */
139 static guint32 gs_timeLastClick
= 0;
141 //-----------------------------------------------------------------------------
143 //-----------------------------------------------------------------------------
147 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
148 GdkEvent
*WXUNUSED(event
),
149 const wxChar
*WXUNUSED(name
) )
152 static bool s_done = FALSE;
155 wxLog::AddTraceMask("focus");
158 wxLogTrace(T("FOCUS NOW AT: %s"), name);
164 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
170 wxChar
*s
= new wxChar
[tmp
.Length()+1];
174 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
175 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
180 //-----------------------------------------------------------------------------
181 // missing gdk functions
182 //-----------------------------------------------------------------------------
185 gdk_window_warp_pointer (GdkWindow
*window
,
189 GdkWindowPrivate
*priv
;
192 window
= (GdkWindow
*) &gdk_root_parent
;
194 priv
= (GdkWindowPrivate
*) window
;
196 if (!priv
->destroyed
)
198 XWarpPointer (priv
->xdisplay
,
199 None
, /* not source window -> move from anywhere */
200 priv
->xwindow
, /* dest window */
201 0, 0, 0, 0, /* not source window -> move from anywhere */
206 //-----------------------------------------------------------------------------
208 //-----------------------------------------------------------------------------
210 extern void wxapp_install_idle_handler();
211 extern bool g_isIdle
;
213 //-----------------------------------------------------------------------------
214 // key event conversion routines
215 //-----------------------------------------------------------------------------
217 #if (GTK_MINOR_VERSION == 0)
218 /* these functions are copied verbatim from GTK 1.2 */
220 gdkx_XConvertCase (KeySym symbol
,
224 register KeySym sym
= symbol
;
226 g_return_if_fail (lower
!= NULL
);
227 g_return_if_fail (upper
!= NULL
);
234 #if defined (GDK_A) && defined (GDK_Ooblique)
235 case 0: /* Latin 1 */
236 if ((sym
>= GDK_A
) && (sym
<= GDK_Z
))
237 *lower
+= (GDK_a
- GDK_A
);
238 else if ((sym
>= GDK_a
) && (sym
<= GDK_z
))
239 *upper
-= (GDK_a
- GDK_A
);
240 else if ((sym
>= GDK_Agrave
) && (sym
<= GDK_Odiaeresis
))
241 *lower
+= (GDK_agrave
- GDK_Agrave
);
242 else if ((sym
>= GDK_agrave
) && (sym
<= GDK_odiaeresis
))
243 *upper
-= (GDK_agrave
- GDK_Agrave
);
244 else if ((sym
>= GDK_Ooblique
) && (sym
<= GDK_Thorn
))
245 *lower
+= (GDK_oslash
- GDK_Ooblique
);
246 else if ((sym
>= GDK_oslash
) && (sym
<= GDK_thorn
))
247 *upper
-= (GDK_oslash
- GDK_Ooblique
);
251 #if defined (GDK_Aogonek) && defined (GDK_tcedilla)
252 case 1: /* Latin 2 */
253 /* Assume the KeySym is a legal value (ignore discontinuities) */
254 if (sym
== GDK_Aogonek
)
255 *lower
= GDK_aogonek
;
256 else if (sym
>= GDK_Lstroke
&& sym
<= GDK_Sacute
)
257 *lower
+= (GDK_lstroke
- GDK_Lstroke
);
258 else if (sym
>= GDK_Scaron
&& sym
<= GDK_Zacute
)
259 *lower
+= (GDK_scaron
- GDK_Scaron
);
260 else if (sym
>= GDK_Zcaron
&& sym
<= GDK_Zabovedot
)
261 *lower
+= (GDK_zcaron
- GDK_Zcaron
);
262 else if (sym
== GDK_aogonek
)
263 *upper
= GDK_Aogonek
;
264 else if (sym
>= GDK_lstroke
&& sym
<= GDK_sacute
)
265 *upper
-= (GDK_lstroke
- GDK_Lstroke
);
266 else if (sym
>= GDK_scaron
&& sym
<= GDK_zacute
)
267 *upper
-= (GDK_scaron
- GDK_Scaron
);
268 else if (sym
>= GDK_zcaron
&& sym
<= GDK_zabovedot
)
269 *upper
-= (GDK_zcaron
- GDK_Zcaron
);
270 else if (sym
>= GDK_Racute
&& sym
<= GDK_Tcedilla
)
271 *lower
+= (GDK_racute
- GDK_Racute
);
272 else if (sym
>= GDK_racute
&& sym
<= GDK_tcedilla
)
273 *upper
-= (GDK_racute
- GDK_Racute
);
277 #if defined (GDK_Hstroke) && defined (GDK_Cabovedot)
278 case 2: /* Latin 3 */
279 /* Assume the KeySym is a legal value (ignore discontinuities) */
280 if (sym
>= GDK_Hstroke
&& sym
<= GDK_Hcircumflex
)
281 *lower
+= (GDK_hstroke
- GDK_Hstroke
);
282 else if (sym
>= GDK_Gbreve
&& sym
<= GDK_Jcircumflex
)
283 *lower
+= (GDK_gbreve
- GDK_Gbreve
);
284 else if (sym
>= GDK_hstroke
&& sym
<= GDK_hcircumflex
)
285 *upper
-= (GDK_hstroke
- GDK_Hstroke
);
286 else if (sym
>= GDK_gbreve
&& sym
<= GDK_jcircumflex
)
287 *upper
-= (GDK_gbreve
- GDK_Gbreve
);
288 else if (sym
>= GDK_Cabovedot
&& sym
<= GDK_Scircumflex
)
289 *lower
+= (GDK_cabovedot
- GDK_Cabovedot
);
290 else if (sym
>= GDK_cabovedot
&& sym
<= GDK_scircumflex
)
291 *upper
-= (GDK_cabovedot
- GDK_Cabovedot
);
295 #if defined (GDK_Rcedilla) && defined (GDK_Amacron)
296 case 3: /* Latin 4 */
297 /* Assume the KeySym is a legal value (ignore discontinuities) */
298 if (sym
>= GDK_Rcedilla
&& sym
<= GDK_Tslash
)
299 *lower
+= (GDK_rcedilla
- GDK_Rcedilla
);
300 else if (sym
>= GDK_rcedilla
&& sym
<= GDK_tslash
)
301 *upper
-= (GDK_rcedilla
- GDK_Rcedilla
);
302 else if (sym
== GDK_ENG
)
304 else if (sym
== GDK_eng
)
306 else if (sym
>= GDK_Amacron
&& sym
<= GDK_Umacron
)
307 *lower
+= (GDK_amacron
- GDK_Amacron
);
308 else if (sym
>= GDK_amacron
&& sym
<= GDK_umacron
)
309 *upper
-= (GDK_amacron
- GDK_Amacron
);
313 #if defined (GDK_Serbian_DJE) && defined (GDK_Cyrillic_yu)
314 case 6: /* Cyrillic */
315 /* Assume the KeySym is a legal value (ignore discontinuities) */
316 if (sym
>= GDK_Serbian_DJE
&& sym
<= GDK_Serbian_DZE
)
317 *lower
-= (GDK_Serbian_DJE
- GDK_Serbian_dje
);
318 else if (sym
>= GDK_Serbian_dje
&& sym
<= GDK_Serbian_dze
)
319 *upper
+= (GDK_Serbian_DJE
- GDK_Serbian_dje
);
320 else if (sym
>= GDK_Cyrillic_YU
&& sym
<= GDK_Cyrillic_HARDSIGN
)
321 *lower
-= (GDK_Cyrillic_YU
- GDK_Cyrillic_yu
);
322 else if (sym
>= GDK_Cyrillic_yu
&& sym
<= GDK_Cyrillic_hardsign
)
323 *upper
+= (GDK_Cyrillic_YU
- GDK_Cyrillic_yu
);
325 #endif /* CYRILLIC */
327 #if defined (GDK_Greek_ALPHAaccent) && defined (GDK_Greek_finalsmallsigma)
329 /* Assume the KeySym is a legal value (ignore discontinuities) */
330 if (sym
>= GDK_Greek_ALPHAaccent
&& sym
<= GDK_Greek_OMEGAaccent
)
331 *lower
+= (GDK_Greek_alphaaccent
- GDK_Greek_ALPHAaccent
);
332 else if (sym
>= GDK_Greek_alphaaccent
&& sym
<= GDK_Greek_omegaaccent
&&
333 sym
!= GDK_Greek_iotaaccentdieresis
&&
334 sym
!= GDK_Greek_upsilonaccentdieresis
)
335 *upper
-= (GDK_Greek_alphaaccent
- GDK_Greek_ALPHAaccent
);
336 else if (sym
>= GDK_Greek_ALPHA
&& sym
<= GDK_Greek_OMEGA
)
337 *lower
+= (GDK_Greek_alpha
- GDK_Greek_ALPHA
);
338 else if (sym
>= GDK_Greek_alpha
&& sym
<= GDK_Greek_omega
&&
339 sym
!= GDK_Greek_finalsmallsigma
)
340 *upper
-= (GDK_Greek_alpha
- GDK_Greek_ALPHA
);
347 gdk_keyval_to_upper (guint keyval
)
351 KeySym lower_val
= 0;
352 KeySym upper_val
= 0;
354 gdkx_XConvertCase (keyval
, &lower_val
, &upper_val
);
361 static long map_to_unmodified_wx_keysym( KeySym keysym
)
368 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
370 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
376 case GDK_Super_R
: key_code
= WXK_ALT
; break;
377 case GDK_Menu
: key_code
= WXK_MENU
; break;
378 case GDK_Help
: key_code
= WXK_HELP
; break;
379 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
380 case GDK_ISO_Left_Tab
:
381 case GDK_Tab
: key_code
= WXK_TAB
; break;
382 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
383 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
384 case GDK_Return
: key_code
= WXK_RETURN
; break;
385 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
386 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
387 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
388 case GDK_Delete
: key_code
= WXK_DELETE
; break;
389 case GDK_Home
: key_code
= WXK_HOME
; break;
390 case GDK_Left
: key_code
= WXK_LEFT
; break;
391 case GDK_Up
: key_code
= WXK_UP
; break;
392 case GDK_Right
: key_code
= WXK_RIGHT
; break;
393 case GDK_Down
: key_code
= WXK_DOWN
; break;
394 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
395 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
396 case GDK_Next
: key_code
= WXK_NEXT
; break;
397 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
398 case GDK_End
: key_code
= WXK_END
; break;
399 case GDK_Begin
: key_code
= WXK_HOME
; break;
400 case GDK_Select
: key_code
= WXK_SELECT
; break;
401 case GDK_Print
: key_code
= WXK_PRINT
; break;
402 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
403 case GDK_Insert
: key_code
= WXK_INSERT
; break;
404 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
406 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
407 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
408 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
409 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
410 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
411 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
412 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
413 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
414 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
415 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
416 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
417 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
418 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
419 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
420 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
421 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
422 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
423 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
424 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
425 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
426 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
427 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
428 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
429 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
430 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
431 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
432 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
433 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
434 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
435 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
436 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
437 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
438 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
439 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
440 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
441 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
442 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
444 case GDK_F1
: key_code
= WXK_F1
; break;
445 case GDK_F2
: key_code
= WXK_F2
; break;
446 case GDK_F3
: key_code
= WXK_F3
; break;
447 case GDK_F4
: key_code
= WXK_F4
; break;
448 case GDK_F5
: key_code
= WXK_F5
; break;
449 case GDK_F6
: key_code
= WXK_F6
; break;
450 case GDK_F7
: key_code
= WXK_F7
; break;
451 case GDK_F8
: key_code
= WXK_F8
; break;
452 case GDK_F9
: key_code
= WXK_F9
; break;
453 case GDK_F10
: key_code
= WXK_F10
; break;
454 case GDK_F11
: key_code
= WXK_F11
; break;
455 case GDK_F12
: key_code
= WXK_F12
; break;
460 guint upper
= gdk_keyval_to_upper( keysym
);
461 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
470 static long map_to_wx_keysym( KeySym keysym
)
476 case GDK_Menu
: key_code
= WXK_MENU
; break;
477 case GDK_Help
: key_code
= WXK_HELP
; break;
478 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
479 case GDK_ISO_Left_Tab
:
480 case GDK_Tab
: key_code
= WXK_TAB
; break;
481 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
482 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
483 case GDK_Return
: key_code
= WXK_RETURN
; break;
484 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
485 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
486 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
487 case GDK_Delete
: key_code
= WXK_DELETE
; break;
488 case GDK_Home
: key_code
= WXK_HOME
; break;
489 case GDK_Left
: key_code
= WXK_LEFT
; break;
490 case GDK_Up
: key_code
= WXK_UP
; break;
491 case GDK_Right
: key_code
= WXK_RIGHT
; break;
492 case GDK_Down
: key_code
= WXK_DOWN
; break;
493 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
494 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
495 case GDK_Next
: key_code
= WXK_NEXT
; break;
496 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
497 case GDK_End
: key_code
= WXK_END
; break;
498 case GDK_Begin
: key_code
= WXK_HOME
; break;
499 case GDK_Select
: key_code
= WXK_SELECT
; break;
500 case GDK_Print
: key_code
= WXK_PRINT
; break;
501 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
502 case GDK_Insert
: key_code
= WXK_INSERT
; break;
503 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
505 case GDK_KP_0
: key_code
= '0'; break;
506 case GDK_KP_1
: key_code
= '1'; break;
507 case GDK_KP_2
: key_code
= '2'; break;
508 case GDK_KP_3
: key_code
= '3'; break;
509 case GDK_KP_4
: key_code
= '4'; break;
510 case GDK_KP_5
: key_code
= '5'; break;
511 case GDK_KP_6
: key_code
= '6'; break;
512 case GDK_KP_7
: key_code
= '7'; break;
513 case GDK_KP_8
: key_code
= '8'; break;
514 case GDK_KP_9
: key_code
= '9'; break;
515 case GDK_KP_Space
: key_code
= ' '; break;
516 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
517 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
518 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
519 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
520 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
521 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
522 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
523 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
524 case GDK_KP_Up
: key_code
= WXK_UP
; break;
525 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
526 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
527 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
528 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
529 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
530 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
531 case GDK_KP_End
: key_code
= WXK_END
; break;
532 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
533 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
534 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
535 case GDK_KP_Equal
: key_code
= '='; break;
536 case GDK_KP_Multiply
: key_code
= '*'; break;
537 case GDK_KP_Add
: key_code
= '+'; break;
538 case GDK_KP_Separator
: key_code
= ','; break;
539 case GDK_KP_Subtract
: key_code
= '-'; break;
540 case GDK_KP_Decimal
: key_code
= '.'; break;
541 case GDK_KP_Divide
: key_code
= '/'; break;
543 case GDK_F1
: key_code
= WXK_F1
; break;
544 case GDK_F2
: key_code
= WXK_F2
; break;
545 case GDK_F3
: key_code
= WXK_F3
; break;
546 case GDK_F4
: key_code
= WXK_F4
; break;
547 case GDK_F5
: key_code
= WXK_F5
; break;
548 case GDK_F6
: key_code
= WXK_F6
; break;
549 case GDK_F7
: key_code
= WXK_F7
; break;
550 case GDK_F8
: key_code
= WXK_F8
; break;
551 case GDK_F9
: key_code
= WXK_F9
; break;
552 case GDK_F10
: key_code
= WXK_F10
; break;
553 case GDK_F11
: key_code
= WXK_F11
; break;
554 case GDK_F12
: key_code
= WXK_F12
; break;
567 //-----------------------------------------------------------------------------
568 // local code (see below)
569 //-----------------------------------------------------------------------------
571 #if (GTK_MINOR_VERSION > 0)
573 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
581 if (win
->HasScrolling())
583 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
584 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget
)->klass
);
587 GtkWidget *hscrollbar = scroll_window->hscrollbar;
588 GtkWidget *vscrollbar = scroll_window->vscrollbar;
590 we use this instead: range.slider_width = 11 + 2*2pts edge
593 if (scroll_window
->vscrollbar_visible
)
595 dw
+= 15; /* dw += vscrollbar->allocation.width; */
596 dw
+= scroll_class
->scrollbar_spacing
;
599 if (scroll_window
->hscrollbar_visible
)
601 dh
+= 15; /* dh += hscrollbar->allocation.height; */
602 dh
+= scroll_class
->scrollbar_spacing
;
608 if (GTK_WIDGET_NO_WINDOW (widget
))
610 dx
+= widget
->allocation
.x
;
611 dy
+= widget
->allocation
.y
;
614 if (win
->HasFlag(wxRAISED_BORDER
))
616 gtk_draw_shadow( widget
->style
,
621 win
->m_width
-dw
, win
->m_height
-dh
);
625 if (win
->HasFlag(wxSUNKEN_BORDER
))
627 gtk_draw_shadow( widget
->style
,
632 win
->m_width
-dw
, win
->m_height
-dh
);
636 if (win
->HasFlag(wxSIMPLE_BORDER
))
638 GdkGC
*gc
= gdk_gc_new( widget
->window
);
639 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
640 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
642 win
->m_width
-dw
-1, win
->m_height
-dh
-1 );
648 //-----------------------------------------------------------------------------
649 // "expose_event" of m_widget
650 //-----------------------------------------------------------------------------
652 static void gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
654 if (gdk_event
->count
> 0) return;
655 draw_frame( widget
, win
);
658 //-----------------------------------------------------------------------------
659 // "draw" of m_wxwindow
660 //-----------------------------------------------------------------------------
662 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
664 draw_frame( widget
, win
);
667 #endif // GTK_MINOR_VERSION > 0
669 //-----------------------------------------------------------------------------
670 // "expose_event" of m_wxwindow
671 //-----------------------------------------------------------------------------
673 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
678 if (gdk_event
->window
!= win
->m_wxwindow
->window
)
681 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
683 gdk_event
->area
.width
,
684 gdk_event
->area
.height
);
686 if (gdk_event
->count
> 0)
690 wxPrintf( "OnExpose from " );
691 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
692 wxPrintf( win->GetClassInfo()->GetClassName() );
693 wxPrintf( " %d %d %d %d\n", (int)gdk_event->area.x,
694 (int)gdk_event->area.y,
695 (int)gdk_event->area.width,
696 (int)gdk_event->area.height );
699 wxPaintEvent
event( win
->GetId() );
700 event
.SetEventObject( win
);
701 win
->GetEventHandler()->ProcessEvent( event
);
703 win
->GetUpdateRegion().Clear();
706 //-----------------------------------------------------------------------------
707 // "draw" of m_wxwindow
708 //-----------------------------------------------------------------------------
710 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
713 wxapp_install_idle_handler();
718 GtkMyFixed
*myfixed
= GTK_MYFIXED (widget
);
719 if (!myfixed
->children
)
720 return; /* mini optimisation */
722 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
,
723 rect
->width
, rect
->height
);
726 wxPrintf( "OnDraw from " );
727 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
728 printf( win->GetClassInfo()->GetClassName() );
729 wxPrintf( " %d %d %d %d\n", (int)rect->x,
735 wxPaintEvent
event( win
->GetId() );
736 event
.SetEventObject( win
);
737 win
->GetEventHandler()->ProcessEvent( event
);
739 win
->GetUpdateRegion().Clear();
742 //-----------------------------------------------------------------------------
743 // "key_press_event" from any window
744 //-----------------------------------------------------------------------------
746 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
749 wxapp_install_idle_handler();
751 if (!win
->m_hasVMT
) return FALSE
;
752 if (g_blockEventsOnDrag
) return FALSE
;
755 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
756 if (gdk_event->state & GDK_SHIFT_MASK)
757 printf( "ShiftDown.\n" );
759 printf( "ShiftUp.\n" );
760 if (gdk_event->state & GDK_CONTROL_MASK)
761 printf( "ControlDown.\n" );
763 printf( "ControlUp.\n" );
768 GdkModifierType state
;
769 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
771 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
773 /* sending unknown key events doesn't really make sense */
774 if (key_code
== 0) return FALSE
;
778 wxKeyEvent
event( wxEVT_KEY_DOWN
);
779 event
.SetTimestamp( gdk_event
->time
);
780 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
781 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
782 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
783 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
784 event
.m_keyCode
= key_code
;
785 event
.m_scanCode
= gdk_event
->keyval
;
788 event
.SetEventObject( win
);
789 ret
= win
->GetEventHandler()->ProcessEvent( event
);
791 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
796 wxWindow
*ancestor
= win
;
799 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
802 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
803 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
806 ancestor
= ancestor
->GetParent();
809 #endif // wxUSE_ACCEL
810 /* wxMSW doesn't send char events with Alt pressed */
811 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
812 will only be sent if it is not a menu accelerator. */
813 if ((key_code
!= 0) && ! ret
)
815 wxKeyEvent
event2( wxEVT_CHAR
);
816 event2
.SetTimestamp( gdk_event
->time
);
817 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
818 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
819 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
820 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
821 event2
.m_keyCode
= key_code
;
822 event2
.m_scanCode
= gdk_event
->keyval
;
825 event2
.SetEventObject( win
);
826 ret
= (ret
|| win
->GetEventHandler()->ProcessEvent( event2
));
829 /* win is a control: tab can be propagated up */
831 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
832 (win
->HasFlag(wxTE_PROCESS_TAB
) == 0))
834 wxNavigationKeyEvent new_event
;
835 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
836 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
837 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
838 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
839 new_event
.SetCurrentFocus( win
);
840 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
843 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
845 (gdk_event
->keyval
== GDK_Escape
) )
847 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
848 new_event
.SetEventObject( win
);
849 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
852 #if (GTK_MINOR_VERSION > 0)
853 /* pressing F10 will activate the menu bar of the top frame */
855 (gdk_event
->keyval
== GDK_F10
) )
857 wxWindow
*ancestor
= win
;
860 if (wxIsKindOf(ancestor
,wxFrame
))
862 wxFrame
*frame
= (wxFrame
*) ancestor
;
863 wxMenuBar
*menubar
= frame
->GetMenuBar();
866 wxNode
*node
= menubar
->GetMenus().First();
869 // doesn't work correctly
870 // wxMenu *firstMenu = (wxMenu*) node->Data();
871 // gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
877 ancestor
= ancestor
->GetParent();
883 Damn, I forgot why this didn't work, but it didn't work.
885 // win is a panel: up can be propagated to the panel
886 if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
887 (gdk_event->keyval == GDK_Up))
889 win->m_parent->SetFocus();
893 // win is a panel: left/right can be propagated to the panel
894 if ((!ret) && (win->m_wxwindow) &&
895 ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
896 (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
898 wxNavigationKeyEvent new_event;
899 new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
900 new_event.SetCurrentFocus( win );
901 ret = win->GetEventHandler()->ProcessEvent( new_event );
907 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
914 //-----------------------------------------------------------------------------
915 // "key_release_event" from any window
916 //-----------------------------------------------------------------------------
918 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
921 wxapp_install_idle_handler();
923 if (!win
->m_hasVMT
) return FALSE
;
924 if (g_blockEventsOnDrag
) return FALSE
;
927 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
928 if (gdk_event->state & GDK_SHIFT_MASK)
929 printf( "ShiftDown.\n" );
931 printf( "ShiftUp.\n" );
932 if (gdk_event->state & GDK_CONTROL_MASK)
933 printf( "ControlDown.\n" );
935 printf( "ControlUp.\n" );
939 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
941 /* sending unknown key events doesn't really make sense */
942 if (key_code
== 0) return FALSE
;
946 GdkModifierType state
;
947 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
949 wxKeyEvent
event( wxEVT_KEY_UP
);
950 event
.SetTimestamp( gdk_event
->time
);
951 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
952 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
953 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
954 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
955 event
.m_keyCode
= key_code
;
956 event
.m_scanCode
= gdk_event
->keyval
;
959 event
.SetEventObject( win
);
961 if (win
->GetEventHandler()->ProcessEvent( event
))
963 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
970 //-----------------------------------------------------------------------------
971 // "button_press_event"
972 //-----------------------------------------------------------------------------
974 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
977 wxapp_install_idle_handler();
980 wxPrintf( T("1) OnButtonPress from ") );
981 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
982 wxPrintf( win->GetClassInfo()->GetClassName() );
983 wxPrintf( T(".\n") );
985 if (!win
->m_hasVMT
) return FALSE
;
986 if (g_blockEventsOnDrag
) return TRUE
;
987 if (g_blockEventsOnScroll
) return TRUE
;
989 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
993 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
995 gtk_widget_grab_focus (win
->m_wxwindow
);
998 wxPrintf( T("GrabFocus from ") );
999 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1000 wxPrintf( win->GetClassInfo()->GetClassName() );
1001 wxPrintf( T(".\n") );
1008 wxPrintf( T("2) OnButtonPress from ") );
1009 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1010 wxPrintf( win->GetClassInfo()->GetClassName() );
1011 wxPrintf( T(".\n") );
1014 wxEventType event_type
= wxEVT_LEFT_DOWN
;
1016 if (gdk_event
->button
== 1)
1018 switch (gdk_event
->type
)
1020 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1021 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1025 else if (gdk_event
->button
== 2)
1027 switch (gdk_event
->type
)
1029 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1030 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1034 else if (gdk_event
->button
== 3)
1036 switch (gdk_event
->type
)
1038 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1039 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1044 wxMouseEvent
event( event_type
);
1045 event
.SetTimestamp( gdk_event
->time
);
1046 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1047 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1048 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1049 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1050 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1051 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1052 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1054 event
.m_x
= (long)gdk_event
->x
;
1055 event
.m_y
= (long)gdk_event
->y
;
1057 // Some control don't have their own X window and thus cannot get
1060 if (!g_captureWindow
)
1062 wxNode
*node
= win
->GetChildren().First();
1065 wxWindow
*child
= (wxWindow
*)node
->Data();
1067 if (child
->m_isStaticBox
)
1069 // wxStaticBox is transparent in the box itself
1072 int xx1
= child
->m_x
;
1073 int yy1
= child
->m_y
;
1074 int xx2
= child
->m_x
+ child
->m_width
;
1075 int yy2
= child
->m_x
+ child
->m_height
;
1078 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1080 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1082 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1084 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1087 event
.m_x
-= child
->m_x
;
1088 event
.m_y
-= child
->m_y
;
1095 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1096 (child
->m_x
<= event
.m_x
) &&
1097 (child
->m_y
<= event
.m_y
) &&
1098 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
1099 (child
->m_y
+child
->m_height
>= event
.m_y
))
1102 event
.m_x
-= child
->m_x
;
1103 event
.m_y
-= child
->m_y
;
1107 node
= node
->Next();
1111 event
.SetEventObject( win
);
1113 gs_timeLastClick
= gdk_event
->time
;
1115 if (win
->GetEventHandler()->ProcessEvent( event
))
1117 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1124 //-----------------------------------------------------------------------------
1125 // "button_release_event"
1126 //-----------------------------------------------------------------------------
1128 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1131 wxapp_install_idle_handler();
1133 if (!win
->m_hasVMT
) return FALSE
;
1134 if (g_blockEventsOnDrag
) return FALSE
;
1135 if (g_blockEventsOnScroll
) return FALSE
;
1137 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1140 printf( "OnButtonRelease from " );
1141 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1142 printf( win->GetClassInfo()->GetClassName() );
1146 wxEventType event_type
= wxEVT_NULL
;
1148 switch (gdk_event
->button
)
1150 case 1: event_type
= wxEVT_LEFT_UP
; break;
1151 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1152 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1155 wxMouseEvent
event( event_type
);
1156 event
.SetTimestamp( gdk_event
->time
);
1157 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1158 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1159 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1160 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1161 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1162 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1163 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1164 event
.m_x
= (long)gdk_event
->x
;
1165 event
.m_y
= (long)gdk_event
->y
;
1167 // Some control don't have their own X window and thus cannot get
1170 if (!g_captureWindow
)
1172 wxNode
*node
= win
->GetChildren().First();
1175 wxWindow
*child
= (wxWindow
*)node
->Data();
1177 if (child
->m_isStaticBox
)
1179 // wxStaticBox is transparent in the box itself
1182 int xx1
= child
->m_x
;
1183 int yy1
= child
->m_y
;
1184 int xx2
= child
->m_x
+ child
->m_width
;
1185 int yy2
= child
->m_x
+ child
->m_height
;
1188 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1190 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1192 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1194 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1197 event
.m_x
-= child
->m_x
;
1198 event
.m_y
-= child
->m_y
;
1205 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1206 (child
->m_x
<= event
.m_x
) &&
1207 (child
->m_y
<= event
.m_y
) &&
1208 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
1209 (child
->m_y
+child
->m_height
>= event
.m_y
))
1212 event
.m_x
-= child
->m_x
;
1213 event
.m_y
-= child
->m_y
;
1217 node
= node
->Next();
1221 event
.SetEventObject( win
);
1223 if (win
->GetEventHandler()->ProcessEvent( event
))
1225 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1232 //-----------------------------------------------------------------------------
1233 // "motion_notify_event"
1234 //-----------------------------------------------------------------------------
1236 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1239 wxapp_install_idle_handler();
1241 if (!win
->m_hasVMT
) return FALSE
;
1242 if (g_blockEventsOnDrag
) return FALSE
;
1243 if (g_blockEventsOnScroll
) return FALSE
;
1245 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1247 if (gdk_event
->is_hint
)
1251 GdkModifierType state
;
1252 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1258 printf( "OnMotion from " );
1259 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1260 printf( win->GetClassInfo()->GetClassName() );
1264 wxMouseEvent
event( wxEVT_MOTION
);
1265 event
.SetTimestamp( gdk_event
->time
);
1266 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1267 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1268 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1269 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1270 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1271 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1272 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1274 event
.m_x
= (long)gdk_event
->x
;
1275 event
.m_y
= (long)gdk_event
->y
;
1277 // Some control don't have their own X window and thus cannot get
1280 if (!g_captureWindow
)
1282 wxNode
*node
= win
->GetChildren().First();
1285 wxWindow
*child
= (wxWindow
*)node
->Data();
1287 if (child
->m_isStaticBox
)
1289 // wxStaticBox is transparent in the box itself
1292 int xx1
= child
->m_x
;
1293 int yy1
= child
->m_y
;
1294 int xx2
= child
->m_x
+ child
->m_width
;
1295 int yy2
= child
->m_x
+ child
->m_height
;
1298 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1300 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1302 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1304 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1307 event
.m_x
-= child
->m_x
;
1308 event
.m_y
-= child
->m_y
;
1315 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1316 (child
->m_x
<= event
.m_x
) &&
1317 (child
->m_y
<= event
.m_y
) &&
1318 (child
->m_x
+child
->m_width
>= event
.m_x
) &&
1319 (child
->m_y
+child
->m_height
>= event
.m_y
))
1322 event
.m_x
-= child
->m_x
;
1323 event
.m_y
-= child
->m_y
;
1327 node
= node
->Next();
1331 event
.SetEventObject( win
);
1333 if (win
->GetEventHandler()->ProcessEvent( event
))
1335 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1342 //-----------------------------------------------------------------------------
1344 //-----------------------------------------------------------------------------
1346 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1349 wxapp_install_idle_handler();
1351 if (!win
->m_hasVMT
) return FALSE
;
1352 if (g_blockEventsOnDrag
) return FALSE
;
1354 g_focusWindow
= win
;
1356 if (win
->m_wxwindow
)
1358 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1360 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1362 printf( "SetFocus flag from " );
1363 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1364 printf( win->GetClassInfo()->GetClassName() );
1372 printf( "OnSetFocus from " );
1373 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1374 printf( win->GetClassInfo()->GetClassName() );
1376 printf( WXSTRINGCAST win->GetLabel() );
1380 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1381 event
.SetEventObject( win
);
1383 if (win
->GetEventHandler()->ProcessEvent( event
))
1385 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1392 //-----------------------------------------------------------------------------
1393 // "focus_out_event"
1394 //-----------------------------------------------------------------------------
1396 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1399 wxapp_install_idle_handler();
1401 if (!win
->m_hasVMT
) return FALSE
;
1402 if (g_blockEventsOnDrag
) return FALSE
;
1404 if (win
->m_wxwindow
)
1406 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1407 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1411 printf( "OnKillFocus from " );
1412 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1413 printf( win->GetClassInfo()->GetClassName() );
1417 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1418 event
.SetEventObject( win
);
1420 if (win
->GetEventHandler()->ProcessEvent( event
))
1422 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1429 //-----------------------------------------------------------------------------
1430 // "enter_notify_event"
1431 //-----------------------------------------------------------------------------
1433 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1436 wxapp_install_idle_handler();
1438 if (!win
->m_hasVMT
) return FALSE
;
1439 if (g_blockEventsOnDrag
) return FALSE
;
1441 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1443 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1444 #if (GTK_MINOR_VERSION > 0)
1445 event
.SetTimestamp( gdk_event
->time
);
1447 event
.SetEventObject( win
);
1451 GdkModifierType state
= (GdkModifierType
)0;
1453 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1455 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1456 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1457 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1458 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1459 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1460 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1461 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1463 event
.m_x
= (long)x
;
1464 event
.m_y
= (long)y
;
1466 if (win
->GetEventHandler()->ProcessEvent( event
))
1468 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1475 //-----------------------------------------------------------------------------
1476 // "leave_notify_event"
1477 //-----------------------------------------------------------------------------
1479 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1482 wxapp_install_idle_handler();
1484 if (!win
->m_hasVMT
) return FALSE
;
1485 if (g_blockEventsOnDrag
) return FALSE
;
1487 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1489 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1490 #if (GTK_MINOR_VERSION > 0)
1491 event
.SetTimestamp( gdk_event
->time
);
1493 event
.SetEventObject( win
);
1497 GdkModifierType state
= (GdkModifierType
)0;
1499 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1501 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1502 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1503 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1504 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1505 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1506 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1507 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1509 event
.m_x
= (long)x
;
1510 event
.m_y
= (long)y
;
1512 if (win
->GetEventHandler()->ProcessEvent( event
))
1514 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1521 //-----------------------------------------------------------------------------
1522 // "value_changed" from m_vAdjust
1523 //-----------------------------------------------------------------------------
1525 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1528 wxapp_install_idle_handler();
1530 if (g_blockEventsOnDrag
) return;
1532 if (!win
->m_hasVMT
) return;
1534 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1535 if (fabs(diff
) < 0.2) return;
1537 win
->m_oldVerticalPos
= adjust
->value
;
1539 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1540 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1542 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1543 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1544 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1545 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1546 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1548 int value
= (int)(adjust
->value
+0.5);
1550 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1551 event
.SetEventObject( win
);
1552 win
->GetEventHandler()->ProcessEvent( event
);
1555 //-----------------------------------------------------------------------------
1556 // "value_changed" from m_hAdjust
1557 //-----------------------------------------------------------------------------
1559 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1562 wxapp_install_idle_handler();
1564 if (g_blockEventsOnDrag
) return;
1565 if (!win
->m_hasVMT
) return;
1567 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1568 if (fabs(diff
) < 0.2) return;
1570 win
->m_oldHorizontalPos
= adjust
->value
;
1572 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1573 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1575 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1576 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1577 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1578 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1579 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1581 int value
= (int)(adjust
->value
+0.5);
1583 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1584 event
.SetEventObject( win
);
1585 win
->GetEventHandler()->ProcessEvent( event
);
1588 //-----------------------------------------------------------------------------
1589 // "changed" from m_vAdjust
1590 //-----------------------------------------------------------------------------
1592 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1595 wxapp_install_idle_handler();
1597 if (g_blockEventsOnDrag
) return;
1598 if (!win
->m_hasVMT
) return;
1600 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1601 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1603 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1604 event
.SetEventObject( win
);
1605 win
->GetEventHandler()->ProcessEvent( event
);
1608 //-----------------------------------------------------------------------------
1609 // "changed" from m_hAdjust
1610 //-----------------------------------------------------------------------------
1612 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1615 wxapp_install_idle_handler();
1617 if (g_blockEventsOnDrag
) return;
1618 if (!win
->m_hasVMT
) return;
1620 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1621 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1623 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1624 event
.SetEventObject( win
);
1625 win
->GetEventHandler()->ProcessEvent( event
);
1628 //-----------------------------------------------------------------------------
1629 // "button_press_event" from scrollbar
1630 //-----------------------------------------------------------------------------
1632 static gint
gtk_scrollbar_button_press_callback( GtkRange
*WXUNUSED(widget
),
1633 GdkEventButton
*WXUNUSED(gdk_event
),
1637 wxapp_install_idle_handler();
1639 // don't test here as we can release the mouse while being over
1640 // a different window than the slider
1642 // if (gdk_event->window != widget->slider) return FALSE;
1644 win
->SetScrolling( TRUE
);
1649 //-----------------------------------------------------------------------------
1650 // "button_release_event" from scrollbar
1651 //-----------------------------------------------------------------------------
1653 static gint
gtk_scrollbar_button_release_callback( GtkRange
*WXUNUSED(widget
),
1654 GdkEventButton
*WXUNUSED(gdk_event
),
1658 // don't test here as we can release the mouse while being over
1659 // a different window than the slider
1661 // if (gdk_event->window != widget->slider) return FALSE;
1663 win
->SetScrolling( FALSE
);
1668 // ----------------------------------------------------------------------------
1669 // this wxWindowBase function is implemented here (in platform-specific file)
1670 // because it is static and so couldn't be made virtual
1671 // ----------------------------------------------------------------------------
1673 wxWindow
*wxWindowBase::FindFocus()
1675 return g_focusWindow
;
1678 //-----------------------------------------------------------------------------
1679 // "realize" from m_widget
1680 //-----------------------------------------------------------------------------
1682 /* we cannot set colours and fonts before the widget has
1683 been realized, so we do this directly after realization */
1686 gtk_window_realized_callback( GtkWidget
* WXUNUSED(widget
), wxWindow
*win
)
1689 wxapp_install_idle_handler();
1691 if (win
->m_delayedFont
)
1692 win
->SetFont( win
->GetFont() );
1694 if (win
->m_delayedBackgroundColour
)
1695 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1697 if (win
->m_delayedForegroundColour
)
1698 win
->SetForegroundColour( win
->GetForegroundColour() );
1700 wxWindowCreateEvent
event( win
);
1701 event
.SetEventObject( win
);
1702 win
->GetEventHandler()->ProcessEvent( event
);
1707 //-----------------------------------------------------------------------------
1708 // InsertChild for wxWindow.
1709 //-----------------------------------------------------------------------------
1711 /* Callback for wxWindow. This very strange beast has to be used because
1712 * C++ has no virtual methods in a constructor. We have to emulate a
1713 * virtual function here as wxNotebook requires a different way to insert
1714 * a child in it. I had opted for creating a wxNotebookPage window class
1715 * which would have made this superfluous (such in the MDI window system),
1716 * but no-one was listening to me... */
1718 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1720 gtk_myfixed_put( GTK_MYFIXED(parent
->m_wxwindow
),
1721 GTK_WIDGET(child
->m_widget
),
1727 if (parent
->HasFlag(wxTAB_TRAVERSAL
))
1729 /* we now allow a window to get the focus as long as it
1730 doesn't have any children. */
1731 GTK_WIDGET_UNSET_FLAGS( parent
->m_wxwindow
, GTK_CAN_FOCUS
);
1735 //-----------------------------------------------------------------------------
1737 //-----------------------------------------------------------------------------
1739 wxWindow
* wxGetActiveWindow()
1741 return g_focusWindow
;
1744 //-----------------------------------------------------------------------------
1746 //-----------------------------------------------------------------------------
1748 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
1750 void wxWindow::Init()
1756 m_widget
= (GtkWidget
*) NULL
;
1757 m_wxwindow
= (GtkWidget
*) NULL
;
1767 m_needParent
= TRUE
;
1768 m_isBeingDeleted
= FALSE
;
1770 m_hasScrolling
= FALSE
;
1771 m_isScrolling
= FALSE
;
1773 m_hAdjust
= (GtkAdjustment
*) NULL
;
1774 m_vAdjust
= (GtkAdjustment
*) NULL
;
1775 m_oldHorizontalPos
= 0.0;
1776 m_oldVerticalPos
= 0.0;
1779 m_scrollGC
= (GdkGC
*) NULL
;
1780 m_widgetStyle
= (GtkStyle
*) NULL
;
1782 m_insertCallback
= (wxInsertChildFunction
) NULL
;
1784 m_isStaticBox
= FALSE
;
1785 m_isRadioButton
= FALSE
;
1786 m_acceptsFocus
= FALSE
;
1788 m_cursor
= *wxSTANDARD_CURSOR
;
1791 wxWindow::wxWindow()
1796 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1797 const wxPoint
&pos
, const wxSize
&size
,
1798 long style
, const wxString
&name
)
1802 Create( parent
, id
, pos
, size
, style
, name
);
1805 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1806 const wxPoint
&pos
, const wxSize
&size
,
1807 long style
, const wxString
&name
)
1809 if (!PreCreation( parent
, pos
, size
) ||
1810 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
1812 wxFAIL_MSG( T("wxWindow creation failed") );
1816 m_insertCallback
= wxInsertChildInWindow
;
1818 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
1819 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1822 debug_focus_in( m_widget
, T("wxWindow::m_widget"), name
);
1825 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
1828 debug_focus_in( scrolledWindow
->hscrollbar
, T("wxWindow::hsrcollbar"), name
);
1829 debug_focus_in( scrolledWindow
->vscrollbar
, T("wxWindow::vsrcollbar"), name
);
1832 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1833 scroll_class
->scrollbar_spacing
= 0;
1835 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1837 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
1838 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
1840 m_wxwindow
= gtk_myfixed_new();
1843 debug_focus_in( m_wxwindow
, T("wxWindow::m_wxwindow"), name
);
1846 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
1848 #if (GTK_MINOR_VERSION > 0)
1849 GtkMyFixed
*myfixed
= GTK_MYFIXED(m_wxwindow
);
1851 if (HasFlag(wxRAISED_BORDER
))
1853 gtk_myfixed_set_shadow_type( myfixed
, GTK_MYSHADOW_OUT
);
1855 else if (HasFlag(wxSUNKEN_BORDER
))
1857 gtk_myfixed_set_shadow_type( myfixed
, GTK_MYSHADOW_IN
);
1859 else if (HasFlag(wxSIMPLE_BORDER
))
1861 gtk_myfixed_set_shadow_type( myfixed
, GTK_MYSHADOW_THIN
);
1865 gtk_myfixed_set_shadow_type( myfixed
, GTK_MYSHADOW_NONE
);
1867 #else // GTK_MINOR_VERSION == 0
1868 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
1870 if (HasFlag(wxRAISED_BORDER
))
1872 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
1874 else if (HasFlag(wxSUNKEN_BORDER
))
1876 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
1880 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
1882 #endif // GTK_MINOR_VERSION
1884 if (HasFlag(wxTAB_TRAVERSAL
))
1886 /* we now allow a window to get the focus as long as it
1887 doesn't have any children. */
1888 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1889 m_acceptsFocus
= FALSE
;
1893 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1894 m_acceptsFocus
= TRUE
;
1897 #if (GTK_MINOR_VERSION == 0)
1898 // shut the viewport up
1899 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1900 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1901 #endif // GTK_MINOR_VERSION == 0
1903 // I _really_ don't want scrollbars in the beginning
1904 m_vAdjust
->lower
= 0.0;
1905 m_vAdjust
->upper
= 1.0;
1906 m_vAdjust
->value
= 0.0;
1907 m_vAdjust
->step_increment
= 1.0;
1908 m_vAdjust
->page_increment
= 1.0;
1909 m_vAdjust
->page_size
= 5.0;
1910 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
1911 m_hAdjust
->lower
= 0.0;
1912 m_hAdjust
->upper
= 1.0;
1913 m_hAdjust
->value
= 0.0;
1914 m_hAdjust
->step_increment
= 1.0;
1915 m_hAdjust
->page_increment
= 1.0;
1916 m_hAdjust
->page_size
= 5.0;
1917 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1919 // these handlers block mouse events to any window during scrolling such as
1920 // motion events and prevent GTK and wxWindows from fighting over where the
1923 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
1924 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1926 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
1927 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1929 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
1930 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1932 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
1933 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1935 // these handlers get notified when screen updates are required either when
1936 // scrolling or when the window size (and therefore scrollbar configuration)
1939 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
1940 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
1941 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
1942 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
1944 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
1945 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
1946 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
1947 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
1949 gtk_widget_show( m_wxwindow
);
1952 m_parent
->DoAddChild( this );
1961 wxWindow::~wxWindow()
1963 m_isBeingDeleted
= TRUE
;
1972 m_parent
->RemoveChild( this );
1976 gtk_style_unref( m_widgetStyle
);
1977 m_widgetStyle
= (GtkStyle
*) NULL
;
1982 gdk_gc_unref( m_scrollGC
);
1983 m_scrollGC
= (GdkGC
*) NULL
;
1988 gtk_widget_destroy( m_wxwindow
);
1989 m_wxwindow
= (GtkWidget
*) NULL
;
1994 gtk_widget_destroy( m_widget
);
1995 m_widget
= (GtkWidget
*) NULL
;
1999 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2001 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, T("Need complete parent.") );
2003 /* this turns -1 into 20 so that a minimal window is
2004 visible even although -1,-1 has been given as the
2005 size of the window. the same trick is used in other
2006 ports and should make debugging easier */
2007 m_width
= WidthDefault(size
.x
);
2008 m_height
= HeightDefault(size
.y
);
2013 /* some reasonable defaults */
2018 m_x
= (gdk_screen_width () - m_width
) / 2;
2019 if (m_x
< 10) m_x
= 10;
2023 m_y
= (gdk_screen_height () - m_height
) / 2;
2024 if (m_y
< 10) m_y
= 10;
2031 void wxWindow::PostCreation()
2033 wxASSERT_MSG( (m_widget
!= NULL
), T("invalid window") );
2037 /* these get reported to wxWindows -> wxPaintEvent */
2038 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2039 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2041 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2042 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2044 #if (GTK_MINOR_VERSION > 0)
2045 /* these are called when the "sunken", "raised" or "simple" borders are drawn */
2046 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2047 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2049 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2050 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2054 GtkWidget
*connect_widget
= GetConnectWidget();
2056 ConnectWidget( connect_widget
);
2058 /* we cannot set colours, fonts and cursors before the widget has
2059 been realized, so we do this directly after realization */
2060 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2061 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2066 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2068 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2069 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2071 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2072 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2074 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2075 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2077 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2078 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2080 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2081 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2083 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
2084 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2086 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
2087 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2089 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2090 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2092 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2093 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2096 bool wxWindow::Destroy()
2098 wxASSERT_MSG( (m_widget
!= NULL
), T("invalid window") );
2102 return wxWindowBase::Destroy();
2105 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2107 wxASSERT_MSG( (m_widget
!= NULL
), T("invalid window") );
2108 wxASSERT_MSG( (m_parent
!= NULL
), T("wxWindow::SetSize requires parent.\n") );
2110 if (m_resizing
) return; /* I don't like recursions */
2113 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2115 /* don't set the size for children of wxNotebook, just take the values. */
2123 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2125 if (x
!= -1) m_x
= x
;
2126 if (y
!= -1) m_y
= y
;
2127 if (width
!= -1) m_width
= width
;
2128 if (height
!= -1) m_height
= height
;
2138 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2140 if (width
== -1) m_width
= 80;
2143 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2145 if (height
== -1) m_height
= 26;
2148 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2149 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2150 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2151 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2154 int bottom_border
= 0;
2156 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2158 /* the default button has a border around it */
2163 /* this is the result of hours of debugging: the following code
2164 means that if we have a m_wxwindow and we set the size of
2165 m_widget, m_widget (which is a GtkScrolledWindow) does NOT
2166 automatically propagate its size down to its m_wxwindow,
2167 which is its client area. therefore, we have to tell the
2168 client area directly that it has to resize itself.
2169 this will lead to that m_widget (GtkScrolledWindow) will
2170 calculate how much size it needs for scrollbars etc and
2171 it will then call XXX_size_allocate of its child, which
2172 is m_wxwindow. m_wxwindow in turn will do the same with its
2173 children and so on. problems can arise if this happens
2174 before all the children have been realized as some widgets
2175 stupidy need to be realized during XXX_size_allocate (e.g.
2176 GtkNotebook) and they will segv if called otherwise. this
2177 emergency is tested in gtk_myfixed_size_allocate. Normally
2178 this shouldn't be needed and only gtk_widget_queue_resize()
2179 should be enough to provoke a resize at the next appropriate
2180 moment, but this seems to fail, e.g. when a wxNotebook contains
2181 a wxSplitterWindow: the splitter window's children won't
2182 show up properly resized then. */
2184 gtk_myfixed_set_size( GTK_MYFIXED(m_parent
->m_wxwindow
),
2189 m_height
+border
+bottom_border
);
2194 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2195 event
.SetEventObject( this );
2196 GetEventHandler()->ProcessEvent( event
);
2201 void wxWindow::OnInternalIdle()
2203 wxCursor cursor
= m_cursor
;
2204 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2208 /* I now set the cursor the anew in every OnInternalIdle call
2209 as setting the cursor in a parent window also effects the
2210 windows above so that checking for the current cursor is
2215 GdkWindow
*window
= m_wxwindow
->window
;
2217 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2219 if (!g_globalCursor
.Ok())
2220 cursor
= *wxSTANDARD_CURSOR
;
2222 window
= m_widget
->window
;
2223 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2224 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2230 GdkWindow
*window
= m_widget
->window
;
2231 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2232 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2240 void wxWindow::DoGetSize( int *width
, int *height
) const
2242 wxCHECK_RET( (m_widget
!= NULL
), T("invalid window") );
2244 if (width
) (*width
) = m_width
;
2245 if (height
) (*height
) = m_height
;
2248 void wxWindow::DoSetClientSize( int width
, int height
)
2250 wxCHECK_RET( (m_widget
!= NULL
), T("invalid window") );
2254 SetSize( width
, height
);
2261 #if (GTK_MINOR_VERSION == 0)
2262 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2266 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2267 #if 0 // unused - if this is ok, just remove this line (VZ)
2268 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2271 GtkWidget
*viewport
= scroll_window
->viewport
;
2272 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2274 dw
+= 2 * viewport_class
->xthickness
;
2275 dh
+= 2 * viewport_class
->ythickness
;
2279 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2281 /* when using GTK 1.2 we set the shadow border size to 2 */
2285 if (HasFlag(wxSIMPLE_BORDER
))
2287 /* when using GTK 1.2 we set the simple border size to 1 */
2296 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2297 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2299 we use this instead: range.slider_width = 11 + 2*2pts edge
2302 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2303 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2305 if (scroll_window
->vscrollbar_visible
)
2307 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2308 dw
+= scroll_class
->scrollbar_spacing
;
2311 if (scroll_window
->hscrollbar_visible
)
2313 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2314 dh
+= scroll_class
->scrollbar_spacing
;
2318 SetSize( width
+dw
, height
+dh
);
2322 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2324 wxCHECK_RET( (m_widget
!= NULL
), T("invalid window") );
2328 if (width
) (*width
) = m_width
;
2329 if (height
) (*height
) = m_height
;
2336 #if (GTK_MINOR_VERSION == 0)
2337 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2341 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2342 #if 0 // unused - if this is ok, just remove this line (VZ)
2343 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2346 GtkWidget
*viewport
= scroll_window
->viewport
;
2347 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2349 dw
+= 2 * viewport_class
->xthickness
;
2350 dh
+= 2 * viewport_class
->ythickness
;
2354 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2356 /* when using GTK 1.2 we set the shadow border size to 2 */
2360 if (HasFlag(wxSIMPLE_BORDER
))
2362 /* when using GTK 1.2 we set the simple border size to 1 */
2370 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2371 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2373 we use this instead: range.slider_width = 11 + 2*2pts edge
2376 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2377 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2379 if (scroll_window
->vscrollbar_visible
)
2381 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2382 dw
+= scroll_class
->scrollbar_spacing
;
2385 if (scroll_window
->hscrollbar_visible
)
2387 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2388 dh
+= scroll_class
->scrollbar_spacing
;
2392 if (width
) (*width
) = m_width
- dw
;
2393 if (height
) (*height
) = m_height
- dh
;
2397 void wxWindow::DoGetPosition( int *x
, int *y
) const
2399 wxCHECK_RET( (m_widget
!= NULL
), T("invalid window") );
2405 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2407 wxCHECK_RET( (m_widget
!= NULL
), T("invalid window") );
2409 if (!m_widget
->window
) return;
2411 GdkWindow
*source
= (GdkWindow
*) NULL
;
2413 source
= m_wxwindow
->window
;
2415 source
= m_widget
->window
;
2419 gdk_window_get_origin( source
, &org_x
, &org_y
);
2423 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2425 org_x
+= m_widget
->allocation
.x
;
2426 org_y
+= m_widget
->allocation
.y
;
2434 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2436 wxCHECK_RET( (m_widget
!= NULL
), T("invalid window") );
2438 if (!m_widget
->window
) return;
2440 GdkWindow
*source
= (GdkWindow
*) NULL
;
2442 source
= m_wxwindow
->window
;
2444 source
= m_widget
->window
;
2448 gdk_window_get_origin( source
, &org_x
, &org_y
);
2452 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2454 org_x
+= m_widget
->allocation
.x
;
2455 org_y
+= m_widget
->allocation
.y
;
2463 bool wxWindow::Show( bool show
)
2465 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, T("invalid window") );
2467 if (!wxWindowBase::Show(show
))
2474 gtk_widget_show( m_widget
);
2476 gtk_widget_hide( m_widget
);
2481 bool wxWindow::Enable( bool enable
)
2483 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, T("invalid window") );
2485 if (!wxWindowBase::Enable(enable
))
2491 gtk_widget_set_sensitive( m_widget
, enable
);
2493 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2498 int wxWindow::GetCharHeight() const
2500 wxCHECK_MSG( (m_widget
!= NULL
), 12, T("invalid window") );
2502 wxCHECK_MSG( m_font
.Ok(), 12, T("invalid font") );
2504 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2506 return font
->ascent
+ font
->descent
;
2509 int wxWindow::GetCharWidth() const
2511 wxCHECK_MSG( (m_widget
!= NULL
), 8, T("invalid window") );
2513 wxCHECK_MSG( m_font
.Ok(), 8, T("invalid font") );
2515 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2517 return gdk_string_width( font
, "H" );
2520 void wxWindow::GetTextExtent( const wxString
& string
,
2524 int *externalLeading
,
2525 const wxFont
*theFont
) const
2527 wxFont fontToUse
= m_font
;
2528 if (theFont
) fontToUse
= *theFont
;
2530 wxCHECK_RET( fontToUse
.Ok(), T("invalid font") );
2532 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2533 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2534 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2535 if (descent
) (*descent
) = font
->descent
;
2536 if (externalLeading
) (*externalLeading
) = 0; // ??
2539 void wxWindow::SetFocus()
2541 wxCHECK_RET( (m_widget
!= NULL
), T("invalid window") );
2543 GtkWidget
*connect_widget
= GetConnectWidget();
2546 if (GTK_WIDGET_CAN_FOCUS(connect_widget
) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
2548 gtk_widget_grab_focus (connect_widget
);
2550 else if (GTK_IS_CONTAINER(connect_widget
))
2552 gtk_container_focus( GTK_CONTAINER(connect_widget
), GTK_DIR_TAB_FORWARD
);
2560 bool wxWindow::AcceptsFocus() const
2562 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2565 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2567 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, T("invalid window") );
2569 wxWindow
*oldParent
= m_parent
,
2570 *newParent
= (wxWindow
*)newParentBase
;
2572 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2574 if ( !wxWindowBase::Reparent(newParent
) )
2577 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2579 /* prevent GTK from deleting the widget arbitrarily */
2580 gtk_widget_ref( m_widget
);
2584 gtk_container_remove( GTK_CONTAINER(oldParent
->m_wxwindow
), m_widget
);
2587 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2591 /* insert GTK representation */
2592 (*(newParent
->m_insertCallback
))(newParent
, this);
2595 /* reverse: prevent GTK from deleting the widget arbitrarily */
2596 gtk_widget_unref( m_widget
);
2601 void wxWindow::DoAddChild(wxWindow
*child
)
2603 wxASSERT_MSG( (m_widget
!= NULL
), T("invalid window") );
2605 wxASSERT_MSG( (child
!= NULL
), T("invalid child window") );
2607 wxASSERT_MSG( (m_insertCallback
!= NULL
), T("invalid child insertion function") );
2612 /* insert GTK representation */
2613 (*m_insertCallback
)(this, child
);
2616 void wxWindow::Raise()
2618 wxCHECK_RET( (m_widget
!= NULL
), T("invalid window") );
2620 if (!m_widget
->window
) return;
2622 gdk_window_raise( m_widget
->window
);
2625 void wxWindow::Lower()
2627 wxCHECK_RET( (m_widget
!= NULL
), T("invalid window") );
2629 if (!m_widget
->window
) return;
2631 gdk_window_lower( m_widget
->window
);
2634 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2636 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, T("invalid window") );
2638 return wxWindowBase::SetCursor( cursor
);
2641 void wxWindow::WarpPointer( int x
, int y
)
2643 wxCHECK_RET( (m_widget
!= NULL
), T("invalid window") );
2645 GtkWidget
*connect_widget
= GetConnectWidget();
2646 if (connect_widget
->window
)
2648 /* we provide this function ourselves as it is
2650 gdk_window_warp_pointer( connect_widget
->window
, x
, y
);
2654 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2656 wxCHECK_RET( (m_widget
!= NULL
), T("invalid window") );
2658 if (!m_widget
->window
) return;
2660 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2664 gdk_window_clear_area( m_wxwindow
->window
,
2666 rect
->width
, rect
->height
);
2670 gdk_window_clear( m_wxwindow
->window
);
2678 /* call the callback directly for preventing GTK from
2679 clearing the background */
2682 GetClientSize( &w
, &h
);
2684 GetUpdateRegion().Union( 0, 0, w
, h
);
2685 wxPaintEvent
event( GetId() );
2686 event
.SetEventObject( this );
2687 GetEventHandler()->ProcessEvent( event
);
2688 GetUpdateRegion().Clear();
2692 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2700 /* call the callback directly for preventing GTK from
2701 clearing the background */
2702 GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
2703 wxPaintEvent
event( GetId() );
2704 event
.SetEventObject( this );
2705 GetEventHandler()->ProcessEvent( event
);
2706 GetUpdateRegion().Clear();
2710 GdkRectangle gdk_rect
;
2711 gdk_rect
.x
= rect
->x
;
2712 gdk_rect
.y
= rect
->y
;
2713 gdk_rect
.width
= rect
->width
;
2714 gdk_rect
.height
= rect
->height
;
2716 gtk_widget_draw( m_widget
, &gdk_rect
);
2721 void wxWindow::Clear()
2723 wxCHECK_RET( m_widget
!= NULL
, T("invalid window") );
2725 if (!m_widget
->window
) return;
2727 if (m_wxwindow
&& m_wxwindow
->window
)
2729 gdk_window_clear( m_wxwindow
->window
);
2734 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2736 wxWindowBase::DoSetToolTip(tip
);
2739 m_tooltip
->Apply( this );
2742 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2744 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
2746 #endif // wxUSE_TOOLTIPS
2748 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2750 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, T("invalid window") );
2752 if (!wxWindowBase::SetBackgroundColour(colour
))
2754 // don't leave if the GTK widget has just
2756 if (!m_delayedBackgroundColour
) return FALSE
;
2759 GtkWidget
*connect_widget
= GetConnectWidget();
2760 if (!connect_widget
->window
)
2762 // indicate that a new style has been set
2763 // but it couldn't get applied as the
2764 // widget hasn't been realized yet.
2765 m_delayedBackgroundColour
= TRUE
;
2767 // pretend we have done something
2771 if (m_wxwindow
&& m_wxwindow
->window
)
2773 /* wxMSW doesn't clear the window here. I don't do that either to
2774 provide compatibility. call Clear() to do the job. */
2776 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_wxwindow
->window
) );
2777 gdk_window_set_background( m_wxwindow
->window
, m_backgroundColour
.GetColor() );
2780 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2781 if (sysbg
== m_backgroundColour
)
2783 m_backgroundColour
= wxNullColour
;
2785 m_backgroundColour
= sysbg
;
2795 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
2797 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, T("invalid window") );
2799 if (!wxWindowBase::SetForegroundColour(colour
))
2801 // don't leave if the GTK widget has just
2803 if (!m_delayedForegroundColour
) return FALSE
;
2806 GtkWidget
*connect_widget
= GetConnectWidget();
2807 if (!connect_widget
->window
)
2809 // indicate that a new style has been set
2810 // but it couldn't get applied as the
2811 // widget hasn't been realized yet.
2812 m_delayedForegroundColour
= TRUE
;
2814 // pretend we have done something
2818 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2819 if ( sysbg
== m_backgroundColour
)
2821 m_backgroundColour
= wxNullColour
;
2823 m_backgroundColour
= sysbg
;
2833 GtkStyle
*wxWindow::GetWidgetStyle()
2835 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
2837 m_widgetStyle
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
2839 return m_widgetStyle
;
2842 void wxWindow::SetWidgetStyle()
2844 GtkStyle
*style
= GetWidgetStyle();
2846 gdk_font_unref( style
->font
);
2847 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2849 if (m_foregroundColour
.Ok())
2851 m_foregroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2852 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
2853 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
2854 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
2857 if (m_backgroundColour
.Ok())
2859 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2860 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2861 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2862 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2863 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2864 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2865 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2866 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2867 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2871 void wxWindow::ApplyWidgetStyle()
2875 //-----------------------------------------------------------------------------
2876 // Pop-up menu stuff
2877 //-----------------------------------------------------------------------------
2879 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
2881 *is_waiting
= FALSE
;
2884 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2886 menu
->SetInvokingWindow( win
);
2887 wxNode
*node
= menu
->GetItems().First();
2890 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
2891 if (menuitem
->IsSubMenu())
2893 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2895 node
= node
->Next();
2899 static gint gs_pop_x
= 0;
2900 static gint gs_pop_y
= 0;
2902 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
2906 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
2911 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
2913 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, T("invalid window") );
2915 wxCHECK_MSG( menu
!= NULL
, FALSE
, T("invalid popup-menu") );
2917 SetInvokingWindow( menu
, this );
2924 bool is_waiting
= TRUE
;
2926 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
2927 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
2930 GTK_MENU(menu
->m_menu
),
2931 (GtkWidget
*) NULL
, // parent menu shell
2932 (GtkWidget
*) NULL
, // parent menu item
2933 (GtkMenuPositionFunc
) pop_pos_callback
,
2934 (gpointer
) this, // client data
2935 0, // button used to activate it
2936 0 //gs_timeLastClick // the time of activation
2941 while (gtk_events_pending())
2942 gtk_main_iteration();
2948 #if wxUSE_DRAG_AND_DROP
2950 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2952 wxCHECK_RET( m_widget
!= NULL
, T("invalid window") );
2954 GtkWidget
*dnd_widget
= GetConnectWidget();
2956 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
2958 if (m_dropTarget
) delete m_dropTarget
;
2959 m_dropTarget
= dropTarget
;
2961 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
2964 #endif // wxUSE_DRAG_AND_DROP
2966 GtkWidget
* wxWindow::GetConnectWidget()
2968 GtkWidget
*connect_widget
= m_widget
;
2969 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2971 return connect_widget
;
2974 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2976 if (m_wxwindow
) return (window
== m_wxwindow
->window
);
2977 return (window
== m_widget
->window
);
2980 bool wxWindow::SetFont( const wxFont
&font
)
2982 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, T("invalid window") );
2984 if (!wxWindowBase::SetFont(font
))
2986 // don't leave if the GTK widget has just
2988 if (!m_delayedFont
) return FALSE
;
2991 GtkWidget
*connect_widget
= GetConnectWidget();
2992 if (!connect_widget
->window
)
2994 // indicate that a new style has been set
2995 // but it couldn't get applied as the
2996 // widget hasn't been realized yet.
2997 m_delayedFont
= TRUE
;
2999 // pretend we have done something
3003 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3004 if ( sysbg
== m_backgroundColour
)
3006 m_backgroundColour
= wxNullColour
;
3008 m_backgroundColour
= sysbg
;
3018 void wxWindow::CaptureMouse()
3020 wxCHECK_RET( m_widget
!= NULL
, T("invalid window") );
3022 wxCHECK_RET( g_captureWindow
== NULL
, T("CaptureMouse called twice") );
3024 GtkWidget
*connect_widget
= GetConnectWidget();
3025 if (!connect_widget
->window
) return;
3027 gdk_pointer_grab( connect_widget
->window
, FALSE
,
3029 (GDK_BUTTON_PRESS_MASK
|
3030 GDK_BUTTON_RELEASE_MASK
|
3031 GDK_POINTER_MOTION_HINT_MASK
|
3032 GDK_POINTER_MOTION_MASK
),
3034 m_cursor
.GetCursor(),
3036 g_captureWindow
= this;
3039 void wxWindow::ReleaseMouse()
3041 wxCHECK_RET( m_widget
!= NULL
, T("invalid window") );
3043 wxCHECK_RET( g_captureWindow
, T("ReleaseMouse called twice") );
3045 GtkWidget
*connect_widget
= GetConnectWidget();
3046 if (!connect_widget
->window
) return;
3048 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
3049 g_captureWindow
= (wxWindow
*) NULL
;
3052 bool wxWindow::IsRetained() const
3057 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3058 int range
, bool refresh
)
3060 wxCHECK_RET( m_widget
!= NULL
, T("invalid window") );
3062 wxCHECK_RET( m_wxwindow
!= NULL
, T("window needs client area for scrolling") );
3064 m_hasScrolling
= TRUE
;
3066 if (orient
== wxHORIZONTAL
)
3068 float fpos
= (float)pos
;
3069 float frange
= (float)range
;
3070 float fthumb
= (float)thumbVisible
;
3071 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3072 if (fpos
< 0.0) fpos
= 0.0;
3074 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3075 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3077 SetScrollPos( orient
, pos
, refresh
);
3081 m_oldHorizontalPos
= fpos
;
3083 m_hAdjust
->lower
= 0.0;
3084 m_hAdjust
->upper
= frange
;
3085 m_hAdjust
->value
= fpos
;
3086 m_hAdjust
->step_increment
= 1.0;
3087 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3088 m_hAdjust
->page_size
= fthumb
;
3092 float fpos
= (float)pos
;
3093 float frange
= (float)range
;
3094 float fthumb
= (float)thumbVisible
;
3095 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3096 if (fpos
< 0.0) fpos
= 0.0;
3098 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3099 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3101 SetScrollPos( orient
, pos
, refresh
);
3105 m_oldVerticalPos
= fpos
;
3107 m_vAdjust
->lower
= 0.0;
3108 m_vAdjust
->upper
= frange
;
3109 m_vAdjust
->value
= fpos
;
3110 m_vAdjust
->step_increment
= 1.0;
3111 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3112 m_vAdjust
->page_size
= fthumb
;
3115 if (orient
== wxHORIZONTAL
)
3116 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3118 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3121 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3123 wxCHECK_RET( m_widget
!= NULL
, T("invalid window") );
3125 wxCHECK_RET( m_wxwindow
!= NULL
, T("window needs client area for scrolling") );
3127 if (orient
== wxHORIZONTAL
)
3129 float fpos
= (float)pos
;
3130 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3131 if (fpos
< 0.0) fpos
= 0.0;
3132 m_oldHorizontalPos
= fpos
;
3134 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3135 m_hAdjust
->value
= fpos
;
3139 float fpos
= (float)pos
;
3140 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3141 if (fpos
< 0.0) fpos
= 0.0;
3142 m_oldVerticalPos
= fpos
;
3144 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3145 m_vAdjust
->value
= fpos
;
3152 if (m_wxwindow
->window
)
3154 if (orient
== wxHORIZONTAL
)
3155 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3157 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3164 int wxWindow::GetScrollThumb( int orient
) const
3166 wxCHECK_MSG( m_widget
!= NULL
, 0, T("invalid window") );
3168 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, T("window needs client area for scrolling") );
3170 if (orient
== wxHORIZONTAL
)
3171 return (int)(m_hAdjust
->page_size
+0.5);
3173 return (int)(m_vAdjust
->page_size
+0.5);
3176 int wxWindow::GetScrollPos( int orient
) const
3178 wxCHECK_MSG( m_widget
!= NULL
, 0, T("invalid window") );
3180 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, T("window needs client area for scrolling") );
3182 if (orient
== wxHORIZONTAL
)
3183 return (int)(m_hAdjust
->value
+0.5);
3185 return (int)(m_vAdjust
->value
+0.5);
3188 int wxWindow::GetScrollRange( int orient
) const
3190 wxCHECK_MSG( m_widget
!= NULL
, 0, T("invalid window") );
3192 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, T("window needs client area for scrolling") );
3194 if (orient
== wxHORIZONTAL
)
3195 return (int)(m_hAdjust
->upper
+0.5);
3197 return (int)(m_vAdjust
->upper
+0.5);
3200 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3202 wxCHECK_RET( m_widget
!= NULL
, T("invalid window") );
3204 wxCHECK_RET( m_wxwindow
!= NULL
, T("window needs client area for scrolling") );
3208 m_scrollGC
= gdk_gc_new( m_wxwindow
->window
);
3209 gdk_gc_set_exposures( m_scrollGC
, TRUE
);
3212 wxNode
*node
= m_children
.First();
3215 wxWindow
*child
= (wxWindow
*) node
->Data();
3218 child
->GetSize( &sx
, &sy
);
3219 child
->SetSize( child
->m_x
+ dx
, child
->m_y
+ dy
, sx
, sy
, wxSIZE_ALLOW_MINUS_ONE
);
3220 node
= node
->Next();
3225 GetClientSize( &cw
, &ch
);
3226 int w
= cw
- abs(dx
);
3227 int h
= ch
- abs(dy
);
3229 if ((h
< 0) || (w
< 0))
3237 if (dx
< 0) s_x
= -dx
;
3238 if (dy
< 0) s_y
= -dy
;
3241 if (dx
> 0) d_x
= dx
;
3242 if (dy
> 0) d_y
= dy
;
3244 gdk_window_copy_area( m_wxwindow
->window
, m_scrollGC
, d_x
, d_y
,
3245 m_wxwindow
->window
, s_x
, s_y
, w
, h
);
3248 if (dx
< 0) rect
.x
= cw
+dx
; else rect
.x
= 0;
3249 if (dy
< 0) rect
.y
= ch
+dy
; else rect
.y
= 0;
3250 if (dy
!= 0) rect
.width
= cw
; else rect
.width
= abs(dx
);
3251 if (dx
!= 0) rect
.height
= ch
; else rect
.height
= abs(dy
);
3253 Refresh( TRUE
, &rect
);
3257 void wxWindow::SetScrolling(bool scroll
)
3259 m_isScrolling
= g_blockEventsOnScroll
= scroll
;