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 //-----------------------------------------------------------------------------
211 #define DISABLE_STYLE_IF_BROKEN_THEME 1
216 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
218 # define DEBUG_MAIN_THREAD
221 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
222 GdkEvent
*WXUNUSED(event
),
223 const wxChar
*WXUNUSED(name
) )
226 static bool s_done = FALSE;
229 wxLog::AddTraceMask("focus");
232 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
238 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
240 // suppress warnings about gtk_debug_focus_in_callback being unused with
245 tmp
+= wxT(" FROM ");
248 wxChar
*s
= new wxChar
[tmp
.Length()+1];
252 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
253 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
258 #define DEBUG_MAIN_THREAD
261 //-----------------------------------------------------------------------------
262 // missing gdk functions
263 //-----------------------------------------------------------------------------
266 gdk_window_warp_pointer (GdkWindow
*window
,
270 GdkWindowPrivate
*priv
;
273 window
= (GdkWindow
*) &gdk_root_parent
;
275 priv
= (GdkWindowPrivate
*) window
;
277 if (!priv
->destroyed
)
279 XWarpPointer (priv
->xdisplay
,
280 None
, /* not source window -> move from anywhere */
281 priv
->xwindow
, /* dest window */
282 0, 0, 0, 0, /* not source window -> move from anywhere */
287 //-----------------------------------------------------------------------------
289 //-----------------------------------------------------------------------------
291 extern void wxapp_install_idle_handler();
292 extern bool g_isIdle
;
294 //-----------------------------------------------------------------------------
295 // local code (see below)
296 //-----------------------------------------------------------------------------
298 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
306 if (win
->m_hasScrolling
)
308 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
310 GtkRequisition vscroll_req
;
311 vscroll_req
.width
= 2;
312 vscroll_req
.height
= 2;
313 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
314 (scroll_window
->vscrollbar
, &vscroll_req
);
316 GtkRequisition hscroll_req
;
317 hscroll_req
.width
= 2;
318 hscroll_req
.height
= 2;
319 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
320 (scroll_window
->hscrollbar
, &hscroll_req
);
322 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget
)->klass
);
324 if (scroll_window
->vscrollbar_visible
)
326 dw
+= vscroll_req
.width
;
327 dw
+= scroll_class
->scrollbar_spacing
;
330 if (scroll_window
->hscrollbar_visible
)
332 dh
+= hscroll_req
.height
;
333 dh
+= scroll_class
->scrollbar_spacing
;
339 if (GTK_WIDGET_NO_WINDOW (widget
))
341 dx
+= widget
->allocation
.x
;
342 dy
+= widget
->allocation
.y
;
345 if (win
->HasFlag(wxRAISED_BORDER
))
347 gtk_draw_shadow( widget
->style
,
352 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
356 if (win
->HasFlag(wxSUNKEN_BORDER
))
358 gtk_draw_shadow( widget
->style
,
363 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
367 if (win
->HasFlag(wxSIMPLE_BORDER
))
370 gc
= gdk_gc_new( widget
->window
);
371 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
372 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
374 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
380 //-----------------------------------------------------------------------------
381 // "expose_event" of m_widget
382 //-----------------------------------------------------------------------------
384 static void gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
386 if (gdk_event
->count
> 0) return;
387 draw_frame( widget
, win
);
390 //-----------------------------------------------------------------------------
391 // "draw" of m_widget
392 //-----------------------------------------------------------------------------
394 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
396 draw_frame( widget
, win
);
399 //-----------------------------------------------------------------------------
400 // key code mapping routines
401 //-----------------------------------------------------------------------------
403 static long map_to_unmodified_wx_keysym( KeySym keysym
)
410 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
412 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
418 case GDK_Super_R
: key_code
= WXK_ALT
; break;
419 case GDK_Menu
: key_code
= WXK_MENU
; break;
420 case GDK_Help
: key_code
= WXK_HELP
; break;
421 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
422 case GDK_ISO_Left_Tab
:
423 case GDK_Tab
: key_code
= WXK_TAB
; break;
424 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
425 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
426 case GDK_Return
: key_code
= WXK_RETURN
; break;
427 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
428 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
429 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
430 case GDK_Delete
: key_code
= WXK_DELETE
; break;
431 case GDK_Home
: key_code
= WXK_HOME
; break;
432 case GDK_Left
: key_code
= WXK_LEFT
; break;
433 case GDK_Up
: key_code
= WXK_UP
; break;
434 case GDK_Right
: key_code
= WXK_RIGHT
; break;
435 case GDK_Down
: key_code
= WXK_DOWN
; break;
436 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
437 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
438 case GDK_Next
: key_code
= WXK_NEXT
; break;
439 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
440 case GDK_End
: key_code
= WXK_END
; break;
441 case GDK_Begin
: key_code
= WXK_HOME
; break;
442 case GDK_Select
: key_code
= WXK_SELECT
; break;
443 case GDK_Print
: key_code
= WXK_PRINT
; break;
444 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
445 case GDK_Insert
: key_code
= WXK_INSERT
; break;
446 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
448 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
449 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
450 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
451 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
452 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
453 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
454 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
455 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
456 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
457 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
458 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
459 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
460 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
461 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
462 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
463 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
464 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
465 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
466 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
467 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
468 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
469 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
470 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
471 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
472 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
473 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
474 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
475 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
476 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
477 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
478 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
479 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
480 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
481 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
482 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
483 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
484 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
486 case GDK_F1
: key_code
= WXK_F1
; break;
487 case GDK_F2
: key_code
= WXK_F2
; break;
488 case GDK_F3
: key_code
= WXK_F3
; break;
489 case GDK_F4
: key_code
= WXK_F4
; break;
490 case GDK_F5
: key_code
= WXK_F5
; break;
491 case GDK_F6
: key_code
= WXK_F6
; break;
492 case GDK_F7
: key_code
= WXK_F7
; break;
493 case GDK_F8
: key_code
= WXK_F8
; break;
494 case GDK_F9
: key_code
= WXK_F9
; break;
495 case GDK_F10
: key_code
= WXK_F10
; break;
496 case GDK_F11
: key_code
= WXK_F11
; break;
497 case GDK_F12
: key_code
= WXK_F12
; break;
502 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
503 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
504 key_code
= (guint
)keysym
;
512 static long map_to_wx_keysym( KeySym keysym
)
518 case GDK_Menu
: key_code
= WXK_MENU
; break;
519 case GDK_Help
: key_code
= WXK_HELP
; break;
520 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
521 case GDK_ISO_Left_Tab
:
522 case GDK_Tab
: key_code
= WXK_TAB
; break;
523 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
524 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
525 case GDK_Return
: key_code
= WXK_RETURN
; break;
526 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
527 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
528 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
529 case GDK_Delete
: key_code
= WXK_DELETE
; break;
530 case GDK_Home
: key_code
= WXK_HOME
; break;
531 case GDK_Left
: key_code
= WXK_LEFT
; break;
532 case GDK_Up
: key_code
= WXK_UP
; break;
533 case GDK_Right
: key_code
= WXK_RIGHT
; break;
534 case GDK_Down
: key_code
= WXK_DOWN
; break;
535 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
536 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
537 case GDK_Next
: key_code
= WXK_NEXT
; break;
538 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
539 case GDK_End
: key_code
= WXK_END
; break;
540 case GDK_Begin
: key_code
= WXK_HOME
; break;
541 case GDK_Select
: key_code
= WXK_SELECT
; break;
542 case GDK_Print
: key_code
= WXK_PRINT
; break;
543 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
544 case GDK_Insert
: key_code
= WXK_INSERT
; break;
545 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
547 case GDK_KP_0
: key_code
= '0'; break;
548 case GDK_KP_1
: key_code
= '1'; break;
549 case GDK_KP_2
: key_code
= '2'; break;
550 case GDK_KP_3
: key_code
= '3'; break;
551 case GDK_KP_4
: key_code
= '4'; break;
552 case GDK_KP_5
: key_code
= '5'; break;
553 case GDK_KP_6
: key_code
= '6'; break;
554 case GDK_KP_7
: key_code
= '7'; break;
555 case GDK_KP_8
: key_code
= '8'; break;
556 case GDK_KP_9
: key_code
= '9'; break;
557 case GDK_KP_Space
: key_code
= ' '; break;
558 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
559 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
560 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
561 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
562 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
563 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
564 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
565 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
566 case GDK_KP_Up
: key_code
= WXK_UP
; break;
567 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
568 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
569 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
570 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
571 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
572 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
573 case GDK_KP_End
: key_code
= WXK_END
; break;
574 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
575 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
576 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
577 case GDK_KP_Equal
: key_code
= '='; break;
578 case GDK_KP_Multiply
: key_code
= '*'; break;
579 case GDK_KP_Add
: key_code
= '+'; break;
580 case GDK_KP_Separator
: key_code
= ','; break;
581 case GDK_KP_Subtract
: key_code
= '-'; break;
582 case GDK_KP_Decimal
: key_code
= '.'; break;
583 case GDK_KP_Divide
: key_code
= '/'; break;
585 case GDK_F1
: key_code
= WXK_F1
; break;
586 case GDK_F2
: key_code
= WXK_F2
; break;
587 case GDK_F3
: key_code
= WXK_F3
; break;
588 case GDK_F4
: key_code
= WXK_F4
; break;
589 case GDK_F5
: key_code
= WXK_F5
; break;
590 case GDK_F6
: key_code
= WXK_F6
; break;
591 case GDK_F7
: key_code
= WXK_F7
; break;
592 case GDK_F8
: key_code
= WXK_F8
; break;
593 case GDK_F9
: key_code
= WXK_F9
; break;
594 case GDK_F10
: key_code
= WXK_F10
; break;
595 case GDK_F11
: key_code
= WXK_F11
; break;
596 case GDK_F12
: key_code
= WXK_F12
; break;
601 key_code
= (guint
)keysym
;
609 //-----------------------------------------------------------------------------
610 // "expose_event" of m_wxwindow
611 //-----------------------------------------------------------------------------
613 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
618 if (win->GetName() == wxT("grid window"))
620 wxPrintf( wxT("OnExpose from ") );
621 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
622 wxPrintf( win->GetClassInfo()->GetClassName() );
623 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
624 (int)gdk_event->area.y,
625 (int)gdk_event->area.width,
626 (int)gdk_event->area.height );
630 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
632 gdk_event
->area
.width
,
633 gdk_event
->area
.height
);
636 if (gdk_event
->count
> 0)
642 wxEraseEvent
eevent( win
->GetId() );
643 eevent
.SetEventObject( win
);
644 win
->GetEventHandler()->ProcessEvent(eevent
);
646 wxPaintEvent
event( win
->GetId() );
647 event
.SetEventObject( win
);
648 win
->GetEventHandler()->ProcessEvent( event
);
650 win
->GetUpdateRegion().Clear();
653 //-----------------------------------------------------------------------------
654 // "draw" of m_wxwindow
655 //-----------------------------------------------------------------------------
657 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
),
658 GdkRectangle
*rect
, wxWindow
*win
)
663 wxapp_install_idle_handler();
665 if ((rect
->x
== 0) && (rect
->y
== 0) && (rect
->width
<= 1) && (rect
->height
<= 1))
669 if (win->GetName() == wxT("grid window"))
671 wxPrintf( wxT("OnDraw from ") );
672 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
673 wxPrintf( win->GetClassInfo()->GetClassName() );
674 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
681 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
,
682 rect
->width
, rect
->height
);
687 wxEraseEvent
eevent( win
->GetId() );
688 eevent
.SetEventObject( win
);
689 win
->GetEventHandler()->ProcessEvent(eevent
);
691 wxPaintEvent
event( win
->GetId() );
692 event
.SetEventObject( win
);
693 win
->GetEventHandler()->ProcessEvent( event
);
695 win
->GetUpdateRegion().Clear();
698 //-----------------------------------------------------------------------------
699 // "key_press_event" from any window
700 //-----------------------------------------------------------------------------
702 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
707 wxapp_install_idle_handler();
709 if (!win
->m_hasVMT
) return FALSE
;
710 if (g_blockEventsOnDrag
) return FALSE
;
714 tmp += (char)gdk_event->keyval;
715 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
716 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
721 GdkModifierType state
;
722 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
726 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
727 /* sending unknown key events doesn't really make sense */
728 if (key_code
== 0) return FALSE
;
730 wxKeyEvent
event( wxEVT_KEY_DOWN
);
731 event
.SetTimestamp( gdk_event
->time
);
732 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
733 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
734 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
735 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
736 event
.m_keyCode
= key_code
;
737 event
.m_scanCode
= gdk_event
->keyval
;
740 event
.SetEventObject( win
);
741 ret
= win
->GetEventHandler()->ProcessEvent( event
);
746 wxWindow
*ancestor
= win
;
749 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
752 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
753 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
756 if (ancestor
->m_isFrame
)
758 ancestor
= ancestor
->GetParent();
761 #endif // wxUSE_ACCEL
763 /* wxMSW doesn't send char events with Alt pressed */
764 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
765 will only be sent if it is not in an accelerator table. */
766 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
771 wxKeyEvent
event2( wxEVT_CHAR
);
772 event2
.SetTimestamp( gdk_event
->time
);
773 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
774 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
775 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
776 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
777 event2
.m_keyCode
= key_code
;
778 event2
.m_scanCode
= gdk_event
->keyval
;
781 event2
.SetEventObject( win
);
782 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
785 /* win is a control: tab can be propagated up */
787 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
788 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
789 (win
->GetParent()) &&
790 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
792 wxNavigationKeyEvent new_event
;
793 new_event
.SetEventObject( win
->GetParent() );
794 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
795 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
796 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
797 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
798 new_event
.SetCurrentFocus( win
);
799 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
802 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
804 (gdk_event
->keyval
== GDK_Escape
) )
806 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
807 new_event
.SetEventObject( win
);
808 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
811 #if (GTK_MINOR_VERSION > 0)
812 /* Pressing F10 will activate the menu bar of the top frame. */
816 (gdk_event->keyval == GDK_F10) )
818 wxWindow *ancestor = win;
821 if (wxIsKindOf(ancestor,wxFrame))
823 wxFrame *frame = (wxFrame*) ancestor;
824 wxMenuBar *menubar = frame->GetMenuBar();
827 wxNode *node = menubar->GetMenus().First();
830 wxMenu *firstMenu = (wxMenu*) node->Data();
831 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
837 ancestor = ancestor->GetParent();
845 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
852 //-----------------------------------------------------------------------------
853 // "key_release_event" from any window
854 //-----------------------------------------------------------------------------
856 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
861 wxapp_install_idle_handler();
863 if (!win
->m_hasVMT
) return FALSE
;
864 if (g_blockEventsOnDrag
) return FALSE
;
867 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
868 if (gdk_event->state & GDK_SHIFT_MASK)
869 printf( "ShiftDown.\n" );
871 printf( "ShiftUp.\n" );
872 if (gdk_event->state & GDK_CONTROL_MASK)
873 printf( "ControlDown.\n" );
875 printf( "ControlUp.\n" );
879 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
881 /* sending unknown key events doesn't really make sense */
882 if (key_code
== 0) return FALSE
;
886 GdkModifierType state
;
887 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
889 wxKeyEvent
event( wxEVT_KEY_UP
);
890 event
.SetTimestamp( gdk_event
->time
);
891 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
892 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
893 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
894 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
895 event
.m_keyCode
= key_code
;
896 event
.m_scanCode
= gdk_event
->keyval
;
899 event
.SetEventObject( win
);
901 if (win
->GetEventHandler()->ProcessEvent( event
))
903 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
910 // ----------------------------------------------------------------------------
911 // mouse event processing helper
912 // ----------------------------------------------------------------------------
914 static void AdjustEventButtonState(wxMouseEvent
& event
)
916 // GDK reports the old state of the button for a button press event, but
917 // for compatibility with MSW and common sense we want m_leftDown be TRUE
918 // for a LEFT_DOWN event, not FALSE, so we will invert
919 // left/right/middleDown for the corresponding click events
920 switch ( event
.GetEventType() )
922 case wxEVT_LEFT_DOWN
:
923 case wxEVT_LEFT_DCLICK
:
925 event
.m_leftDown
= !event
.m_leftDown
;
928 case wxEVT_MIDDLE_DOWN
:
929 case wxEVT_MIDDLE_DCLICK
:
930 case wxEVT_MIDDLE_UP
:
931 event
.m_middleDown
= !event
.m_middleDown
;
934 case wxEVT_RIGHT_DOWN
:
935 case wxEVT_RIGHT_DCLICK
:
937 event
.m_rightDown
= !event
.m_rightDown
;
942 //-----------------------------------------------------------------------------
943 // "button_press_event"
944 //-----------------------------------------------------------------------------
946 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
951 wxapp_install_idle_handler();
954 wxPrintf( wxT("1) OnButtonPress from ") );
955 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
956 wxPrintf( win->GetClassInfo()->GetClassName() );
957 wxPrintf( wxT(".\n") );
959 if (!win
->m_hasVMT
) return FALSE
;
960 if (g_blockEventsOnDrag
) return TRUE
;
961 if (g_blockEventsOnScroll
) return TRUE
;
963 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
967 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
969 gtk_widget_grab_focus (win
->m_wxwindow
);
972 wxPrintf( wxT("GrabFocus from ") );
973 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
974 wxPrintf( win->GetClassInfo()->GetClassName() );
975 wxPrintf( wxT(".\n") );
981 wxEventType event_type
= wxEVT_NULL
;
983 if (gdk_event
->button
== 1)
985 switch (gdk_event
->type
)
987 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
988 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
992 else if (gdk_event
->button
== 2)
994 switch (gdk_event
->type
)
996 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
997 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1001 else if (gdk_event
->button
== 3)
1003 switch (gdk_event
->type
)
1005 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1006 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1011 if ( event_type
== wxEVT_NULL
)
1013 // unknown mouse button or click type
1017 wxMouseEvent
event( event_type
);
1018 event
.SetTimestamp( gdk_event
->time
);
1019 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1020 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1021 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1022 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1023 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1024 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1025 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1027 event
.m_x
= (wxCoord
)gdk_event
->x
;
1028 event
.m_y
= (wxCoord
)gdk_event
->y
;
1030 AdjustEventButtonState(event
);
1032 // Some control don't have their own X window and thus cannot get
1035 if (!g_captureWindow
)
1037 wxCoord x
= event
.m_x
;
1038 wxCoord y
= event
.m_y
;
1039 if (win
->m_wxwindow
)
1041 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1042 x
+= pizza
->xoffset
;
1043 y
+= pizza
->yoffset
;
1046 wxNode
*node
= win
->GetChildren().First();
1049 wxWindow
*child
= (wxWindow
*)node
->Data();
1051 node
= node
->Next();
1052 if (!child
->IsShown())
1055 if (child
->m_isStaticBox
)
1057 // wxStaticBox is transparent in the box itself
1058 int xx1
= child
->m_x
;
1059 int yy1
= child
->m_y
;
1060 int xx2
= child
->m_x
+ child
->m_width
;
1061 int yy2
= child
->m_x
+ child
->m_height
;
1064 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1066 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1068 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1070 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1073 event
.m_x
-= child
->m_x
;
1074 event
.m_y
-= child
->m_y
;
1081 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1082 (child
->m_x
<= x
) &&
1083 (child
->m_y
<= y
) &&
1084 (child
->m_x
+child
->m_width
>= x
) &&
1085 (child
->m_y
+child
->m_height
>= y
))
1088 event
.m_x
-= child
->m_x
;
1089 event
.m_y
-= child
->m_y
;
1096 event
.SetEventObject( win
);
1098 gs_timeLastClick
= gdk_event
->time
;
1101 wxPrintf( wxT("2) OnButtonPress from ") );
1102 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1103 wxPrintf( win->GetClassInfo()->GetClassName() );
1104 wxPrintf( wxT(".\n") );
1107 if (win
->GetEventHandler()->ProcessEvent( event
))
1109 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1116 //-----------------------------------------------------------------------------
1117 // "button_release_event"
1118 //-----------------------------------------------------------------------------
1120 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1125 wxapp_install_idle_handler();
1127 if (!win
->m_hasVMT
) return FALSE
;
1128 if (g_blockEventsOnDrag
) return FALSE
;
1129 if (g_blockEventsOnScroll
) return FALSE
;
1131 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1134 printf( "OnButtonRelease from " );
1135 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1136 printf( win->GetClassInfo()->GetClassName() );
1140 wxEventType event_type
= wxEVT_NULL
;
1142 switch (gdk_event
->button
)
1144 case 1: event_type
= wxEVT_LEFT_UP
; break;
1145 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1146 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1147 default: return FALSE
;
1150 wxMouseEvent
event( event_type
);
1151 event
.SetTimestamp( gdk_event
->time
);
1152 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1153 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1154 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1155 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1156 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1157 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1158 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1159 event
.m_x
= (wxCoord
)gdk_event
->x
;
1160 event
.m_y
= (wxCoord
)gdk_event
->y
;
1162 AdjustEventButtonState(event
);
1164 // Some control don't have their own X window and thus cannot get
1167 if (!g_captureWindow
)
1169 wxCoord x
= event
.m_x
;
1170 wxCoord y
= event
.m_y
;
1171 if (win
->m_wxwindow
)
1173 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1174 x
+= pizza
->xoffset
;
1175 y
+= pizza
->yoffset
;
1178 wxNode
*node
= win
->GetChildren().First();
1181 wxWindow
*child
= (wxWindow
*)node
->Data();
1183 node
= node
->Next();
1184 if (!child
->IsShown())
1187 if (child
->m_isStaticBox
)
1189 // wxStaticBox is transparent in the box itself
1190 int xx1
= child
->m_x
;
1191 int yy1
= child
->m_y
;
1192 int xx2
= child
->m_x
+ child
->m_width
;
1193 int yy2
= child
->m_x
+ child
->m_height
;
1196 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1198 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1200 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1202 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1205 event
.m_x
-= child
->m_x
;
1206 event
.m_y
-= child
->m_y
;
1213 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1214 (child
->m_x
<= x
) &&
1215 (child
->m_y
<= y
) &&
1216 (child
->m_x
+child
->m_width
>= x
) &&
1217 (child
->m_y
+child
->m_height
>= y
))
1220 event
.m_x
-= child
->m_x
;
1221 event
.m_y
-= child
->m_y
;
1228 event
.SetEventObject( win
);
1230 if (win
->GetEventHandler()->ProcessEvent( event
))
1232 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1239 //-----------------------------------------------------------------------------
1240 // "motion_notify_event"
1241 //-----------------------------------------------------------------------------
1243 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1248 wxapp_install_idle_handler();
1250 if (!win
->m_hasVMT
) return FALSE
;
1251 if (g_blockEventsOnDrag
) return FALSE
;
1252 if (g_blockEventsOnScroll
) return FALSE
;
1254 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1256 if (gdk_event
->is_hint
)
1260 GdkModifierType state
;
1261 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1267 printf( "OnMotion from " );
1268 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1269 printf( win->GetClassInfo()->GetClassName() );
1273 wxMouseEvent
event( wxEVT_MOTION
);
1274 event
.SetTimestamp( gdk_event
->time
);
1275 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1276 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1277 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1278 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1279 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1280 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1281 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1283 event
.m_x
= (wxCoord
)gdk_event
->x
;
1284 event
.m_y
= (wxCoord
)gdk_event
->y
;
1286 // Some control don't have their own X window and thus cannot get
1289 if (!g_captureWindow
)
1291 wxCoord x
= event
.m_x
;
1292 wxCoord y
= event
.m_y
;
1293 if (win
->m_wxwindow
)
1295 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1296 x
+= pizza
->xoffset
;
1297 y
+= pizza
->yoffset
;
1300 wxNode
*node
= win
->GetChildren().First();
1303 wxWindow
*child
= (wxWindow
*)node
->Data();
1305 node
= node
->Next();
1306 if (!child
->IsShown())
1309 if (child
->m_isStaticBox
)
1311 // wxStaticBox is transparent in the box itself
1312 int xx1
= child
->m_x
;
1313 int yy1
= child
->m_y
;
1314 int xx2
= child
->m_x
+ child
->m_width
;
1315 int yy2
= child
->m_x
+ child
->m_height
;
1318 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1320 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1322 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1324 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1327 event
.m_x
-= child
->m_x
;
1328 event
.m_y
-= child
->m_y
;
1335 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1336 (child
->m_x
<= x
) &&
1337 (child
->m_y
<= y
) &&
1338 (child
->m_x
+child
->m_width
>= x
) &&
1339 (child
->m_y
+child
->m_height
>= y
))
1342 event
.m_x
-= child
->m_x
;
1343 event
.m_y
-= child
->m_y
;
1350 event
.SetEventObject( win
);
1352 if (win
->GetEventHandler()->ProcessEvent( event
))
1354 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1361 //-----------------------------------------------------------------------------
1363 //-----------------------------------------------------------------------------
1365 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1370 wxapp_install_idle_handler();
1372 if (!win
->m_hasVMT
) return FALSE
;
1373 if (g_blockEventsOnDrag
) return FALSE
;
1375 switch ( g_sendActivateEvent
)
1378 // we've got focus from outside, synthtize wxActivateEvent
1379 g_sendActivateEvent
= 1;
1383 // another our window just lost focus, it was already ours before
1384 // - don't send any wxActivateEvent
1385 g_sendActivateEvent
= -1;
1389 g_focusWindow
= win
;
1392 printf( "OnSetFocus from " );
1393 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1394 printf( win->GetClassInfo()->GetClassName() );
1396 printf( WXSTRINGCAST win->GetLabel() );
1400 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1403 panel
->SetLastFocus(win
);
1408 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1411 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1412 event
.SetEventObject( win
);
1414 if (win
->GetEventHandler()->ProcessEvent( event
))
1416 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1423 //-----------------------------------------------------------------------------
1424 // "focus_out_event"
1425 //-----------------------------------------------------------------------------
1427 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1432 wxapp_install_idle_handler();
1434 if (!win
->m_hasVMT
) return FALSE
;
1435 if (g_blockEventsOnDrag
) return FALSE
;
1437 // if the focus goes out of our app alltogether, OnIdle() will send
1438 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1439 // g_sendActivateEvent to -1
1440 g_sendActivateEvent
= 0;
1442 g_focusWindow
= (wxWindow
*)NULL
;
1445 printf( "OnKillFocus from " );
1446 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1447 printf( win->GetClassInfo()->GetClassName() );
1456 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1457 event
.SetEventObject( win
);
1459 if (win
->GetEventHandler()->ProcessEvent( event
))
1461 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1468 //-----------------------------------------------------------------------------
1469 // "enter_notify_event"
1470 //-----------------------------------------------------------------------------
1472 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1477 wxapp_install_idle_handler();
1479 if (!win
->m_hasVMT
) return FALSE
;
1480 if (g_blockEventsOnDrag
) return FALSE
;
1482 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1484 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1485 #if (GTK_MINOR_VERSION > 0)
1486 event
.SetTimestamp( gdk_event
->time
);
1488 event
.SetEventObject( win
);
1492 GdkModifierType state
= (GdkModifierType
)0;
1494 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1496 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1497 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1498 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1499 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1500 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1501 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1502 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1507 if (win
->GetEventHandler()->ProcessEvent( event
))
1509 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1516 //-----------------------------------------------------------------------------
1517 // "leave_notify_event"
1518 //-----------------------------------------------------------------------------
1520 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1525 wxapp_install_idle_handler();
1527 if (!win
->m_hasVMT
) return FALSE
;
1528 if (g_blockEventsOnDrag
) return FALSE
;
1530 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1532 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1533 #if (GTK_MINOR_VERSION > 0)
1534 event
.SetTimestamp( gdk_event
->time
);
1536 event
.SetEventObject( win
);
1540 GdkModifierType state
= (GdkModifierType
)0;
1542 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1544 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1545 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1546 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1547 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1548 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1549 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1550 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1555 if (win
->GetEventHandler()->ProcessEvent( event
))
1557 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1564 //-----------------------------------------------------------------------------
1565 // "value_changed" from m_vAdjust
1566 //-----------------------------------------------------------------------------
1568 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1573 wxapp_install_idle_handler();
1575 if (g_blockEventsOnDrag
) return;
1577 if (!win
->m_hasVMT
) return;
1579 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1580 if (fabs(diff
) < 0.2) return;
1582 win
->m_oldVerticalPos
= adjust
->value
;
1584 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1585 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1587 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1588 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1589 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1590 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1591 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1593 int value
= (int)(adjust
->value
+0.5);
1595 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1596 event
.SetEventObject( win
);
1597 win
->GetEventHandler()->ProcessEvent( event
);
1600 //-----------------------------------------------------------------------------
1601 // "value_changed" from m_hAdjust
1602 //-----------------------------------------------------------------------------
1604 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1609 wxapp_install_idle_handler();
1611 if (g_blockEventsOnDrag
) return;
1612 if (!win
->m_hasVMT
) return;
1614 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1615 if (fabs(diff
) < 0.2) return;
1617 win
->m_oldHorizontalPos
= adjust
->value
;
1619 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1620 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1622 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1623 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1624 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1625 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1626 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1628 int value
= (int)(adjust
->value
+0.5);
1630 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1631 event
.SetEventObject( win
);
1632 win
->GetEventHandler()->ProcessEvent( event
);
1635 //-----------------------------------------------------------------------------
1636 // "button_press_event" from scrollbar
1637 //-----------------------------------------------------------------------------
1639 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1640 GdkEventButton
*gdk_event
,
1646 wxapp_install_idle_handler();
1648 g_blockEventsOnScroll
= TRUE
;
1649 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1654 //-----------------------------------------------------------------------------
1655 // "button_release_event" from scrollbar
1656 //-----------------------------------------------------------------------------
1658 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1659 GdkEventButton
*WXUNUSED(gdk_event
),
1664 // don't test here as we can release the mouse while being over
1665 // a different window than the slider
1667 // if (gdk_event->window != widget->slider) return FALSE;
1669 g_blockEventsOnScroll
= FALSE
;
1671 if (win
->m_isScrolling
)
1673 wxEventType command
= wxEVT_SCROLL_THUMBRELEASE
;
1677 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1678 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1680 value
= (int)(win
->m_hAdjust
->value
+0.5);
1683 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1685 value
= (int)(win
->m_vAdjust
->value
+0.5);
1689 wxScrollWinEvent
event( command
, value
, dir
);
1690 event
.SetEventObject( win
);
1691 win
->GetEventHandler()->ProcessEvent( event
);
1694 win
->m_isScrolling
= FALSE
;
1699 // ----------------------------------------------------------------------------
1700 // this wxWindowBase function is implemented here (in platform-specific file)
1701 // because it is static and so couldn't be made virtual
1702 // ----------------------------------------------------------------------------
1704 wxWindow
*wxWindowBase::FindFocus()
1706 return g_focusWindow
;
1709 //-----------------------------------------------------------------------------
1710 // "realize" from m_widget
1711 //-----------------------------------------------------------------------------
1713 /* We cannot set colours and fonts before the widget has
1714 been realized, so we do this directly after realization. */
1717 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1722 wxapp_install_idle_handler();
1724 if (win
->m_delayedBackgroundColour
)
1725 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1727 if (win
->m_delayedForegroundColour
)
1728 win
->SetForegroundColour( win
->GetForegroundColour() );
1730 wxWindowCreateEvent
event( win
);
1731 event
.SetEventObject( win
);
1732 win
->GetEventHandler()->ProcessEvent( event
);
1737 //-----------------------------------------------------------------------------
1739 //-----------------------------------------------------------------------------
1742 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
1743 GtkAllocation
*WXUNUSED(alloc
),
1747 wxapp_install_idle_handler();
1749 if (!win
->m_hasScrolling
) return;
1751 int client_width
= 0;
1752 int client_height
= 0;
1753 win
->GetClientSize( &client_width
, &client_height
);
1754 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
1757 win
->m_oldClientWidth
= client_width
;
1758 win
->m_oldClientHeight
= client_height
;
1760 if (!win
->m_nativeSizeEvent
)
1762 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
1763 event
.SetEventObject( win
);
1764 win
->GetEventHandler()->ProcessEvent( event
);
1770 #define WXUNUSED_UNLESS_XIM(param) param
1772 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1775 /* Resize XIM window */
1778 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1779 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1780 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1783 wxapp_install_idle_handler();
1789 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1793 gdk_window_get_size (widget
->window
, &width
, &height
);
1794 win
->m_icattr
->preedit_area
.width
= width
;
1795 win
->m_icattr
->preedit_area
.height
= height
;
1796 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
1801 //-----------------------------------------------------------------------------
1802 // "realize" from m_wxwindow
1803 //-----------------------------------------------------------------------------
1805 /* Initialize XIM support */
1808 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1809 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1812 wxapp_install_idle_handler();
1815 if (win
->m_ic
) return FALSE
;
1816 if (!widget
) return FALSE
;
1817 if (!gdk_im_ready()) return FALSE
;
1819 win
->m_icattr
= gdk_ic_attr_new();
1820 if (!win
->m_icattr
) return FALSE
;
1824 GdkColormap
*colormap
;
1825 GdkICAttr
*attr
= win
->m_icattr
;
1826 unsigned attrmask
= GDK_IC_ALL_REQ
;
1828 GdkIMStyle supported_style
= (GdkIMStyle
)
1829 (GDK_IM_PREEDIT_NONE
|
1830 GDK_IM_PREEDIT_NOTHING
|
1831 GDK_IM_PREEDIT_POSITION
|
1832 GDK_IM_STATUS_NONE
|
1833 GDK_IM_STATUS_NOTHING
);
1835 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1836 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
1838 attr
->style
= style
= gdk_im_decide_style (supported_style
);
1839 attr
->client_window
= widget
->window
;
1841 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
1842 gtk_widget_get_default_colormap ())
1844 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
1845 attr
->preedit_colormap
= colormap
;
1848 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
1849 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
1850 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
1851 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
1853 switch (style
& GDK_IM_PREEDIT_MASK
)
1855 case GDK_IM_PREEDIT_POSITION
:
1856 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1858 g_warning ("over-the-spot style requires fontset");
1862 gdk_window_get_size (widget
->window
, &width
, &height
);
1864 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
1865 attr
->spot_location
.x
= 0;
1866 attr
->spot_location
.y
= height
;
1867 attr
->preedit_area
.x
= 0;
1868 attr
->preedit_area
.y
= 0;
1869 attr
->preedit_area
.width
= width
;
1870 attr
->preedit_area
.height
= height
;
1871 attr
->preedit_fontset
= widget
->style
->font
;
1876 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
1878 if (win
->m_ic
== NULL
)
1879 g_warning ("Can't create input context.");
1882 mask
= gdk_window_get_events (widget
->window
);
1883 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
1884 gdk_window_set_events (widget
->window
, mask
);
1886 if (GTK_WIDGET_HAS_FOCUS(widget
))
1887 gdk_im_begin (win
->m_ic
, widget
->window
);
1894 //-----------------------------------------------------------------------------
1895 // InsertChild for wxWindow.
1896 //-----------------------------------------------------------------------------
1898 /* Callback for wxWindow. This very strange beast has to be used because
1899 * C++ has no virtual methods in a constructor. We have to emulate a
1900 * virtual function here as wxNotebook requires a different way to insert
1901 * a child in it. I had opted for creating a wxNotebookPage window class
1902 * which would have made this superfluous (such in the MDI window system),
1903 * but no-one was listening to me... */
1905 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1907 /* the window might have been scrolled already, do we
1908 have to adapt the position */
1909 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
1910 child
->m_x
+= pizza
->xoffset
;
1911 child
->m_y
+= pizza
->yoffset
;
1913 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
1914 GTK_WIDGET(child
->m_widget
),
1921 //-----------------------------------------------------------------------------
1923 //-----------------------------------------------------------------------------
1925 wxWindow
* wxGetActiveWindow()
1927 return g_focusWindow
;
1930 //-----------------------------------------------------------------------------
1932 //-----------------------------------------------------------------------------
1934 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
1936 void wxWindow::Init()
1942 m_widget
= (GtkWidget
*) NULL
;
1943 m_wxwindow
= (GtkWidget
*) NULL
;
1953 m_needParent
= TRUE
;
1954 m_isBeingDeleted
= FALSE
;
1957 m_nativeSizeEvent
= FALSE
;
1959 m_hasScrolling
= FALSE
;
1960 m_isScrolling
= FALSE
;
1962 m_hAdjust
= (GtkAdjustment
*) NULL
;
1963 m_vAdjust
= (GtkAdjustment
*) NULL
;
1964 m_oldHorizontalPos
= 0.0;
1965 m_oldVerticalPos
= 0.0;
1968 m_widgetStyle
= (GtkStyle
*) NULL
;
1970 m_insertCallback
= (wxInsertChildFunction
) NULL
;
1972 m_isStaticBox
= FALSE
;
1973 m_isRadioButton
= FALSE
;
1975 m_acceptsFocus
= FALSE
;
1977 m_cursor
= *wxSTANDARD_CURSOR
;
1980 m_ic
= (GdkIC
*) NULL
;
1981 m_icattr
= (GdkICAttr
*) NULL
;
1985 wxWindow::wxWindow()
1990 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1991 const wxPoint
&pos
, const wxSize
&size
,
1992 long style
, const wxString
&name
)
1996 Create( parent
, id
, pos
, size
, style
, name
);
1999 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
2000 const wxPoint
&pos
, const wxSize
&size
,
2001 long style
, const wxString
&name
)
2003 if (!PreCreation( parent
, pos
, size
) ||
2004 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2006 wxFAIL_MSG( wxT("wxWindow creation failed") );
2010 m_insertCallback
= wxInsertChildInWindow
;
2012 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2013 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2016 debug_focus_in( m_widget
, wxT("wxWindow::m_widget"), name
);
2019 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2022 debug_focus_in( scrolledWindow
->hscrollbar
, wxT("wxWindow::hsrcollbar"), name
);
2023 debug_focus_in( scrolledWindow
->vscrollbar
, wxT("wxWindow::vsrcollbar"), name
);
2026 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2027 scroll_class
->scrollbar_spacing
= 0;
2029 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2031 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2032 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2034 m_wxwindow
= gtk_pizza_new();
2037 debug_focus_in( m_wxwindow
, wxT("wxWindow::m_wxwindow"), name
);
2040 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2042 #if (GTK_MINOR_VERSION > 0)
2043 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2045 if (HasFlag(wxRAISED_BORDER
))
2047 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2049 else if (HasFlag(wxSUNKEN_BORDER
))
2051 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2053 else if (HasFlag(wxSIMPLE_BORDER
))
2055 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2059 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2061 #else // GTK_MINOR_VERSION == 0
2062 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2064 if (HasFlag(wxRAISED_BORDER
))
2066 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2068 else if (HasFlag(wxSUNKEN_BORDER
))
2070 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2074 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2076 #endif // GTK_MINOR_VERSION
2078 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2079 m_acceptsFocus
= TRUE
;
2081 #if (GTK_MINOR_VERSION == 0)
2082 // shut the viewport up
2083 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2084 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2085 #endif // GTK_MINOR_VERSION == 0
2087 // I _really_ don't want scrollbars in the beginning
2088 m_vAdjust
->lower
= 0.0;
2089 m_vAdjust
->upper
= 1.0;
2090 m_vAdjust
->value
= 0.0;
2091 m_vAdjust
->step_increment
= 1.0;
2092 m_vAdjust
->page_increment
= 1.0;
2093 m_vAdjust
->page_size
= 5.0;
2094 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2095 m_hAdjust
->lower
= 0.0;
2096 m_hAdjust
->upper
= 1.0;
2097 m_hAdjust
->value
= 0.0;
2098 m_hAdjust
->step_increment
= 1.0;
2099 m_hAdjust
->page_increment
= 1.0;
2100 m_hAdjust
->page_size
= 5.0;
2101 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2103 // these handlers block mouse events to any window during scrolling such as
2104 // motion events and prevent GTK and wxWindows from fighting over where the
2107 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2108 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2110 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2111 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2113 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2114 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2116 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2117 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2119 // these handlers get notified when screen updates are required either when
2120 // scrolling or when the window size (and therefore scrollbar configuration)
2123 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2124 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2125 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2126 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2128 gtk_widget_show( m_wxwindow
);
2131 m_parent
->DoAddChild( this );
2140 wxWindow::~wxWindow()
2142 m_isBeingDeleted
= TRUE
;
2151 m_parent
->RemoveChild( this );
2155 gdk_ic_destroy (m_ic
);
2157 gdk_ic_attr_destroy (m_icattr
);
2162 #if DISABLE_STYLE_IF_BROKEN_THEME
2163 // don't delete if it's a pixmap theme style
2164 if (!m_widgetStyle
->engine_data
)
2165 gtk_style_unref( m_widgetStyle
);
2167 m_widgetStyle
= (GtkStyle
*) NULL
;
2172 gtk_widget_destroy( m_wxwindow
);
2173 m_wxwindow
= (GtkWidget
*) NULL
;
2178 gtk_widget_destroy( m_widget
);
2179 m_widget
= (GtkWidget
*) NULL
;
2183 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2185 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2187 /* this turns -1 into 20 so that a minimal window is
2188 visible even although -1,-1 has been given as the
2189 size of the window. the same trick is used in other
2190 ports and should make debugging easier */
2191 m_width
= WidthDefault(size
.x
);
2192 m_height
= HeightDefault(size
.y
);
2197 /* some reasonable defaults */
2202 m_x
= (gdk_screen_width () - m_width
) / 2;
2203 if (m_x
< 10) m_x
= 10;
2207 m_y
= (gdk_screen_height () - m_height
) / 2;
2208 if (m_y
< 10) m_y
= 10;
2215 void wxWindow::PostCreation()
2217 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2223 /* these get reported to wxWindows -> wxPaintEvent */
2224 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2225 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2227 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2228 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2231 #if (GTK_MINOR_VERSION > 0)
2232 /* these are called when the "sunken" or "raised" borders are drawn */
2233 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2234 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2236 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2237 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2241 if (m_wxwindow
&& m_needParent
)
2243 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2244 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2246 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2247 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2251 // For dialogs and frames, we are interested mainly in
2252 // m_widget's focus.
2254 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2255 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2257 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2258 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2261 GtkWidget
*connect_widget
= GetConnectWidget();
2263 ConnectWidget( connect_widget
);
2265 /* We cannot set colours, fonts and cursors before the widget has
2266 been realized, so we do this directly after realization */
2267 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2268 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2272 /* Catch native resize events. */
2273 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2274 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2276 /* Initialize XIM support. */
2277 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2278 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2280 /* And resize XIM window. */
2281 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2282 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2288 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2290 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2291 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2293 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2294 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2296 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2297 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2299 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2300 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2302 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2303 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2305 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2306 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2308 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2309 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2312 bool wxWindow::Destroy()
2314 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2318 return wxWindowBase::Destroy();
2321 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2323 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2326 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2328 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2329 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2331 if (m_resizing
) return; /* I don't like recursions */
2334 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2336 /* don't set the size for children of wxNotebook, just take the values. */
2344 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2346 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2348 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2349 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2350 if (width
!= -1) m_width
= width
;
2351 if (height
!= -1) m_height
= height
;
2355 m_x
= x
+ pizza
->xoffset
;
2356 m_y
= y
+ pizza
->yoffset
;
2361 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2363 if (width
== -1) m_width
= 80;
2366 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2368 if (height
== -1) m_height
= 26;
2371 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2372 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2373 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2374 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2377 int bottom_border
= 0;
2379 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2381 /* the default button has a border around it */
2386 DoMoveWindow( m_x
-border
,
2389 m_height
+border
+bottom_border
);
2394 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2398 wxPrintf( "OnSize sent from " );
2399 if (GetClassInfo() && GetClassInfo()->GetClassName())
2400 wxPrintf( GetClassInfo()->GetClassName() );
2401 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2404 if (!m_nativeSizeEvent
)
2406 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2407 event
.SetEventObject( this );
2408 GetEventHandler()->ProcessEvent( event
);
2414 void wxWindow::OnInternalIdle()
2416 if ( g_sendActivateEvent
!= -1 )
2418 bool activate
= g_sendActivateEvent
!= 0;
2421 g_sendActivateEvent
= -1;
2423 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2424 event
.SetEventObject(this);
2426 (void)GetEventHandler()->ProcessEvent(event
);
2429 wxCursor cursor
= m_cursor
;
2430 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2434 /* I now set the cursor anew in every OnInternalIdle call
2435 as setting the cursor in a parent window also effects the
2436 windows above so that checking for the current cursor is
2441 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2443 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2445 if (!g_globalCursor
.Ok())
2446 cursor
= *wxSTANDARD_CURSOR
;
2448 window
= m_widget
->window
;
2449 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2450 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2456 GdkWindow
*window
= m_widget
->window
;
2457 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2458 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2466 void wxWindow::DoGetSize( int *width
, int *height
) const
2468 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2470 if (width
) (*width
) = m_width
;
2471 if (height
) (*height
) = m_height
;
2474 void wxWindow::DoSetClientSize( int width
, int height
)
2476 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2480 SetSize( width
, height
);
2487 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2489 /* when using GTK 1.2 we set the shadow border size to 2 */
2493 if (HasFlag(wxSIMPLE_BORDER
))
2495 /* when using GTK 1.2 we set the simple border size to 1 */
2502 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2504 GtkRequisition vscroll_req
;
2505 vscroll_req
.width
= 2;
2506 vscroll_req
.height
= 2;
2507 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
2508 (scroll_window
->vscrollbar
, &vscroll_req
);
2510 GtkRequisition hscroll_req
;
2511 hscroll_req
.width
= 2;
2512 hscroll_req
.height
= 2;
2513 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
2514 (scroll_window
->hscrollbar
, &hscroll_req
);
2516 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2518 if (scroll_window
->vscrollbar_visible
)
2520 dw
+= vscroll_req
.width
;
2521 dw
+= scroll_class
->scrollbar_spacing
;
2524 if (scroll_window
->hscrollbar_visible
)
2526 dh
+= hscroll_req
.height
;
2527 dh
+= scroll_class
->scrollbar_spacing
;
2531 SetSize( width
+dw
, height
+dh
);
2535 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2537 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2541 if (width
) (*width
) = m_width
;
2542 if (height
) (*height
) = m_height
;
2549 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2551 /* when using GTK 1.2 we set the shadow border size to 2 */
2555 if (HasFlag(wxSIMPLE_BORDER
))
2557 /* when using GTK 1.2 we set the simple border size to 1 */
2564 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2566 GtkRequisition vscroll_req
;
2567 vscroll_req
.width
= 2;
2568 vscroll_req
.height
= 2;
2569 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
2570 (scroll_window
->vscrollbar
, &vscroll_req
);
2572 GtkRequisition hscroll_req
;
2573 hscroll_req
.width
= 2;
2574 hscroll_req
.height
= 2;
2575 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
2576 (scroll_window
->hscrollbar
, &hscroll_req
);
2578 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2580 if (scroll_window
->vscrollbar_visible
)
2582 dw
+= vscroll_req
.width
;
2583 dw
+= scroll_class
->scrollbar_spacing
;
2586 if (scroll_window
->hscrollbar_visible
)
2588 dh
+= hscroll_req
.height
;
2589 dh
+= scroll_class
->scrollbar_spacing
;
2593 if (width
) (*width
) = m_width
- dw
;
2594 if (height
) (*height
) = m_height
- dh
;
2598 void wxWindow::DoGetPosition( int *x
, int *y
) const
2600 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2604 if (m_parent
&& m_parent
->m_wxwindow
)
2606 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2607 dx
= pizza
->xoffset
;
2608 dy
= pizza
->yoffset
;
2611 if (x
) (*x
) = m_x
- dx
;
2612 if (y
) (*y
) = m_y
- dy
;
2615 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2617 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2619 if (!m_widget
->window
) return;
2621 GdkWindow
*source
= (GdkWindow
*) NULL
;
2623 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2625 source
= m_widget
->window
;
2629 gdk_window_get_origin( source
, &org_x
, &org_y
);
2633 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2635 org_x
+= m_widget
->allocation
.x
;
2636 org_y
+= m_widget
->allocation
.y
;
2644 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2646 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2648 if (!m_widget
->window
) return;
2650 GdkWindow
*source
= (GdkWindow
*) NULL
;
2652 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2654 source
= m_widget
->window
;
2658 gdk_window_get_origin( source
, &org_x
, &org_y
);
2662 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2664 org_x
+= m_widget
->allocation
.x
;
2665 org_y
+= m_widget
->allocation
.y
;
2673 bool wxWindow::Show( bool show
)
2675 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2677 if (!wxWindowBase::Show(show
))
2684 gtk_widget_show( m_widget
);
2686 gtk_widget_hide( m_widget
);
2691 bool wxWindow::Enable( bool enable
)
2693 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2695 if (!wxWindowBase::Enable(enable
))
2701 gtk_widget_set_sensitive( m_widget
, enable
);
2703 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2708 int wxWindow::GetCharHeight() const
2710 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2712 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2714 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2716 return font
->ascent
+ font
->descent
;
2719 int wxWindow::GetCharWidth() const
2721 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2723 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2725 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2727 return gdk_string_width( font
, "H" );
2730 void wxWindow::GetTextExtent( const wxString
& string
,
2734 int *externalLeading
,
2735 const wxFont
*theFont
) const
2737 wxFont fontToUse
= m_font
;
2738 if (theFont
) fontToUse
= *theFont
;
2740 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2742 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2743 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2744 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2745 if (descent
) (*descent
) = font
->descent
;
2746 if (externalLeading
) (*externalLeading
) = 0; // ??
2749 void wxWindow::SetFocus()
2751 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2755 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2756 gtk_widget_grab_focus (m_wxwindow
);
2762 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2764 gtk_widget_grab_focus (m_widget
);
2766 else if (GTK_IS_CONTAINER(m_widget
))
2768 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2777 bool wxWindow::AcceptsFocus() const
2779 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2782 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2784 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2786 wxWindow
*oldParent
= m_parent
,
2787 *newParent
= (wxWindow
*)newParentBase
;
2789 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2791 if ( !wxWindowBase::Reparent(newParent
) )
2794 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2796 /* prevent GTK from deleting the widget arbitrarily */
2797 gtk_widget_ref( m_widget
);
2801 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2804 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2808 /* insert GTK representation */
2809 (*(newParent
->m_insertCallback
))(newParent
, this);
2812 /* reverse: prevent GTK from deleting the widget arbitrarily */
2813 gtk_widget_unref( m_widget
);
2818 void wxWindow::DoAddChild(wxWindow
*child
)
2820 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2822 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
2824 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
2829 /* insert GTK representation */
2830 (*m_insertCallback
)(this, child
);
2833 void wxWindow::Raise()
2835 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2837 if (!m_widget
->window
) return;
2839 gdk_window_raise( m_widget
->window
);
2842 void wxWindow::Lower()
2844 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2846 if (!m_widget
->window
) return;
2848 gdk_window_lower( m_widget
->window
);
2851 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2853 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2855 return wxWindowBase::SetCursor( cursor
);
2858 void wxWindow::WarpPointer( int x
, int y
)
2860 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2862 /* we provide this function ourselves as it is
2863 missing in GDK (top of this file) */
2865 GdkWindow
*window
= (GdkWindow
*) NULL
;
2867 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2869 window
= GetConnectWidget()->window
;
2872 gdk_window_warp_pointer( window
, x
, y
);
2875 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2877 if (!m_widget
) return;
2878 if (!m_widget
->window
) return;
2880 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2884 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
2886 rect
->width
, rect
->height
);
2890 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
2894 /* there is no GTK equivalent of "draw only, don't clear" so we
2895 invent our own in the GtkPizza widget */
2901 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2902 gboolean old_clear
= pizza
->clear_on_draw
;
2903 gtk_pizza_set_clear( pizza
, FALSE
);
2905 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2907 gtk_pizza_set_clear( pizza
, old_clear
);
2910 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2914 GdkRectangle gdk_rect
;
2915 gdk_rect
.x
= rect
->x
;
2916 gdk_rect
.y
= rect
->y
;
2917 gdk_rect
.width
= rect
->width
;
2918 gdk_rect
.height
= rect
->height
;
2922 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2923 gboolean old_clear
= pizza
->clear_on_draw
;
2924 gtk_pizza_set_clear( pizza
, FALSE
);
2926 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2928 gtk_pizza_set_clear( pizza
, old_clear
);
2931 gtk_widget_draw( m_widget
, &gdk_rect
);
2935 void wxWindow::Clear()
2937 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
2939 if (!m_widget
->window
) return;
2941 if (m_wxwindow
&& m_wxwindow
->window
)
2943 // gdk_window_clear( m_wxwindow->window );
2948 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2950 wxWindowBase::DoSetToolTip(tip
);
2953 m_tooltip
->Apply( this );
2956 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2958 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
2960 #endif // wxUSE_TOOLTIPS
2962 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2964 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2966 if (!wxWindowBase::SetBackgroundColour(colour
))
2968 // don't leave if the GTK widget has just
2970 if (!m_delayedBackgroundColour
) return FALSE
;
2973 GdkWindow
*window
= (GdkWindow
*) NULL
;
2975 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2977 window
= GetConnectWidget()->window
;
2981 // indicate that a new style has been set
2982 // but it couldn't get applied as the
2983 // widget hasn't been realized yet.
2984 m_delayedBackgroundColour
= TRUE
;
2988 (m_wxwindow
->window
) &&
2989 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
2991 /* wxMSW doesn't clear the window here. I don't do that either to
2992 provide compatibility. call Clear() to do the job. */
2994 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
2995 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3003 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
3005 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3007 if (!wxWindowBase::SetForegroundColour(colour
))
3009 // don't leave if the GTK widget has just
3011 if (!m_delayedForegroundColour
) return FALSE
;
3014 GdkWindow
*window
= (GdkWindow
*) NULL
;
3016 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3018 window
= GetConnectWidget()->window
;
3022 // indicate that a new style has been set
3023 // but it couldn't get applied as the
3024 // widget hasn't been realized yet.
3025 m_delayedForegroundColour
= TRUE
;
3033 GtkStyle
*wxWindow::GetWidgetStyle()
3037 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3038 remake
->klass
= m_widgetStyle
->klass
;
3040 gtk_style_unref( m_widgetStyle
);
3041 m_widgetStyle
= remake
;
3045 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3048 def
= gtk_widget_get_default_style();
3050 m_widgetStyle
= gtk_style_copy( def
);
3051 m_widgetStyle
->klass
= def
->klass
;
3054 return m_widgetStyle
;
3057 void wxWindow::SetWidgetStyle()
3059 #if DISABLE_STYLE_IF_BROKEN_THEM
3060 if (m_widget
->style
->engine_data
)
3062 static bool s_warningPrinted
= FALSE
;
3063 if (!s_warningPrinted
)
3065 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3066 s_warningPrinted
= TRUE
;
3068 m_widgetStyle
= m_widget
->style
;
3073 GtkStyle
*style
= GetWidgetStyle();
3075 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3077 gdk_font_unref( style
->font
);
3078 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3081 if (m_foregroundColour
.Ok())
3083 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3084 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3086 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3087 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3088 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3092 if (m_backgroundColour
.Ok())
3094 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3095 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3097 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3098 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3099 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3100 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3101 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3102 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3103 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3104 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3109 void wxWindow::ApplyWidgetStyle()
3113 //-----------------------------------------------------------------------------
3114 // Pop-up menu stuff
3115 //-----------------------------------------------------------------------------
3117 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3119 *is_waiting
= FALSE
;
3122 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3124 menu
->SetInvokingWindow( win
);
3125 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3128 wxMenuItem
*menuitem
= node
->GetData();
3129 if (menuitem
->IsSubMenu())
3131 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3134 node
= node
->GetNext();
3138 static gint gs_pop_x
= 0;
3139 static gint gs_pop_y
= 0;
3141 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3145 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3150 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3152 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3154 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3156 SetInvokingWindow( menu
, this );
3163 bool is_waiting
= TRUE
;
3165 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3166 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3169 GTK_MENU(menu
->m_menu
),
3170 (GtkWidget
*) NULL
, // parent menu shell
3171 (GtkWidget
*) NULL
, // parent menu item
3172 (GtkMenuPositionFunc
) pop_pos_callback
,
3173 (gpointer
) this, // client data
3174 0, // button used to activate it
3175 gs_timeLastClick
// the time of activation
3180 while (gtk_events_pending())
3181 gtk_main_iteration();
3187 #if wxUSE_DRAG_AND_DROP
3189 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3191 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3193 GtkWidget
*dnd_widget
= GetConnectWidget();
3195 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3197 if (m_dropTarget
) delete m_dropTarget
;
3198 m_dropTarget
= dropTarget
;
3200 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3203 #endif // wxUSE_DRAG_AND_DROP
3205 GtkWidget
* wxWindow::GetConnectWidget()
3207 GtkWidget
*connect_widget
= m_widget
;
3208 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3210 return connect_widget
;
3213 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3216 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3218 return (window
== m_widget
->window
);
3221 bool wxWindow::SetFont( const wxFont
&font
)
3223 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3225 if (!wxWindowBase::SetFont(font
))
3230 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3231 if ( sysbg
== m_backgroundColour
)
3233 m_backgroundColour
= wxNullColour
;
3235 m_backgroundColour
= sysbg
;
3245 void wxWindow::CaptureMouse()
3247 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3249 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3251 GdkWindow
*window
= (GdkWindow
*) NULL
;
3253 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3255 window
= GetConnectWidget()->window
;
3257 if (!window
) return;
3259 gdk_pointer_grab( window
, FALSE
,
3261 (GDK_BUTTON_PRESS_MASK
|
3262 GDK_BUTTON_RELEASE_MASK
|
3263 GDK_POINTER_MOTION_HINT_MASK
|
3264 GDK_POINTER_MOTION_MASK
),
3266 m_cursor
.GetCursor(),
3267 (guint32
)GDK_CURRENT_TIME
);
3268 g_captureWindow
= this;
3271 void wxWindow::ReleaseMouse()
3273 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3275 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3277 GdkWindow
*window
= (GdkWindow
*) NULL
;
3279 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3281 window
= GetConnectWidget()->window
;
3286 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3287 g_captureWindow
= (wxWindow
*) NULL
;
3290 bool wxWindow::IsRetained() const
3295 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3296 int range
, bool refresh
)
3298 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3300 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3302 m_hasScrolling
= TRUE
;
3304 if (orient
== wxHORIZONTAL
)
3306 float fpos
= (float)pos
;
3307 float frange
= (float)range
;
3308 float fthumb
= (float)thumbVisible
;
3309 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3310 if (fpos
< 0.0) fpos
= 0.0;
3312 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3313 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3315 SetScrollPos( orient
, pos
, refresh
);
3319 m_oldHorizontalPos
= fpos
;
3321 m_hAdjust
->lower
= 0.0;
3322 m_hAdjust
->upper
= frange
;
3323 m_hAdjust
->value
= fpos
;
3324 m_hAdjust
->step_increment
= 1.0;
3325 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3326 m_hAdjust
->page_size
= fthumb
;
3330 float fpos
= (float)pos
;
3331 float frange
= (float)range
;
3332 float fthumb
= (float)thumbVisible
;
3333 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3334 if (fpos
< 0.0) fpos
= 0.0;
3336 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3337 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3339 SetScrollPos( orient
, pos
, refresh
);
3343 m_oldVerticalPos
= fpos
;
3345 m_vAdjust
->lower
= 0.0;
3346 m_vAdjust
->upper
= frange
;
3347 m_vAdjust
->value
= fpos
;
3348 m_vAdjust
->step_increment
= 1.0;
3349 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3350 m_vAdjust
->page_size
= fthumb
;
3353 if (orient
== wxHORIZONTAL
)
3354 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3356 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3359 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3361 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3363 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3365 if (orient
== wxHORIZONTAL
)
3367 float fpos
= (float)pos
;
3368 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3369 if (fpos
< 0.0) fpos
= 0.0;
3370 m_oldHorizontalPos
= fpos
;
3372 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3373 m_hAdjust
->value
= fpos
;
3377 float fpos
= (float)pos
;
3378 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3379 if (fpos
< 0.0) fpos
= 0.0;
3380 m_oldVerticalPos
= fpos
;
3382 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3383 m_vAdjust
->value
= fpos
;
3386 if (m_wxwindow
->window
)
3388 if (orient
== wxHORIZONTAL
)
3390 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3391 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3393 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3395 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3396 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3400 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3401 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3403 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3405 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3406 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3411 int wxWindow::GetScrollThumb( int orient
) const
3413 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3415 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3417 if (orient
== wxHORIZONTAL
)
3418 return (int)(m_hAdjust
->page_size
+0.5);
3420 return (int)(m_vAdjust
->page_size
+0.5);
3423 int wxWindow::GetScrollPos( int orient
) const
3425 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3427 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3429 if (orient
== wxHORIZONTAL
)
3430 return (int)(m_hAdjust
->value
+0.5);
3432 return (int)(m_vAdjust
->value
+0.5);
3435 int wxWindow::GetScrollRange( int orient
) const
3437 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3439 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3441 if (orient
== wxHORIZONTAL
)
3442 return (int)(m_hAdjust
->upper
+0.5);
3444 return (int)(m_vAdjust
->upper
+0.5);
3447 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3449 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3451 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3453 if ((dx
== 0) && (dy
== 0)) return;
3455 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3458 if (m_children.GetCount() > 0)
3460 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3464 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3466 pizza->xoffset -= dx;
3467 pizza->yoffset -= dy;
3469 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3470 gdk_gc_set_exposures( m_scrollGC, TRUE );
3474 GetClientSize( &cw, &ch );
3475 int w = cw - abs(dx);
3476 int h = ch - abs(dy);
3478 if ((h < 0) || (w < 0))
3486 if (dx < 0) s_x = -dx;
3487 if (dy < 0) s_y = -dy;
3490 if (dx > 0) d_x = dx;
3491 if (dy > 0) d_y = dy;
3493 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3494 pizza->bin_window, s_x, s_y, w, h );
3497 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3498 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3499 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3500 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3502 Refresh( TRUE, &rect );
3505 gdk_gc_unref( m_scrollGC );