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 // don't delete if it's a pixmap theme style
2151 if (!m_widgetStyle
->engine_data
)
2152 gtk_style_unref( m_widgetStyle
);
2154 m_widgetStyle
= (GtkStyle
*) NULL
;
2159 gtk_widget_destroy( m_wxwindow
);
2160 m_wxwindow
= (GtkWidget
*) NULL
;
2165 gtk_widget_destroy( m_widget
);
2166 m_widget
= (GtkWidget
*) NULL
;
2170 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2172 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2174 /* this turns -1 into 20 so that a minimal window is
2175 visible even although -1,-1 has been given as the
2176 size of the window. the same trick is used in other
2177 ports and should make debugging easier */
2178 m_width
= WidthDefault(size
.x
);
2179 m_height
= HeightDefault(size
.y
);
2184 /* some reasonable defaults */
2189 m_x
= (gdk_screen_width () - m_width
) / 2;
2190 if (m_x
< 10) m_x
= 10;
2194 m_y
= (gdk_screen_height () - m_height
) / 2;
2195 if (m_y
< 10) m_y
= 10;
2202 void wxWindow::PostCreation()
2204 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2210 /* these get reported to wxWindows -> wxPaintEvent */
2211 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2212 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2214 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2215 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2218 #if (GTK_MINOR_VERSION > 0)
2219 /* these are called when the "sunken" or "raised" borders are drawn */
2220 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2221 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2223 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2224 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2228 if (m_wxwindow
&& m_needParent
)
2230 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2231 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2233 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2234 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2238 // For dialogs and frames, we are interested mainly in
2239 // m_widget's focus.
2241 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2242 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2244 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2245 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2248 GtkWidget
*connect_widget
= GetConnectWidget();
2250 ConnectWidget( connect_widget
);
2252 /* We cannot set colours, fonts and cursors before the widget has
2253 been realized, so we do this directly after realization */
2254 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2255 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2259 /* Catch native resize events. */
2260 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2261 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2263 /* Initialize XIM support. */
2264 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2265 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2267 /* And resize XIM window. */
2268 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2269 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2275 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2277 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2278 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2280 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2281 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2283 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2284 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2286 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2287 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2289 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2290 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2292 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2293 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2295 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2296 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2299 bool wxWindow::Destroy()
2301 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2305 return wxWindowBase::Destroy();
2308 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2310 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2313 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2315 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2316 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2318 if (m_resizing
) return; /* I don't like recursions */
2321 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2323 /* don't set the size for children of wxNotebook, just take the values. */
2331 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2333 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2335 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2336 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2337 if (width
!= -1) m_width
= width
;
2338 if (height
!= -1) m_height
= height
;
2342 m_x
= x
+ pizza
->xoffset
;
2343 m_y
= y
+ pizza
->yoffset
;
2348 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2350 if (width
== -1) m_width
= 80;
2353 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2355 if (height
== -1) m_height
= 26;
2358 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2359 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2360 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2361 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2364 int bottom_border
= 0;
2366 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2368 /* the default button has a border around it */
2373 DoMoveWindow( m_x
-border
,
2376 m_height
+border
+bottom_border
);
2381 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2385 wxPrintf( "OnSize sent from " );
2386 if (GetClassInfo() && GetClassInfo()->GetClassName())
2387 wxPrintf( GetClassInfo()->GetClassName() );
2388 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2391 if (!m_nativeSizeEvent
)
2393 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2394 event
.SetEventObject( this );
2395 GetEventHandler()->ProcessEvent( event
);
2401 void wxWindow::OnInternalIdle()
2403 if ( g_sendActivateEvent
!= -1 )
2405 bool activate
= g_sendActivateEvent
!= 0;
2408 g_sendActivateEvent
= -1;
2410 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2411 event
.SetEventObject(this);
2413 (void)GetEventHandler()->ProcessEvent(event
);
2416 wxCursor cursor
= m_cursor
;
2417 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2421 /* I now set the cursor anew in every OnInternalIdle call
2422 as setting the cursor in a parent window also effects the
2423 windows above so that checking for the current cursor is
2428 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2430 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2432 if (!g_globalCursor
.Ok())
2433 cursor
= *wxSTANDARD_CURSOR
;
2435 window
= m_widget
->window
;
2436 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2437 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2443 GdkWindow
*window
= m_widget
->window
;
2444 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2445 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2453 void wxWindow::DoGetSize( int *width
, int *height
) const
2455 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2457 if (width
) (*width
) = m_width
;
2458 if (height
) (*height
) = m_height
;
2461 void wxWindow::DoSetClientSize( int width
, int height
)
2463 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2467 SetSize( width
, height
);
2474 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2476 /* when using GTK 1.2 we set the shadow border size to 2 */
2480 if (HasFlag(wxSIMPLE_BORDER
))
2482 /* when using GTK 1.2 we set the simple border size to 1 */
2489 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2491 GtkRequisition vscroll_req
;
2492 vscroll_req
.width
= 2;
2493 vscroll_req
.height
= 2;
2494 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
2495 (scroll_window
->vscrollbar
, &vscroll_req
);
2497 GtkRequisition hscroll_req
;
2498 hscroll_req
.width
= 2;
2499 hscroll_req
.height
= 2;
2500 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
2501 (scroll_window
->hscrollbar
, &hscroll_req
);
2503 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2505 if (scroll_window
->vscrollbar_visible
)
2507 dw
+= vscroll_req
.width
;
2508 dw
+= scroll_class
->scrollbar_spacing
;
2511 if (scroll_window
->hscrollbar_visible
)
2513 dh
+= hscroll_req
.height
;
2514 dh
+= scroll_class
->scrollbar_spacing
;
2518 SetSize( width
+dw
, height
+dh
);
2522 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2524 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2528 if (width
) (*width
) = m_width
;
2529 if (height
) (*height
) = m_height
;
2536 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2538 /* when using GTK 1.2 we set the shadow border size to 2 */
2542 if (HasFlag(wxSIMPLE_BORDER
))
2544 /* when using GTK 1.2 we set the simple border size to 1 */
2551 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2553 GtkRequisition vscroll_req
;
2554 vscroll_req
.width
= 2;
2555 vscroll_req
.height
= 2;
2556 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
2557 (scroll_window
->vscrollbar
, &vscroll_req
);
2559 GtkRequisition hscroll_req
;
2560 hscroll_req
.width
= 2;
2561 hscroll_req
.height
= 2;
2562 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
2563 (scroll_window
->hscrollbar
, &hscroll_req
);
2565 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2567 if (scroll_window
->vscrollbar_visible
)
2569 dw
+= vscroll_req
.width
;
2570 dw
+= scroll_class
->scrollbar_spacing
;
2573 if (scroll_window
->hscrollbar_visible
)
2575 dh
+= hscroll_req
.height
;
2576 dh
+= scroll_class
->scrollbar_spacing
;
2580 if (width
) (*width
) = m_width
- dw
;
2581 if (height
) (*height
) = m_height
- dh
;
2585 void wxWindow::DoGetPosition( int *x
, int *y
) const
2587 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2591 if (m_parent
&& m_parent
->m_wxwindow
)
2593 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2594 dx
= pizza
->xoffset
;
2595 dy
= pizza
->yoffset
;
2598 if (x
) (*x
) = m_x
- dx
;
2599 if (y
) (*y
) = m_y
- dy
;
2602 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2604 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2606 if (!m_widget
->window
) return;
2608 GdkWindow
*source
= (GdkWindow
*) NULL
;
2610 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2612 source
= m_widget
->window
;
2616 gdk_window_get_origin( source
, &org_x
, &org_y
);
2620 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2622 org_x
+= m_widget
->allocation
.x
;
2623 org_y
+= m_widget
->allocation
.y
;
2631 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2633 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2635 if (!m_widget
->window
) return;
2637 GdkWindow
*source
= (GdkWindow
*) NULL
;
2639 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2641 source
= m_widget
->window
;
2645 gdk_window_get_origin( source
, &org_x
, &org_y
);
2649 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2651 org_x
+= m_widget
->allocation
.x
;
2652 org_y
+= m_widget
->allocation
.y
;
2660 bool wxWindow::Show( bool show
)
2662 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2664 if (!wxWindowBase::Show(show
))
2671 gtk_widget_show( m_widget
);
2673 gtk_widget_hide( m_widget
);
2678 bool wxWindow::Enable( bool enable
)
2680 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2682 if (!wxWindowBase::Enable(enable
))
2688 gtk_widget_set_sensitive( m_widget
, enable
);
2690 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2695 int wxWindow::GetCharHeight() const
2697 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2699 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2701 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2703 return font
->ascent
+ font
->descent
;
2706 int wxWindow::GetCharWidth() const
2708 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2710 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2712 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2714 return gdk_string_width( font
, "H" );
2717 void wxWindow::GetTextExtent( const wxString
& string
,
2721 int *externalLeading
,
2722 const wxFont
*theFont
) const
2724 wxFont fontToUse
= m_font
;
2725 if (theFont
) fontToUse
= *theFont
;
2727 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2729 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2730 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2731 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2732 if (descent
) (*descent
) = font
->descent
;
2733 if (externalLeading
) (*externalLeading
) = 0; // ??
2736 void wxWindow::SetFocus()
2738 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2742 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2743 gtk_widget_grab_focus (m_wxwindow
);
2749 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2751 gtk_widget_grab_focus (m_widget
);
2753 else if (GTK_IS_CONTAINER(m_widget
))
2755 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2764 bool wxWindow::AcceptsFocus() const
2766 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2769 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2771 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2773 wxWindow
*oldParent
= m_parent
,
2774 *newParent
= (wxWindow
*)newParentBase
;
2776 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2778 if ( !wxWindowBase::Reparent(newParent
) )
2781 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2783 /* prevent GTK from deleting the widget arbitrarily */
2784 gtk_widget_ref( m_widget
);
2788 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2791 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2795 /* insert GTK representation */
2796 (*(newParent
->m_insertCallback
))(newParent
, this);
2799 /* reverse: prevent GTK from deleting the widget arbitrarily */
2800 gtk_widget_unref( m_widget
);
2805 void wxWindow::DoAddChild(wxWindow
*child
)
2807 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2809 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
2811 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
2816 /* insert GTK representation */
2817 (*m_insertCallback
)(this, child
);
2820 void wxWindow::Raise()
2822 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2824 if (!m_widget
->window
) return;
2826 gdk_window_raise( m_widget
->window
);
2829 void wxWindow::Lower()
2831 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2833 if (!m_widget
->window
) return;
2835 gdk_window_lower( m_widget
->window
);
2838 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2840 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2842 return wxWindowBase::SetCursor( cursor
);
2845 void wxWindow::WarpPointer( int x
, int y
)
2847 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2849 /* we provide this function ourselves as it is
2850 missing in GDK (top of this file) */
2852 GdkWindow
*window
= (GdkWindow
*) NULL
;
2854 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2856 window
= GetConnectWidget()->window
;
2859 gdk_window_warp_pointer( window
, x
, y
);
2862 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2864 if (!m_widget
) return;
2865 if (!m_widget
->window
) return;
2867 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2871 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
2873 rect
->width
, rect
->height
);
2877 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
2881 /* there is no GTK equivalent of "draw only, don't clear" so we
2882 invent our own in the GtkPizza widget */
2888 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2889 gboolean old_clear
= pizza
->clear_on_draw
;
2890 gtk_pizza_set_clear( pizza
, FALSE
);
2892 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2894 gtk_pizza_set_clear( pizza
, old_clear
);
2897 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2901 GdkRectangle gdk_rect
;
2902 gdk_rect
.x
= rect
->x
;
2903 gdk_rect
.y
= rect
->y
;
2904 gdk_rect
.width
= rect
->width
;
2905 gdk_rect
.height
= rect
->height
;
2909 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2910 gboolean old_clear
= pizza
->clear_on_draw
;
2911 gtk_pizza_set_clear( pizza
, FALSE
);
2913 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2915 gtk_pizza_set_clear( pizza
, old_clear
);
2918 gtk_widget_draw( m_widget
, &gdk_rect
);
2922 void wxWindow::Clear()
2924 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
2926 if (!m_widget
->window
) return;
2928 if (m_wxwindow
&& m_wxwindow
->window
)
2930 gdk_window_clear( m_wxwindow
->window
);
2935 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2937 wxWindowBase::DoSetToolTip(tip
);
2940 m_tooltip
->Apply( this );
2943 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2945 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
2947 #endif // wxUSE_TOOLTIPS
2949 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2951 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2953 if (!wxWindowBase::SetBackgroundColour(colour
))
2955 // don't leave if the GTK widget has just
2957 if (!m_delayedBackgroundColour
) return FALSE
;
2960 GdkWindow
*window
= (GdkWindow
*) NULL
;
2962 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2964 window
= GetConnectWidget()->window
;
2968 // indicate that a new style has been set
2969 // but it couldn't get applied as the
2970 // widget hasn't been realized yet.
2971 m_delayedBackgroundColour
= TRUE
;
2975 (m_wxwindow
->window
) &&
2976 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
2978 /* wxMSW doesn't clear the window here. I don't do that either to
2979 provide compatibility. call Clear() to do the job. */
2981 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
2982 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
2990 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
2992 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2994 if (!wxWindowBase::SetForegroundColour(colour
))
2996 // don't leave if the GTK widget has just
2998 if (!m_delayedForegroundColour
) return FALSE
;
3001 GdkWindow
*window
= (GdkWindow
*) NULL
;
3003 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3005 window
= GetConnectWidget()->window
;
3009 // indicate that a new style has been set
3010 // but it couldn't get applied as the
3011 // widget hasn't been realized yet.
3012 m_delayedForegroundColour
= TRUE
;
3020 GtkStyle
*wxWindow::GetWidgetStyle()
3024 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3025 remake
->klass
= m_widgetStyle
->klass
;
3027 gtk_style_unref( m_widgetStyle
);
3028 m_widgetStyle
= remake
;
3032 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3035 def
= gtk_widget_get_default_style();
3037 m_widgetStyle
= gtk_style_copy( def
);
3038 m_widgetStyle
->klass
= def
->klass
;
3041 return m_widgetStyle
;
3044 void wxWindow::SetWidgetStyle()
3046 if (m_widget
->style
->engine_data
)
3048 static bool s_warningPrinted
= FALSE
;
3049 if (!s_warningPrinted
)
3051 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3052 s_warningPrinted
= TRUE
;
3054 m_widgetStyle
= m_widget
->style
;
3058 GtkStyle
*style
= GetWidgetStyle();
3060 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3062 gdk_font_unref( style
->font
);
3063 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3066 if (m_foregroundColour
.Ok())
3068 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3069 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3071 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3072 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3073 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3077 if (m_backgroundColour
.Ok())
3079 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3080 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3082 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3083 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3084 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3085 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3086 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3087 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3088 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3089 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3094 void wxWindow::ApplyWidgetStyle()
3098 //-----------------------------------------------------------------------------
3099 // Pop-up menu stuff
3100 //-----------------------------------------------------------------------------
3102 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3104 *is_waiting
= FALSE
;
3107 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3109 menu
->SetInvokingWindow( win
);
3110 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3113 wxMenuItem
*menuitem
= node
->GetData();
3114 if (menuitem
->IsSubMenu())
3116 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3119 node
= node
->GetNext();
3123 static gint gs_pop_x
= 0;
3124 static gint gs_pop_y
= 0;
3126 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3130 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3135 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3137 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3139 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3141 SetInvokingWindow( menu
, this );
3148 bool is_waiting
= TRUE
;
3150 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3151 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3154 GTK_MENU(menu
->m_menu
),
3155 (GtkWidget
*) NULL
, // parent menu shell
3156 (GtkWidget
*) NULL
, // parent menu item
3157 (GtkMenuPositionFunc
) pop_pos_callback
,
3158 (gpointer
) this, // client data
3159 0, // button used to activate it
3160 gs_timeLastClick
// the time of activation
3165 while (gtk_events_pending())
3166 gtk_main_iteration();
3172 #if wxUSE_DRAG_AND_DROP
3174 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3176 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3178 GtkWidget
*dnd_widget
= GetConnectWidget();
3180 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3182 if (m_dropTarget
) delete m_dropTarget
;
3183 m_dropTarget
= dropTarget
;
3185 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3188 #endif // wxUSE_DRAG_AND_DROP
3190 GtkWidget
* wxWindow::GetConnectWidget()
3192 GtkWidget
*connect_widget
= m_widget
;
3193 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3195 return connect_widget
;
3198 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3201 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3203 return (window
== m_widget
->window
);
3206 bool wxWindow::SetFont( const wxFont
&font
)
3208 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3210 if (!wxWindowBase::SetFont(font
))
3215 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3216 if ( sysbg
== m_backgroundColour
)
3218 m_backgroundColour
= wxNullColour
;
3220 m_backgroundColour
= sysbg
;
3230 void wxWindow::CaptureMouse()
3232 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3234 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3236 GdkWindow
*window
= (GdkWindow
*) NULL
;
3238 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3240 window
= GetConnectWidget()->window
;
3242 if (!window
) return;
3244 gdk_pointer_grab( window
, FALSE
,
3246 (GDK_BUTTON_PRESS_MASK
|
3247 GDK_BUTTON_RELEASE_MASK
|
3248 GDK_POINTER_MOTION_HINT_MASK
|
3249 GDK_POINTER_MOTION_MASK
),
3251 m_cursor
.GetCursor(),
3252 (guint32
)GDK_CURRENT_TIME
);
3253 g_captureWindow
= this;
3256 void wxWindow::ReleaseMouse()
3258 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3260 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3262 GdkWindow
*window
= (GdkWindow
*) NULL
;
3264 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3266 window
= GetConnectWidget()->window
;
3271 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3272 g_captureWindow
= (wxWindow
*) NULL
;
3275 bool wxWindow::IsRetained() const
3280 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3281 int range
, bool refresh
)
3283 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3285 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3287 m_hasScrolling
= TRUE
;
3289 if (orient
== wxHORIZONTAL
)
3291 float fpos
= (float)pos
;
3292 float frange
= (float)range
;
3293 float fthumb
= (float)thumbVisible
;
3294 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3295 if (fpos
< 0.0) fpos
= 0.0;
3297 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3298 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3300 SetScrollPos( orient
, pos
, refresh
);
3304 m_oldHorizontalPos
= fpos
;
3306 m_hAdjust
->lower
= 0.0;
3307 m_hAdjust
->upper
= frange
;
3308 m_hAdjust
->value
= fpos
;
3309 m_hAdjust
->step_increment
= 1.0;
3310 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3311 m_hAdjust
->page_size
= fthumb
;
3315 float fpos
= (float)pos
;
3316 float frange
= (float)range
;
3317 float fthumb
= (float)thumbVisible
;
3318 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3319 if (fpos
< 0.0) fpos
= 0.0;
3321 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3322 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3324 SetScrollPos( orient
, pos
, refresh
);
3328 m_oldVerticalPos
= fpos
;
3330 m_vAdjust
->lower
= 0.0;
3331 m_vAdjust
->upper
= frange
;
3332 m_vAdjust
->value
= fpos
;
3333 m_vAdjust
->step_increment
= 1.0;
3334 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3335 m_vAdjust
->page_size
= fthumb
;
3338 if (orient
== wxHORIZONTAL
)
3339 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3341 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3344 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3346 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3348 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3350 if (orient
== wxHORIZONTAL
)
3352 float fpos
= (float)pos
;
3353 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3354 if (fpos
< 0.0) fpos
= 0.0;
3355 m_oldHorizontalPos
= fpos
;
3357 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3358 m_hAdjust
->value
= fpos
;
3362 float fpos
= (float)pos
;
3363 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3364 if (fpos
< 0.0) fpos
= 0.0;
3365 m_oldVerticalPos
= fpos
;
3367 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3368 m_vAdjust
->value
= fpos
;
3371 if (m_wxwindow
->window
)
3373 if (orient
== wxHORIZONTAL
)
3375 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3376 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3378 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3380 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3381 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3385 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3386 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3388 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3390 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3391 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3396 int wxWindow::GetScrollThumb( int orient
) const
3398 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3400 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3402 if (orient
== wxHORIZONTAL
)
3403 return (int)(m_hAdjust
->page_size
+0.5);
3405 return (int)(m_vAdjust
->page_size
+0.5);
3408 int wxWindow::GetScrollPos( int orient
) const
3410 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3412 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3414 if (orient
== wxHORIZONTAL
)
3415 return (int)(m_hAdjust
->value
+0.5);
3417 return (int)(m_vAdjust
->value
+0.5);
3420 int wxWindow::GetScrollRange( int orient
) const
3422 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3424 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3426 if (orient
== wxHORIZONTAL
)
3427 return (int)(m_hAdjust
->upper
+0.5);
3429 return (int)(m_vAdjust
->upper
+0.5);
3432 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3434 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3436 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3439 printf( "ScrollWindow: %d %d\n", dx, dy );
3442 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3447 m_scrollGC = gdk_gc_new( m_wxwindow->window );
3448 gdk_gc_set_exposures( m_scrollGC, TRUE );
3451 wxNode *node = m_children.First();
3454 wxWindow *child = (wxWindow*) node->Data();
3457 child->GetSize( &sx, &sy );
3458 child->SetSize( child->m_x + dx, child->m_y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
3459 node = node->Next();
3464 GetClientSize( &cw, &ch );
3465 int w = cw - abs(dx);
3466 int h = ch - abs(dy);
3468 if ((h < 0) || (w < 0))
3476 if (dx < 0) s_x = -dx;
3477 if (dy < 0) s_y = -dy;
3480 if (dx > 0) d_x = dx;
3481 if (dy > 0) d_y = dy;
3483 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
3484 m_wxwindow->window, s_x, s_y, w, h );
3487 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3488 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3489 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3490 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3492 Refresh( TRUE, &rect );