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"
40 #include "wx/thread.h"
47 #include <gdk/gdkprivate.h>
48 #include <gdk/gdkkeysyms.h>
49 #include <wx/gtk/win_gtk.h>
53 //-----------------------------------------------------------------------------
54 // documentation on internals
55 //-----------------------------------------------------------------------------
58 I have been asked several times about writing some documentation about
59 the GTK port of wxWindows, especially its internal structures. Obviously,
60 you cannot understand wxGTK without knowing a little about the GTK, but
61 some more information about what the wxWindow, which is the base class
62 for all other window classes, does seems required as well.
66 What does wxWindow do? It contains the common interface for the following
67 jobs of its descendants:
69 1) Define the rudimentary behaviour common to all window classes, such as
70 resizing, intercepting user input (so as to make it possible to use these
71 events for special purposes in a derived class), window names etc.
73 2) Provide the possibility to contain and manage children, if the derived
74 class is allowed to contain children, which holds true for those window
75 classes which do not display a native GTK widget. To name them, these
76 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
77 work classes are a special case and are handled a bit differently from
78 the rest. The same holds true for the wxNotebook class.
80 3) Provide the possibility to draw into a client area of a window. This,
81 too, only holds true for classes that do not display a native GTK widget
84 4) Provide the entire mechanism for scrolling widgets. This actual inter-
85 face for this is usually in wxScrolledWindow, but the GTK implementation
88 5) A multitude of helper or extra methods for special purposes, such as
89 Drag'n'Drop, managing validators etc.
91 6) Display a border (sunken, raised, simple or none).
93 Normally one might expect, that one wxWindows window would always correspond
94 to one GTK widget. Under GTK, there is no such allround widget that has all
95 the functionality. Moreover, the GTK defines a client area as a different
96 widget from the actual widget you are handling. Last but not least some
97 special classes (e.g. wxFrame) handle different categories of widgets and
98 still have the possibility to draw something in the client area.
99 It was therefore required to write a special purpose GTK widget, that would
100 represent a client area in the sense of wxWindows capable to do the jobs
101 2), 3) and 4). I have written this class and it resides in win_gtk.c of
104 All windows must have a widget, with which they interact with other under-
105 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
106 thw wxWindow class has a member variable called m_widget which holds a
107 pointer to this widget. When the window class represents a GTK native widget,
108 this is (in most cases) the only GTK widget the class manages. E.g. the
109 wxStatitText class handles only a GtkLabel widget a pointer to which you
110 can find in m_widget (defined in wxWindow)
112 When the class has a client area for drawing into and for containing children
113 it has to handle the client area widget (of the type GtkPizza, defined in
114 win_gtk.c), but there could be any number of widgets, handled by a class
115 The common rule for all windows is only, that the widget that interacts with
116 the rest of GTK must be referenced in m_widget and all other widgets must be
117 children of this widget on the GTK level. The top-most widget, which also
118 represents the client area, must be in the m_wxwindow field and must be of
121 As I said, the window classes that display a GTK native widget only have
122 one widget, so in the case of e.g. the wxButton class m_widget holds a
123 pointer to a GtkButton widget. But windows with client areas (for drawing
124 and children) have a m_widget field that is a pointer to a GtkScrolled-
125 Window and a m_wxwindow field that is pointer to a GtkPizza and this
126 one is (in the GTK sense) a child of the GtkScrolledWindow.
128 If the m_wxwindow field is set, then all input to this widget is inter-
129 cepted and sent to the wxWindows class. If not, all input to the widget
130 that gets pointed to by m_widget gets intercepted and sent to the class.
134 The design of scrolling in wxWindows is markedly different from that offered
135 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
136 clicking on a scrollbar belonging to scrolled window will inevitably move
137 the window. In wxWindows, the scrollbar will only emit an event, send this
138 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
139 which actually moves the window and its subchildren. Note that GtkPizza
140 memorizes how much it has been scrolled but that wxWindows forgets this
141 so that the two coordinates systems have to be kept in synch. This is done
142 in various places using the pizza->xoffset and pizza->yoffset values.
146 Singularily the most broken code in GTK is the code that is supposes to
147 inform subwindows (child windows) about new positions. Very often, duplicate
148 events are sent without changes in size or position, equally often no
149 events are sent at all (All this is due to a bug in the GtkContainer code
150 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
151 GTK's own system and it simply waits for size events for toplevel windows
152 and then iterates down the respective size events to all window. This has
153 the disadvantage, that windows might get size events before the GTK widget
154 actually has the reported size. This doesn't normally pose any problem, but
155 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
156 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
157 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
158 window that is used for OpenGl output really has that size (as reported by
163 If someone at some point of time feels the immense desire to have a look at,
164 change or attempt to optimse the Refresh() logic, this person will need an
165 intimate understanding of what a "draw" and what an "expose" events are and
166 what there are used for, in particular when used in connection with GTK's
167 own windowless widgets. Beware.
171 Cursors, too, have been a constant source of pleasure. The main difficulty
172 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
173 for the parent. To prevent this from doing too much harm, I use idle time
174 to set the cursor over and over again, starting from the toplevel windows
175 and ending with the youngest generation (speaking of parent and child windows).
176 Also don't forget that cursors (like much else) are connected to GdkWindows,
177 not GtkWidgets and that the "window" field of a GtkWidget might very well
178 point to the GdkWindow of the parent widget (-> "window less widget") and
179 that the two obviously have very different meanings.
183 //-----------------------------------------------------------------------------
185 //-----------------------------------------------------------------------------
187 extern wxList wxPendingDelete
;
188 extern bool g_blockEventsOnDrag
;
189 extern bool g_blockEventsOnScroll
;
190 extern wxCursor g_globalCursor
;
191 static wxWindow
*g_captureWindow
= (wxWindow
*) NULL
;
193 /* extern */ wxWindow
*g_focusWindow
= (wxWindow
*) NULL
;
195 // if we detect that the app has got/lost the focus, we set this variable to
196 // either TRUE or FALSE and an activate event will be sent during the next
197 // OnIdle() call and it is reset to -1: this value means that we shouldn't
198 // send any activate events at all
199 static int g_sendActivateEvent
= -1;
201 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
202 the last click here */
203 static guint32 gs_timeLastClick
= 0;
205 extern bool g_mainThreadLocked
;
207 //-----------------------------------------------------------------------------
209 //-----------------------------------------------------------------------------
214 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
216 # define DEBUG_MAIN_THREAD
219 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
220 GdkEvent
*WXUNUSED(event
),
221 const wxChar
*WXUNUSED(name
) )
224 static bool s_done = FALSE;
227 wxLog::AddTraceMask("focus");
230 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
236 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
238 // suppress warnings about gtk_debug_focus_in_callback being unused with
243 tmp
+= wxT(" FROM ");
246 wxChar
*s
= new wxChar
[tmp
.Length()+1];
250 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
251 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
256 #define DEBUG_MAIN_THREAD
259 //-----------------------------------------------------------------------------
260 // missing gdk functions
261 //-----------------------------------------------------------------------------
264 gdk_window_warp_pointer (GdkWindow
*window
,
268 GdkWindowPrivate
*priv
;
271 window
= (GdkWindow
*) &gdk_root_parent
;
273 priv
= (GdkWindowPrivate
*) window
;
275 if (!priv
->destroyed
)
277 XWarpPointer (priv
->xdisplay
,
278 None
, /* not source window -> move from anywhere */
279 priv
->xwindow
, /* dest window */
280 0, 0, 0, 0, /* not source window -> move from anywhere */
285 //-----------------------------------------------------------------------------
287 //-----------------------------------------------------------------------------
289 extern void wxapp_install_idle_handler();
290 extern bool g_isIdle
;
292 //-----------------------------------------------------------------------------
293 // local code (see below)
294 //-----------------------------------------------------------------------------
296 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
304 if (win
->m_hasScrolling
)
306 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
308 GtkRequisition vscroll_req
;
309 vscroll_req
.width
= 2;
310 vscroll_req
.height
= 2;
311 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
312 (scroll_window
->vscrollbar
, &vscroll_req
);
314 GtkRequisition hscroll_req
;
315 hscroll_req
.width
= 2;
316 hscroll_req
.height
= 2;
317 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
318 (scroll_window
->hscrollbar
, &hscroll_req
);
320 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget
)->klass
);
322 if (scroll_window
->vscrollbar_visible
)
324 dw
+= vscroll_req
.width
;
325 dw
+= scroll_class
->scrollbar_spacing
;
328 if (scroll_window
->hscrollbar_visible
)
330 dh
+= hscroll_req
.height
;
331 dh
+= scroll_class
->scrollbar_spacing
;
337 if (GTK_WIDGET_NO_WINDOW (widget
))
339 dx
+= widget
->allocation
.x
;
340 dy
+= widget
->allocation
.y
;
343 if (win
->HasFlag(wxRAISED_BORDER
))
345 gtk_draw_shadow( widget
->style
,
350 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
354 if (win
->HasFlag(wxSUNKEN_BORDER
))
356 gtk_draw_shadow( widget
->style
,
361 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
365 if (win
->HasFlag(wxSIMPLE_BORDER
))
368 gc
= gdk_gc_new( widget
->window
);
369 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
370 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
372 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
378 //-----------------------------------------------------------------------------
379 // "expose_event" of m_widget
380 //-----------------------------------------------------------------------------
382 static void gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
384 if (gdk_event
->count
> 0) return;
385 draw_frame( widget
, win
);
388 //-----------------------------------------------------------------------------
389 // "draw" of m_widget
390 //-----------------------------------------------------------------------------
392 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
394 draw_frame( widget
, win
);
397 //-----------------------------------------------------------------------------
398 // key code mapping routines
399 //-----------------------------------------------------------------------------
401 static long map_to_unmodified_wx_keysym( KeySym keysym
)
408 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
410 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
416 case GDK_Super_R
: key_code
= WXK_ALT
; break;
417 case GDK_Menu
: key_code
= WXK_MENU
; break;
418 case GDK_Help
: key_code
= WXK_HELP
; break;
419 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
420 case GDK_ISO_Left_Tab
:
421 case GDK_Tab
: key_code
= WXK_TAB
; break;
422 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
423 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
424 case GDK_Return
: key_code
= WXK_RETURN
; break;
425 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
426 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
427 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
428 case GDK_Delete
: key_code
= WXK_DELETE
; break;
429 case GDK_Home
: key_code
= WXK_HOME
; break;
430 case GDK_Left
: key_code
= WXK_LEFT
; break;
431 case GDK_Up
: key_code
= WXK_UP
; break;
432 case GDK_Right
: key_code
= WXK_RIGHT
; break;
433 case GDK_Down
: key_code
= WXK_DOWN
; break;
434 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
435 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
436 case GDK_Next
: key_code
= WXK_NEXT
; break;
437 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
438 case GDK_End
: key_code
= WXK_END
; break;
439 case GDK_Begin
: key_code
= WXK_HOME
; break;
440 case GDK_Select
: key_code
= WXK_SELECT
; break;
441 case GDK_Print
: key_code
= WXK_PRINT
; break;
442 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
443 case GDK_Insert
: key_code
= WXK_INSERT
; break;
444 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
446 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
447 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
448 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
449 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
450 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
451 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
452 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
453 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
454 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
455 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
456 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
457 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
458 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
459 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
460 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
461 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
462 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
463 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
464 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
465 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
466 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
467 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
468 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
469 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
470 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
471 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
472 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
473 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
474 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
475 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
476 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
477 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
478 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
479 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
480 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
481 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
482 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
484 case GDK_F1
: key_code
= WXK_F1
; break;
485 case GDK_F2
: key_code
= WXK_F2
; break;
486 case GDK_F3
: key_code
= WXK_F3
; break;
487 case GDK_F4
: key_code
= WXK_F4
; break;
488 case GDK_F5
: key_code
= WXK_F5
; break;
489 case GDK_F6
: key_code
= WXK_F6
; break;
490 case GDK_F7
: key_code
= WXK_F7
; break;
491 case GDK_F8
: key_code
= WXK_F8
; break;
492 case GDK_F9
: key_code
= WXK_F9
; break;
493 case GDK_F10
: key_code
= WXK_F10
; break;
494 case GDK_F11
: key_code
= WXK_F11
; break;
495 case GDK_F12
: key_code
= WXK_F12
; break;
500 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
501 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
502 key_code
= (guint
)keysym
;
510 static long map_to_wx_keysym( KeySym keysym
)
516 case GDK_Menu
: key_code
= WXK_MENU
; break;
517 case GDK_Help
: key_code
= WXK_HELP
; break;
518 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
519 case GDK_ISO_Left_Tab
:
520 case GDK_Tab
: key_code
= WXK_TAB
; break;
521 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
522 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
523 case GDK_Return
: key_code
= WXK_RETURN
; break;
524 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
525 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
526 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
527 case GDK_Delete
: key_code
= WXK_DELETE
; break;
528 case GDK_Home
: key_code
= WXK_HOME
; break;
529 case GDK_Left
: key_code
= WXK_LEFT
; break;
530 case GDK_Up
: key_code
= WXK_UP
; break;
531 case GDK_Right
: key_code
= WXK_RIGHT
; break;
532 case GDK_Down
: key_code
= WXK_DOWN
; break;
533 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
534 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
535 case GDK_Next
: key_code
= WXK_NEXT
; break;
536 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
537 case GDK_End
: key_code
= WXK_END
; break;
538 case GDK_Begin
: key_code
= WXK_HOME
; break;
539 case GDK_Select
: key_code
= WXK_SELECT
; break;
540 case GDK_Print
: key_code
= WXK_PRINT
; break;
541 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
542 case GDK_Insert
: key_code
= WXK_INSERT
; break;
543 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
545 case GDK_KP_0
: key_code
= '0'; break;
546 case GDK_KP_1
: key_code
= '1'; break;
547 case GDK_KP_2
: key_code
= '2'; break;
548 case GDK_KP_3
: key_code
= '3'; break;
549 case GDK_KP_4
: key_code
= '4'; break;
550 case GDK_KP_5
: key_code
= '5'; break;
551 case GDK_KP_6
: key_code
= '6'; break;
552 case GDK_KP_7
: key_code
= '7'; break;
553 case GDK_KP_8
: key_code
= '8'; break;
554 case GDK_KP_9
: key_code
= '9'; break;
555 case GDK_KP_Space
: key_code
= ' '; break;
556 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
557 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
558 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
559 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
560 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
561 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
562 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
563 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
564 case GDK_KP_Up
: key_code
= WXK_UP
; break;
565 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
566 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
567 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
568 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
569 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
570 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
571 case GDK_KP_End
: key_code
= WXK_END
; break;
572 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
573 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
574 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
575 case GDK_KP_Equal
: key_code
= '='; break;
576 case GDK_KP_Multiply
: key_code
= '*'; break;
577 case GDK_KP_Add
: key_code
= '+'; break;
578 case GDK_KP_Separator
: key_code
= ','; break;
579 case GDK_KP_Subtract
: key_code
= '-'; break;
580 case GDK_KP_Decimal
: key_code
= '.'; break;
581 case GDK_KP_Divide
: key_code
= '/'; break;
583 case GDK_F1
: key_code
= WXK_F1
; break;
584 case GDK_F2
: key_code
= WXK_F2
; break;
585 case GDK_F3
: key_code
= WXK_F3
; break;
586 case GDK_F4
: key_code
= WXK_F4
; break;
587 case GDK_F5
: key_code
= WXK_F5
; break;
588 case GDK_F6
: key_code
= WXK_F6
; break;
589 case GDK_F7
: key_code
= WXK_F7
; break;
590 case GDK_F8
: key_code
= WXK_F8
; break;
591 case GDK_F9
: key_code
= WXK_F9
; break;
592 case GDK_F10
: key_code
= WXK_F10
; break;
593 case GDK_F11
: key_code
= WXK_F11
; break;
594 case GDK_F12
: key_code
= WXK_F12
; break;
599 key_code
= (guint
)keysym
;
607 //-----------------------------------------------------------------------------
608 // "expose_event" of m_wxwindow
609 //-----------------------------------------------------------------------------
611 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
618 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
620 gdk_event
->area
.width
,
621 gdk_event
->area
.height
);
624 wxPrintf( "OnExpose from " );
625 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
626 wxPrintf( win->GetClassInfo()->GetClassName() );
627 wxPrintf( " %d %d %d %d\n", (int)gdk_event->area.x,
628 (int)gdk_event->area.y,
629 (int)gdk_event->area.width,
630 (int)gdk_event->area.height );
633 if (gdk_event
->count
> 0)
636 wxEraseEvent
eevent( win
->GetId() );
637 eevent
.SetEventObject( win
);
638 win
->GetEventHandler()->ProcessEvent(eevent
);
640 wxPaintEvent
event( win
->GetId() );
641 event
.SetEventObject( win
);
642 win
->GetEventHandler()->ProcessEvent( event
);
644 win
->GetUpdateRegion().Clear();
647 //-----------------------------------------------------------------------------
648 // "draw" of m_wxwindow
649 //-----------------------------------------------------------------------------
651 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
),
652 GdkRectangle
*rect
, wxWindow
*win
)
657 wxapp_install_idle_handler();
662 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
,
663 rect
->width
, rect
->height
);
666 wxPrintf( "OnDraw from " );
667 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
668 printf( win->GetClassInfo()->GetClassName() );
669 wxPrintf( " %d %d %d %d\n", (int)rect->x,
675 wxEraseEvent
eevent( win
->GetId() );
676 eevent
.SetEventObject( win
);
677 win
->GetEventHandler()->ProcessEvent(eevent
);
679 wxPaintEvent
event( win
->GetId() );
680 event
.SetEventObject( win
);
681 win
->GetEventHandler()->ProcessEvent( event
);
683 win
->GetUpdateRegion().Clear();
686 //-----------------------------------------------------------------------------
687 // "key_press_event" from any window
688 //-----------------------------------------------------------------------------
690 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
695 wxapp_install_idle_handler();
697 if (!win
->m_hasVMT
) return FALSE
;
698 if (g_blockEventsOnDrag
) return FALSE
;
702 tmp += (char)gdk_event->keyval;
703 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
704 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
709 GdkModifierType state
;
710 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
714 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
715 /* sending unknown key events doesn't really make sense */
716 if (key_code
== 0) return FALSE
;
718 wxKeyEvent
event( wxEVT_KEY_DOWN
);
719 event
.SetTimestamp( gdk_event
->time
);
720 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
721 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
722 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
723 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
724 event
.m_keyCode
= key_code
;
725 event
.m_scanCode
= gdk_event
->keyval
;
728 event
.SetEventObject( win
);
729 ret
= win
->GetEventHandler()->ProcessEvent( event
);
734 wxWindow
*ancestor
= win
;
737 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
740 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
741 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
744 if (ancestor
->m_isFrame
)
746 ancestor
= ancestor
->GetParent();
749 #endif // wxUSE_ACCEL
751 /* wxMSW doesn't send char events with Alt pressed */
752 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
753 will only be sent if it is not in an accelerator table. */
754 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
759 wxKeyEvent
event2( wxEVT_CHAR
);
760 event2
.SetTimestamp( gdk_event
->time
);
761 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
762 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
763 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
764 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
765 event2
.m_keyCode
= key_code
;
766 event2
.m_scanCode
= gdk_event
->keyval
;
769 event2
.SetEventObject( win
);
770 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
773 /* win is a control: tab can be propagated up */
775 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
776 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
777 (win
->GetParent()) &&
778 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
780 wxNavigationKeyEvent new_event
;
781 new_event
.SetEventObject( win
->GetParent() );
782 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
783 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
784 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
785 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
786 new_event
.SetCurrentFocus( win
);
787 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
790 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
792 (gdk_event
->keyval
== GDK_Escape
) )
794 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
795 new_event
.SetEventObject( win
);
796 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
799 #if (GTK_MINOR_VERSION > 0)
800 /* Pressing F10 will activate the menu bar of the top frame. */
804 (gdk_event->keyval == GDK_F10) )
806 wxWindow *ancestor = win;
809 if (wxIsKindOf(ancestor,wxFrame))
811 wxFrame *frame = (wxFrame*) ancestor;
812 wxMenuBar *menubar = frame->GetMenuBar();
815 wxNode *node = menubar->GetMenus().First();
818 wxMenu *firstMenu = (wxMenu*) node->Data();
819 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
825 ancestor = ancestor->GetParent();
833 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
840 //-----------------------------------------------------------------------------
841 // "key_release_event" from any window
842 //-----------------------------------------------------------------------------
844 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
849 wxapp_install_idle_handler();
851 if (!win
->m_hasVMT
) return FALSE
;
852 if (g_blockEventsOnDrag
) return FALSE
;
855 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
856 if (gdk_event->state & GDK_SHIFT_MASK)
857 printf( "ShiftDown.\n" );
859 printf( "ShiftUp.\n" );
860 if (gdk_event->state & GDK_CONTROL_MASK)
861 printf( "ControlDown.\n" );
863 printf( "ControlUp.\n" );
867 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
869 /* sending unknown key events doesn't really make sense */
870 if (key_code
== 0) return FALSE
;
874 GdkModifierType state
;
875 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
877 wxKeyEvent
event( wxEVT_KEY_UP
);
878 event
.SetTimestamp( gdk_event
->time
);
879 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
880 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
881 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
882 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
883 event
.m_keyCode
= key_code
;
884 event
.m_scanCode
= gdk_event
->keyval
;
887 event
.SetEventObject( win
);
889 if (win
->GetEventHandler()->ProcessEvent( event
))
891 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
898 // ----------------------------------------------------------------------------
899 // mouse event processing helper
900 // ----------------------------------------------------------------------------
902 static void AdjustEventButtonState(wxMouseEvent
& event
)
904 // GDK reports the old state of the button for a button press event, but
905 // for compatibility with MSW and common sense we want m_leftDown be TRUE
906 // for a LEFT_DOWN event, not FALSE, so we will invert
907 // left/right/middleDown for the corresponding click events
908 switch ( event
.GetEventType() )
910 case wxEVT_LEFT_DOWN
:
911 case wxEVT_LEFT_DCLICK
:
913 event
.m_leftDown
= !event
.m_leftDown
;
916 case wxEVT_MIDDLE_DOWN
:
917 case wxEVT_MIDDLE_DCLICK
:
918 case wxEVT_MIDDLE_UP
:
919 event
.m_middleDown
= !event
.m_middleDown
;
922 case wxEVT_RIGHT_DOWN
:
923 case wxEVT_RIGHT_DCLICK
:
925 event
.m_rightDown
= !event
.m_rightDown
;
930 //-----------------------------------------------------------------------------
931 // "button_press_event"
932 //-----------------------------------------------------------------------------
934 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
939 wxapp_install_idle_handler();
942 wxPrintf( wxT("1) OnButtonPress from ") );
943 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
944 wxPrintf( win->GetClassInfo()->GetClassName() );
945 wxPrintf( wxT(".\n") );
947 if (!win
->m_hasVMT
) return FALSE
;
948 if (g_blockEventsOnDrag
) return TRUE
;
949 if (g_blockEventsOnScroll
) return TRUE
;
951 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
955 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
957 gtk_widget_grab_focus (win
->m_wxwindow
);
960 wxPrintf( wxT("GrabFocus from ") );
961 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
962 wxPrintf( win->GetClassInfo()->GetClassName() );
963 wxPrintf( wxT(".\n") );
969 wxEventType event_type
= wxEVT_NULL
;
971 if (gdk_event
->button
== 1)
973 switch (gdk_event
->type
)
975 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
976 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
980 else if (gdk_event
->button
== 2)
982 switch (gdk_event
->type
)
984 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
985 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
989 else if (gdk_event
->button
== 3)
991 switch (gdk_event
->type
)
993 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
994 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
999 if ( event_type
== wxEVT_NULL
)
1001 // unknown mouse button or click type
1005 wxMouseEvent
event( event_type
);
1006 event
.SetTimestamp( gdk_event
->time
);
1007 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1008 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1009 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1010 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1011 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1012 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1013 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1015 event
.m_x
= (wxCoord
)gdk_event
->x
;
1016 event
.m_y
= (wxCoord
)gdk_event
->y
;
1018 AdjustEventButtonState(event
);
1020 // Some control don't have their own X window and thus cannot get
1023 if (!g_captureWindow
)
1025 wxCoord x
= event
.m_x
;
1026 wxCoord y
= event
.m_y
;
1027 if (win
->m_wxwindow
)
1029 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1030 x
+= pizza
->xoffset
;
1031 y
+= pizza
->yoffset
;
1034 wxNode
*node
= win
->GetChildren().First();
1037 wxWindow
*child
= (wxWindow
*)node
->Data();
1039 node
= node
->Next();
1040 if (!child
->IsShown())
1043 if (child
->m_isStaticBox
)
1045 // wxStaticBox is transparent in the box itself
1046 int xx1
= child
->m_x
;
1047 int yy1
= child
->m_y
;
1048 int xx2
= child
->m_x
+ child
->m_width
;
1049 int yy2
= child
->m_x
+ child
->m_height
;
1052 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1054 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1056 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1058 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1061 event
.m_x
-= child
->m_x
;
1062 event
.m_y
-= child
->m_y
;
1069 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1070 (child
->m_x
<= x
) &&
1071 (child
->m_y
<= y
) &&
1072 (child
->m_x
+child
->m_width
>= x
) &&
1073 (child
->m_y
+child
->m_height
>= y
))
1076 event
.m_x
-= child
->m_x
;
1077 event
.m_y
-= child
->m_y
;
1084 event
.SetEventObject( win
);
1086 gs_timeLastClick
= gdk_event
->time
;
1089 wxPrintf( wxT("2) OnButtonPress from ") );
1090 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1091 wxPrintf( win->GetClassInfo()->GetClassName() );
1092 wxPrintf( wxT(".\n") );
1095 if (win
->GetEventHandler()->ProcessEvent( event
))
1097 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1104 //-----------------------------------------------------------------------------
1105 // "button_release_event"
1106 //-----------------------------------------------------------------------------
1108 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1113 wxapp_install_idle_handler();
1115 if (!win
->m_hasVMT
) return FALSE
;
1116 if (g_blockEventsOnDrag
) return FALSE
;
1117 if (g_blockEventsOnScroll
) return FALSE
;
1119 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1122 printf( "OnButtonRelease from " );
1123 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1124 printf( win->GetClassInfo()->GetClassName() );
1128 wxEventType event_type
= wxEVT_NULL
;
1130 switch (gdk_event
->button
)
1132 case 1: event_type
= wxEVT_LEFT_UP
; break;
1133 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1134 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1135 default: return FALSE
;
1138 wxMouseEvent
event( event_type
);
1139 event
.SetTimestamp( gdk_event
->time
);
1140 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1141 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1142 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1143 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1144 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1145 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1146 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1147 event
.m_x
= (wxCoord
)gdk_event
->x
;
1148 event
.m_y
= (wxCoord
)gdk_event
->y
;
1150 AdjustEventButtonState(event
);
1152 // Some control don't have their own X window and thus cannot get
1155 if (!g_captureWindow
)
1157 wxCoord x
= event
.m_x
;
1158 wxCoord y
= event
.m_y
;
1159 if (win
->m_wxwindow
)
1161 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1162 x
+= pizza
->xoffset
;
1163 y
+= pizza
->yoffset
;
1166 wxNode
*node
= win
->GetChildren().First();
1169 wxWindow
*child
= (wxWindow
*)node
->Data();
1171 node
= node
->Next();
1172 if (!child
->IsShown())
1175 if (child
->m_isStaticBox
)
1177 // wxStaticBox is transparent in the box itself
1178 int xx1
= child
->m_x
;
1179 int yy1
= child
->m_y
;
1180 int xx2
= child
->m_x
+ child
->m_width
;
1181 int yy2
= child
->m_x
+ child
->m_height
;
1184 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1186 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1188 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1190 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1193 event
.m_x
-= child
->m_x
;
1194 event
.m_y
-= child
->m_y
;
1201 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1202 (child
->m_x
<= x
) &&
1203 (child
->m_y
<= y
) &&
1204 (child
->m_x
+child
->m_width
>= x
) &&
1205 (child
->m_y
+child
->m_height
>= y
))
1208 event
.m_x
-= child
->m_x
;
1209 event
.m_y
-= child
->m_y
;
1216 event
.SetEventObject( win
);
1218 if (win
->GetEventHandler()->ProcessEvent( event
))
1220 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1227 //-----------------------------------------------------------------------------
1228 // "motion_notify_event"
1229 //-----------------------------------------------------------------------------
1231 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1236 wxapp_install_idle_handler();
1238 if (!win
->m_hasVMT
) return FALSE
;
1239 if (g_blockEventsOnDrag
) return FALSE
;
1240 if (g_blockEventsOnScroll
) return FALSE
;
1242 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1244 if (gdk_event
->is_hint
)
1248 GdkModifierType state
;
1249 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1255 printf( "OnMotion from " );
1256 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1257 printf( win->GetClassInfo()->GetClassName() );
1261 wxMouseEvent
event( wxEVT_MOTION
);
1262 event
.SetTimestamp( gdk_event
->time
);
1263 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1264 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1265 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1266 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1267 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1268 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1269 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1271 event
.m_x
= (wxCoord
)gdk_event
->x
;
1272 event
.m_y
= (wxCoord
)gdk_event
->y
;
1274 // Some control don't have their own X window and thus cannot get
1277 if (!g_captureWindow
)
1279 wxCoord x
= event
.m_x
;
1280 wxCoord y
= event
.m_y
;
1281 if (win
->m_wxwindow
)
1283 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1284 x
+= pizza
->xoffset
;
1285 y
+= pizza
->yoffset
;
1288 wxNode
*node
= win
->GetChildren().First();
1291 wxWindow
*child
= (wxWindow
*)node
->Data();
1293 node
= node
->Next();
1294 if (!child
->IsShown())
1297 if (child
->m_isStaticBox
)
1299 // wxStaticBox is transparent in the box itself
1300 int xx1
= child
->m_x
;
1301 int yy1
= child
->m_y
;
1302 int xx2
= child
->m_x
+ child
->m_width
;
1303 int yy2
= child
->m_x
+ child
->m_height
;
1306 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1308 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1310 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1312 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1315 event
.m_x
-= child
->m_x
;
1316 event
.m_y
-= child
->m_y
;
1323 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1324 (child
->m_x
<= x
) &&
1325 (child
->m_y
<= y
) &&
1326 (child
->m_x
+child
->m_width
>= x
) &&
1327 (child
->m_y
+child
->m_height
>= y
))
1330 event
.m_x
-= child
->m_x
;
1331 event
.m_y
-= child
->m_y
;
1338 event
.SetEventObject( win
);
1340 if (win
->GetEventHandler()->ProcessEvent( event
))
1342 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1349 //-----------------------------------------------------------------------------
1351 //-----------------------------------------------------------------------------
1353 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1358 wxapp_install_idle_handler();
1360 if (!win
->m_hasVMT
) return FALSE
;
1361 if (g_blockEventsOnDrag
) return FALSE
;
1363 switch ( g_sendActivateEvent
)
1366 // we've got focus from outside, synthtize wxActivateEvent
1367 g_sendActivateEvent
= 1;
1371 // another our window just lost focus, it was already ours before
1372 // - don't send any wxActivateEvent
1373 g_sendActivateEvent
= -1;
1377 g_focusWindow
= win
;
1380 printf( "OnSetFocus from " );
1381 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1382 printf( win->GetClassInfo()->GetClassName() );
1384 printf( WXSTRINGCAST win->GetLabel() );
1388 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1391 panel
->SetLastFocus(win
);
1396 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1399 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1400 event
.SetEventObject( win
);
1402 if (win
->GetEventHandler()->ProcessEvent( event
))
1404 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1411 //-----------------------------------------------------------------------------
1412 // "focus_out_event"
1413 //-----------------------------------------------------------------------------
1415 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1420 wxapp_install_idle_handler();
1422 if (!win
->m_hasVMT
) return FALSE
;
1423 if (g_blockEventsOnDrag
) return FALSE
;
1425 // if the focus goes out of our app alltogether, OnIdle() will send
1426 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1427 // g_sendActivateEvent to -1
1428 g_sendActivateEvent
= 0;
1430 g_focusWindow
= (wxWindow
*)NULL
;
1433 printf( "OnKillFocus from " );
1434 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1435 printf( win->GetClassInfo()->GetClassName() );
1444 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1445 event
.SetEventObject( win
);
1447 if (win
->GetEventHandler()->ProcessEvent( event
))
1449 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1456 //-----------------------------------------------------------------------------
1457 // "enter_notify_event"
1458 //-----------------------------------------------------------------------------
1460 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1465 wxapp_install_idle_handler();
1467 if (!win
->m_hasVMT
) return FALSE
;
1468 if (g_blockEventsOnDrag
) return FALSE
;
1470 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1472 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1473 #if (GTK_MINOR_VERSION > 0)
1474 event
.SetTimestamp( gdk_event
->time
);
1476 event
.SetEventObject( win
);
1480 GdkModifierType state
= (GdkModifierType
)0;
1482 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1484 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1485 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1486 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1487 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1488 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1489 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1490 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1495 if (win
->GetEventHandler()->ProcessEvent( event
))
1497 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1504 //-----------------------------------------------------------------------------
1505 // "leave_notify_event"
1506 //-----------------------------------------------------------------------------
1508 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1513 wxapp_install_idle_handler();
1515 if (!win
->m_hasVMT
) return FALSE
;
1516 if (g_blockEventsOnDrag
) return FALSE
;
1518 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1520 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1521 #if (GTK_MINOR_VERSION > 0)
1522 event
.SetTimestamp( gdk_event
->time
);
1524 event
.SetEventObject( win
);
1528 GdkModifierType state
= (GdkModifierType
)0;
1530 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1532 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1533 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1534 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1535 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1536 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1537 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1538 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1543 if (win
->GetEventHandler()->ProcessEvent( event
))
1545 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1552 //-----------------------------------------------------------------------------
1553 // "value_changed" from m_vAdjust
1554 //-----------------------------------------------------------------------------
1556 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1561 wxapp_install_idle_handler();
1563 if (g_blockEventsOnDrag
) return;
1565 if (!win
->m_hasVMT
) return;
1567 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1568 if (fabs(diff
) < 0.2) return;
1570 win
->m_oldVerticalPos
= adjust
->value
;
1572 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1573 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
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
, wxVERTICAL
);
1584 event
.SetEventObject( win
);
1585 win
->GetEventHandler()->ProcessEvent( event
);
1588 //-----------------------------------------------------------------------------
1589 // "value_changed" from m_hAdjust
1590 //-----------------------------------------------------------------------------
1592 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1597 wxapp_install_idle_handler();
1599 if (g_blockEventsOnDrag
) return;
1600 if (!win
->m_hasVMT
) return;
1602 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1603 if (fabs(diff
) < 0.2) return;
1605 win
->m_oldHorizontalPos
= adjust
->value
;
1607 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1608 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1610 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1611 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1612 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1613 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1614 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1616 int value
= (int)(adjust
->value
+0.5);
1618 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1619 event
.SetEventObject( win
);
1620 win
->GetEventHandler()->ProcessEvent( event
);
1623 //-----------------------------------------------------------------------------
1624 // "button_press_event" from scrollbar
1625 //-----------------------------------------------------------------------------
1627 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1628 GdkEventButton
*gdk_event
,
1634 wxapp_install_idle_handler();
1636 g_blockEventsOnScroll
= TRUE
;
1637 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1642 //-----------------------------------------------------------------------------
1643 // "button_release_event" from scrollbar
1644 //-----------------------------------------------------------------------------
1646 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1647 GdkEventButton
*WXUNUSED(gdk_event
),
1652 // don't test here as we can release the mouse while being over
1653 // a different window than the slider
1655 // if (gdk_event->window != widget->slider) return FALSE;
1657 g_blockEventsOnScroll
= FALSE
;
1659 if (win
->m_isScrolling
)
1661 wxEventType command
= wxEVT_SCROLL_THUMBRELEASE
;
1665 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1666 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1668 value
= (int)(win
->m_hAdjust
->value
+0.5);
1671 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1673 value
= (int)(win
->m_vAdjust
->value
+0.5);
1677 wxScrollWinEvent
event( command
, value
, dir
);
1678 event
.SetEventObject( win
);
1679 win
->GetEventHandler()->ProcessEvent( event
);
1682 win
->m_isScrolling
= FALSE
;
1687 // ----------------------------------------------------------------------------
1688 // this wxWindowBase function is implemented here (in platform-specific file)
1689 // because it is static and so couldn't be made virtual
1690 // ----------------------------------------------------------------------------
1692 wxWindow
*wxWindowBase::FindFocus()
1694 return g_focusWindow
;
1697 //-----------------------------------------------------------------------------
1698 // "realize" from m_widget
1699 //-----------------------------------------------------------------------------
1701 /* We cannot set colours and fonts before the widget has
1702 been realized, so we do this directly after realization. */
1705 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1710 wxapp_install_idle_handler();
1712 if (win
->m_delayedBackgroundColour
)
1713 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1715 if (win
->m_delayedForegroundColour
)
1716 win
->SetForegroundColour( win
->GetForegroundColour() );
1718 wxWindowCreateEvent
event( win
);
1719 event
.SetEventObject( win
);
1720 win
->GetEventHandler()->ProcessEvent( event
);
1725 //-----------------------------------------------------------------------------
1727 //-----------------------------------------------------------------------------
1730 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
1731 GtkAllocation
*WXUNUSED(alloc
),
1735 wxapp_install_idle_handler();
1737 if (!win
->m_hasScrolling
) return;
1739 int client_width
= 0;
1740 int client_height
= 0;
1741 win
->GetClientSize( &client_width
, &client_height
);
1742 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
1745 win
->m_oldClientWidth
= client_width
;
1746 win
->m_oldClientHeight
= client_height
;
1748 if (!win
->m_nativeSizeEvent
)
1750 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
1751 event
.SetEventObject( win
);
1752 win
->GetEventHandler()->ProcessEvent( event
);
1758 #define WXUNUSED_UNLESS_XIM(param) param
1760 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1763 /* Resize XIM window */
1766 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1767 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1768 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1771 wxapp_install_idle_handler();
1777 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1781 gdk_window_get_size (widget
->window
, &width
, &height
);
1782 win
->m_icattr
->preedit_area
.width
= width
;
1783 win
->m_icattr
->preedit_area
.height
= height
;
1784 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
1789 //-----------------------------------------------------------------------------
1790 // "realize" from m_wxwindow
1791 //-----------------------------------------------------------------------------
1793 /* Initialize XIM support */
1796 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1797 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1800 wxapp_install_idle_handler();
1803 if (win
->m_ic
) return FALSE
;
1804 if (!widget
) return FALSE
;
1805 if (!gdk_im_ready()) return FALSE
;
1807 win
->m_icattr
= gdk_ic_attr_new();
1808 if (!win
->m_icattr
) return FALSE
;
1812 GdkColormap
*colormap
;
1813 GdkICAttr
*attr
= win
->m_icattr
;
1814 unsigned attrmask
= GDK_IC_ALL_REQ
;
1816 GdkIMStyle supported_style
= (GdkIMStyle
)
1817 (GDK_IM_PREEDIT_NONE
|
1818 GDK_IM_PREEDIT_NOTHING
|
1819 GDK_IM_PREEDIT_POSITION
|
1820 GDK_IM_STATUS_NONE
|
1821 GDK_IM_STATUS_NOTHING
);
1823 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1824 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
1826 attr
->style
= style
= gdk_im_decide_style (supported_style
);
1827 attr
->client_window
= widget
->window
;
1829 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
1830 gtk_widget_get_default_colormap ())
1832 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
1833 attr
->preedit_colormap
= colormap
;
1836 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
1837 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
1838 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
1839 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
1841 switch (style
& GDK_IM_PREEDIT_MASK
)
1843 case GDK_IM_PREEDIT_POSITION
:
1844 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1846 g_warning ("over-the-spot style requires fontset");
1850 gdk_window_get_size (widget
->window
, &width
, &height
);
1852 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
1853 attr
->spot_location
.x
= 0;
1854 attr
->spot_location
.y
= height
;
1855 attr
->preedit_area
.x
= 0;
1856 attr
->preedit_area
.y
= 0;
1857 attr
->preedit_area
.width
= width
;
1858 attr
->preedit_area
.height
= height
;
1859 attr
->preedit_fontset
= widget
->style
->font
;
1864 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
1866 if (win
->m_ic
== NULL
)
1867 g_warning ("Can't create input context.");
1870 mask
= gdk_window_get_events (widget
->window
);
1871 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
1872 gdk_window_set_events (widget
->window
, mask
);
1874 if (GTK_WIDGET_HAS_FOCUS(widget
))
1875 gdk_im_begin (win
->m_ic
, widget
->window
);
1882 //-----------------------------------------------------------------------------
1883 // InsertChild for wxWindow.
1884 //-----------------------------------------------------------------------------
1886 /* Callback for wxWindow. This very strange beast has to be used because
1887 * C++ has no virtual methods in a constructor. We have to emulate a
1888 * virtual function here as wxNotebook requires a different way to insert
1889 * a child in it. I had opted for creating a wxNotebookPage window class
1890 * which would have made this superfluous (such in the MDI window system),
1891 * but no-one was listening to me... */
1893 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1895 /* the window might have been scrolled already, do we
1896 have to adapt the position */
1897 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
1898 child
->m_x
+= pizza
->xoffset
;
1899 child
->m_y
+= pizza
->yoffset
;
1901 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
1902 GTK_WIDGET(child
->m_widget
),
1909 //-----------------------------------------------------------------------------
1911 //-----------------------------------------------------------------------------
1913 wxWindow
* wxGetActiveWindow()
1915 return g_focusWindow
;
1918 //-----------------------------------------------------------------------------
1920 //-----------------------------------------------------------------------------
1922 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
1924 void wxWindow::Init()
1930 m_widget
= (GtkWidget
*) NULL
;
1931 m_wxwindow
= (GtkWidget
*) NULL
;
1941 m_needParent
= TRUE
;
1942 m_isBeingDeleted
= FALSE
;
1945 m_nativeSizeEvent
= FALSE
;
1947 m_hasScrolling
= FALSE
;
1948 m_isScrolling
= FALSE
;
1950 m_hAdjust
= (GtkAdjustment
*) NULL
;
1951 m_vAdjust
= (GtkAdjustment
*) NULL
;
1952 m_oldHorizontalPos
= 0.0;
1953 m_oldVerticalPos
= 0.0;
1956 m_widgetStyle
= (GtkStyle
*) NULL
;
1958 m_insertCallback
= (wxInsertChildFunction
) NULL
;
1960 m_isStaticBox
= FALSE
;
1961 m_isRadioButton
= FALSE
;
1963 m_acceptsFocus
= FALSE
;
1965 m_cursor
= *wxSTANDARD_CURSOR
;
1968 m_ic
= (GdkIC
*) NULL
;
1969 m_icattr
= (GdkICAttr
*) NULL
;
1973 wxWindow::wxWindow()
1978 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1979 const wxPoint
&pos
, const wxSize
&size
,
1980 long style
, const wxString
&name
)
1984 Create( parent
, id
, pos
, size
, style
, name
);
1987 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1988 const wxPoint
&pos
, const wxSize
&size
,
1989 long style
, const wxString
&name
)
1991 if (!PreCreation( parent
, pos
, size
) ||
1992 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
1994 wxFAIL_MSG( wxT("wxWindow creation failed") );
1998 m_insertCallback
= wxInsertChildInWindow
;
2000 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2001 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2004 debug_focus_in( m_widget
, wxT("wxWindow::m_widget"), name
);
2007 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2010 debug_focus_in( scrolledWindow
->hscrollbar
, wxT("wxWindow::hsrcollbar"), name
);
2011 debug_focus_in( scrolledWindow
->vscrollbar
, wxT("wxWindow::vsrcollbar"), name
);
2014 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2015 scroll_class
->scrollbar_spacing
= 0;
2017 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2019 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2020 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2022 m_wxwindow
= gtk_pizza_new();
2025 debug_focus_in( m_wxwindow
, wxT("wxWindow::m_wxwindow"), name
);
2028 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2030 #if (GTK_MINOR_VERSION > 0)
2031 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2033 if (HasFlag(wxRAISED_BORDER
))
2035 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2037 else if (HasFlag(wxSUNKEN_BORDER
))
2039 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2041 else if (HasFlag(wxSIMPLE_BORDER
))
2043 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2047 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2049 #else // GTK_MINOR_VERSION == 0
2050 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2052 if (HasFlag(wxRAISED_BORDER
))
2054 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2056 else if (HasFlag(wxSUNKEN_BORDER
))
2058 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2062 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2064 #endif // GTK_MINOR_VERSION
2066 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2067 m_acceptsFocus
= TRUE
;
2069 #if (GTK_MINOR_VERSION == 0)
2070 // shut the viewport up
2071 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2072 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2073 #endif // GTK_MINOR_VERSION == 0
2075 // I _really_ don't want scrollbars in the beginning
2076 m_vAdjust
->lower
= 0.0;
2077 m_vAdjust
->upper
= 1.0;
2078 m_vAdjust
->value
= 0.0;
2079 m_vAdjust
->step_increment
= 1.0;
2080 m_vAdjust
->page_increment
= 1.0;
2081 m_vAdjust
->page_size
= 5.0;
2082 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2083 m_hAdjust
->lower
= 0.0;
2084 m_hAdjust
->upper
= 1.0;
2085 m_hAdjust
->value
= 0.0;
2086 m_hAdjust
->step_increment
= 1.0;
2087 m_hAdjust
->page_increment
= 1.0;
2088 m_hAdjust
->page_size
= 5.0;
2089 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2091 // these handlers block mouse events to any window during scrolling such as
2092 // motion events and prevent GTK and wxWindows from fighting over where the
2095 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2096 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2098 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2099 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2101 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2102 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2104 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2105 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2107 // these handlers get notified when screen updates are required either when
2108 // scrolling or when the window size (and therefore scrollbar configuration)
2111 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2112 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2113 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2114 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2116 gtk_widget_show( m_wxwindow
);
2119 m_parent
->DoAddChild( this );
2128 wxWindow::~wxWindow()
2130 m_isBeingDeleted
= TRUE
;
2139 m_parent
->RemoveChild( this );
2143 gdk_ic_destroy (m_ic
);
2145 gdk_ic_attr_destroy (m_icattr
);
2150 gtk_style_unref( m_widgetStyle
);
2151 m_widgetStyle
= (GtkStyle
*) NULL
;
2156 gtk_widget_destroy( m_wxwindow
);
2157 m_wxwindow
= (GtkWidget
*) NULL
;
2162 gtk_widget_destroy( m_widget
);
2163 m_widget
= (GtkWidget
*) NULL
;
2167 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2169 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2171 /* this turns -1 into 20 so that a minimal window is
2172 visible even although -1,-1 has been given as the
2173 size of the window. the same trick is used in other
2174 ports and should make debugging easier */
2175 m_width
= WidthDefault(size
.x
);
2176 m_height
= HeightDefault(size
.y
);
2181 /* some reasonable defaults */
2186 m_x
= (gdk_screen_width () - m_width
) / 2;
2187 if (m_x
< 10) m_x
= 10;
2191 m_y
= (gdk_screen_height () - m_height
) / 2;
2192 if (m_y
< 10) m_y
= 10;
2199 void wxWindow::PostCreation()
2201 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2207 /* these get reported to wxWindows -> wxPaintEvent */
2208 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2209 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2211 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2212 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2215 #if (GTK_MINOR_VERSION > 0)
2216 /* these are called when the "sunken" or "raised" borders are drawn */
2217 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2218 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2220 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2221 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2225 if (m_wxwindow
&& m_needParent
)
2227 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2228 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2230 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2231 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2235 // For dialogs and frames, we are interested mainly in
2236 // m_widget's focus.
2238 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2239 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2241 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2242 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2245 GtkWidget
*connect_widget
= GetConnectWidget();
2247 ConnectWidget( connect_widget
);
2249 /* We cannot set colours, fonts and cursors before the widget has
2250 been realized, so we do this directly after realization */
2251 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2252 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2256 /* Catch native resize events. */
2257 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2258 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2260 /* Initialize XIM support. */
2261 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2262 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2264 /* And resize XIM window. */
2265 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2266 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2272 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2274 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2275 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2277 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2278 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2280 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2281 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2283 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2284 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2286 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2287 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2289 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2290 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2292 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2293 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2296 bool wxWindow::Destroy()
2298 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2302 return wxWindowBase::Destroy();
2305 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2307 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2310 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2312 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2313 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2315 if (m_resizing
) return; /* I don't like recursions */
2318 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2320 /* don't set the size for children of wxNotebook, just take the values. */
2328 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2330 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2332 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2333 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2334 if (width
!= -1) m_width
= width
;
2335 if (height
!= -1) m_height
= height
;
2339 m_x
= x
+ pizza
->xoffset
;
2340 m_y
= y
+ pizza
->yoffset
;
2345 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2347 if (width
== -1) m_width
= 80;
2350 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2352 if (height
== -1) m_height
= 26;
2355 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2356 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2357 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2358 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2361 int bottom_border
= 0;
2363 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2365 /* the default button has a border around it */
2370 DoMoveWindow( m_x
-border
,
2373 m_height
+border
+bottom_border
);
2378 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2382 wxPrintf( "OnSize sent from " );
2383 if (GetClassInfo() && GetClassInfo()->GetClassName())
2384 wxPrintf( GetClassInfo()->GetClassName() );
2385 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2388 if (!m_nativeSizeEvent
)
2390 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2391 event
.SetEventObject( this );
2392 GetEventHandler()->ProcessEvent( event
);
2398 void wxWindow::OnInternalIdle()
2400 if ( g_sendActivateEvent
!= -1 )
2402 bool activate
= g_sendActivateEvent
!= 0;
2405 g_sendActivateEvent
= -1;
2407 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2408 event
.SetEventObject(this);
2410 (void)GetEventHandler()->ProcessEvent(event
);
2413 wxCursor cursor
= m_cursor
;
2414 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2418 /* I now set the cursor anew in every OnInternalIdle call
2419 as setting the cursor in a parent window also effects the
2420 windows above so that checking for the current cursor is
2425 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2427 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2429 if (!g_globalCursor
.Ok())
2430 cursor
= *wxSTANDARD_CURSOR
;
2432 window
= m_widget
->window
;
2433 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2434 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2440 GdkWindow
*window
= m_widget
->window
;
2441 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2442 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2450 void wxWindow::DoGetSize( int *width
, int *height
) const
2452 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2454 if (width
) (*width
) = m_width
;
2455 if (height
) (*height
) = m_height
;
2458 void wxWindow::DoSetClientSize( int width
, int height
)
2460 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2464 SetSize( width
, height
);
2471 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2473 /* when using GTK 1.2 we set the shadow border size to 2 */
2477 if (HasFlag(wxSIMPLE_BORDER
))
2479 /* when using GTK 1.2 we set the simple border size to 1 */
2486 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2488 GtkRequisition vscroll_req
;
2489 vscroll_req
.width
= 2;
2490 vscroll_req
.height
= 2;
2491 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
2492 (scroll_window
->vscrollbar
, &vscroll_req
);
2494 GtkRequisition hscroll_req
;
2495 hscroll_req
.width
= 2;
2496 hscroll_req
.height
= 2;
2497 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
2498 (scroll_window
->hscrollbar
, &hscroll_req
);
2500 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2502 if (scroll_window
->vscrollbar_visible
)
2504 dw
+= vscroll_req
.width
;
2505 dw
+= scroll_class
->scrollbar_spacing
;
2508 if (scroll_window
->hscrollbar_visible
)
2510 dh
+= hscroll_req
.height
;
2511 dh
+= scroll_class
->scrollbar_spacing
;
2515 SetSize( width
+dw
, height
+dh
);
2519 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2521 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2525 if (width
) (*width
) = m_width
;
2526 if (height
) (*height
) = m_height
;
2533 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2535 /* when using GTK 1.2 we set the shadow border size to 2 */
2539 if (HasFlag(wxSIMPLE_BORDER
))
2541 /* when using GTK 1.2 we set the simple border size to 1 */
2548 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2550 GtkRequisition vscroll_req
;
2551 vscroll_req
.width
= 2;
2552 vscroll_req
.height
= 2;
2553 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
2554 (scroll_window
->vscrollbar
, &vscroll_req
);
2556 GtkRequisition hscroll_req
;
2557 hscroll_req
.width
= 2;
2558 hscroll_req
.height
= 2;
2559 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
2560 (scroll_window
->hscrollbar
, &hscroll_req
);
2562 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2564 if (scroll_window
->vscrollbar_visible
)
2566 dw
+= vscroll_req
.width
;
2567 dw
+= scroll_class
->scrollbar_spacing
;
2570 if (scroll_window
->hscrollbar_visible
)
2572 dh
+= hscroll_req
.height
;
2573 dh
+= scroll_class
->scrollbar_spacing
;
2577 if (width
) (*width
) = m_width
- dw
;
2578 if (height
) (*height
) = m_height
- dh
;
2582 void wxWindow::DoGetPosition( int *x
, int *y
) const
2584 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2588 if (m_parent
&& m_parent
->m_wxwindow
)
2590 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2591 dx
= pizza
->xoffset
;
2592 dy
= pizza
->yoffset
;
2595 if (x
) (*x
) = m_x
- dx
;
2596 if (y
) (*y
) = m_y
- dy
;
2599 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2601 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2603 if (!m_widget
->window
) return;
2605 GdkWindow
*source
= (GdkWindow
*) NULL
;
2607 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2609 source
= m_widget
->window
;
2613 gdk_window_get_origin( source
, &org_x
, &org_y
);
2617 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2619 org_x
+= m_widget
->allocation
.x
;
2620 org_y
+= m_widget
->allocation
.y
;
2628 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2630 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2632 if (!m_widget
->window
) return;
2634 GdkWindow
*source
= (GdkWindow
*) NULL
;
2636 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2638 source
= m_widget
->window
;
2642 gdk_window_get_origin( source
, &org_x
, &org_y
);
2646 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2648 org_x
+= m_widget
->allocation
.x
;
2649 org_y
+= m_widget
->allocation
.y
;
2657 bool wxWindow::Show( bool show
)
2659 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2661 if (!wxWindowBase::Show(show
))
2668 gtk_widget_show( m_widget
);
2670 gtk_widget_hide( m_widget
);
2675 bool wxWindow::Enable( bool enable
)
2677 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2679 if (!wxWindowBase::Enable(enable
))
2685 gtk_widget_set_sensitive( m_widget
, enable
);
2687 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2692 int wxWindow::GetCharHeight() const
2694 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2696 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2698 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2700 return font
->ascent
+ font
->descent
;
2703 int wxWindow::GetCharWidth() const
2705 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2707 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2709 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2711 return gdk_string_width( font
, "H" );
2714 void wxWindow::GetTextExtent( const wxString
& string
,
2718 int *externalLeading
,
2719 const wxFont
*theFont
) const
2721 wxFont fontToUse
= m_font
;
2722 if (theFont
) fontToUse
= *theFont
;
2724 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2726 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2727 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2728 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2729 if (descent
) (*descent
) = font
->descent
;
2730 if (externalLeading
) (*externalLeading
) = 0; // ??
2733 void wxWindow::SetFocus()
2735 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2739 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2740 gtk_widget_grab_focus (m_wxwindow
);
2746 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2748 gtk_widget_grab_focus (m_widget
);
2750 else if (GTK_IS_CONTAINER(m_widget
))
2752 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2761 bool wxWindow::AcceptsFocus() const
2763 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2766 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2768 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2770 wxWindow
*oldParent
= m_parent
,
2771 *newParent
= (wxWindow
*)newParentBase
;
2773 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2775 if ( !wxWindowBase::Reparent(newParent
) )
2778 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2780 /* prevent GTK from deleting the widget arbitrarily */
2781 gtk_widget_ref( m_widget
);
2785 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2788 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2792 /* insert GTK representation */
2793 (*(newParent
->m_insertCallback
))(newParent
, this);
2796 /* reverse: prevent GTK from deleting the widget arbitrarily */
2797 gtk_widget_unref( m_widget
);
2802 void wxWindow::DoAddChild(wxWindow
*child
)
2804 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2806 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
2808 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
2813 /* insert GTK representation */
2814 (*m_insertCallback
)(this, child
);
2817 void wxWindow::Raise()
2819 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2821 if (!m_widget
->window
) return;
2823 gdk_window_raise( m_widget
->window
);
2826 void wxWindow::Lower()
2828 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2830 if (!m_widget
->window
) return;
2832 gdk_window_lower( m_widget
->window
);
2835 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2837 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2839 return wxWindowBase::SetCursor( cursor
);
2842 void wxWindow::WarpPointer( int x
, int y
)
2844 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2846 /* we provide this function ourselves as it is
2847 missing in GDK (top of this file) */
2849 GdkWindow
*window
= (GdkWindow
*) NULL
;
2851 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2853 window
= GetConnectWidget()->window
;
2856 gdk_window_warp_pointer( window
, x
, y
);
2859 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2861 if (!m_widget
) return;
2862 if (!m_widget
->window
) return;
2864 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2868 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
2870 rect
->width
, rect
->height
);
2874 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
2878 /* there is no GTK equivalent of "draw only, don't clear" so we
2879 invent our own in the GtkPizza widget */
2885 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2886 gboolean old_clear
= pizza
->clear_on_draw
;
2887 gtk_pizza_set_clear( pizza
, FALSE
);
2889 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2891 gtk_pizza_set_clear( pizza
, old_clear
);
2894 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2898 GdkRectangle gdk_rect
;
2899 gdk_rect
.x
= rect
->x
;
2900 gdk_rect
.y
= rect
->y
;
2901 gdk_rect
.width
= rect
->width
;
2902 gdk_rect
.height
= rect
->height
;
2906 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2907 gboolean old_clear
= pizza
->clear_on_draw
;
2908 gtk_pizza_set_clear( pizza
, FALSE
);
2910 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2912 gtk_pizza_set_clear( pizza
, old_clear
);
2915 gtk_widget_draw( m_widget
, &gdk_rect
);
2919 void wxWindow::Clear()
2921 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
2923 if (!m_widget
->window
) return;
2925 if (m_wxwindow
&& m_wxwindow
->window
)
2927 gdk_window_clear( m_wxwindow
->window
);
2932 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2934 wxWindowBase::DoSetToolTip(tip
);
2937 m_tooltip
->Apply( this );
2940 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2942 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
2944 #endif // wxUSE_TOOLTIPS
2946 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2948 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2950 if (!wxWindowBase::SetBackgroundColour(colour
))
2952 // don't leave if the GTK widget has just
2954 if (!m_delayedBackgroundColour
) return FALSE
;
2957 GdkWindow
*window
= (GdkWindow
*) NULL
;
2959 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2961 window
= GetConnectWidget()->window
;
2965 // indicate that a new style has been set
2966 // but it couldn't get applied as the
2967 // widget hasn't been realized yet.
2968 m_delayedBackgroundColour
= TRUE
;
2972 (m_wxwindow
->window
) &&
2973 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
2975 /* wxMSW doesn't clear the window here. I don't do that either to
2976 provide compatibility. call Clear() to do the job. */
2978 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
2979 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
2987 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
2989 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2991 if (!wxWindowBase::SetForegroundColour(colour
))
2993 // don't leave if the GTK widget has just
2995 if (!m_delayedForegroundColour
) return FALSE
;
2998 GdkWindow
*window
= (GdkWindow
*) NULL
;
3000 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3002 window
= GetConnectWidget()->window
;
3006 // indicate that a new style has been set
3007 // but it couldn't get applied as the
3008 // widget hasn't been realized yet.
3009 m_delayedForegroundColour
= TRUE
;
3017 GtkStyle
*wxWindow::GetWidgetStyle()
3021 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3022 remake
->klass
= m_widgetStyle
->klass
;
3024 gtk_style_unref( m_widgetStyle
);
3025 m_widgetStyle
= remake
;
3029 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3032 def
= gtk_widget_get_default_style();
3034 m_widgetStyle
= gtk_style_copy( def
);
3035 m_widgetStyle
->klass
= def
->klass
;
3038 return m_widgetStyle
;
3041 void wxWindow::SetWidgetStyle()
3043 GtkStyle
*style
= GetWidgetStyle();
3045 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3047 gdk_font_unref( style
->font
);
3048 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3051 if (m_foregroundColour
.Ok())
3053 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3054 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3056 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3057 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3058 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3062 if (m_backgroundColour
.Ok())
3064 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3065 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3067 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3068 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3069 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3070 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3071 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3072 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3073 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3074 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3079 void wxWindow::ApplyWidgetStyle()
3083 //-----------------------------------------------------------------------------
3084 // Pop-up menu stuff
3085 //-----------------------------------------------------------------------------
3087 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3089 *is_waiting
= FALSE
;
3092 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3094 menu
->SetInvokingWindow( win
);
3095 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3098 wxMenuItem
*menuitem
= node
->GetData();
3099 if (menuitem
->IsSubMenu())
3101 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3104 node
= node
->GetNext();
3108 static gint gs_pop_x
= 0;
3109 static gint gs_pop_y
= 0;
3111 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3115 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3120 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3122 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3124 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3126 SetInvokingWindow( menu
, this );
3133 bool is_waiting
= TRUE
;
3135 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3136 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3139 GTK_MENU(menu
->m_menu
),
3140 (GtkWidget
*) NULL
, // parent menu shell
3141 (GtkWidget
*) NULL
, // parent menu item
3142 (GtkMenuPositionFunc
) pop_pos_callback
,
3143 (gpointer
) this, // client data
3144 0, // button used to activate it
3145 gs_timeLastClick
// the time of activation
3150 while (gtk_events_pending())
3151 gtk_main_iteration();
3157 #if wxUSE_DRAG_AND_DROP
3159 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3161 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3163 GtkWidget
*dnd_widget
= GetConnectWidget();
3165 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3167 if (m_dropTarget
) delete m_dropTarget
;
3168 m_dropTarget
= dropTarget
;
3170 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3173 #endif // wxUSE_DRAG_AND_DROP
3175 GtkWidget
* wxWindow::GetConnectWidget()
3177 GtkWidget
*connect_widget
= m_widget
;
3178 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3180 return connect_widget
;
3183 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3186 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3188 return (window
== m_widget
->window
);
3191 bool wxWindow::SetFont( const wxFont
&font
)
3193 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3195 if (!wxWindowBase::SetFont(font
))
3200 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3201 if ( sysbg
== m_backgroundColour
)
3203 m_backgroundColour
= wxNullColour
;
3205 m_backgroundColour
= sysbg
;
3215 void wxWindow::CaptureMouse()
3217 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3219 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3221 GdkWindow
*window
= (GdkWindow
*) NULL
;
3223 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3225 window
= GetConnectWidget()->window
;
3227 if (!window
) return;
3229 gdk_pointer_grab( window
, FALSE
,
3231 (GDK_BUTTON_PRESS_MASK
|
3232 GDK_BUTTON_RELEASE_MASK
|
3233 GDK_POINTER_MOTION_HINT_MASK
|
3234 GDK_POINTER_MOTION_MASK
),
3236 m_cursor
.GetCursor(),
3237 (guint32
)GDK_CURRENT_TIME
);
3238 g_captureWindow
= this;
3241 void wxWindow::ReleaseMouse()
3243 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3245 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3247 GdkWindow
*window
= (GdkWindow
*) NULL
;
3249 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3251 window
= GetConnectWidget()->window
;
3256 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3257 g_captureWindow
= (wxWindow
*) NULL
;
3260 bool wxWindow::IsRetained() const
3265 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3266 int range
, bool refresh
)
3268 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3270 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3272 m_hasScrolling
= TRUE
;
3274 if (orient
== wxHORIZONTAL
)
3276 float fpos
= (float)pos
;
3277 float frange
= (float)range
;
3278 float fthumb
= (float)thumbVisible
;
3279 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3280 if (fpos
< 0.0) fpos
= 0.0;
3282 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3283 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3285 SetScrollPos( orient
, pos
, refresh
);
3289 m_oldHorizontalPos
= fpos
;
3291 m_hAdjust
->lower
= 0.0;
3292 m_hAdjust
->upper
= frange
;
3293 m_hAdjust
->value
= fpos
;
3294 m_hAdjust
->step_increment
= 1.0;
3295 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3296 m_hAdjust
->page_size
= fthumb
;
3300 float fpos
= (float)pos
;
3301 float frange
= (float)range
;
3302 float fthumb
= (float)thumbVisible
;
3303 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3304 if (fpos
< 0.0) fpos
= 0.0;
3306 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3307 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3309 SetScrollPos( orient
, pos
, refresh
);
3313 m_oldVerticalPos
= fpos
;
3315 m_vAdjust
->lower
= 0.0;
3316 m_vAdjust
->upper
= frange
;
3317 m_vAdjust
->value
= fpos
;
3318 m_vAdjust
->step_increment
= 1.0;
3319 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3320 m_vAdjust
->page_size
= fthumb
;
3323 if (orient
== wxHORIZONTAL
)
3324 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3326 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3329 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3331 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3333 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3335 if (orient
== wxHORIZONTAL
)
3337 float fpos
= (float)pos
;
3338 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3339 if (fpos
< 0.0) fpos
= 0.0;
3340 m_oldHorizontalPos
= fpos
;
3342 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3343 m_hAdjust
->value
= fpos
;
3347 float fpos
= (float)pos
;
3348 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3349 if (fpos
< 0.0) fpos
= 0.0;
3350 m_oldVerticalPos
= fpos
;
3352 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3353 m_vAdjust
->value
= fpos
;
3356 if (m_wxwindow
->window
)
3358 if (orient
== wxHORIZONTAL
)
3360 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3361 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3363 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3365 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3366 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3370 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3371 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3373 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3375 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3376 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3381 int wxWindow::GetScrollThumb( int orient
) const
3383 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3385 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3387 if (orient
== wxHORIZONTAL
)
3388 return (int)(m_hAdjust
->page_size
+0.5);
3390 return (int)(m_vAdjust
->page_size
+0.5);
3393 int wxWindow::GetScrollPos( int orient
) const
3395 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3397 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3399 if (orient
== wxHORIZONTAL
)
3400 return (int)(m_hAdjust
->value
+0.5);
3402 return (int)(m_vAdjust
->value
+0.5);
3405 int wxWindow::GetScrollRange( int orient
) const
3407 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3409 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3411 if (orient
== wxHORIZONTAL
)
3412 return (int)(m_hAdjust
->upper
+0.5);
3414 return (int)(m_vAdjust
->upper
+0.5);
3417 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3419 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3421 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3424 printf( "ScrollWindow: %d %d\n", dx, dy );
3427 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3432 m_scrollGC = gdk_gc_new( m_wxwindow->window );
3433 gdk_gc_set_exposures( m_scrollGC, TRUE );
3436 wxNode *node = m_children.First();
3439 wxWindow *child = (wxWindow*) node->Data();
3442 child->GetSize( &sx, &sy );
3443 child->SetSize( child->m_x + dx, child->m_y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
3444 node = node->Next();
3449 GetClientSize( &cw, &ch );
3450 int w = cw - abs(dx);
3451 int h = ch - abs(dy);
3453 if ((h < 0) || (w < 0))
3461 if (dx < 0) s_x = -dx;
3462 if (dy < 0) s_y = -dy;
3465 if (dx > 0) d_x = dx;
3466 if (dy > 0) d_y = dy;
3468 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
3469 m_wxwindow->window, s_x, s_y, w, h );
3472 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3473 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3474 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3475 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3477 Refresh( TRUE, &rect );