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
);
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
->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 // "button_press_event"
900 //-----------------------------------------------------------------------------
902 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
907 wxapp_install_idle_handler();
910 wxPrintf( wxT("1) OnButtonPress from ") );
911 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
912 wxPrintf( win->GetClassInfo()->GetClassName() );
913 wxPrintf( wxT(".\n") );
915 if (!win
->m_hasVMT
) return FALSE
;
916 if (g_blockEventsOnDrag
) return TRUE
;
917 if (g_blockEventsOnScroll
) return TRUE
;
919 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
923 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
925 gtk_widget_grab_focus (win
->m_wxwindow
);
928 wxPrintf( wxT("GrabFocus from ") );
929 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
930 wxPrintf( win->GetClassInfo()->GetClassName() );
931 wxPrintf( wxT(".\n") );
937 wxEventType event_type
= wxEVT_LEFT_DOWN
;
939 if (gdk_event
->button
== 1)
941 switch (gdk_event
->type
)
943 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
944 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
948 else if (gdk_event
->button
== 2)
950 switch (gdk_event
->type
)
952 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
953 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
957 else if (gdk_event
->button
== 3)
959 switch (gdk_event
->type
)
961 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
962 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
967 wxMouseEvent
event( event_type
);
968 event
.SetTimestamp( gdk_event
->time
);
969 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
970 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
971 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
972 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
973 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
974 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
975 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
977 event
.m_x
= (wxCoord
)gdk_event
->x
;
978 event
.m_y
= (wxCoord
)gdk_event
->y
;
980 // Some control don't have their own X window and thus cannot get
983 if (!g_captureWindow
)
985 wxCoord x
= event
.m_x
;
986 wxCoord y
= event
.m_y
;
989 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
994 wxNode
*node
= win
->GetChildren().First();
997 wxWindow
*child
= (wxWindow
*)node
->Data();
1000 if (!child
->IsShown())
1003 if (child
->m_isStaticBox
)
1005 // wxStaticBox is transparent in the box itself
1006 int xx1
= child
->m_x
;
1007 int yy1
= child
->m_y
;
1008 int xx2
= child
->m_x
+ child
->m_width
;
1009 int yy2
= child
->m_x
+ child
->m_height
;
1012 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1014 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1016 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1018 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1021 event
.m_x
-= child
->m_x
;
1022 event
.m_y
-= child
->m_y
;
1029 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1030 (child
->m_x
<= x
) &&
1031 (child
->m_y
<= y
) &&
1032 (child
->m_x
+child
->m_width
>= x
) &&
1033 (child
->m_y
+child
->m_height
>= y
))
1036 event
.m_x
-= child
->m_x
;
1037 event
.m_y
-= child
->m_y
;
1044 event
.SetEventObject( win
);
1046 gs_timeLastClick
= gdk_event
->time
;
1049 wxPrintf( wxT("2) OnButtonPress from ") );
1050 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1051 wxPrintf( win->GetClassInfo()->GetClassName() );
1052 wxPrintf( wxT(".\n") );
1055 if (win
->GetEventHandler()->ProcessEvent( event
))
1057 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1064 //-----------------------------------------------------------------------------
1065 // "button_release_event"
1066 //-----------------------------------------------------------------------------
1068 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1073 wxapp_install_idle_handler();
1075 if (!win
->m_hasVMT
) return FALSE
;
1076 if (g_blockEventsOnDrag
) return FALSE
;
1077 if (g_blockEventsOnScroll
) return FALSE
;
1079 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1082 printf( "OnButtonRelease from " );
1083 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1084 printf( win->GetClassInfo()->GetClassName() );
1088 wxEventType event_type
= wxEVT_NULL
;
1090 switch (gdk_event
->button
)
1092 case 1: event_type
= wxEVT_LEFT_UP
; break;
1093 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1094 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1097 wxMouseEvent
event( event_type
);
1098 event
.SetTimestamp( gdk_event
->time
);
1099 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1100 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1101 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1102 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1103 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1104 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1105 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1106 event
.m_x
= (wxCoord
)gdk_event
->x
;
1107 event
.m_y
= (wxCoord
)gdk_event
->y
;
1109 // Some control don't have their own X window and thus cannot get
1112 if (!g_captureWindow
)
1114 wxCoord x
= event
.m_x
;
1115 wxCoord y
= event
.m_y
;
1116 if (win
->m_wxwindow
)
1118 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1119 x
+= pizza
->xoffset
;
1120 y
+= pizza
->yoffset
;
1123 wxNode
*node
= win
->GetChildren().First();
1126 wxWindow
*child
= (wxWindow
*)node
->Data();
1128 node
= node
->Next();
1129 if (!child
->IsShown())
1132 if (child
->m_isStaticBox
)
1134 // wxStaticBox is transparent in the box itself
1135 int xx1
= child
->m_x
;
1136 int yy1
= child
->m_y
;
1137 int xx2
= child
->m_x
+ child
->m_width
;
1138 int yy2
= child
->m_x
+ child
->m_height
;
1141 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1143 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1145 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1147 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1150 event
.m_x
-= child
->m_x
;
1151 event
.m_y
-= child
->m_y
;
1158 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1159 (child
->m_x
<= x
) &&
1160 (child
->m_y
<= y
) &&
1161 (child
->m_x
+child
->m_width
>= x
) &&
1162 (child
->m_y
+child
->m_height
>= y
))
1165 event
.m_x
-= child
->m_x
;
1166 event
.m_y
-= child
->m_y
;
1173 event
.SetEventObject( win
);
1175 if (win
->GetEventHandler()->ProcessEvent( event
))
1177 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1184 //-----------------------------------------------------------------------------
1185 // "motion_notify_event"
1186 //-----------------------------------------------------------------------------
1188 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1193 wxapp_install_idle_handler();
1195 if (!win
->m_hasVMT
) return FALSE
;
1196 if (g_blockEventsOnDrag
) return FALSE
;
1197 if (g_blockEventsOnScroll
) return FALSE
;
1199 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1201 if (gdk_event
->is_hint
)
1205 GdkModifierType state
;
1206 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1212 printf( "OnMotion from " );
1213 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1214 printf( win->GetClassInfo()->GetClassName() );
1218 wxMouseEvent
event( wxEVT_MOTION
);
1219 event
.SetTimestamp( gdk_event
->time
);
1220 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1221 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1222 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1223 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1224 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1225 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1226 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1228 event
.m_x
= (wxCoord
)gdk_event
->x
;
1229 event
.m_y
= (wxCoord
)gdk_event
->y
;
1231 // Some control don't have their own X window and thus cannot get
1234 if (!g_captureWindow
)
1236 wxCoord x
= event
.m_x
;
1237 wxCoord y
= event
.m_y
;
1238 if (win
->m_wxwindow
)
1240 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1241 x
+= pizza
->xoffset
;
1242 y
+= pizza
->yoffset
;
1245 wxNode
*node
= win
->GetChildren().First();
1248 wxWindow
*child
= (wxWindow
*)node
->Data();
1250 node
= node
->Next();
1251 if (!child
->IsShown())
1254 if (child
->m_isStaticBox
)
1256 // wxStaticBox is transparent in the box itself
1257 int xx1
= child
->m_x
;
1258 int yy1
= child
->m_y
;
1259 int xx2
= child
->m_x
+ child
->m_width
;
1260 int yy2
= child
->m_x
+ child
->m_height
;
1263 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1265 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1267 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1269 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1272 event
.m_x
-= child
->m_x
;
1273 event
.m_y
-= child
->m_y
;
1280 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1281 (child
->m_x
<= x
) &&
1282 (child
->m_y
<= y
) &&
1283 (child
->m_x
+child
->m_width
>= x
) &&
1284 (child
->m_y
+child
->m_height
>= y
))
1287 event
.m_x
-= child
->m_x
;
1288 event
.m_y
-= child
->m_y
;
1295 event
.SetEventObject( win
);
1297 if (win
->GetEventHandler()->ProcessEvent( event
))
1299 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1306 //-----------------------------------------------------------------------------
1308 //-----------------------------------------------------------------------------
1310 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1315 wxapp_install_idle_handler();
1317 if (!win
->m_hasVMT
) return FALSE
;
1318 if (g_blockEventsOnDrag
) return FALSE
;
1320 switch ( g_sendActivateEvent
)
1323 // we've got focus from outside, synthtize wxActivateEvent
1324 g_sendActivateEvent
= 1;
1328 // another our window just lost focus, it was already ours before
1329 // - don't send any wxActivateEvent
1330 g_sendActivateEvent
= -1;
1334 g_focusWindow
= win
;
1337 printf( "OnSetFocus from " );
1338 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1339 printf( win->GetClassInfo()->GetClassName() );
1341 printf( WXSTRINGCAST win->GetLabel() );
1345 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1348 panel
->SetLastFocus(win
);
1353 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1356 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1357 event
.SetEventObject( win
);
1359 if (win
->GetEventHandler()->ProcessEvent( event
))
1361 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1368 //-----------------------------------------------------------------------------
1369 // "focus_out_event"
1370 //-----------------------------------------------------------------------------
1372 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1377 wxapp_install_idle_handler();
1379 if (!win
->m_hasVMT
) return FALSE
;
1380 if (g_blockEventsOnDrag
) return FALSE
;
1382 // if the focus goes out of our app alltogether, OnIdle() will send
1383 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1384 // g_sendActivateEvent to -1
1385 g_sendActivateEvent
= 0;
1387 g_focusWindow
= (wxWindow
*)NULL
;
1390 printf( "OnKillFocus from " );
1391 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1392 printf( win->GetClassInfo()->GetClassName() );
1401 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1402 event
.SetEventObject( win
);
1404 if (win
->GetEventHandler()->ProcessEvent( event
))
1406 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1413 //-----------------------------------------------------------------------------
1414 // "enter_notify_event"
1415 //-----------------------------------------------------------------------------
1417 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1422 wxapp_install_idle_handler();
1424 if (!win
->m_hasVMT
) return FALSE
;
1425 if (g_blockEventsOnDrag
) return FALSE
;
1427 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1429 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1430 #if (GTK_MINOR_VERSION > 0)
1431 event
.SetTimestamp( gdk_event
->time
);
1433 event
.SetEventObject( win
);
1437 GdkModifierType state
= (GdkModifierType
)0;
1439 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1441 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1442 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1443 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1444 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1445 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1446 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1447 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1452 if (win
->GetEventHandler()->ProcessEvent( event
))
1454 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1461 //-----------------------------------------------------------------------------
1462 // "leave_notify_event"
1463 //-----------------------------------------------------------------------------
1465 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1470 wxapp_install_idle_handler();
1472 if (!win
->m_hasVMT
) return FALSE
;
1473 if (g_blockEventsOnDrag
) return FALSE
;
1475 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1477 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1478 #if (GTK_MINOR_VERSION > 0)
1479 event
.SetTimestamp( gdk_event
->time
);
1481 event
.SetEventObject( win
);
1485 GdkModifierType state
= (GdkModifierType
)0;
1487 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1489 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1490 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1491 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1492 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1493 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1494 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1495 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1500 if (win
->GetEventHandler()->ProcessEvent( event
))
1502 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1509 //-----------------------------------------------------------------------------
1510 // "value_changed" from m_vAdjust
1511 //-----------------------------------------------------------------------------
1513 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1518 wxapp_install_idle_handler();
1520 if (g_blockEventsOnDrag
) return;
1522 if (!win
->m_hasVMT
) return;
1524 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1525 if (fabs(diff
) < 0.2) return;
1527 win
->m_oldVerticalPos
= adjust
->value
;
1529 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1530 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1532 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1533 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1534 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1535 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1536 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1538 int value
= (int)(adjust
->value
+0.5);
1540 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1541 event
.SetEventObject( win
);
1542 win
->GetEventHandler()->ProcessEvent( event
);
1545 //-----------------------------------------------------------------------------
1546 // "value_changed" from m_hAdjust
1547 //-----------------------------------------------------------------------------
1549 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1554 wxapp_install_idle_handler();
1556 if (g_blockEventsOnDrag
) return;
1557 if (!win
->m_hasVMT
) return;
1559 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1560 if (fabs(diff
) < 0.2) return;
1562 win
->m_oldHorizontalPos
= adjust
->value
;
1564 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1565 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1567 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1568 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1569 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1570 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1571 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1573 int value
= (int)(adjust
->value
+0.5);
1575 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1576 event
.SetEventObject( win
);
1577 win
->GetEventHandler()->ProcessEvent( event
);
1580 //-----------------------------------------------------------------------------
1581 // "changed" from m_vAdjust
1582 //-----------------------------------------------------------------------------
1584 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1589 wxapp_install_idle_handler();
1591 if (g_blockEventsOnDrag
) return;
1592 if (!win
->m_hasVMT
) return;
1594 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1595 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1597 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1598 event
.SetEventObject( win
);
1599 win
->GetEventHandler()->ProcessEvent( event
);
1602 //-----------------------------------------------------------------------------
1603 // "changed" from m_hAdjust
1604 //-----------------------------------------------------------------------------
1606 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1611 wxapp_install_idle_handler();
1613 if (g_blockEventsOnDrag
) return;
1614 if (!win
->m_hasVMT
) return;
1616 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1617 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1619 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1620 event
.SetEventObject( win
);
1621 win
->GetEventHandler()->ProcessEvent( event
);
1624 //-----------------------------------------------------------------------------
1625 // "button_press_event" from scrollbar
1626 //-----------------------------------------------------------------------------
1628 static gint
gtk_scrollbar_button_press_callback( GtkRange
*WXUNUSED(widget
),
1629 GdkEventButton
*WXUNUSED(gdk_event
),
1635 wxapp_install_idle_handler();
1637 // don't test here as we can release the mouse while being over
1638 // a different window than the slider
1640 // if (gdk_event->window != widget->slider) return FALSE;
1642 g_blockEventsOnScroll
= TRUE
;
1643 win
->m_isScrolling
= TRUE
;
1648 //-----------------------------------------------------------------------------
1649 // "button_release_event" from scrollbar
1650 //-----------------------------------------------------------------------------
1652 static gint
gtk_scrollbar_button_release_callback( GtkRange
*WXUNUSED(widget
),
1653 GdkEventButton
*WXUNUSED(gdk_event
),
1659 // don't test here as we can release the mouse while being over
1660 // a different window than the slider
1662 // if (gdk_event->window != widget->slider) return FALSE;
1664 g_blockEventsOnScroll
= FALSE
;
1665 win
->m_isScrolling
= FALSE
;
1670 // ----------------------------------------------------------------------------
1671 // this wxWindowBase function is implemented here (in platform-specific file)
1672 // because it is static and so couldn't be made virtual
1673 // ----------------------------------------------------------------------------
1675 wxWindow
*wxWindowBase::FindFocus()
1677 return g_focusWindow
;
1680 //-----------------------------------------------------------------------------
1681 // "realize" from m_widget
1682 //-----------------------------------------------------------------------------
1684 /* We cannot set colours and fonts before the widget has
1685 been realized, so we do this directly after realization. */
1688 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1693 wxapp_install_idle_handler();
1695 if (win
->m_delayedBackgroundColour
)
1696 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1698 if (win
->m_delayedForegroundColour
)
1699 win
->SetForegroundColour( win
->GetForegroundColour() );
1701 wxWindowCreateEvent
event( win
);
1702 event
.SetEventObject( win
);
1703 win
->GetEventHandler()->ProcessEvent( event
);
1708 //-----------------------------------------------------------------------------
1710 //-----------------------------------------------------------------------------
1713 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
1714 GtkAllocation
*WXUNUSED(alloc
),
1718 wxapp_install_idle_handler();
1720 if (!win
->m_hasScrolling
) return;
1722 int client_width
= 0;
1723 int client_height
= 0;
1724 win
->GetClientSize( &client_width
, &client_height
);
1725 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
1728 win
->m_oldClientWidth
= client_width
;
1729 win
->m_oldClientHeight
= client_height
;
1731 if (!win
->m_nativeSizeEvent
)
1733 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
1734 event
.SetEventObject( win
);
1735 win
->GetEventHandler()->ProcessEvent( event
);
1741 #define WXUNUSED_UNLESS_XIM(param) param
1743 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1746 /* Resize XIM window */
1749 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1750 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1751 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1754 wxapp_install_idle_handler();
1760 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1764 gdk_window_get_size (widget
->window
, &width
, &height
);
1765 win
->m_icattr
->preedit_area
.width
= width
;
1766 win
->m_icattr
->preedit_area
.height
= height
;
1767 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
1772 //-----------------------------------------------------------------------------
1773 // "realize" from m_wxwindow
1774 //-----------------------------------------------------------------------------
1776 /* Initialize XIM support */
1779 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1780 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1783 wxapp_install_idle_handler();
1786 if (win
->m_ic
) return FALSE
;
1787 if (!widget
) return FALSE
;
1788 if (!gdk_im_ready()) return FALSE
;
1790 win
->m_icattr
= gdk_ic_attr_new();
1791 if (!win
->m_icattr
) return FALSE
;
1795 GdkColormap
*colormap
;
1796 GdkICAttr
*attr
= win
->m_icattr
;
1797 unsigned attrmask
= GDK_IC_ALL_REQ
;
1799 GdkIMStyle supported_style
= (GdkIMStyle
)
1800 (GDK_IM_PREEDIT_NONE
|
1801 GDK_IM_PREEDIT_NOTHING
|
1802 GDK_IM_PREEDIT_POSITION
|
1803 GDK_IM_STATUS_NONE
|
1804 GDK_IM_STATUS_NOTHING
);
1806 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1807 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
1809 attr
->style
= style
= gdk_im_decide_style (supported_style
);
1810 attr
->client_window
= widget
->window
;
1812 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
1813 gtk_widget_get_default_colormap ())
1815 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
1816 attr
->preedit_colormap
= colormap
;
1819 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
1820 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
1821 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
1822 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
1824 switch (style
& GDK_IM_PREEDIT_MASK
)
1826 case GDK_IM_PREEDIT_POSITION
:
1827 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1829 g_warning ("over-the-spot style requires fontset");
1833 gdk_window_get_size (widget
->window
, &width
, &height
);
1835 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
1836 attr
->spot_location
.x
= 0;
1837 attr
->spot_location
.y
= height
;
1838 attr
->preedit_area
.x
= 0;
1839 attr
->preedit_area
.y
= 0;
1840 attr
->preedit_area
.width
= width
;
1841 attr
->preedit_area
.height
= height
;
1842 attr
->preedit_fontset
= widget
->style
->font
;
1847 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
1849 if (win
->m_ic
== NULL
)
1850 g_warning ("Can't create input context.");
1853 mask
= gdk_window_get_events (widget
->window
);
1854 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
1855 gdk_window_set_events (widget
->window
, mask
);
1857 if (GTK_WIDGET_HAS_FOCUS(widget
))
1858 gdk_im_begin (win
->m_ic
, widget
->window
);
1865 //-----------------------------------------------------------------------------
1866 // InsertChild for wxWindow.
1867 //-----------------------------------------------------------------------------
1869 /* Callback for wxWindow. This very strange beast has to be used because
1870 * C++ has no virtual methods in a constructor. We have to emulate a
1871 * virtual function here as wxNotebook requires a different way to insert
1872 * a child in it. I had opted for creating a wxNotebookPage window class
1873 * which would have made this superfluous (such in the MDI window system),
1874 * but no-one was listening to me... */
1876 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1878 /* the window might have been scrolled already, do we
1879 have to adapt the position */
1880 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
1881 child
->m_x
+= pizza
->xoffset
;
1882 child
->m_y
+= pizza
->yoffset
;
1884 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
1885 GTK_WIDGET(child
->m_widget
),
1892 //-----------------------------------------------------------------------------
1894 //-----------------------------------------------------------------------------
1896 wxWindow
* wxGetActiveWindow()
1898 return g_focusWindow
;
1901 //-----------------------------------------------------------------------------
1903 //-----------------------------------------------------------------------------
1905 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
1907 void wxWindow::Init()
1913 m_widget
= (GtkWidget
*) NULL
;
1914 m_wxwindow
= (GtkWidget
*) NULL
;
1924 m_needParent
= TRUE
;
1925 m_isBeingDeleted
= FALSE
;
1928 m_nativeSizeEvent
= FALSE
;
1930 m_hasScrolling
= FALSE
;
1931 m_isScrolling
= FALSE
;
1933 m_hAdjust
= (GtkAdjustment
*) NULL
;
1934 m_vAdjust
= (GtkAdjustment
*) NULL
;
1935 m_oldHorizontalPos
= 0.0;
1936 m_oldVerticalPos
= 0.0;
1939 m_widgetStyle
= (GtkStyle
*) NULL
;
1941 m_insertCallback
= (wxInsertChildFunction
) NULL
;
1943 m_isStaticBox
= FALSE
;
1944 m_isRadioButton
= FALSE
;
1946 m_acceptsFocus
= FALSE
;
1948 m_cursor
= *wxSTANDARD_CURSOR
;
1951 m_ic
= (GdkIC
*) NULL
;
1952 m_icattr
= (GdkICAttr
*) NULL
;
1956 wxWindow::wxWindow()
1961 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1962 const wxPoint
&pos
, const wxSize
&size
,
1963 long style
, const wxString
&name
)
1967 Create( parent
, id
, pos
, size
, style
, name
);
1970 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1971 const wxPoint
&pos
, const wxSize
&size
,
1972 long style
, const wxString
&name
)
1974 if (!PreCreation( parent
, pos
, size
) ||
1975 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
1977 wxFAIL_MSG( wxT("wxWindow creation failed") );
1981 m_insertCallback
= wxInsertChildInWindow
;
1983 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
1984 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1987 debug_focus_in( m_widget
, wxT("wxWindow::m_widget"), name
);
1990 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
1993 debug_focus_in( scrolledWindow
->hscrollbar
, wxT("wxWindow::hsrcollbar"), name
);
1994 debug_focus_in( scrolledWindow
->vscrollbar
, wxT("wxWindow::vsrcollbar"), name
);
1997 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1998 scroll_class
->scrollbar_spacing
= 0;
2000 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2002 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2003 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2005 m_wxwindow
= gtk_pizza_new();
2008 debug_focus_in( m_wxwindow
, wxT("wxWindow::m_wxwindow"), name
);
2011 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2013 #if (GTK_MINOR_VERSION > 0)
2014 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2016 if (HasFlag(wxRAISED_BORDER
))
2018 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2020 else if (HasFlag(wxSUNKEN_BORDER
))
2022 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2024 else if (HasFlag(wxSIMPLE_BORDER
))
2026 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2030 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2032 #else // GTK_MINOR_VERSION == 0
2033 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2035 if (HasFlag(wxRAISED_BORDER
))
2037 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2039 else if (HasFlag(wxSUNKEN_BORDER
))
2041 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2045 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2047 #endif // GTK_MINOR_VERSION
2049 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2050 m_acceptsFocus
= TRUE
;
2052 #if (GTK_MINOR_VERSION == 0)
2053 // shut the viewport up
2054 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2055 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2056 #endif // GTK_MINOR_VERSION == 0
2058 // I _really_ don't want scrollbars in the beginning
2059 m_vAdjust
->lower
= 0.0;
2060 m_vAdjust
->upper
= 1.0;
2061 m_vAdjust
->value
= 0.0;
2062 m_vAdjust
->step_increment
= 1.0;
2063 m_vAdjust
->page_increment
= 1.0;
2064 m_vAdjust
->page_size
= 5.0;
2065 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2066 m_hAdjust
->lower
= 0.0;
2067 m_hAdjust
->upper
= 1.0;
2068 m_hAdjust
->value
= 0.0;
2069 m_hAdjust
->step_increment
= 1.0;
2070 m_hAdjust
->page_increment
= 1.0;
2071 m_hAdjust
->page_size
= 5.0;
2072 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2074 // these handlers block mouse events to any window during scrolling such as
2075 // motion events and prevent GTK and wxWindows from fighting over where the
2078 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2079 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2081 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2082 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2084 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2085 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2087 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2088 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2090 // these handlers get notified when screen updates are required either when
2091 // scrolling or when the window size (and therefore scrollbar configuration)
2094 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2095 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2096 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2097 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2099 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
2100 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
2101 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
2102 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
2104 gtk_widget_show( m_wxwindow
);
2107 m_parent
->DoAddChild( this );
2116 wxWindow::~wxWindow()
2118 m_isBeingDeleted
= TRUE
;
2127 m_parent
->RemoveChild( this );
2131 gdk_ic_destroy (m_ic
);
2133 gdk_ic_attr_destroy (m_icattr
);
2138 gtk_style_unref( m_widgetStyle
);
2139 m_widgetStyle
= (GtkStyle
*) NULL
;
2144 gtk_widget_destroy( m_wxwindow
);
2145 m_wxwindow
= (GtkWidget
*) NULL
;
2150 gtk_widget_destroy( m_widget
);
2151 m_widget
= (GtkWidget
*) NULL
;
2155 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2157 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2159 /* this turns -1 into 20 so that a minimal window is
2160 visible even although -1,-1 has been given as the
2161 size of the window. the same trick is used in other
2162 ports and should make debugging easier */
2163 m_width
= WidthDefault(size
.x
);
2164 m_height
= HeightDefault(size
.y
);
2169 /* some reasonable defaults */
2174 m_x
= (gdk_screen_width () - m_width
) / 2;
2175 if (m_x
< 10) m_x
= 10;
2179 m_y
= (gdk_screen_height () - m_height
) / 2;
2180 if (m_y
< 10) m_y
= 10;
2187 void wxWindow::PostCreation()
2189 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2195 /* these get reported to wxWindows -> wxPaintEvent */
2196 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2197 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2199 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2200 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2203 #if (GTK_MINOR_VERSION > 0)
2204 /* these are called when the "sunken" or "raised" borders are drawn */
2205 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2206 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2208 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2209 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2213 if (m_wxwindow
&& m_needParent
)
2215 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2216 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2218 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2219 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2223 // For dialogs and frames, we are interested mainly in
2224 // m_widget's focus.
2226 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2227 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2229 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2230 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2233 GtkWidget
*connect_widget
= GetConnectWidget();
2235 ConnectWidget( connect_widget
);
2237 /* We cannot set colours, fonts and cursors before the widget has
2238 been realized, so we do this directly after realization */
2239 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2240 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2244 /* Catch native resize events. */
2245 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2246 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2248 /* Initialize XIM support. */
2249 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2250 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2252 /* And resize XIM window. */
2253 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2254 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2260 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2262 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2263 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2265 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2266 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2268 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2269 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2271 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2272 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2274 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2275 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2277 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2278 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2280 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2281 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2284 bool wxWindow::Destroy()
2286 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2290 return wxWindowBase::Destroy();
2293 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2295 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2298 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2300 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2301 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2303 if (m_resizing
) return; /* I don't like recursions */
2306 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2308 /* don't set the size for children of wxNotebook, just take the values. */
2316 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2318 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2320 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2321 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2322 if (width
!= -1) m_width
= width
;
2323 if (height
!= -1) m_height
= height
;
2327 m_x
= x
+ pizza
->xoffset
;
2328 m_y
= y
+ pizza
->yoffset
;
2333 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2335 if (width
== -1) m_width
= 80;
2338 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2340 if (height
== -1) m_height
= 26;
2343 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2344 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2345 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2346 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2349 int bottom_border
= 0;
2351 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2353 /* the default button has a border around it */
2358 DoMoveWindow( m_x
-border
,
2361 m_height
+border
+bottom_border
);
2366 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2370 wxPrintf( "OnSize sent from " );
2371 if (GetClassInfo() && GetClassInfo()->GetClassName())
2372 wxPrintf( GetClassInfo()->GetClassName() );
2373 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2376 if (!m_nativeSizeEvent
)
2378 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2379 event
.SetEventObject( this );
2380 GetEventHandler()->ProcessEvent( event
);
2386 void wxWindow::OnInternalIdle()
2388 if ( g_sendActivateEvent
!= -1 )
2390 bool activate
= g_sendActivateEvent
!= 0;
2393 g_sendActivateEvent
= -1;
2395 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2396 event
.SetEventObject(this);
2398 (void)GetEventHandler()->ProcessEvent(event
);
2401 wxCursor cursor
= m_cursor
;
2402 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2406 /* I now set the cursor anew in every OnInternalIdle call
2407 as setting the cursor in a parent window also effects the
2408 windows above so that checking for the current cursor is
2413 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2415 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2417 if (!g_globalCursor
.Ok())
2418 cursor
= *wxSTANDARD_CURSOR
;
2420 window
= m_widget
->window
;
2421 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2422 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2428 GdkWindow
*window
= m_widget
->window
;
2429 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2430 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2438 void wxWindow::DoGetSize( int *width
, int *height
) const
2440 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2442 if (width
) (*width
) = m_width
;
2443 if (height
) (*height
) = m_height
;
2446 void wxWindow::DoSetClientSize( int width
, int height
)
2448 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2452 SetSize( width
, height
);
2459 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2461 /* when using GTK 1.2 we set the shadow border size to 2 */
2465 if (HasFlag(wxSIMPLE_BORDER
))
2467 /* when using GTK 1.2 we set the simple border size to 1 */
2474 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2476 GtkRequisition vscroll_req
;
2477 vscroll_req
.width
= 2;
2478 vscroll_req
.height
= 2;
2479 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
2480 (scroll_window
->vscrollbar
, &vscroll_req
);
2482 GtkRequisition hscroll_req
;
2483 hscroll_req
.width
= 2;
2484 hscroll_req
.height
= 2;
2485 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
2486 (scroll_window
->hscrollbar
, &hscroll_req
);
2488 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2490 if (scroll_window
->vscrollbar_visible
)
2492 dw
+= vscroll_req
.width
;
2493 dw
+= scroll_class
->scrollbar_spacing
;
2496 if (scroll_window
->hscrollbar_visible
)
2498 dh
+= hscroll_req
.height
;
2499 dh
+= scroll_class
->scrollbar_spacing
;
2503 SetSize( width
+dw
, height
+dh
);
2507 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2509 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2513 if (width
) (*width
) = m_width
;
2514 if (height
) (*height
) = m_height
;
2521 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2523 /* when using GTK 1.2 we set the shadow border size to 2 */
2527 if (HasFlag(wxSIMPLE_BORDER
))
2529 /* when using GTK 1.2 we set the simple border size to 1 */
2536 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2538 GtkRequisition vscroll_req
;
2539 vscroll_req
.width
= 2;
2540 vscroll_req
.height
= 2;
2541 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
2542 (scroll_window
->vscrollbar
, &vscroll_req
);
2544 GtkRequisition hscroll_req
;
2545 hscroll_req
.width
= 2;
2546 hscroll_req
.height
= 2;
2547 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
2548 (scroll_window
->hscrollbar
, &hscroll_req
);
2550 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2552 if (scroll_window
->vscrollbar_visible
)
2554 dw
+= vscroll_req
.width
;
2555 dw
+= scroll_class
->scrollbar_spacing
;
2558 if (scroll_window
->hscrollbar_visible
)
2560 dh
+= hscroll_req
.height
;
2561 dh
+= scroll_class
->scrollbar_spacing
;
2565 if (width
) (*width
) = m_width
- dw
;
2566 if (height
) (*height
) = m_height
- dh
;
2570 void wxWindow::DoGetPosition( int *x
, int *y
) const
2572 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2576 if (m_parent
&& m_parent
->m_wxwindow
)
2578 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2579 dx
= pizza
->xoffset
;
2580 dy
= pizza
->yoffset
;
2583 if (x
) (*x
) = m_x
- dx
;
2584 if (y
) (*y
) = m_y
- dy
;
2587 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2589 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2591 if (!m_widget
->window
) return;
2593 GdkWindow
*source
= (GdkWindow
*) NULL
;
2595 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2597 source
= m_widget
->window
;
2601 gdk_window_get_origin( source
, &org_x
, &org_y
);
2605 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2607 org_x
+= m_widget
->allocation
.x
;
2608 org_y
+= m_widget
->allocation
.y
;
2616 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2618 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2620 if (!m_widget
->window
) return;
2622 GdkWindow
*source
= (GdkWindow
*) NULL
;
2624 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2626 source
= m_widget
->window
;
2630 gdk_window_get_origin( source
, &org_x
, &org_y
);
2634 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2636 org_x
+= m_widget
->allocation
.x
;
2637 org_y
+= m_widget
->allocation
.y
;
2645 bool wxWindow::Show( bool show
)
2647 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2649 if (!wxWindowBase::Show(show
))
2656 gtk_widget_show( m_widget
);
2658 gtk_widget_hide( m_widget
);
2663 bool wxWindow::Enable( bool enable
)
2665 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2667 if (!wxWindowBase::Enable(enable
))
2673 gtk_widget_set_sensitive( m_widget
, enable
);
2675 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2680 int wxWindow::GetCharHeight() const
2682 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2684 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2686 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2688 return font
->ascent
+ font
->descent
;
2691 int wxWindow::GetCharWidth() const
2693 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2695 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2697 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2699 return gdk_string_width( font
, "H" );
2702 void wxWindow::GetTextExtent( const wxString
& string
,
2706 int *externalLeading
,
2707 const wxFont
*theFont
) const
2709 wxFont fontToUse
= m_font
;
2710 if (theFont
) fontToUse
= *theFont
;
2712 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2714 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2715 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2716 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2717 if (descent
) (*descent
) = font
->descent
;
2718 if (externalLeading
) (*externalLeading
) = 0; // ??
2721 void wxWindow::SetFocus()
2723 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2727 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2728 gtk_widget_grab_focus (m_wxwindow
);
2734 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2736 gtk_widget_grab_focus (m_widget
);
2738 else if (GTK_IS_CONTAINER(m_widget
))
2740 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2749 bool wxWindow::AcceptsFocus() const
2751 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2754 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2756 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2758 wxWindow
*oldParent
= m_parent
,
2759 *newParent
= (wxWindow
*)newParentBase
;
2761 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2763 if ( !wxWindowBase::Reparent(newParent
) )
2766 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2768 /* prevent GTK from deleting the widget arbitrarily */
2769 gtk_widget_ref( m_widget
);
2773 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2776 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2780 /* insert GTK representation */
2781 (*(newParent
->m_insertCallback
))(newParent
, this);
2784 /* reverse: prevent GTK from deleting the widget arbitrarily */
2785 gtk_widget_unref( m_widget
);
2790 void wxWindow::DoAddChild(wxWindow
*child
)
2792 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2794 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
2796 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
2801 /* insert GTK representation */
2802 (*m_insertCallback
)(this, child
);
2805 void wxWindow::Raise()
2807 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2809 if (!m_widget
->window
) return;
2811 gdk_window_raise( m_widget
->window
);
2814 void wxWindow::Lower()
2816 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2818 if (!m_widget
->window
) return;
2820 gdk_window_lower( m_widget
->window
);
2823 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2825 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2827 return wxWindowBase::SetCursor( cursor
);
2830 void wxWindow::WarpPointer( int x
, int y
)
2832 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2834 /* we provide this function ourselves as it is
2835 missing in GDK (top of this file) */
2837 GdkWindow
*window
= (GdkWindow
*) NULL
;
2839 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2841 window
= GetConnectWidget()->window
;
2844 gdk_window_warp_pointer( window
, x
, y
);
2847 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2849 if (!m_widget
) return;
2850 if (!m_widget
->window
) return;
2852 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2856 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
2858 rect
->width
, rect
->height
);
2862 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
2866 /* there is no GTK equivalent of "draw only, don't clear" so we
2867 invent our own in the GtkPizza widget */
2873 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2874 gboolean old_clear
= pizza
->clear_on_draw
;
2875 gtk_pizza_set_clear( pizza
, FALSE
);
2877 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2879 gtk_pizza_set_clear( pizza
, old_clear
);
2882 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2886 GdkRectangle gdk_rect
;
2887 gdk_rect
.x
= rect
->x
;
2888 gdk_rect
.y
= rect
->y
;
2889 gdk_rect
.width
= rect
->width
;
2890 gdk_rect
.height
= rect
->height
;
2894 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2895 gboolean old_clear
= pizza
->clear_on_draw
;
2896 gtk_pizza_set_clear( pizza
, FALSE
);
2898 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2900 gtk_pizza_set_clear( pizza
, old_clear
);
2903 gtk_widget_draw( m_widget
, &gdk_rect
);
2907 void wxWindow::Clear()
2909 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
2911 if (!m_widget
->window
) return;
2913 if (m_wxwindow
&& m_wxwindow
->window
)
2915 gdk_window_clear( m_wxwindow
->window
);
2920 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2922 wxWindowBase::DoSetToolTip(tip
);
2925 m_tooltip
->Apply( this );
2928 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2930 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
2932 #endif // wxUSE_TOOLTIPS
2934 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2936 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2938 if (!wxWindowBase::SetBackgroundColour(colour
))
2940 // don't leave if the GTK widget has just
2942 if (!m_delayedBackgroundColour
) return FALSE
;
2945 GdkWindow
*window
= (GdkWindow
*) NULL
;
2947 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2949 window
= GetConnectWidget()->window
;
2953 // indicate that a new style has been set
2954 // but it couldn't get applied as the
2955 // widget hasn't been realized yet.
2956 m_delayedBackgroundColour
= TRUE
;
2958 // pretend we have done something
2963 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
2965 /* wxMSW doesn't clear the window here. I don't do that either to
2966 provide compatibility. call Clear() to do the job. */
2968 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
2969 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
2977 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
2979 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2981 if (!wxWindowBase::SetForegroundColour(colour
))
2983 // don't leave if the GTK widget has just
2985 if (!m_delayedForegroundColour
) return FALSE
;
2988 GdkWindow
*window
= (GdkWindow
*) NULL
;
2990 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2992 window
= GetConnectWidget()->window
;
2996 // indicate that a new style has been set
2997 // but it couldn't get applied as the
2998 // widget hasn't been realized yet.
2999 m_delayedForegroundColour
= TRUE
;
3001 // pretend we have done something
3010 GtkStyle
*wxWindow::GetWidgetStyle()
3012 if (m_widgetStyle
) return m_widgetStyle
;
3014 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3017 def
= gtk_widget_get_default_style();
3019 m_widgetStyle
= gtk_style_copy( def
);
3020 m_widgetStyle
->klass
= def
->klass
;
3022 return m_widgetStyle
;
3025 void wxWindow::SetWidgetStyle()
3027 GtkStyle
*style
= GetWidgetStyle();
3029 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3031 gdk_font_unref( style
->font
);
3032 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3035 if (m_foregroundColour
.Ok())
3037 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3038 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3040 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3041 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3042 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3046 if (m_backgroundColour
.Ok())
3048 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3049 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3051 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3052 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3053 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3054 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3055 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3056 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3057 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3058 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3063 void wxWindow::ApplyWidgetStyle()
3067 //-----------------------------------------------------------------------------
3068 // Pop-up menu stuff
3069 //-----------------------------------------------------------------------------
3071 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3073 *is_waiting
= FALSE
;
3076 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3078 menu
->SetInvokingWindow( win
);
3079 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3082 wxMenuItem
*menuitem
= node
->GetData();
3083 if (menuitem
->IsSubMenu())
3085 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3088 node
= node
->GetNext();
3092 static gint gs_pop_x
= 0;
3093 static gint gs_pop_y
= 0;
3095 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3099 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3104 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3106 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3108 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3110 SetInvokingWindow( menu
, this );
3117 bool is_waiting
= TRUE
;
3119 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3120 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3123 GTK_MENU(menu
->m_menu
),
3124 (GtkWidget
*) NULL
, // parent menu shell
3125 (GtkWidget
*) NULL
, // parent menu item
3126 (GtkMenuPositionFunc
) pop_pos_callback
,
3127 (gpointer
) this, // client data
3128 0, // button used to activate it
3129 gs_timeLastClick
// the time of activation
3134 while (gtk_events_pending())
3135 gtk_main_iteration();
3141 #if wxUSE_DRAG_AND_DROP
3143 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3145 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3147 GtkWidget
*dnd_widget
= GetConnectWidget();
3149 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3151 if (m_dropTarget
) delete m_dropTarget
;
3152 m_dropTarget
= dropTarget
;
3154 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3157 #endif // wxUSE_DRAG_AND_DROP
3159 GtkWidget
* wxWindow::GetConnectWidget()
3161 GtkWidget
*connect_widget
= m_widget
;
3162 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3164 return connect_widget
;
3167 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3170 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3172 return (window
== m_widget
->window
);
3175 bool wxWindow::SetFont( const wxFont
&font
)
3177 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3179 if (!wxWindowBase::SetFont(font
))
3184 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3185 if ( sysbg
== m_backgroundColour
)
3187 m_backgroundColour
= wxNullColour
;
3189 m_backgroundColour
= sysbg
;
3199 void wxWindow::CaptureMouse()
3201 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3203 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3205 GdkWindow
*window
= (GdkWindow
*) NULL
;
3207 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3209 window
= GetConnectWidget()->window
;
3211 if (!window
) return;
3213 gdk_pointer_grab( window
, FALSE
,
3215 (GDK_BUTTON_PRESS_MASK
|
3216 GDK_BUTTON_RELEASE_MASK
|
3217 GDK_POINTER_MOTION_HINT_MASK
|
3218 GDK_POINTER_MOTION_MASK
),
3220 m_cursor
.GetCursor(),
3221 (guint32
)GDK_CURRENT_TIME
);
3222 g_captureWindow
= this;
3225 void wxWindow::ReleaseMouse()
3227 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3229 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3231 GdkWindow
*window
= (GdkWindow
*) NULL
;
3233 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3235 window
= GetConnectWidget()->window
;
3240 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3241 g_captureWindow
= (wxWindow
*) NULL
;
3244 bool wxWindow::IsRetained() const
3249 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3250 int range
, bool refresh
)
3252 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3254 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3256 m_hasScrolling
= TRUE
;
3258 if (orient
== wxHORIZONTAL
)
3260 float fpos
= (float)pos
;
3261 float frange
= (float)range
;
3262 float fthumb
= (float)thumbVisible
;
3263 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3264 if (fpos
< 0.0) fpos
= 0.0;
3266 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3267 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3269 SetScrollPos( orient
, pos
, refresh
);
3273 m_oldHorizontalPos
= fpos
;
3275 m_hAdjust
->lower
= 0.0;
3276 m_hAdjust
->upper
= frange
;
3277 m_hAdjust
->value
= fpos
;
3278 m_hAdjust
->step_increment
= 1.0;
3279 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3280 m_hAdjust
->page_size
= fthumb
;
3284 float fpos
= (float)pos
;
3285 float frange
= (float)range
;
3286 float fthumb
= (float)thumbVisible
;
3287 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3288 if (fpos
< 0.0) fpos
= 0.0;
3290 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3291 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3293 SetScrollPos( orient
, pos
, refresh
);
3297 m_oldVerticalPos
= fpos
;
3299 m_vAdjust
->lower
= 0.0;
3300 m_vAdjust
->upper
= frange
;
3301 m_vAdjust
->value
= fpos
;
3302 m_vAdjust
->step_increment
= 1.0;
3303 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3304 m_vAdjust
->page_size
= fthumb
;
3307 if (orient
== wxHORIZONTAL
)
3308 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3310 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3313 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3315 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3317 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3319 if (orient
== wxHORIZONTAL
)
3321 float fpos
= (float)pos
;
3322 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3323 if (fpos
< 0.0) fpos
= 0.0;
3324 m_oldHorizontalPos
= fpos
;
3326 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3327 m_hAdjust
->value
= fpos
;
3331 float fpos
= (float)pos
;
3332 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3333 if (fpos
< 0.0) fpos
= 0.0;
3334 m_oldVerticalPos
= fpos
;
3336 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3337 m_vAdjust
->value
= fpos
;
3340 if (m_wxwindow
->window
)
3342 if (orient
== wxHORIZONTAL
)
3343 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3345 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3349 int wxWindow::GetScrollThumb( int orient
) const
3351 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3353 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3355 if (orient
== wxHORIZONTAL
)
3356 return (int)(m_hAdjust
->page_size
+0.5);
3358 return (int)(m_vAdjust
->page_size
+0.5);
3361 int wxWindow::GetScrollPos( int orient
) const
3363 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3365 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3367 if (orient
== wxHORIZONTAL
)
3368 return (int)(m_hAdjust
->value
+0.5);
3370 return (int)(m_vAdjust
->value
+0.5);
3373 int wxWindow::GetScrollRange( int orient
) const
3375 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3377 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3379 if (orient
== wxHORIZONTAL
)
3380 return (int)(m_hAdjust
->upper
+0.5);
3382 return (int)(m_vAdjust
->upper
+0.5);
3385 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3387 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3389 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3392 printf( "ScrollWindow: %d %d\n", dx, dy );
3395 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3400 m_scrollGC = gdk_gc_new( m_wxwindow->window );
3401 gdk_gc_set_exposures( m_scrollGC, TRUE );
3404 wxNode *node = m_children.First();
3407 wxWindow *child = (wxWindow*) node->Data();
3410 child->GetSize( &sx, &sy );
3411 child->SetSize( child->m_x + dx, child->m_y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
3412 node = node->Next();
3417 GetClientSize( &cw, &ch );
3418 int w = cw - abs(dx);
3419 int h = ch - abs(dy);
3421 if ((h < 0) || (w < 0))
3429 if (dx < 0) s_x = -dx;
3430 if (dy < 0) s_y = -dy;
3433 if (dx > 0) d_x = dx;
3434 if (dy > 0) d_y = dy;
3436 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
3437 m_wxwindow->window, s_x, s_y, w, h );
3440 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3441 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3442 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3443 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3445 Refresh( TRUE, &rect );