1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #include "wx/window.h"
20 #include "wx/layout.h"
22 #include "wx/dialog.h"
23 #include "wx/msgdlg.h"
25 #if wxUSE_DRAG_AND_DROP
30 #include "wx/tooltip.h"
34 #include "wx/statusbr.h"
36 #include "wx/settings.h"
43 #include "gdk/gdkprivate.h"
44 #include "gdk/gdkkeysyms.h"
45 #include "wx/gtk/win_gtk.h"
49 //-----------------------------------------------------------------------------
50 // documentation on internals
51 //-----------------------------------------------------------------------------
54 I have been asked several times about writing some documentation about
55 the GTK port of wxWindows, especially its internal structures. Obviously,
56 you cannot understand wxGTK without knowing a little about the GTK, but
57 some more information about what the wxWindow, which is the base class
58 for all other window classes, does seems required as well.
62 What does wxWindow do? It contains the common interface for the following
63 jobs of its descendants:
65 1) Define the rudimentary behaviour common to all window classes, such as
66 resizing, intercepting user input (so as to make it possible to use these
67 events for special purposes in a derived class), window names etc.
69 2) Provide the possibility to contain and manage children, if the derived
70 class is allowed to contain children, which holds true for those window
71 classes which do not display a native GTK widget. To name them, these
72 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
73 work classes are a special case and are handled a bit differently from
74 the rest. The same holds true for the wxNotebook class.
76 3) Provide the possibility to draw into a client area of a window. This,
77 too, only holds true for classes that do not display a native GTK widget
80 4) Provide the entire mechanism for scrolling widgets. This actual inter-
81 face for this is usually in wxScrolledWindow, but the GTK implementation
84 5) A multitude of helper or extra methods for special purposes, such as
85 Drag'n'Drop, managing validators etc.
87 6) Display a border (sunken, raised, simple or none).
89 Normally one might expect, that one wxWindows window would always correspond
90 to one GTK widget. Under GTK, there is no such allround widget that has all
91 the functionality. Moreover, the GTK defines a client area as a different
92 widget from the actual widget you are handling. Last but not least some
93 special classes (e.g. wxFrame) handle different categories of widgets and
94 still have the possibility to draw something in the client area.
95 It was therefore required to write a special purpose GTK widget, that would
96 represent a client area in the sense of wxWindows capable to do the jobs
97 2), 3) and 4). I have written this class and it resides in win_gtk.c of
100 All windows must have a widget, with which they interact with other under-
101 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
102 thw wxWindow class has a member variable called m_widget which holds a
103 pointer to this widget. When the window class represents a GTK native widget,
104 this is (in most cases) the only GTK widget the class manages. E.g. the
105 wxStatitText class handles only a GtkLabel widget a pointer to which you
106 can find in m_widget (defined in wxWindow)
108 When the class has a client area for drawing into and for containing children
109 it has to handle the client area widget (of the type GtkPizza, defined in
110 win_gtk.c), but there could be any number of widgets, handled by a class
111 The common rule for all windows is only, that the widget that interacts with
112 the rest of GTK must be referenced in m_widget and all other widgets must be
113 children of this widget on the GTK level. The top-most widget, which also
114 represents the client area, must be in the m_wxwindow field and must be of
117 As I said, the window classes that display a GTK native widget only have
118 one widget, so in the case of e.g. the wxButton class m_widget holds a
119 pointer to a GtkButton widget. But windows with client areas (for drawing
120 and children) have a m_widget field that is a pointer to a GtkScrolled-
121 Window and a m_wxwindow field that is pointer to a GtkPizza and this
122 one is (in the GTK sense) a child of the GtkScrolledWindow.
124 If the m_wxwindow field is set, then all input to this widget is inter-
125 cepted and sent to the wxWindows class. If not, all input to the widget
126 that gets pointed to by m_widget gets intercepted and sent to the class.
130 The design of scrolling in wxWindows is markedly different from that offered
131 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
132 clicking on a scrollbar belonging to scrolled window will inevitably move
133 the window. In wxWindows, the scrollbar will only emit an event, send this
134 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
135 which actually moves the window and its subchildren. Note that GtkPizza
136 memorizes how much it has been scrolled but that wxWindows forgets this
137 so that the two coordinates systems have to be kept in synch. This is done
138 in various places using the pizza->xoffset and pizza->yoffset values.
142 Singularily the most broken code in GTK is the code that is supposes to
143 inform subwindows (child windows) about new positions. Very often, duplicate
144 events are sent without changes in size or position, equally often no
145 events are sent at all (All this is due to a bug in the GtkContainer code
146 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
147 GTK's own system and it simply waits for size events for toplevel windows
148 and then iterates down the respective size events to all window. This has
149 the disadvantage, that windows might get size events before the GTK widget
150 actually has the reported size. This doesn't normally pose any problem, but
151 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
152 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
153 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
154 window that is used for OpenGl output really has that size (as reported by
159 If someone at some point of time feels the immense desire to have a look at,
160 change or attempt to optimse the Refresh() logic, this person will need an
161 intimate understanding of what a "draw" and what an "expose" events are and
162 what there are used for, in particular when used in connection with GTK's
163 own windowless widgets. Beware.
167 Cursors, too, have been a constant source of pleasure. The main difficulty
168 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
169 for the parent. To prevent this from doing too much harm, I use idle time
170 to set the cursor over and over again, starting from the toplevel windows
171 and ending with the youngest generation (speaking of parent and child windows).
172 Also don't forget that cursors (like much else) are connected to GdkWindows,
173 not GtkWidgets and that the "window" field of a GtkWidget might very well
174 point to the GdkWindow of the parent widget (-> "window less widget") and
175 that the two obviously have very different meanings.
179 //-----------------------------------------------------------------------------
181 //-----------------------------------------------------------------------------
183 extern wxList wxPendingDelete
;
184 extern bool g_blockEventsOnDrag
;
185 extern bool g_blockEventsOnScroll
;
186 extern wxCursor g_globalCursor
;
187 static wxWindow
*g_captureWindow
= (wxWindow
*) NULL
;
189 /* extern */ wxWindow
*g_focusWindow
= (wxWindow
*) NULL
;
191 // if we detect that the app has got/lost the focus, we set this variable to
192 // either TRUE or FALSE and an activate event will be sent during the next
193 // OnIdle() call and it is reset to -1: this value means that we shouldn't
194 // send any activate events at all
195 static int g_sendActivateEvent
= -1;
197 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
198 the last click here */
199 static guint32 gs_timeLastClick
= 0;
201 //-----------------------------------------------------------------------------
203 //-----------------------------------------------------------------------------
207 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
208 GdkEvent
*WXUNUSED(event
),
209 const wxChar
*WXUNUSED(name
) )
212 static bool s_done = FALSE;
215 wxLog::AddTraceMask("focus");
218 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
224 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
228 tmp += wxT(" FROM ");
231 wxChar *s = new wxChar[tmp.Length()+1];
235 gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event",
236 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback), (gpointer)s );
242 //-----------------------------------------------------------------------------
243 // missing gdk functions
244 //-----------------------------------------------------------------------------
247 gdk_window_warp_pointer (GdkWindow
*window
,
251 GdkWindowPrivate
*priv
;
254 window
= (GdkWindow
*) &gdk_root_parent
;
256 priv
= (GdkWindowPrivate
*) window
;
258 if (!priv
->destroyed
)
260 XWarpPointer (priv
->xdisplay
,
261 None
, /* not source window -> move from anywhere */
262 priv
->xwindow
, /* dest window */
263 0, 0, 0, 0, /* not source window -> move from anywhere */
268 //-----------------------------------------------------------------------------
270 //-----------------------------------------------------------------------------
272 extern void wxapp_install_idle_handler();
273 extern bool g_isIdle
;
275 //-----------------------------------------------------------------------------
276 // local code (see below)
277 //-----------------------------------------------------------------------------
279 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
287 if (win
->HasScrolling())
289 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
290 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget
)->klass
);
293 GtkWidget *hscrollbar = scroll_window->hscrollbar;
294 GtkWidget *vscrollbar = scroll_window->vscrollbar;
296 we use this instead: range.slider_width = 11 + 2*2pts edge
299 if (scroll_window
->vscrollbar_visible
)
301 dw
+= 15; /* dw += vscrollbar->allocation.width; */
302 dw
+= scroll_class
->scrollbar_spacing
;
305 if (scroll_window
->hscrollbar_visible
)
307 dh
+= 15; /* dh += hscrollbar->allocation.height; */
308 dh
+= scroll_class
->scrollbar_spacing
;
314 if (GTK_WIDGET_NO_WINDOW (widget
))
316 dx
+= widget
->allocation
.x
;
317 dy
+= widget
->allocation
.y
;
320 if (win
->HasFlag(wxRAISED_BORDER
))
322 gtk_draw_shadow( widget
->style
,
327 win
->m_width
-dw
, win
->m_height
-dh
);
331 if (win
->HasFlag(wxSUNKEN_BORDER
))
333 gtk_draw_shadow( widget
->style
,
338 win
->m_width
-dw
, win
->m_height
-dh
);
342 if (win
->HasFlag(wxSIMPLE_BORDER
))
345 gc
= gdk_gc_new( widget
->window
);
346 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
347 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
349 win
->m_width
-dw
-1, win
->m_height
-dh
-1 );
355 //-----------------------------------------------------------------------------
356 // "expose_event" of m_widget
357 //-----------------------------------------------------------------------------
359 static void gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
361 if (gdk_event
->count
> 0) return;
362 draw_frame( widget
, win
);
365 //-----------------------------------------------------------------------------
366 // "draw" of m_widget
367 //-----------------------------------------------------------------------------
369 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
371 draw_frame( widget
, win
);
374 //-----------------------------------------------------------------------------
375 // key code mapping routines
376 //-----------------------------------------------------------------------------
378 static long map_to_unmodified_wx_keysym( KeySym keysym
)
385 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
387 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
393 case GDK_Super_R
: key_code
= WXK_ALT
; break;
394 case GDK_Menu
: key_code
= WXK_MENU
; break;
395 case GDK_Help
: key_code
= WXK_HELP
; break;
396 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
397 case GDK_ISO_Left_Tab
:
398 case GDK_Tab
: key_code
= WXK_TAB
; break;
399 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
400 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
401 case GDK_Return
: key_code
= WXK_RETURN
; break;
402 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
403 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
404 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
405 case GDK_Delete
: key_code
= WXK_DELETE
; break;
406 case GDK_Home
: key_code
= WXK_HOME
; break;
407 case GDK_Left
: key_code
= WXK_LEFT
; break;
408 case GDK_Up
: key_code
= WXK_UP
; break;
409 case GDK_Right
: key_code
= WXK_RIGHT
; break;
410 case GDK_Down
: key_code
= WXK_DOWN
; break;
411 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
412 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
413 case GDK_Next
: key_code
= WXK_NEXT
; break;
414 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
415 case GDK_End
: key_code
= WXK_END
; break;
416 case GDK_Begin
: key_code
= WXK_HOME
; break;
417 case GDK_Select
: key_code
= WXK_SELECT
; break;
418 case GDK_Print
: key_code
= WXK_PRINT
; break;
419 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
420 case GDK_Insert
: key_code
= WXK_INSERT
; break;
421 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
423 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
424 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
425 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
426 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
427 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
428 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
429 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
430 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
431 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
432 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
433 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
434 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
435 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
436 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
437 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
438 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
439 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
440 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
441 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
442 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
443 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
444 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
445 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
446 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
447 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
448 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
449 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
450 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
451 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
452 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
453 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
454 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
455 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
456 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
457 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
458 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
459 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
461 case GDK_F1
: key_code
= WXK_F1
; break;
462 case GDK_F2
: key_code
= WXK_F2
; break;
463 case GDK_F3
: key_code
= WXK_F3
; break;
464 case GDK_F4
: key_code
= WXK_F4
; break;
465 case GDK_F5
: key_code
= WXK_F5
; break;
466 case GDK_F6
: key_code
= WXK_F6
; break;
467 case GDK_F7
: key_code
= WXK_F7
; break;
468 case GDK_F8
: key_code
= WXK_F8
; break;
469 case GDK_F9
: key_code
= WXK_F9
; break;
470 case GDK_F10
: key_code
= WXK_F10
; break;
471 case GDK_F11
: key_code
= WXK_F11
; break;
472 case GDK_F12
: key_code
= WXK_F12
; break;
477 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
478 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
479 key_code
= (guint
)keysym
;
487 static long map_to_wx_keysym( KeySym keysym
)
493 case GDK_Menu
: key_code
= WXK_MENU
; break;
494 case GDK_Help
: key_code
= WXK_HELP
; break;
495 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
496 case GDK_ISO_Left_Tab
:
497 case GDK_Tab
: key_code
= WXK_TAB
; break;
498 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
499 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
500 case GDK_Return
: key_code
= WXK_RETURN
; break;
501 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
502 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
503 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
504 case GDK_Delete
: key_code
= WXK_DELETE
; break;
505 case GDK_Home
: key_code
= WXK_HOME
; break;
506 case GDK_Left
: key_code
= WXK_LEFT
; break;
507 case GDK_Up
: key_code
= WXK_UP
; break;
508 case GDK_Right
: key_code
= WXK_RIGHT
; break;
509 case GDK_Down
: key_code
= WXK_DOWN
; break;
510 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
511 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
512 case GDK_Next
: key_code
= WXK_NEXT
; break;
513 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
514 case GDK_End
: key_code
= WXK_END
; break;
515 case GDK_Begin
: key_code
= WXK_HOME
; break;
516 case GDK_Select
: key_code
= WXK_SELECT
; break;
517 case GDK_Print
: key_code
= WXK_PRINT
; break;
518 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
519 case GDK_Insert
: key_code
= WXK_INSERT
; break;
520 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
522 case GDK_KP_0
: key_code
= '0'; break;
523 case GDK_KP_1
: key_code
= '1'; break;
524 case GDK_KP_2
: key_code
= '2'; break;
525 case GDK_KP_3
: key_code
= '3'; break;
526 case GDK_KP_4
: key_code
= '4'; break;
527 case GDK_KP_5
: key_code
= '5'; break;
528 case GDK_KP_6
: key_code
= '6'; break;
529 case GDK_KP_7
: key_code
= '7'; break;
530 case GDK_KP_8
: key_code
= '8'; break;
531 case GDK_KP_9
: key_code
= '9'; break;
532 case GDK_KP_Space
: key_code
= ' '; break;
533 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
534 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
535 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
536 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
537 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
538 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
539 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
540 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
541 case GDK_KP_Up
: key_code
= WXK_UP
; break;
542 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
543 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
544 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
545 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
546 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
547 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
548 case GDK_KP_End
: key_code
= WXK_END
; break;
549 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
550 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
551 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
552 case GDK_KP_Equal
: key_code
= '='; break;
553 case GDK_KP_Multiply
: key_code
= '*'; break;
554 case GDK_KP_Add
: key_code
= '+'; break;
555 case GDK_KP_Separator
: key_code
= ','; break;
556 case GDK_KP_Subtract
: key_code
= '-'; break;
557 case GDK_KP_Decimal
: key_code
= '.'; break;
558 case GDK_KP_Divide
: key_code
= '/'; break;
560 case GDK_F1
: key_code
= WXK_F1
; break;
561 case GDK_F2
: key_code
= WXK_F2
; break;
562 case GDK_F3
: key_code
= WXK_F3
; break;
563 case GDK_F4
: key_code
= WXK_F4
; break;
564 case GDK_F5
: key_code
= WXK_F5
; break;
565 case GDK_F6
: key_code
= WXK_F6
; break;
566 case GDK_F7
: key_code
= WXK_F7
; break;
567 case GDK_F8
: key_code
= WXK_F8
; break;
568 case GDK_F9
: key_code
= WXK_F9
; break;
569 case GDK_F10
: key_code
= WXK_F10
; break;
570 case GDK_F11
: key_code
= WXK_F11
; break;
571 case GDK_F12
: key_code
= WXK_F12
; break;
576 key_code
= (guint
)keysym
;
584 //-----------------------------------------------------------------------------
585 // "expose_event" of m_wxwindow
586 //-----------------------------------------------------------------------------
588 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
593 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
595 gdk_event
->area
.width
,
596 gdk_event
->area
.height
);
598 if (gdk_event
->count
> 0)
602 wxPrintf( "OnExpose from " );
603 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
604 wxPrintf( win->GetClassInfo()->GetClassName() );
605 wxPrintf( " %d %d %d %d\n", (int)gdk_event->area.x,
606 (int)gdk_event->area.y,
607 (int)gdk_event->area.width,
608 (int)gdk_event->area.height );
611 wxEraseEvent
eevent( win
->GetId() );
612 eevent
.SetEventObject( win
);
613 win
->GetEventHandler()->ProcessEvent(eevent
);
615 wxPaintEvent
event( win
->GetId() );
616 event
.SetEventObject( win
);
617 win
->GetEventHandler()->ProcessEvent( event
);
619 win
->GetUpdateRegion().Clear();
622 //-----------------------------------------------------------------------------
623 // "draw" of m_wxwindow
624 //-----------------------------------------------------------------------------
626 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
),
627 GdkRectangle
*rect
, wxWindow
*win
)
630 wxapp_install_idle_handler();
635 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
,
636 rect
->width
, rect
->height
);
639 wxPrintf( "OnDraw from " );
640 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
641 printf( win->GetClassInfo()->GetClassName() );
642 wxPrintf( " %d %d %d %d\n", (int)rect->x,
648 wxEraseEvent
eevent( win
->GetId() );
649 eevent
.SetEventObject( win
);
650 win
->GetEventHandler()->ProcessEvent(eevent
);
652 wxPaintEvent
event( win
->GetId() );
653 event
.SetEventObject( win
);
654 win
->GetEventHandler()->ProcessEvent( event
);
656 win
->GetUpdateRegion().Clear();
659 //-----------------------------------------------------------------------------
660 // "key_press_event" from any window
661 //-----------------------------------------------------------------------------
663 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
666 wxapp_install_idle_handler();
668 if (!win
->m_hasVMT
) return FALSE
;
669 if (g_blockEventsOnDrag
) return FALSE
;
672 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
673 if (gdk_event->state & GDK_SHIFT_MASK)
674 printf( "ShiftDown.\n" );
676 printf( "ShiftUp.\n" );
677 if (gdk_event->state & GDK_CONTROL_MASK)
678 printf( "ControlDown.\n" );
680 printf( "ControlUp.\n" );
685 GdkModifierType state
;
686 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
690 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
691 /* sending unknown key events doesn't really make sense */
692 if (key_code
== 0) return FALSE
;
694 wxKeyEvent
event( wxEVT_KEY_DOWN
);
695 event
.SetTimestamp( gdk_event
->time
);
696 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
697 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
698 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
699 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
700 event
.m_keyCode
= key_code
;
701 event
.m_scanCode
= gdk_event
->keyval
;
704 event
.SetEventObject( win
);
705 ret
= win
->GetEventHandler()->ProcessEvent( event
);
710 wxWindow
*ancestor
= win
;
713 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
716 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
717 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
720 if (ancestor
->m_isFrame
)
722 ancestor
= ancestor
->GetParent();
725 #endif // wxUSE_ACCEL
727 /* wxMSW doesn't send char events with Alt pressed */
728 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
729 will only be sent if it is not in an accelerator table. */
730 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
735 wxKeyEvent
event2( wxEVT_CHAR
);
736 event2
.SetTimestamp( gdk_event
->time
);
737 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
738 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
739 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
740 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
741 event2
.m_keyCode
= key_code
;
742 event2
.m_scanCode
= gdk_event
->keyval
;
745 event2
.SetEventObject( win
);
746 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
749 /* win is a control: tab can be propagated up */
751 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
752 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
753 (win
->GetParent()) &&
754 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
756 wxNavigationKeyEvent new_event
;
757 new_event
.SetEventObject( win
);
758 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
759 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
760 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
761 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
762 new_event
.SetCurrentFocus( win
);
763 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
766 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
768 (gdk_event
->keyval
== GDK_Escape
) )
770 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
771 new_event
.SetEventObject( win
);
772 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
775 #if (GTK_MINOR_VERSION > 0)
776 /* Pressing F10 will activate the menu bar of the top frame. */
780 (gdk_event->keyval == GDK_F10) )
782 wxWindow *ancestor = win;
785 if (wxIsKindOf(ancestor,wxFrame))
787 wxFrame *frame = (wxFrame*) ancestor;
788 wxMenuBar *menubar = frame->GetMenuBar();
791 wxNode *node = menubar->GetMenus().First();
794 wxMenu *firstMenu = (wxMenu*) node->Data();
795 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
801 ancestor = ancestor->GetParent();
809 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
816 //-----------------------------------------------------------------------------
817 // "key_release_event" from any window
818 //-----------------------------------------------------------------------------
820 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
823 wxapp_install_idle_handler();
825 if (!win
->m_hasVMT
) return FALSE
;
826 if (g_blockEventsOnDrag
) return FALSE
;
829 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
830 if (gdk_event->state & GDK_SHIFT_MASK)
831 printf( "ShiftDown.\n" );
833 printf( "ShiftUp.\n" );
834 if (gdk_event->state & GDK_CONTROL_MASK)
835 printf( "ControlDown.\n" );
837 printf( "ControlUp.\n" );
841 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
843 /* sending unknown key events doesn't really make sense */
844 if (key_code
== 0) return FALSE
;
848 GdkModifierType state
;
849 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
851 wxKeyEvent
event( wxEVT_KEY_UP
);
852 event
.SetTimestamp( gdk_event
->time
);
853 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
854 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
855 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
856 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
857 event
.m_keyCode
= key_code
;
858 event
.m_scanCode
= gdk_event
->keyval
;
861 event
.SetEventObject( win
);
863 if (win
->GetEventHandler()->ProcessEvent( event
))
865 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
872 //-----------------------------------------------------------------------------
873 // "button_press_event"
874 //-----------------------------------------------------------------------------
876 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
879 wxapp_install_idle_handler();
882 wxPrintf( wxT("1) OnButtonPress from ") );
883 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
884 wxPrintf( win->GetClassInfo()->GetClassName() );
885 wxPrintf( wxT(".\n") );
887 if (!win
->m_hasVMT
) return FALSE
;
888 if (g_blockEventsOnDrag
) return TRUE
;
889 if (g_blockEventsOnScroll
) return TRUE
;
891 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
895 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
897 gtk_widget_grab_focus (win
->m_wxwindow
);
900 wxPrintf( wxT("GrabFocus from ") );
901 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
902 wxPrintf( win->GetClassInfo()->GetClassName() );
903 wxPrintf( wxT(".\n") );
909 wxEventType event_type
= wxEVT_LEFT_DOWN
;
911 if (gdk_event
->button
== 1)
913 switch (gdk_event
->type
)
915 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
916 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
920 else if (gdk_event
->button
== 2)
922 switch (gdk_event
->type
)
924 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
925 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
929 else if (gdk_event
->button
== 3)
931 switch (gdk_event
->type
)
933 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
934 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
939 wxMouseEvent
event( event_type
);
940 event
.SetTimestamp( gdk_event
->time
);
941 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
942 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
943 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
944 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
945 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
946 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
947 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
949 event
.m_x
= (long)gdk_event
->x
;
950 event
.m_y
= (long)gdk_event
->y
;
952 // Some control don't have their own X window and thus cannot get
955 if (!g_captureWindow
)
957 wxCoord x
= event
.m_x
;
958 wxCoord y
= event
.m_y
;
961 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
966 wxNode
*node
= win
->GetChildren().First();
969 wxWindow
*child
= (wxWindow
*)node
->Data();
972 if (!child
->IsShown())
975 if (child
->m_isStaticBox
)
977 // wxStaticBox is transparent in the box itself
978 int xx1
= child
->m_x
;
979 int yy1
= child
->m_y
;
980 int xx2
= child
->m_x
+ child
->m_width
;
981 int yy2
= child
->m_x
+ child
->m_height
;
984 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
986 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
988 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
990 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
993 event
.m_x
-= child
->m_x
;
994 event
.m_y
-= child
->m_y
;
1001 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1002 (child
->m_x
<= x
) &&
1003 (child
->m_y
<= y
) &&
1004 (child
->m_x
+child
->m_width
>= x
) &&
1005 (child
->m_y
+child
->m_height
>= y
))
1008 event
.m_x
-= child
->m_x
;
1009 event
.m_y
-= child
->m_y
;
1016 event
.SetEventObject( win
);
1018 gs_timeLastClick
= gdk_event
->time
;
1021 wxPrintf( wxT("2) OnButtonPress from ") );
1022 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1023 wxPrintf( win->GetClassInfo()->GetClassName() );
1024 wxPrintf( wxT(".\n") );
1027 if (win
->GetEventHandler()->ProcessEvent( event
))
1029 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1036 //-----------------------------------------------------------------------------
1037 // "button_release_event"
1038 //-----------------------------------------------------------------------------
1040 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1043 wxapp_install_idle_handler();
1045 if (!win
->m_hasVMT
) return FALSE
;
1046 if (g_blockEventsOnDrag
) return FALSE
;
1047 if (g_blockEventsOnScroll
) return FALSE
;
1049 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1052 printf( "OnButtonRelease from " );
1053 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1054 printf( win->GetClassInfo()->GetClassName() );
1058 wxEventType event_type
= wxEVT_NULL
;
1060 switch (gdk_event
->button
)
1062 case 1: event_type
= wxEVT_LEFT_UP
; break;
1063 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1064 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1067 wxMouseEvent
event( event_type
);
1068 event
.SetTimestamp( gdk_event
->time
);
1069 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1070 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1071 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1072 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1073 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1074 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1075 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1076 event
.m_x
= (long)gdk_event
->x
;
1077 event
.m_y
= (long)gdk_event
->y
;
1079 // Some control don't have their own X window and thus cannot get
1082 if (!g_captureWindow
)
1084 wxCoord x
= event
.m_x
;
1085 wxCoord y
= event
.m_y
;
1086 if (win
->m_wxwindow
)
1088 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1089 x
+= pizza
->xoffset
;
1090 y
+= pizza
->yoffset
;
1093 wxNode
*node
= win
->GetChildren().First();
1096 wxWindow
*child
= (wxWindow
*)node
->Data();
1098 node
= node
->Next();
1099 if (!child
->IsShown())
1102 if (child
->m_isStaticBox
)
1104 // wxStaticBox is transparent in the box itself
1105 int xx1
= child
->m_x
;
1106 int yy1
= child
->m_y
;
1107 int xx2
= child
->m_x
+ child
->m_width
;
1108 int yy2
= child
->m_x
+ child
->m_height
;
1111 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1113 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1115 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1117 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1120 event
.m_x
-= child
->m_x
;
1121 event
.m_y
-= child
->m_y
;
1128 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1129 (child
->m_x
<= x
) &&
1130 (child
->m_y
<= y
) &&
1131 (child
->m_x
+child
->m_width
>= x
) &&
1132 (child
->m_y
+child
->m_height
>= y
))
1135 event
.m_x
-= child
->m_x
;
1136 event
.m_y
-= child
->m_y
;
1143 event
.SetEventObject( win
);
1145 if (win
->GetEventHandler()->ProcessEvent( event
))
1147 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1154 //-----------------------------------------------------------------------------
1155 // "motion_notify_event"
1156 //-----------------------------------------------------------------------------
1158 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1161 wxapp_install_idle_handler();
1163 if (!win
->m_hasVMT
) return FALSE
;
1164 if (g_blockEventsOnDrag
) return FALSE
;
1165 if (g_blockEventsOnScroll
) return FALSE
;
1167 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1169 if (gdk_event
->is_hint
)
1173 GdkModifierType state
;
1174 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1180 printf( "OnMotion from " );
1181 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1182 printf( win->GetClassInfo()->GetClassName() );
1186 wxMouseEvent
event( wxEVT_MOTION
);
1187 event
.SetTimestamp( gdk_event
->time
);
1188 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1189 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1190 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1191 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1192 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1193 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1194 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1196 event
.m_x
= (long)gdk_event
->x
;
1197 event
.m_y
= (long)gdk_event
->y
;
1199 // Some control don't have their own X window and thus cannot get
1202 if (!g_captureWindow
)
1204 wxCoord x
= event
.m_x
;
1205 wxCoord y
= event
.m_y
;
1206 if (win
->m_wxwindow
)
1208 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1209 x
+= pizza
->xoffset
;
1210 y
+= pizza
->yoffset
;
1213 wxNode
*node
= win
->GetChildren().First();
1216 wxWindow
*child
= (wxWindow
*)node
->Data();
1218 node
= node
->Next();
1219 if (!child
->IsShown())
1222 if (child
->m_isStaticBox
)
1224 // wxStaticBox is transparent in the box itself
1225 int xx1
= child
->m_x
;
1226 int yy1
= child
->m_y
;
1227 int xx2
= child
->m_x
+ child
->m_width
;
1228 int yy2
= child
->m_x
+ child
->m_height
;
1231 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1233 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1235 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1237 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1240 event
.m_x
-= child
->m_x
;
1241 event
.m_y
-= child
->m_y
;
1248 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1249 (child
->m_x
<= x
) &&
1250 (child
->m_y
<= y
) &&
1251 (child
->m_x
+child
->m_width
>= x
) &&
1252 (child
->m_y
+child
->m_height
>= y
))
1255 event
.m_x
-= child
->m_x
;
1256 event
.m_y
-= child
->m_y
;
1263 event
.SetEventObject( win
);
1265 if (win
->GetEventHandler()->ProcessEvent( event
))
1267 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1274 //-----------------------------------------------------------------------------
1276 //-----------------------------------------------------------------------------
1278 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1281 wxapp_install_idle_handler();
1283 if (!win
->m_hasVMT
) return FALSE
;
1284 if (g_blockEventsOnDrag
) return FALSE
;
1286 switch ( g_sendActivateEvent
)
1289 // we've got focus from outside, synthtize wxActivateEvent
1290 g_sendActivateEvent
= 1;
1294 // another our window just lost focus, it was already ours before
1295 // - don't send any wxActivateEvent
1296 g_sendActivateEvent
= -1;
1300 g_focusWindow
= win
;
1303 printf( "OnSetFocus from " );
1304 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1305 printf( win->GetClassInfo()->GetClassName() );
1307 printf( WXSTRINGCAST win->GetLabel() );
1311 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1314 panel
->SetLastFocus(win
);
1317 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1318 event
.SetEventObject( win
);
1320 if (win
->GetEventHandler()->ProcessEvent( event
))
1322 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1329 //-----------------------------------------------------------------------------
1330 // "focus_out_event"
1331 //-----------------------------------------------------------------------------
1333 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1336 wxapp_install_idle_handler();
1338 if (!win
->m_hasVMT
) return FALSE
;
1339 if (g_blockEventsOnDrag
) return FALSE
;
1341 // if the focus goes out of our app alltogether, OnIdle() will send
1342 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1343 // g_sendActivateEvent to -1
1344 g_sendActivateEvent
= 0;
1346 g_focusWindow
= (wxWindow
*)NULL
;
1349 printf( "OnKillFocus from " );
1350 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1351 printf( win->GetClassInfo()->GetClassName() );
1355 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1356 event
.SetEventObject( win
);
1358 if (win
->GetEventHandler()->ProcessEvent( event
))
1360 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1367 //-----------------------------------------------------------------------------
1368 // "enter_notify_event"
1369 //-----------------------------------------------------------------------------
1371 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1374 wxapp_install_idle_handler();
1376 if (!win
->m_hasVMT
) return FALSE
;
1377 if (g_blockEventsOnDrag
) return FALSE
;
1379 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1381 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1382 #if (GTK_MINOR_VERSION > 0)
1383 event
.SetTimestamp( gdk_event
->time
);
1385 event
.SetEventObject( win
);
1389 GdkModifierType state
= (GdkModifierType
)0;
1391 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1393 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1394 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1395 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1396 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1397 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1398 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1399 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1401 event
.m_x
= (long)x
;
1402 event
.m_y
= (long)y
;
1404 if (win
->GetEventHandler()->ProcessEvent( event
))
1406 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1413 //-----------------------------------------------------------------------------
1414 // "leave_notify_event"
1415 //-----------------------------------------------------------------------------
1417 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1420 wxapp_install_idle_handler();
1422 if (!win
->m_hasVMT
) return FALSE
;
1423 if (g_blockEventsOnDrag
) return FALSE
;
1425 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1427 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1428 #if (GTK_MINOR_VERSION > 0)
1429 event
.SetTimestamp( gdk_event
->time
);
1431 event
.SetEventObject( win
);
1435 GdkModifierType state
= (GdkModifierType
)0;
1437 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1439 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1440 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1441 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1442 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1443 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1444 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1445 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1447 event
.m_x
= (long)x
;
1448 event
.m_y
= (long)y
;
1450 if (win
->GetEventHandler()->ProcessEvent( event
))
1452 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1459 //-----------------------------------------------------------------------------
1460 // "value_changed" from m_vAdjust
1461 //-----------------------------------------------------------------------------
1463 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1466 wxapp_install_idle_handler();
1468 if (g_blockEventsOnDrag
) return;
1470 if (!win
->m_hasVMT
) return;
1472 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1473 if (fabs(diff
) < 0.2) return;
1475 win
->m_oldVerticalPos
= adjust
->value
;
1477 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1478 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1480 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1481 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1482 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1483 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1484 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1486 int value
= (int)(adjust
->value
+0.5);
1488 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1489 event
.SetEventObject( win
);
1490 win
->GetEventHandler()->ProcessEvent( event
);
1493 //-----------------------------------------------------------------------------
1494 // "value_changed" from m_hAdjust
1495 //-----------------------------------------------------------------------------
1497 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1500 wxapp_install_idle_handler();
1502 if (g_blockEventsOnDrag
) return;
1503 if (!win
->m_hasVMT
) return;
1505 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1506 if (fabs(diff
) < 0.2) return;
1508 win
->m_oldHorizontalPos
= adjust
->value
;
1510 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1511 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1513 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1514 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1515 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1516 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1517 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1519 int value
= (int)(adjust
->value
+0.5);
1521 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1522 event
.SetEventObject( win
);
1523 win
->GetEventHandler()->ProcessEvent( event
);
1526 //-----------------------------------------------------------------------------
1527 // "changed" from m_vAdjust
1528 //-----------------------------------------------------------------------------
1530 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1533 wxapp_install_idle_handler();
1535 if (g_blockEventsOnDrag
) return;
1536 if (!win
->m_hasVMT
) return;
1538 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1539 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1541 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1542 event
.SetEventObject( win
);
1543 win
->GetEventHandler()->ProcessEvent( event
);
1546 //-----------------------------------------------------------------------------
1547 // "changed" from m_hAdjust
1548 //-----------------------------------------------------------------------------
1550 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1553 wxapp_install_idle_handler();
1555 if (g_blockEventsOnDrag
) return;
1556 if (!win
->m_hasVMT
) return;
1558 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1559 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1561 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1562 event
.SetEventObject( win
);
1563 win
->GetEventHandler()->ProcessEvent( event
);
1566 //-----------------------------------------------------------------------------
1567 // "button_press_event" from scrollbar
1568 //-----------------------------------------------------------------------------
1570 static gint
gtk_scrollbar_button_press_callback( GtkRange
*WXUNUSED(widget
),
1571 GdkEventButton
*WXUNUSED(gdk_event
),
1575 wxapp_install_idle_handler();
1577 // don't test here as we can release the mouse while being over
1578 // a different window than the slider
1580 // if (gdk_event->window != widget->slider) return FALSE;
1582 win
->SetScrolling( TRUE
);
1587 //-----------------------------------------------------------------------------
1588 // "button_release_event" from scrollbar
1589 //-----------------------------------------------------------------------------
1591 static gint
gtk_scrollbar_button_release_callback( GtkRange
*WXUNUSED(widget
),
1592 GdkEventButton
*WXUNUSED(gdk_event
),
1596 // don't test here as we can release the mouse while being over
1597 // a different window than the slider
1599 // if (gdk_event->window != widget->slider) return FALSE;
1601 win
->SetScrolling( FALSE
);
1606 // ----------------------------------------------------------------------------
1607 // this wxWindowBase function is implemented here (in platform-specific file)
1608 // because it is static and so couldn't be made virtual
1609 // ----------------------------------------------------------------------------
1611 wxWindow
*wxWindowBase::FindFocus()
1613 return g_focusWindow
;
1616 //-----------------------------------------------------------------------------
1617 // "realize" from m_widget
1618 //-----------------------------------------------------------------------------
1620 /* we cannot set colours and fonts before the widget has
1621 been realized, so we do this directly after realization */
1624 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1627 wxapp_install_idle_handler();
1629 if (win
->m_delayedFont
)
1630 win
->SetFont( win
->GetFont() );
1632 if (win
->m_delayedBackgroundColour
)
1633 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1635 if (win
->m_delayedForegroundColour
)
1636 win
->SetForegroundColour( win
->GetForegroundColour() );
1638 wxWindowCreateEvent
event( win
);
1639 event
.SetEventObject( win
);
1640 win
->GetEventHandler()->ProcessEvent( event
);
1645 //-----------------------------------------------------------------------------
1646 // "realize" from m_wxwindow
1647 //-----------------------------------------------------------------------------
1649 /* Initialize XIM support */
1652 gtk_wxwindow_realized_callback( GtkWidget
*widget
, wxWindow
*win
)
1655 wxapp_install_idle_handler();
1658 if (win
->m_ic
) return FALSE
;
1659 if (!widget
) return FALSE
;
1660 if (!gdk_im_ready()) return FALSE
;
1662 win
->m_icattr
= gdk_ic_attr_new();
1663 if (!win
->m_icattr
) return FALSE
;
1667 GdkColormap
*colormap
;
1668 GdkICAttr
*attr
= win
->m_icattr
;
1669 GdkICAttributesType attrmask
= GDK_IC_ALL_REQ
;
1671 GdkIMStyle supported_style
= GDK_IM_PREEDIT_NONE
|
1672 GDK_IM_PREEDIT_NOTHING
|
1673 GDK_IM_PREEDIT_POSITION
|
1674 GDK_IM_STATUS_NONE
|
1675 GDK_IM_STATUS_NOTHING
;
1677 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1678 supported_style
&= ~GDK_IM_PREEDIT_POSITION
;
1680 attr
->style
= style
= gdk_im_decide_style (supported_style
);
1681 attr
->client_window
= widget
->window
;
1683 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
1684 gtk_widget_get_default_colormap ())
1686 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
1687 attr
->preedit_colormap
= colormap
;
1690 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
1691 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
1692 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
1693 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
1695 switch (style
& GDK_IM_PREEDIT_MASK
)
1697 case GDK_IM_PREEDIT_POSITION
:
1698 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1700 g_warning ("over-the-spot style requires fontset");
1704 gdk_window_get_size (widget
->window
, &width
, &height
);
1706 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
1707 attr
->spot_location
.x
= 0;
1708 attr
->spot_location
.y
= height
;
1709 attr
->preedit_area
.x
= 0;
1710 attr
->preedit_area
.y
= 0;
1711 attr
->preedit_area
.width
= width
;
1712 attr
->preedit_area
.height
= height
;
1713 attr
->preedit_fontset
= widget
->style
->font
;
1718 win
->m_ic
= gdk_ic_new (attr
, attrmask
);
1720 if (win
->m_ic
== NULL
)
1721 g_warning ("Can't create input context.");
1724 mask
= gdk_window_get_events (widget
->window
);
1725 mask
|= gdk_ic_get_events (win
->m_ic
);
1726 gdk_window_set_events (widget
->window
, mask
);
1728 if (GTK_WIDGET_HAS_FOCUS(widget
))
1729 gdk_im_begin (win
->m_ic
, widget
->window
);
1736 //-----------------------------------------------------------------------------
1737 // InsertChild for wxWindow.
1738 //-----------------------------------------------------------------------------
1740 /* Callback for wxWindow. This very strange beast has to be used because
1741 * C++ has no virtual methods in a constructor. We have to emulate a
1742 * virtual function here as wxNotebook requires a different way to insert
1743 * a child in it. I had opted for creating a wxNotebookPage window class
1744 * which would have made this superfluous (such in the MDI window system),
1745 * but no-one was listening to me... */
1747 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1749 /* the window might have been scrolled already, do we
1750 have to adapt the position */
1751 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
1752 child
->m_x
+= pizza
->xoffset
;
1753 child
->m_y
+= pizza
->yoffset
;
1755 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
1756 GTK_WIDGET(child
->m_widget
),
1763 //-----------------------------------------------------------------------------
1765 //-----------------------------------------------------------------------------
1767 wxWindow
* wxGetActiveWindow()
1769 return g_focusWindow
;
1772 //-----------------------------------------------------------------------------
1774 //-----------------------------------------------------------------------------
1776 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
1778 void wxWindow::Init()
1784 m_widget
= (GtkWidget
*) NULL
;
1785 m_wxwindow
= (GtkWidget
*) NULL
;
1795 m_needParent
= TRUE
;
1796 m_isBeingDeleted
= FALSE
;
1799 m_nativeSizeEvent
= FALSE
;
1801 m_hasScrolling
= FALSE
;
1802 m_isScrolling
= FALSE
;
1804 m_hAdjust
= (GtkAdjustment
*) NULL
;
1805 m_vAdjust
= (GtkAdjustment
*) NULL
;
1806 m_oldHorizontalPos
= 0.0;
1807 m_oldVerticalPos
= 0.0;
1810 m_widgetStyle
= (GtkStyle
*) NULL
;
1812 m_insertCallback
= (wxInsertChildFunction
) NULL
;
1814 m_isStaticBox
= FALSE
;
1815 m_isRadioButton
= FALSE
;
1817 m_acceptsFocus
= FALSE
;
1819 m_cursor
= *wxSTANDARD_CURSOR
;
1822 m_ic
= (GdkIC
*) NULL
;
1823 m_icattr
= (GdkICAttr
*) NULL
;
1827 wxWindow::wxWindow()
1832 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1833 const wxPoint
&pos
, const wxSize
&size
,
1834 long style
, const wxString
&name
)
1838 Create( parent
, id
, pos
, size
, style
, name
);
1841 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1842 const wxPoint
&pos
, const wxSize
&size
,
1843 long style
, const wxString
&name
)
1845 if (!PreCreation( parent
, pos
, size
) ||
1846 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
1848 wxFAIL_MSG( wxT("wxWindow creation failed") );
1852 m_insertCallback
= wxInsertChildInWindow
;
1854 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
1855 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1858 debug_focus_in( m_widget
, wxT("wxWindow::m_widget"), name
);
1861 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
1864 debug_focus_in( scrolledWindow
->hscrollbar
, wxT("wxWindow::hsrcollbar"), name
);
1865 debug_focus_in( scrolledWindow
->vscrollbar
, wxT("wxWindow::vsrcollbar"), name
);
1868 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1869 scroll_class
->scrollbar_spacing
= 0;
1871 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1873 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
1874 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
1876 m_wxwindow
= gtk_pizza_new();
1879 debug_focus_in( m_wxwindow
, wxT("wxWindow::m_wxwindow"), name
);
1882 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
1884 #if (GTK_MINOR_VERSION > 0)
1885 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
1887 if (HasFlag(wxRAISED_BORDER
))
1889 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
1891 else if (HasFlag(wxSUNKEN_BORDER
))
1893 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
1895 else if (HasFlag(wxSIMPLE_BORDER
))
1897 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
1901 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
1903 #else // GTK_MINOR_VERSION == 0
1904 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
1906 if (HasFlag(wxRAISED_BORDER
))
1908 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
1910 else if (HasFlag(wxSUNKEN_BORDER
))
1912 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
1916 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
1918 #endif // GTK_MINOR_VERSION
1920 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1921 m_acceptsFocus
= TRUE
;
1923 #if (GTK_MINOR_VERSION == 0)
1924 // shut the viewport up
1925 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1926 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1927 #endif // GTK_MINOR_VERSION == 0
1929 // I _really_ don't want scrollbars in the beginning
1930 m_vAdjust
->lower
= 0.0;
1931 m_vAdjust
->upper
= 1.0;
1932 m_vAdjust
->value
= 0.0;
1933 m_vAdjust
->step_increment
= 1.0;
1934 m_vAdjust
->page_increment
= 1.0;
1935 m_vAdjust
->page_size
= 5.0;
1936 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
1937 m_hAdjust
->lower
= 0.0;
1938 m_hAdjust
->upper
= 1.0;
1939 m_hAdjust
->value
= 0.0;
1940 m_hAdjust
->step_increment
= 1.0;
1941 m_hAdjust
->page_increment
= 1.0;
1942 m_hAdjust
->page_size
= 5.0;
1943 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1945 // these handlers block mouse events to any window during scrolling such as
1946 // motion events and prevent GTK and wxWindows from fighting over where the
1949 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
1950 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1952 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
1953 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1955 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
1956 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1958 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
1959 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1961 // these handlers get notified when screen updates are required either when
1962 // scrolling or when the window size (and therefore scrollbar configuration)
1965 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
1966 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
1967 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
1968 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
1970 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
1971 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
1972 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
1973 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
1975 gtk_widget_show( m_wxwindow
);
1978 m_parent
->DoAddChild( this );
1987 wxWindow::~wxWindow()
1989 m_isBeingDeleted
= TRUE
;
1998 m_parent
->RemoveChild( this );
2002 gdk_ic_destroy (m_ic
);
2004 gdk_ic_attr_destroy (m_icattr
);
2009 gtk_style_unref( m_widgetStyle
);
2010 m_widgetStyle
= (GtkStyle
*) NULL
;
2015 gtk_widget_destroy( m_wxwindow
);
2016 m_wxwindow
= (GtkWidget
*) NULL
;
2021 gtk_widget_destroy( m_widget
);
2022 m_widget
= (GtkWidget
*) NULL
;
2026 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2028 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2030 /* this turns -1 into 20 so that a minimal window is
2031 visible even although -1,-1 has been given as the
2032 size of the window. the same trick is used in other
2033 ports and should make debugging easier */
2034 m_width
= WidthDefault(size
.x
);
2035 m_height
= HeightDefault(size
.y
);
2040 /* some reasonable defaults */
2045 m_x
= (gdk_screen_width () - m_width
) / 2;
2046 if (m_x
< 10) m_x
= 10;
2050 m_y
= (gdk_screen_height () - m_height
) / 2;
2051 if (m_y
< 10) m_y
= 10;
2058 void wxWindow::PostCreation()
2060 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2066 /* these get reported to wxWindows -> wxPaintEvent */
2067 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2068 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2070 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2071 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2074 #if (GTK_MINOR_VERSION > 0)
2075 /* these are called when the "sunken" or "raised" borders are drawn */
2076 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2077 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2079 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2080 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2084 if (m_wxwindow
&& m_needParent
)
2086 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2087 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2089 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2090 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2094 // For dialogs and frames, we are interested mainly in
2095 // m_widget's focus.
2097 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2098 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2100 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2101 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2104 GtkWidget
*connect_widget
= GetConnectWidget();
2106 ConnectWidget( connect_widget
);
2108 /* We cannot set colours, fonts and cursors before the widget has
2109 been realized, so we do this directly after realization */
2110 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2111 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2113 /* Initialize XIM support. */
2116 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2117 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2123 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2125 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2126 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2128 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2129 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2131 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2132 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2134 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2135 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2137 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2138 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2140 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2141 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2143 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2144 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2147 bool wxWindow::Destroy()
2149 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2153 return wxWindowBase::Destroy();
2156 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2158 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2159 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2161 if (m_resizing
) return; /* I don't like recursions */
2164 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2166 /* don't set the size for children of wxNotebook, just take the values. */
2174 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2176 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2178 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2179 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2180 if (width
!= -1) m_width
= width
;
2181 if (height
!= -1) m_height
= height
;
2185 m_x
= x
+ pizza
->xoffset
;
2186 m_y
= y
+ pizza
->yoffset
;
2191 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2193 if (width
== -1) m_width
= 80;
2196 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2198 if (height
== -1) m_height
= 26;
2201 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2202 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2203 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2204 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2207 int bottom_border
= 0;
2209 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2211 /* the default button has a border around it */
2216 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
),
2221 m_height
+border
+bottom_border
);
2225 wxPrintf( "OnSize sent from " );
2226 if (GetClassInfo() && GetClassInfo()->GetClassName())
2227 wxPrintf( GetClassInfo()->GetClassName() );
2228 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2231 if (!m_nativeSizeEvent
)
2233 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2234 event
.SetEventObject( this );
2235 GetEventHandler()->ProcessEvent( event
);
2241 void wxWindow::OnInternalIdle()
2243 if ( g_sendActivateEvent
!= -1 )
2245 bool activate
= g_sendActivateEvent
!= 0;
2248 g_sendActivateEvent
= -1;
2250 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2251 event
.SetEventObject(this);
2253 (void)GetEventHandler()->ProcessEvent(event
);
2256 wxCursor cursor
= m_cursor
;
2257 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2261 /* I now set the cursor anew in every OnInternalIdle call
2262 as setting the cursor in a parent window also effects the
2263 windows above so that checking for the current cursor is
2268 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2270 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2272 if (!g_globalCursor
.Ok())
2273 cursor
= *wxSTANDARD_CURSOR
;
2275 window
= m_widget
->window
;
2276 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2277 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2283 GdkWindow
*window
= m_widget
->window
;
2284 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2285 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2293 void wxWindow::DoGetSize( int *width
, int *height
) const
2295 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2297 if (width
) (*width
) = m_width
;
2298 if (height
) (*height
) = m_height
;
2301 void wxWindow::DoSetClientSize( int width
, int height
)
2303 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2307 SetSize( width
, height
);
2314 #if (GTK_MINOR_VERSION == 0)
2315 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2319 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2320 #if 0 // unused - if this is ok, just remove this line (VZ)
2321 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2324 GtkWidget
*viewport
= scroll_window
->viewport
;
2325 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2327 dw
+= 2 * viewport_class
->xthickness
;
2328 dh
+= 2 * viewport_class
->ythickness
;
2332 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2334 /* when using GTK 1.2 we set the shadow border size to 2 */
2338 if (HasFlag(wxSIMPLE_BORDER
))
2340 /* when using GTK 1.2 we set the simple border size to 1 */
2349 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2350 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2352 we use this instead: range.slider_width = 11 + 2*2pts edge
2355 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2356 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2358 if (scroll_window
->vscrollbar_visible
)
2360 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2361 dw
+= scroll_class
->scrollbar_spacing
;
2364 if (scroll_window
->hscrollbar_visible
)
2366 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2367 dh
+= scroll_class
->scrollbar_spacing
;
2371 SetSize( width
+dw
, height
+dh
);
2375 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2377 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2381 if (width
) (*width
) = m_width
;
2382 if (height
) (*height
) = m_height
;
2389 #if (GTK_MINOR_VERSION == 0)
2390 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2394 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2395 #if 0 // unused - if this is ok, just remove this line (VZ)
2396 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2399 GtkWidget
*viewport
= scroll_window
->viewport
;
2400 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2402 dw
+= 2 * viewport_class
->xthickness
;
2403 dh
+= 2 * viewport_class
->ythickness
;
2407 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2409 /* when using GTK 1.2 we set the shadow border size to 2 */
2413 if (HasFlag(wxSIMPLE_BORDER
))
2415 /* when using GTK 1.2 we set the simple border size to 1 */
2423 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2424 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2426 we use this instead: range.slider_width = 11 + 2*2pts edge
2429 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2430 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2432 if (scroll_window
->vscrollbar_visible
)
2434 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2435 dw
+= scroll_class
->scrollbar_spacing
;
2438 if (scroll_window
->hscrollbar_visible
)
2440 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2441 dh
+= scroll_class
->scrollbar_spacing
;
2445 if (width
) (*width
) = m_width
- dw
;
2446 if (height
) (*height
) = m_height
- dh
;
2450 void wxWindow::DoGetPosition( int *x
, int *y
) const
2452 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2456 if (m_parent
&& m_parent
->m_wxwindow
)
2458 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2459 dx
= pizza
->xoffset
;
2460 dy
= pizza
->yoffset
;
2463 if (x
) (*x
) = m_x
- dx
;
2464 if (y
) (*y
) = m_y
- dy
;
2467 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2469 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2471 if (!m_widget
->window
) return;
2473 GdkWindow
*source
= (GdkWindow
*) NULL
;
2475 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2477 source
= m_widget
->window
;
2481 gdk_window_get_origin( source
, &org_x
, &org_y
);
2485 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2487 org_x
+= m_widget
->allocation
.x
;
2488 org_y
+= m_widget
->allocation
.y
;
2496 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2498 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2500 if (!m_widget
->window
) return;
2502 GdkWindow
*source
= (GdkWindow
*) NULL
;
2504 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2506 source
= m_widget
->window
;
2510 gdk_window_get_origin( source
, &org_x
, &org_y
);
2514 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2516 org_x
+= m_widget
->allocation
.x
;
2517 org_y
+= m_widget
->allocation
.y
;
2525 bool wxWindow::Show( bool show
)
2527 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2529 if (!wxWindowBase::Show(show
))
2536 gtk_widget_show( m_widget
);
2538 gtk_widget_hide( m_widget
);
2543 bool wxWindow::Enable( bool enable
)
2545 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2547 if (!wxWindowBase::Enable(enable
))
2553 gtk_widget_set_sensitive( m_widget
, enable
);
2555 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2560 int wxWindow::GetCharHeight() const
2562 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2564 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2566 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2568 return font
->ascent
+ font
->descent
;
2571 int wxWindow::GetCharWidth() const
2573 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2575 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2577 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2579 return gdk_string_width( font
, "H" );
2582 void wxWindow::GetTextExtent( const wxString
& string
,
2586 int *externalLeading
,
2587 const wxFont
*theFont
) const
2589 wxFont fontToUse
= m_font
;
2590 if (theFont
) fontToUse
= *theFont
;
2592 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2594 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2595 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2596 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2597 if (descent
) (*descent
) = font
->descent
;
2598 if (externalLeading
) (*externalLeading
) = 0; // ??
2601 void wxWindow::SetFocus()
2603 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2607 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2608 gtk_widget_grab_focus (m_wxwindow
);
2614 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2616 gtk_widget_grab_focus (m_widget
);
2618 else if (GTK_IS_CONTAINER(m_widget
))
2620 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2629 bool wxWindow::AcceptsFocus() const
2631 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2634 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2636 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2638 wxWindow
*oldParent
= m_parent
,
2639 *newParent
= (wxWindow
*)newParentBase
;
2641 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2643 if ( !wxWindowBase::Reparent(newParent
) )
2646 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2648 /* prevent GTK from deleting the widget arbitrarily */
2649 gtk_widget_ref( m_widget
);
2653 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2656 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2660 /* insert GTK representation */
2661 (*(newParent
->m_insertCallback
))(newParent
, this);
2664 /* reverse: prevent GTK from deleting the widget arbitrarily */
2665 gtk_widget_unref( m_widget
);
2670 void wxWindow::DoAddChild(wxWindow
*child
)
2672 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2674 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
2676 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
2681 /* insert GTK representation */
2682 (*m_insertCallback
)(this, child
);
2685 void wxWindow::Raise()
2687 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2689 if (!m_widget
->window
) return;
2691 gdk_window_raise( m_widget
->window
);
2694 void wxWindow::Lower()
2696 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2698 if (!m_widget
->window
) return;
2700 gdk_window_lower( m_widget
->window
);
2703 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2705 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2707 return wxWindowBase::SetCursor( cursor
);
2710 void wxWindow::WarpPointer( int x
, int y
)
2712 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2714 /* we provide this function ourselves as it is
2715 missing in GDK (top of this file) */
2717 GdkWindow
*window
= (GdkWindow
*) NULL
;
2719 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2721 window
= GetConnectWidget()->window
;
2724 gdk_window_warp_pointer( window
, x
, y
);
2727 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2729 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2731 if (!m_widget
->window
) return;
2733 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2737 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
2739 rect
->width
, rect
->height
);
2743 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
2747 /* there is no GTK equivalent of "draw only, don't clear" so we
2748 invent our own in the GtkPizza widget */
2754 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2755 gboolean old_clear
= pizza
->clear_on_draw
;
2756 gtk_pizza_set_clear( pizza
, FALSE
);
2758 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2760 gtk_pizza_set_clear( pizza
, old_clear
);
2763 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2767 GdkRectangle gdk_rect
;
2768 gdk_rect
.x
= rect
->x
;
2769 gdk_rect
.y
= rect
->y
;
2770 gdk_rect
.width
= rect
->width
;
2771 gdk_rect
.height
= rect
->height
;
2775 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2776 gboolean old_clear
= pizza
->clear_on_draw
;
2777 gtk_pizza_set_clear( pizza
, FALSE
);
2779 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2781 gtk_pizza_set_clear( pizza
, old_clear
);
2784 gtk_widget_draw( m_widget
, &gdk_rect
);
2788 void wxWindow::Clear()
2790 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
2792 if (!m_widget
->window
) return;
2794 if (m_wxwindow
&& m_wxwindow
->window
)
2796 gdk_window_clear( m_wxwindow
->window
);
2801 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2803 wxWindowBase::DoSetToolTip(tip
);
2806 m_tooltip
->Apply( this );
2809 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2811 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
2813 #endif // wxUSE_TOOLTIPS
2815 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2817 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2819 if (!wxWindowBase::SetBackgroundColour(colour
))
2821 // don't leave if the GTK widget has just
2823 if (!m_delayedBackgroundColour
) return FALSE
;
2826 GdkWindow
*window
= (GdkWindow
*) NULL
;
2828 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2830 window
= GetConnectWidget()->window
;
2834 // indicate that a new style has been set
2835 // but it couldn't get applied as the
2836 // widget hasn't been realized yet.
2837 m_delayedBackgroundColour
= TRUE
;
2839 // pretend we have done something
2845 /* wxMSW doesn't clear the window here. I don't do that either to
2846 provide compatibility. call Clear() to do the job. */
2848 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
2849 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
2852 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2853 if (sysbg
== m_backgroundColour
)
2855 m_backgroundColour
= wxNullColour
;
2857 m_backgroundColour
= sysbg
;
2867 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
2869 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2871 if (!wxWindowBase::SetForegroundColour(colour
))
2873 // don't leave if the GTK widget has just
2875 if (!m_delayedForegroundColour
) return FALSE
;
2878 GdkWindow
*window
= (GdkWindow
*) NULL
;
2880 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2882 window
= GetConnectWidget()->window
;
2886 // indicate that a new style has been set
2887 // but it couldn't get applied as the
2888 // widget hasn't been realized yet.
2889 m_delayedForegroundColour
= TRUE
;
2891 // pretend we have done something
2895 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2896 if ( sysbg
== m_backgroundColour
)
2898 m_backgroundColour
= wxNullColour
;
2900 m_backgroundColour
= sysbg
;
2910 GtkStyle
*wxWindow::GetWidgetStyle()
2912 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
2914 m_widgetStyle
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
2916 return m_widgetStyle
;
2919 void wxWindow::SetWidgetStyle()
2921 GtkStyle
*style
= GetWidgetStyle();
2923 gdk_font_unref( style
->font
);
2924 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2926 if (m_foregroundColour
.Ok())
2928 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
2929 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
2930 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
2931 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
2934 if (m_backgroundColour
.Ok())
2936 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
2937 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2938 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2939 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2940 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2941 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2942 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2943 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2944 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2948 void wxWindow::ApplyWidgetStyle()
2952 //-----------------------------------------------------------------------------
2953 // Pop-up menu stuff
2954 //-----------------------------------------------------------------------------
2956 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
2958 *is_waiting
= FALSE
;
2961 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2963 menu
->SetInvokingWindow( win
);
2964 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
2967 wxMenuItem
*menuitem
= node
->GetData();
2968 if (menuitem
->IsSubMenu())
2970 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2973 node
= node
->GetNext();
2977 static gint gs_pop_x
= 0;
2978 static gint gs_pop_y
= 0;
2980 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
2984 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
2989 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
2991 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2993 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
2995 SetInvokingWindow( menu
, this );
3002 bool is_waiting
= TRUE
;
3004 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3005 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3008 GTK_MENU(menu
->m_menu
),
3009 (GtkWidget
*) NULL
, // parent menu shell
3010 (GtkWidget
*) NULL
, // parent menu item
3011 (GtkMenuPositionFunc
) pop_pos_callback
,
3012 (gpointer
) this, // client data
3013 0, // button used to activate it
3014 gs_timeLastClick
// the time of activation
3019 while (gtk_events_pending())
3020 gtk_main_iteration();
3026 #if wxUSE_DRAG_AND_DROP
3028 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3030 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3032 GtkWidget
*dnd_widget
= GetConnectWidget();
3034 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3036 if (m_dropTarget
) delete m_dropTarget
;
3037 m_dropTarget
= dropTarget
;
3039 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3042 #endif // wxUSE_DRAG_AND_DROP
3044 GtkWidget
* wxWindow::GetConnectWidget()
3046 GtkWidget
*connect_widget
= m_widget
;
3047 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3049 return connect_widget
;
3052 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3055 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3057 return (window
== m_widget
->window
);
3060 bool wxWindow::SetFont( const wxFont
&font
)
3062 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3064 if (!wxWindowBase::SetFont(font
))
3069 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3070 if ( sysbg
== m_backgroundColour
)
3072 m_backgroundColour
= wxNullColour
;
3074 m_backgroundColour
= sysbg
;
3084 void wxWindow::CaptureMouse()
3086 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3088 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3090 GdkWindow
*window
= (GdkWindow
*) NULL
;
3092 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3094 window
= GetConnectWidget()->window
;
3096 if (!window
) return;
3098 gdk_pointer_grab( window
, FALSE
,
3100 (GDK_BUTTON_PRESS_MASK
|
3101 GDK_BUTTON_RELEASE_MASK
|
3102 GDK_POINTER_MOTION_HINT_MASK
|
3103 GDK_POINTER_MOTION_MASK
),
3105 m_cursor
.GetCursor(),
3106 (guint32
)GDK_CURRENT_TIME
);
3107 g_captureWindow
= this;
3110 void wxWindow::ReleaseMouse()
3112 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3114 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3116 GdkWindow
*window
= (GdkWindow
*) NULL
;
3118 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3120 window
= GetConnectWidget()->window
;
3125 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3126 g_captureWindow
= (wxWindow
*) NULL
;
3129 bool wxWindow::IsRetained() const
3134 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3135 int range
, bool refresh
)
3137 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3139 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3141 m_hasScrolling
= TRUE
;
3143 if (orient
== wxHORIZONTAL
)
3145 float fpos
= (float)pos
;
3146 float frange
= (float)range
;
3147 float fthumb
= (float)thumbVisible
;
3148 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3149 if (fpos
< 0.0) fpos
= 0.0;
3151 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3152 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3154 SetScrollPos( orient
, pos
, refresh
);
3158 m_oldHorizontalPos
= fpos
;
3160 m_hAdjust
->lower
= 0.0;
3161 m_hAdjust
->upper
= frange
;
3162 m_hAdjust
->value
= fpos
;
3163 m_hAdjust
->step_increment
= 1.0;
3164 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3165 m_hAdjust
->page_size
= fthumb
;
3169 float fpos
= (float)pos
;
3170 float frange
= (float)range
;
3171 float fthumb
= (float)thumbVisible
;
3172 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3173 if (fpos
< 0.0) fpos
= 0.0;
3175 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3176 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3178 SetScrollPos( orient
, pos
, refresh
);
3182 m_oldVerticalPos
= fpos
;
3184 m_vAdjust
->lower
= 0.0;
3185 m_vAdjust
->upper
= frange
;
3186 m_vAdjust
->value
= fpos
;
3187 m_vAdjust
->step_increment
= 1.0;
3188 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3189 m_vAdjust
->page_size
= fthumb
;
3192 if (orient
== wxHORIZONTAL
)
3193 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3195 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3198 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3200 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3202 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3204 if (orient
== wxHORIZONTAL
)
3206 float fpos
= (float)pos
;
3207 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3208 if (fpos
< 0.0) fpos
= 0.0;
3209 m_oldHorizontalPos
= fpos
;
3211 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3212 m_hAdjust
->value
= fpos
;
3216 float fpos
= (float)pos
;
3217 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3218 if (fpos
< 0.0) fpos
= 0.0;
3219 m_oldVerticalPos
= fpos
;
3221 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3222 m_vAdjust
->value
= fpos
;
3229 if (m_wxwindow
->window
)
3231 if (orient
== wxHORIZONTAL
)
3232 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3234 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3241 int wxWindow::GetScrollThumb( int orient
) const
3243 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3245 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3247 if (orient
== wxHORIZONTAL
)
3248 return (int)(m_hAdjust
->page_size
+0.5);
3250 return (int)(m_vAdjust
->page_size
+0.5);
3253 int wxWindow::GetScrollPos( int orient
) const
3255 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3257 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3259 if (orient
== wxHORIZONTAL
)
3260 return (int)(m_hAdjust
->value
+0.5);
3262 return (int)(m_vAdjust
->value
+0.5);
3265 int wxWindow::GetScrollRange( int orient
) const
3267 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3269 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3271 if (orient
== wxHORIZONTAL
)
3272 return (int)(m_hAdjust
->upper
+0.5);
3274 return (int)(m_vAdjust
->upper
+0.5);
3277 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3279 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3281 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3283 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3288 m_scrollGC = gdk_gc_new( m_wxwindow->window );
3289 gdk_gc_set_exposures( m_scrollGC, TRUE );
3292 wxNode *node = m_children.First();
3295 wxWindow *child = (wxWindow*) node->Data();
3298 child->GetSize( &sx, &sy );
3299 child->SetSize( child->m_x + dx, child->m_y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
3300 node = node->Next();
3305 GetClientSize( &cw, &ch );
3306 int w = cw - abs(dx);
3307 int h = ch - abs(dy);
3309 if ((h < 0) || (w < 0))
3317 if (dx < 0) s_x = -dx;
3318 if (dy < 0) s_y = -dy;
3321 if (dx > 0) d_x = dx;
3322 if (dy > 0) d_y = dy;
3324 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
3325 m_wxwindow->window, s_x, s_y, w, h );
3328 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3329 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3330 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3331 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3333 Refresh( TRUE, &rect );
3338 void wxWindow::SetScrolling(bool scroll
)
3340 m_isScrolling
= g_blockEventsOnScroll
= scroll
;