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
;
673 tmp += (char)gdk_event->keyval;
674 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
675 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
680 GdkModifierType state
;
681 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
685 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
686 /* sending unknown key events doesn't really make sense */
687 if (key_code
== 0) return FALSE
;
689 wxKeyEvent
event( wxEVT_KEY_DOWN
);
690 event
.SetTimestamp( gdk_event
->time
);
691 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
692 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
693 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
694 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
695 event
.m_keyCode
= key_code
;
696 event
.m_scanCode
= gdk_event
->keyval
;
699 event
.SetEventObject( win
);
700 ret
= win
->GetEventHandler()->ProcessEvent( event
);
705 wxWindow
*ancestor
= win
;
708 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
711 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
712 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
715 if (ancestor
->m_isFrame
)
717 ancestor
= ancestor
->GetParent();
720 #endif // wxUSE_ACCEL
722 /* wxMSW doesn't send char events with Alt pressed */
723 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
724 will only be sent if it is not in an accelerator table. */
725 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
730 wxKeyEvent
event2( wxEVT_CHAR
);
731 event2
.SetTimestamp( gdk_event
->time
);
732 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
733 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
734 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
735 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
736 event2
.m_keyCode
= key_code
;
737 event2
.m_scanCode
= gdk_event
->keyval
;
740 event2
.SetEventObject( win
);
741 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
744 /* win is a control: tab can be propagated up */
746 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
747 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
748 (win
->GetParent()) &&
749 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
751 wxNavigationKeyEvent new_event
;
752 new_event
.SetEventObject( win
);
753 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
754 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
755 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
756 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
757 new_event
.SetCurrentFocus( win
);
758 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
761 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
763 (gdk_event
->keyval
== GDK_Escape
) )
765 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
766 new_event
.SetEventObject( win
);
767 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
770 #if (GTK_MINOR_VERSION > 0)
771 /* Pressing F10 will activate the menu bar of the top frame. */
775 (gdk_event->keyval == GDK_F10) )
777 wxWindow *ancestor = win;
780 if (wxIsKindOf(ancestor,wxFrame))
782 wxFrame *frame = (wxFrame*) ancestor;
783 wxMenuBar *menubar = frame->GetMenuBar();
786 wxNode *node = menubar->GetMenus().First();
789 wxMenu *firstMenu = (wxMenu*) node->Data();
790 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
796 ancestor = ancestor->GetParent();
804 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
811 //-----------------------------------------------------------------------------
812 // "key_release_event" from any window
813 //-----------------------------------------------------------------------------
815 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
818 wxapp_install_idle_handler();
820 if (!win
->m_hasVMT
) return FALSE
;
821 if (g_blockEventsOnDrag
) return FALSE
;
824 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
825 if (gdk_event->state & GDK_SHIFT_MASK)
826 printf( "ShiftDown.\n" );
828 printf( "ShiftUp.\n" );
829 if (gdk_event->state & GDK_CONTROL_MASK)
830 printf( "ControlDown.\n" );
832 printf( "ControlUp.\n" );
836 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
838 /* sending unknown key events doesn't really make sense */
839 if (key_code
== 0) return FALSE
;
843 GdkModifierType state
;
844 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
846 wxKeyEvent
event( wxEVT_KEY_UP
);
847 event
.SetTimestamp( gdk_event
->time
);
848 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
849 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
850 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
851 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
852 event
.m_keyCode
= key_code
;
853 event
.m_scanCode
= gdk_event
->keyval
;
856 event
.SetEventObject( win
);
858 if (win
->GetEventHandler()->ProcessEvent( event
))
860 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
867 //-----------------------------------------------------------------------------
868 // "button_press_event"
869 //-----------------------------------------------------------------------------
871 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
874 wxapp_install_idle_handler();
877 wxPrintf( wxT("1) OnButtonPress from ") );
878 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
879 wxPrintf( win->GetClassInfo()->GetClassName() );
880 wxPrintf( wxT(".\n") );
882 if (!win
->m_hasVMT
) return FALSE
;
883 if (g_blockEventsOnDrag
) return TRUE
;
884 if (g_blockEventsOnScroll
) return TRUE
;
886 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
890 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
892 gtk_widget_grab_focus (win
->m_wxwindow
);
895 wxPrintf( wxT("GrabFocus from ") );
896 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
897 wxPrintf( win->GetClassInfo()->GetClassName() );
898 wxPrintf( wxT(".\n") );
904 wxEventType event_type
= wxEVT_LEFT_DOWN
;
906 if (gdk_event
->button
== 1)
908 switch (gdk_event
->type
)
910 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
911 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
915 else if (gdk_event
->button
== 2)
917 switch (gdk_event
->type
)
919 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
920 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
924 else if (gdk_event
->button
== 3)
926 switch (gdk_event
->type
)
928 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
929 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
934 wxMouseEvent
event( event_type
);
935 event
.SetTimestamp( gdk_event
->time
);
936 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
937 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
938 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
939 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
940 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
941 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
942 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
944 event
.m_x
= (long)gdk_event
->x
;
945 event
.m_y
= (long)gdk_event
->y
;
947 // Some control don't have their own X window and thus cannot get
950 if (!g_captureWindow
)
952 wxCoord x
= event
.m_x
;
953 wxCoord y
= event
.m_y
;
956 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
961 wxNode
*node
= win
->GetChildren().First();
964 wxWindow
*child
= (wxWindow
*)node
->Data();
967 if (!child
->IsShown())
970 if (child
->m_isStaticBox
)
972 // wxStaticBox is transparent in the box itself
973 int xx1
= child
->m_x
;
974 int yy1
= child
->m_y
;
975 int xx2
= child
->m_x
+ child
->m_width
;
976 int yy2
= child
->m_x
+ child
->m_height
;
979 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
981 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
983 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
985 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
988 event
.m_x
-= child
->m_x
;
989 event
.m_y
-= child
->m_y
;
996 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
999 (child
->m_x
+child
->m_width
>= x
) &&
1000 (child
->m_y
+child
->m_height
>= y
))
1003 event
.m_x
-= child
->m_x
;
1004 event
.m_y
-= child
->m_y
;
1011 event
.SetEventObject( win
);
1013 gs_timeLastClick
= gdk_event
->time
;
1016 wxPrintf( wxT("2) OnButtonPress from ") );
1017 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1018 wxPrintf( win->GetClassInfo()->GetClassName() );
1019 wxPrintf( wxT(".\n") );
1022 if (win
->GetEventHandler()->ProcessEvent( event
))
1024 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1031 //-----------------------------------------------------------------------------
1032 // "button_release_event"
1033 //-----------------------------------------------------------------------------
1035 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1038 wxapp_install_idle_handler();
1040 if (!win
->m_hasVMT
) return FALSE
;
1041 if (g_blockEventsOnDrag
) return FALSE
;
1042 if (g_blockEventsOnScroll
) return FALSE
;
1044 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1047 printf( "OnButtonRelease from " );
1048 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1049 printf( win->GetClassInfo()->GetClassName() );
1053 wxEventType event_type
= wxEVT_NULL
;
1055 switch (gdk_event
->button
)
1057 case 1: event_type
= wxEVT_LEFT_UP
; break;
1058 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1059 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1062 wxMouseEvent
event( event_type
);
1063 event
.SetTimestamp( gdk_event
->time
);
1064 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1065 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1066 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1067 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1068 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1069 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1070 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1071 event
.m_x
= (long)gdk_event
->x
;
1072 event
.m_y
= (long)gdk_event
->y
;
1074 // Some control don't have their own X window and thus cannot get
1077 if (!g_captureWindow
)
1079 wxCoord x
= event
.m_x
;
1080 wxCoord y
= event
.m_y
;
1081 if (win
->m_wxwindow
)
1083 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1084 x
+= pizza
->xoffset
;
1085 y
+= pizza
->yoffset
;
1088 wxNode
*node
= win
->GetChildren().First();
1091 wxWindow
*child
= (wxWindow
*)node
->Data();
1093 node
= node
->Next();
1094 if (!child
->IsShown())
1097 if (child
->m_isStaticBox
)
1099 // wxStaticBox is transparent in the box itself
1100 int xx1
= child
->m_x
;
1101 int yy1
= child
->m_y
;
1102 int xx2
= child
->m_x
+ child
->m_width
;
1103 int yy2
= child
->m_x
+ child
->m_height
;
1106 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1108 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1110 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1112 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1115 event
.m_x
-= child
->m_x
;
1116 event
.m_y
-= child
->m_y
;
1123 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1124 (child
->m_x
<= x
) &&
1125 (child
->m_y
<= y
) &&
1126 (child
->m_x
+child
->m_width
>= x
) &&
1127 (child
->m_y
+child
->m_height
>= y
))
1130 event
.m_x
-= child
->m_x
;
1131 event
.m_y
-= child
->m_y
;
1138 event
.SetEventObject( win
);
1140 if (win
->GetEventHandler()->ProcessEvent( event
))
1142 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1149 //-----------------------------------------------------------------------------
1150 // "motion_notify_event"
1151 //-----------------------------------------------------------------------------
1153 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1156 wxapp_install_idle_handler();
1158 if (!win
->m_hasVMT
) return FALSE
;
1159 if (g_blockEventsOnDrag
) return FALSE
;
1160 if (g_blockEventsOnScroll
) return FALSE
;
1162 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1164 if (gdk_event
->is_hint
)
1168 GdkModifierType state
;
1169 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1175 printf( "OnMotion from " );
1176 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1177 printf( win->GetClassInfo()->GetClassName() );
1181 wxMouseEvent
event( wxEVT_MOTION
);
1182 event
.SetTimestamp( gdk_event
->time
);
1183 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1184 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1185 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1186 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1187 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1188 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1189 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1191 event
.m_x
= (long)gdk_event
->x
;
1192 event
.m_y
= (long)gdk_event
->y
;
1194 // Some control don't have their own X window and thus cannot get
1197 if (!g_captureWindow
)
1199 wxCoord x
= event
.m_x
;
1200 wxCoord y
= event
.m_y
;
1201 if (win
->m_wxwindow
)
1203 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1204 x
+= pizza
->xoffset
;
1205 y
+= pizza
->yoffset
;
1208 wxNode
*node
= win
->GetChildren().First();
1211 wxWindow
*child
= (wxWindow
*)node
->Data();
1213 node
= node
->Next();
1214 if (!child
->IsShown())
1217 if (child
->m_isStaticBox
)
1219 // wxStaticBox is transparent in the box itself
1220 int xx1
= child
->m_x
;
1221 int yy1
= child
->m_y
;
1222 int xx2
= child
->m_x
+ child
->m_width
;
1223 int yy2
= child
->m_x
+ child
->m_height
;
1226 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1228 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1230 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1232 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1235 event
.m_x
-= child
->m_x
;
1236 event
.m_y
-= child
->m_y
;
1243 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1244 (child
->m_x
<= x
) &&
1245 (child
->m_y
<= y
) &&
1246 (child
->m_x
+child
->m_width
>= x
) &&
1247 (child
->m_y
+child
->m_height
>= y
))
1250 event
.m_x
-= child
->m_x
;
1251 event
.m_y
-= child
->m_y
;
1258 event
.SetEventObject( win
);
1260 if (win
->GetEventHandler()->ProcessEvent( event
))
1262 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1269 //-----------------------------------------------------------------------------
1271 //-----------------------------------------------------------------------------
1273 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1276 wxapp_install_idle_handler();
1278 if (!win
->m_hasVMT
) return FALSE
;
1279 if (g_blockEventsOnDrag
) return FALSE
;
1281 switch ( g_sendActivateEvent
)
1284 // we've got focus from outside, synthtize wxActivateEvent
1285 g_sendActivateEvent
= 1;
1289 // another our window just lost focus, it was already ours before
1290 // - don't send any wxActivateEvent
1291 g_sendActivateEvent
= -1;
1295 g_focusWindow
= win
;
1298 printf( "OnSetFocus from " );
1299 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1300 printf( win->GetClassInfo()->GetClassName() );
1302 printf( WXSTRINGCAST win->GetLabel() );
1306 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1309 panel
->SetLastFocus(win
);
1314 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
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() );
1360 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1361 event
.SetEventObject( win
);
1363 if (win
->GetEventHandler()->ProcessEvent( event
))
1365 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1372 //-----------------------------------------------------------------------------
1373 // "enter_notify_event"
1374 //-----------------------------------------------------------------------------
1376 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1379 wxapp_install_idle_handler();
1381 if (!win
->m_hasVMT
) return FALSE
;
1382 if (g_blockEventsOnDrag
) return FALSE
;
1384 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1386 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1387 #if (GTK_MINOR_VERSION > 0)
1388 event
.SetTimestamp( gdk_event
->time
);
1390 event
.SetEventObject( win
);
1394 GdkModifierType state
= (GdkModifierType
)0;
1396 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1398 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1399 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1400 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1401 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1402 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1403 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1404 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1406 event
.m_x
= (long)x
;
1407 event
.m_y
= (long)y
;
1409 if (win
->GetEventHandler()->ProcessEvent( event
))
1411 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1418 //-----------------------------------------------------------------------------
1419 // "leave_notify_event"
1420 //-----------------------------------------------------------------------------
1422 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1425 wxapp_install_idle_handler();
1427 if (!win
->m_hasVMT
) return FALSE
;
1428 if (g_blockEventsOnDrag
) return FALSE
;
1430 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1432 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1433 #if (GTK_MINOR_VERSION > 0)
1434 event
.SetTimestamp( gdk_event
->time
);
1436 event
.SetEventObject( win
);
1440 GdkModifierType state
= (GdkModifierType
)0;
1442 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1444 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1445 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1446 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1447 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1448 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1449 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1450 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1452 event
.m_x
= (long)x
;
1453 event
.m_y
= (long)y
;
1455 if (win
->GetEventHandler()->ProcessEvent( event
))
1457 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1464 //-----------------------------------------------------------------------------
1465 // "value_changed" from m_vAdjust
1466 //-----------------------------------------------------------------------------
1468 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1471 wxapp_install_idle_handler();
1473 if (g_blockEventsOnDrag
) return;
1475 if (!win
->m_hasVMT
) return;
1477 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1478 if (fabs(diff
) < 0.2) return;
1480 win
->m_oldVerticalPos
= adjust
->value
;
1482 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1483 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1485 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1486 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1487 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1488 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1489 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1491 int value
= (int)(adjust
->value
+0.5);
1493 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1494 event
.SetEventObject( win
);
1495 win
->GetEventHandler()->ProcessEvent( event
);
1498 //-----------------------------------------------------------------------------
1499 // "value_changed" from m_hAdjust
1500 //-----------------------------------------------------------------------------
1502 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1505 wxapp_install_idle_handler();
1507 if (g_blockEventsOnDrag
) return;
1508 if (!win
->m_hasVMT
) return;
1510 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1511 if (fabs(diff
) < 0.2) return;
1513 win
->m_oldHorizontalPos
= adjust
->value
;
1515 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1516 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1518 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1519 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1520 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1521 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1522 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1524 int value
= (int)(adjust
->value
+0.5);
1526 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1527 event
.SetEventObject( win
);
1528 win
->GetEventHandler()->ProcessEvent( event
);
1531 //-----------------------------------------------------------------------------
1532 // "changed" from m_vAdjust
1533 //-----------------------------------------------------------------------------
1535 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1538 wxapp_install_idle_handler();
1540 if (g_blockEventsOnDrag
) return;
1541 if (!win
->m_hasVMT
) return;
1543 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1544 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1546 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1547 event
.SetEventObject( win
);
1548 win
->GetEventHandler()->ProcessEvent( event
);
1551 //-----------------------------------------------------------------------------
1552 // "changed" from m_hAdjust
1553 //-----------------------------------------------------------------------------
1555 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1558 wxapp_install_idle_handler();
1560 if (g_blockEventsOnDrag
) return;
1561 if (!win
->m_hasVMT
) return;
1563 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1564 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1566 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1567 event
.SetEventObject( win
);
1568 win
->GetEventHandler()->ProcessEvent( event
);
1571 //-----------------------------------------------------------------------------
1572 // "button_press_event" from scrollbar
1573 //-----------------------------------------------------------------------------
1575 static gint
gtk_scrollbar_button_press_callback( GtkRange
*WXUNUSED(widget
),
1576 GdkEventButton
*WXUNUSED(gdk_event
),
1580 wxapp_install_idle_handler();
1582 // don't test here as we can release the mouse while being over
1583 // a different window than the slider
1585 // if (gdk_event->window != widget->slider) return FALSE;
1587 win
->SetScrolling( TRUE
);
1592 //-----------------------------------------------------------------------------
1593 // "button_release_event" from scrollbar
1594 //-----------------------------------------------------------------------------
1596 static gint
gtk_scrollbar_button_release_callback( GtkRange
*WXUNUSED(widget
),
1597 GdkEventButton
*WXUNUSED(gdk_event
),
1601 // don't test here as we can release the mouse while being over
1602 // a different window than the slider
1604 // if (gdk_event->window != widget->slider) return FALSE;
1606 win
->SetScrolling( FALSE
);
1611 // ----------------------------------------------------------------------------
1612 // this wxWindowBase function is implemented here (in platform-specific file)
1613 // because it is static and so couldn't be made virtual
1614 // ----------------------------------------------------------------------------
1616 wxWindow
*wxWindowBase::FindFocus()
1618 return g_focusWindow
;
1621 //-----------------------------------------------------------------------------
1622 // "realize" from m_widget
1623 //-----------------------------------------------------------------------------
1625 /* We cannot set colours and fonts before the widget has
1626 been realized, so we do this directly after realization. */
1629 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1632 wxapp_install_idle_handler();
1634 if (win
->m_delayedFont
)
1635 win
->SetFont( win
->GetFont() );
1637 if (win
->m_delayedBackgroundColour
)
1638 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1640 if (win
->m_delayedForegroundColour
)
1641 win
->SetForegroundColour( win
->GetForegroundColour() );
1643 wxWindowCreateEvent
event( win
);
1644 event
.SetEventObject( win
);
1645 win
->GetEventHandler()->ProcessEvent( event
);
1650 //-----------------------------------------------------------------------------
1652 //-----------------------------------------------------------------------------
1654 /* Resize XIM window */
1656 static void gtk_wxwindow_size_callback( GtkWidget
*widget
, GtkAllocation
* alloc
, wxFrame
*win
)
1659 wxapp_install_idle_handler();
1665 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1669 gdk_window_get_size (widget
->window
, &width
, &height
);
1670 win
->m_icattr
->preedit_area
.width
= width
;
1671 win
->m_icattr
->preedit_area
.height
= height
;
1672 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
1677 //-----------------------------------------------------------------------------
1678 // "realize" from m_wxwindow
1679 //-----------------------------------------------------------------------------
1681 /* Initialize XIM support */
1684 gtk_wxwindow_realized_callback( GtkWidget
*widget
, wxWindow
*win
)
1687 wxapp_install_idle_handler();
1690 if (win
->m_ic
) return FALSE
;
1691 if (!widget
) return FALSE
;
1692 if (!gdk_im_ready()) return FALSE
;
1694 win
->m_icattr
= gdk_ic_attr_new();
1695 if (!win
->m_icattr
) return FALSE
;
1699 GdkColormap
*colormap
;
1700 GdkICAttr
*attr
= win
->m_icattr
;
1701 GdkICAttributesType attrmask
= GDK_IC_ALL_REQ
;
1703 GdkIMStyle supported_style
= (GdkIMStyle
)
1704 (GDK_IM_PREEDIT_NONE
|
1705 GDK_IM_PREEDIT_NOTHING
|
1706 GDK_IM_PREEDIT_POSITION
|
1707 GDK_IM_STATUS_NONE
|
1708 GDK_IM_STATUS_NOTHING
);
1710 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1711 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
1713 attr
->style
= style
= gdk_im_decide_style (supported_style
);
1714 attr
->client_window
= widget
->window
;
1716 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
1717 gtk_widget_get_default_colormap ())
1719 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
1720 attr
->preedit_colormap
= colormap
;
1723 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
1724 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
1725 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
1726 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
1728 switch (style
& GDK_IM_PREEDIT_MASK
)
1730 case GDK_IM_PREEDIT_POSITION
:
1731 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1733 g_warning ("over-the-spot style requires fontset");
1737 gdk_window_get_size (widget
->window
, &width
, &height
);
1739 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
1740 attr
->spot_location
.x
= 0;
1741 attr
->spot_location
.y
= height
;
1742 attr
->preedit_area
.x
= 0;
1743 attr
->preedit_area
.y
= 0;
1744 attr
->preedit_area
.width
= width
;
1745 attr
->preedit_area
.height
= height
;
1746 attr
->preedit_fontset
= widget
->style
->font
;
1751 win
->m_ic
= gdk_ic_new (attr
, attrmask
);
1753 if (win
->m_ic
== NULL
)
1754 g_warning ("Can't create input context.");
1757 mask
= gdk_window_get_events (widget
->window
);
1758 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
1759 gdk_window_set_events (widget
->window
, mask
);
1761 if (GTK_WIDGET_HAS_FOCUS(widget
))
1762 gdk_im_begin (win
->m_ic
, widget
->window
);
1769 //-----------------------------------------------------------------------------
1770 // InsertChild for wxWindow.
1771 //-----------------------------------------------------------------------------
1773 /* Callback for wxWindow. This very strange beast has to be used because
1774 * C++ has no virtual methods in a constructor. We have to emulate a
1775 * virtual function here as wxNotebook requires a different way to insert
1776 * a child in it. I had opted for creating a wxNotebookPage window class
1777 * which would have made this superfluous (such in the MDI window system),
1778 * but no-one was listening to me... */
1780 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1782 /* the window might have been scrolled already, do we
1783 have to adapt the position */
1784 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
1785 child
->m_x
+= pizza
->xoffset
;
1786 child
->m_y
+= pizza
->yoffset
;
1788 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
1789 GTK_WIDGET(child
->m_widget
),
1796 //-----------------------------------------------------------------------------
1798 //-----------------------------------------------------------------------------
1800 wxWindow
* wxGetActiveWindow()
1802 return g_focusWindow
;
1805 //-----------------------------------------------------------------------------
1807 //-----------------------------------------------------------------------------
1809 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
1811 void wxWindow::Init()
1817 m_widget
= (GtkWidget
*) NULL
;
1818 m_wxwindow
= (GtkWidget
*) NULL
;
1828 m_needParent
= TRUE
;
1829 m_isBeingDeleted
= FALSE
;
1832 m_nativeSizeEvent
= FALSE
;
1834 m_hasScrolling
= FALSE
;
1835 m_isScrolling
= FALSE
;
1837 m_hAdjust
= (GtkAdjustment
*) NULL
;
1838 m_vAdjust
= (GtkAdjustment
*) NULL
;
1839 m_oldHorizontalPos
= 0.0;
1840 m_oldVerticalPos
= 0.0;
1843 m_widgetStyle
= (GtkStyle
*) NULL
;
1845 m_insertCallback
= (wxInsertChildFunction
) NULL
;
1847 m_isStaticBox
= FALSE
;
1848 m_isRadioButton
= FALSE
;
1850 m_acceptsFocus
= FALSE
;
1852 m_cursor
= *wxSTANDARD_CURSOR
;
1855 m_ic
= (GdkIC
*) NULL
;
1856 m_icattr
= (GdkICAttr
*) NULL
;
1860 wxWindow::wxWindow()
1865 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1866 const wxPoint
&pos
, const wxSize
&size
,
1867 long style
, const wxString
&name
)
1871 Create( parent
, id
, pos
, size
, style
, name
);
1874 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1875 const wxPoint
&pos
, const wxSize
&size
,
1876 long style
, const wxString
&name
)
1878 if (!PreCreation( parent
, pos
, size
) ||
1879 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
1881 wxFAIL_MSG( wxT("wxWindow creation failed") );
1885 m_insertCallback
= wxInsertChildInWindow
;
1887 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
1888 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1891 debug_focus_in( m_widget
, wxT("wxWindow::m_widget"), name
);
1894 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
1897 debug_focus_in( scrolledWindow
->hscrollbar
, wxT("wxWindow::hsrcollbar"), name
);
1898 debug_focus_in( scrolledWindow
->vscrollbar
, wxT("wxWindow::vsrcollbar"), name
);
1901 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1902 scroll_class
->scrollbar_spacing
= 0;
1904 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1906 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
1907 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
1909 m_wxwindow
= gtk_pizza_new();
1912 debug_focus_in( m_wxwindow
, wxT("wxWindow::m_wxwindow"), name
);
1915 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
1917 #if (GTK_MINOR_VERSION > 0)
1918 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
1920 if (HasFlag(wxRAISED_BORDER
))
1922 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
1924 else if (HasFlag(wxSUNKEN_BORDER
))
1926 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
1928 else if (HasFlag(wxSIMPLE_BORDER
))
1930 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
1934 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
1936 #else // GTK_MINOR_VERSION == 0
1937 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
1939 if (HasFlag(wxRAISED_BORDER
))
1941 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
1943 else if (HasFlag(wxSUNKEN_BORDER
))
1945 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
1949 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
1951 #endif // GTK_MINOR_VERSION
1953 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1954 m_acceptsFocus
= TRUE
;
1956 #if (GTK_MINOR_VERSION == 0)
1957 // shut the viewport up
1958 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1959 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1960 #endif // GTK_MINOR_VERSION == 0
1962 // I _really_ don't want scrollbars in the beginning
1963 m_vAdjust
->lower
= 0.0;
1964 m_vAdjust
->upper
= 1.0;
1965 m_vAdjust
->value
= 0.0;
1966 m_vAdjust
->step_increment
= 1.0;
1967 m_vAdjust
->page_increment
= 1.0;
1968 m_vAdjust
->page_size
= 5.0;
1969 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
1970 m_hAdjust
->lower
= 0.0;
1971 m_hAdjust
->upper
= 1.0;
1972 m_hAdjust
->value
= 0.0;
1973 m_hAdjust
->step_increment
= 1.0;
1974 m_hAdjust
->page_increment
= 1.0;
1975 m_hAdjust
->page_size
= 5.0;
1976 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1978 // these handlers block mouse events to any window during scrolling such as
1979 // motion events and prevent GTK and wxWindows from fighting over where the
1982 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
1983 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1985 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
1986 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1988 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
1989 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1991 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
1992 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1994 // these handlers get notified when screen updates are required either when
1995 // scrolling or when the window size (and therefore scrollbar configuration)
1998 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
1999 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2000 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2001 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2003 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
2004 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
2005 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
2006 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
2008 gtk_widget_show( m_wxwindow
);
2011 m_parent
->DoAddChild( this );
2020 wxWindow::~wxWindow()
2022 m_isBeingDeleted
= TRUE
;
2031 m_parent
->RemoveChild( this );
2035 gdk_ic_destroy (m_ic
);
2037 gdk_ic_attr_destroy (m_icattr
);
2042 gtk_style_unref( m_widgetStyle
);
2043 m_widgetStyle
= (GtkStyle
*) NULL
;
2048 gtk_widget_destroy( m_wxwindow
);
2049 m_wxwindow
= (GtkWidget
*) NULL
;
2054 gtk_widget_destroy( m_widget
);
2055 m_widget
= (GtkWidget
*) NULL
;
2059 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2061 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2063 /* this turns -1 into 20 so that a minimal window is
2064 visible even although -1,-1 has been given as the
2065 size of the window. the same trick is used in other
2066 ports and should make debugging easier */
2067 m_width
= WidthDefault(size
.x
);
2068 m_height
= HeightDefault(size
.y
);
2073 /* some reasonable defaults */
2078 m_x
= (gdk_screen_width () - m_width
) / 2;
2079 if (m_x
< 10) m_x
= 10;
2083 m_y
= (gdk_screen_height () - m_height
) / 2;
2084 if (m_y
< 10) m_y
= 10;
2091 void wxWindow::PostCreation()
2093 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2099 /* these get reported to wxWindows -> wxPaintEvent */
2100 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2101 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2103 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2104 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2107 #if (GTK_MINOR_VERSION > 0)
2108 /* these are called when the "sunken" or "raised" borders are drawn */
2109 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2110 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2112 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2113 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2117 if (m_wxwindow
&& m_needParent
)
2119 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2120 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2122 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2123 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2127 // For dialogs and frames, we are interested mainly in
2128 // m_widget's focus.
2130 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2131 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2133 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2134 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2137 GtkWidget
*connect_widget
= GetConnectWidget();
2139 ConnectWidget( connect_widget
);
2141 /* We cannot set colours, fonts and cursors before the widget has
2142 been realized, so we do this directly after realization */
2143 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2144 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2148 /* Initialize XIM support. */
2149 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2150 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2152 /* And resize XIM window. */
2153 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2154 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2160 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2162 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2163 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2165 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2166 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2168 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2169 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2171 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2172 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2174 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2175 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2177 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2178 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2180 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2181 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2184 bool wxWindow::Destroy()
2186 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2190 return wxWindowBase::Destroy();
2193 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2195 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2196 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2198 if (m_resizing
) return; /* I don't like recursions */
2201 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2203 /* don't set the size for children of wxNotebook, just take the values. */
2211 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2213 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2215 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2216 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2217 if (width
!= -1) m_width
= width
;
2218 if (height
!= -1) m_height
= height
;
2222 m_x
= x
+ pizza
->xoffset
;
2223 m_y
= y
+ pizza
->yoffset
;
2228 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2230 if (width
== -1) m_width
= 80;
2233 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2235 if (height
== -1) m_height
= 26;
2238 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2239 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2240 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2241 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2244 int bottom_border
= 0;
2246 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2248 /* the default button has a border around it */
2253 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
),
2258 m_height
+border
+bottom_border
);
2262 wxPrintf( "OnSize sent from " );
2263 if (GetClassInfo() && GetClassInfo()->GetClassName())
2264 wxPrintf( GetClassInfo()->GetClassName() );
2265 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2268 if (!m_nativeSizeEvent
)
2270 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2271 event
.SetEventObject( this );
2272 GetEventHandler()->ProcessEvent( event
);
2278 void wxWindow::OnInternalIdle()
2280 if ( g_sendActivateEvent
!= -1 )
2282 bool activate
= g_sendActivateEvent
!= 0;
2285 g_sendActivateEvent
= -1;
2287 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2288 event
.SetEventObject(this);
2290 (void)GetEventHandler()->ProcessEvent(event
);
2293 wxCursor cursor
= m_cursor
;
2294 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2298 /* I now set the cursor anew in every OnInternalIdle call
2299 as setting the cursor in a parent window also effects the
2300 windows above so that checking for the current cursor is
2305 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2307 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2309 if (!g_globalCursor
.Ok())
2310 cursor
= *wxSTANDARD_CURSOR
;
2312 window
= m_widget
->window
;
2313 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2314 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2320 GdkWindow
*window
= m_widget
->window
;
2321 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2322 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2330 void wxWindow::DoGetSize( int *width
, int *height
) const
2332 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2334 if (width
) (*width
) = m_width
;
2335 if (height
) (*height
) = m_height
;
2338 void wxWindow::DoSetClientSize( int width
, int height
)
2340 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2344 SetSize( width
, height
);
2351 #if (GTK_MINOR_VERSION == 0)
2352 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2356 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2357 #if 0 // unused - if this is ok, just remove this line (VZ)
2358 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2361 GtkWidget
*viewport
= scroll_window
->viewport
;
2362 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2364 dw
+= 2 * viewport_class
->xthickness
;
2365 dh
+= 2 * viewport_class
->ythickness
;
2369 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2371 /* when using GTK 1.2 we set the shadow border size to 2 */
2375 if (HasFlag(wxSIMPLE_BORDER
))
2377 /* when using GTK 1.2 we set the simple border size to 1 */
2386 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2387 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2389 we use this instead: range.slider_width = 11 + 2*2pts edge
2392 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2393 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2395 if (scroll_window
->vscrollbar_visible
)
2397 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2398 dw
+= scroll_class
->scrollbar_spacing
;
2401 if (scroll_window
->hscrollbar_visible
)
2403 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2404 dh
+= scroll_class
->scrollbar_spacing
;
2408 SetSize( width
+dw
, height
+dh
);
2412 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2414 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2418 if (width
) (*width
) = m_width
;
2419 if (height
) (*height
) = m_height
;
2426 #if (GTK_MINOR_VERSION == 0)
2427 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2431 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2432 #if 0 // unused - if this is ok, just remove this line (VZ)
2433 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2436 GtkWidget
*viewport
= scroll_window
->viewport
;
2437 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2439 dw
+= 2 * viewport_class
->xthickness
;
2440 dh
+= 2 * viewport_class
->ythickness
;
2444 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2446 /* when using GTK 1.2 we set the shadow border size to 2 */
2450 if (HasFlag(wxSIMPLE_BORDER
))
2452 /* when using GTK 1.2 we set the simple border size to 1 */
2460 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2461 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2463 we use this instead: range.slider_width = 11 + 2*2pts edge
2466 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2467 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2469 if (scroll_window
->vscrollbar_visible
)
2471 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2472 dw
+= scroll_class
->scrollbar_spacing
;
2475 if (scroll_window
->hscrollbar_visible
)
2477 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2478 dh
+= scroll_class
->scrollbar_spacing
;
2482 if (width
) (*width
) = m_width
- dw
;
2483 if (height
) (*height
) = m_height
- dh
;
2487 void wxWindow::DoGetPosition( int *x
, int *y
) const
2489 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2493 if (m_parent
&& m_parent
->m_wxwindow
)
2495 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2496 dx
= pizza
->xoffset
;
2497 dy
= pizza
->yoffset
;
2500 if (x
) (*x
) = m_x
- dx
;
2501 if (y
) (*y
) = m_y
- dy
;
2504 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2506 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2508 if (!m_widget
->window
) return;
2510 GdkWindow
*source
= (GdkWindow
*) NULL
;
2512 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2514 source
= m_widget
->window
;
2518 gdk_window_get_origin( source
, &org_x
, &org_y
);
2522 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2524 org_x
+= m_widget
->allocation
.x
;
2525 org_y
+= m_widget
->allocation
.y
;
2533 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2535 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2537 if (!m_widget
->window
) return;
2539 GdkWindow
*source
= (GdkWindow
*) NULL
;
2541 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2543 source
= m_widget
->window
;
2547 gdk_window_get_origin( source
, &org_x
, &org_y
);
2551 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2553 org_x
+= m_widget
->allocation
.x
;
2554 org_y
+= m_widget
->allocation
.y
;
2562 bool wxWindow::Show( bool show
)
2564 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2566 if (!wxWindowBase::Show(show
))
2573 gtk_widget_show( m_widget
);
2575 gtk_widget_hide( m_widget
);
2580 bool wxWindow::Enable( bool enable
)
2582 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2584 if (!wxWindowBase::Enable(enable
))
2590 gtk_widget_set_sensitive( m_widget
, enable
);
2592 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2597 int wxWindow::GetCharHeight() const
2599 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2601 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2603 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2605 return font
->ascent
+ font
->descent
;
2608 int wxWindow::GetCharWidth() const
2610 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2612 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2614 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2616 return gdk_string_width( font
, "H" );
2619 void wxWindow::GetTextExtent( const wxString
& string
,
2623 int *externalLeading
,
2624 const wxFont
*theFont
) const
2626 wxFont fontToUse
= m_font
;
2627 if (theFont
) fontToUse
= *theFont
;
2629 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2631 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2632 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2633 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2634 if (descent
) (*descent
) = font
->descent
;
2635 if (externalLeading
) (*externalLeading
) = 0; // ??
2638 void wxWindow::SetFocus()
2640 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2644 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2645 gtk_widget_grab_focus (m_wxwindow
);
2651 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2653 gtk_widget_grab_focus (m_widget
);
2655 else if (GTK_IS_CONTAINER(m_widget
))
2657 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2666 bool wxWindow::AcceptsFocus() const
2668 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2671 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2673 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2675 wxWindow
*oldParent
= m_parent
,
2676 *newParent
= (wxWindow
*)newParentBase
;
2678 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2680 if ( !wxWindowBase::Reparent(newParent
) )
2683 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2685 /* prevent GTK from deleting the widget arbitrarily */
2686 gtk_widget_ref( m_widget
);
2690 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2693 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2697 /* insert GTK representation */
2698 (*(newParent
->m_insertCallback
))(newParent
, this);
2701 /* reverse: prevent GTK from deleting the widget arbitrarily */
2702 gtk_widget_unref( m_widget
);
2707 void wxWindow::DoAddChild(wxWindow
*child
)
2709 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2711 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
2713 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
2718 /* insert GTK representation */
2719 (*m_insertCallback
)(this, child
);
2722 void wxWindow::Raise()
2724 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2726 if (!m_widget
->window
) return;
2728 gdk_window_raise( m_widget
->window
);
2731 void wxWindow::Lower()
2733 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2735 if (!m_widget
->window
) return;
2737 gdk_window_lower( m_widget
->window
);
2740 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2742 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2744 return wxWindowBase::SetCursor( cursor
);
2747 void wxWindow::WarpPointer( int x
, int y
)
2749 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2751 /* we provide this function ourselves as it is
2752 missing in GDK (top of this file) */
2754 GdkWindow
*window
= (GdkWindow
*) NULL
;
2756 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2758 window
= GetConnectWidget()->window
;
2761 gdk_window_warp_pointer( window
, x
, y
);
2764 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2766 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2768 if (!m_widget
->window
) return;
2770 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2774 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
2776 rect
->width
, rect
->height
);
2780 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
2784 /* there is no GTK equivalent of "draw only, don't clear" so we
2785 invent our own in the GtkPizza widget */
2791 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2792 gboolean old_clear
= pizza
->clear_on_draw
;
2793 gtk_pizza_set_clear( pizza
, FALSE
);
2795 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2797 gtk_pizza_set_clear( pizza
, old_clear
);
2800 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2804 GdkRectangle gdk_rect
;
2805 gdk_rect
.x
= rect
->x
;
2806 gdk_rect
.y
= rect
->y
;
2807 gdk_rect
.width
= rect
->width
;
2808 gdk_rect
.height
= rect
->height
;
2812 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2813 gboolean old_clear
= pizza
->clear_on_draw
;
2814 gtk_pizza_set_clear( pizza
, FALSE
);
2816 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2818 gtk_pizza_set_clear( pizza
, old_clear
);
2821 gtk_widget_draw( m_widget
, &gdk_rect
);
2825 void wxWindow::Clear()
2827 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
2829 if (!m_widget
->window
) return;
2831 if (m_wxwindow
&& m_wxwindow
->window
)
2833 gdk_window_clear( m_wxwindow
->window
);
2838 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2840 wxWindowBase::DoSetToolTip(tip
);
2843 m_tooltip
->Apply( this );
2846 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2848 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
2850 #endif // wxUSE_TOOLTIPS
2852 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2854 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2856 if (!wxWindowBase::SetBackgroundColour(colour
))
2858 // don't leave if the GTK widget has just
2860 if (!m_delayedBackgroundColour
) return FALSE
;
2863 GdkWindow
*window
= (GdkWindow
*) NULL
;
2865 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2867 window
= GetConnectWidget()->window
;
2871 // indicate that a new style has been set
2872 // but it couldn't get applied as the
2873 // widget hasn't been realized yet.
2874 m_delayedBackgroundColour
= TRUE
;
2876 // pretend we have done something
2882 /* wxMSW doesn't clear the window here. I don't do that either to
2883 provide compatibility. call Clear() to do the job. */
2885 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
2886 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
2889 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2890 if (sysbg
== m_backgroundColour
)
2892 m_backgroundColour
= wxNullColour
;
2894 m_backgroundColour
= sysbg
;
2904 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
2906 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2908 if (!wxWindowBase::SetForegroundColour(colour
))
2910 // don't leave if the GTK widget has just
2912 if (!m_delayedForegroundColour
) return FALSE
;
2915 GdkWindow
*window
= (GdkWindow
*) NULL
;
2917 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2919 window
= GetConnectWidget()->window
;
2923 // indicate that a new style has been set
2924 // but it couldn't get applied as the
2925 // widget hasn't been realized yet.
2926 m_delayedForegroundColour
= TRUE
;
2928 // pretend we have done something
2932 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2933 if ( sysbg
== m_backgroundColour
)
2935 m_backgroundColour
= wxNullColour
;
2937 m_backgroundColour
= sysbg
;
2947 GtkStyle
*wxWindow::GetWidgetStyle()
2949 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
2951 m_widgetStyle
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
2953 return m_widgetStyle
;
2956 void wxWindow::SetWidgetStyle()
2958 GtkStyle
*style
= GetWidgetStyle();
2960 gdk_font_unref( style
->font
);
2961 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2963 if (m_foregroundColour
.Ok())
2965 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
2966 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
2967 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
2968 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
2971 if (m_backgroundColour
.Ok())
2973 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
2974 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2975 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2976 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2977 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2978 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2979 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2980 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2981 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2985 void wxWindow::ApplyWidgetStyle()
2989 //-----------------------------------------------------------------------------
2990 // Pop-up menu stuff
2991 //-----------------------------------------------------------------------------
2993 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
2995 *is_waiting
= FALSE
;
2998 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3000 menu
->SetInvokingWindow( win
);
3001 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3004 wxMenuItem
*menuitem
= node
->GetData();
3005 if (menuitem
->IsSubMenu())
3007 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3010 node
= node
->GetNext();
3014 static gint gs_pop_x
= 0;
3015 static gint gs_pop_y
= 0;
3017 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3021 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3026 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3028 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3030 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3032 SetInvokingWindow( menu
, this );
3039 bool is_waiting
= TRUE
;
3041 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3042 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3045 GTK_MENU(menu
->m_menu
),
3046 (GtkWidget
*) NULL
, // parent menu shell
3047 (GtkWidget
*) NULL
, // parent menu item
3048 (GtkMenuPositionFunc
) pop_pos_callback
,
3049 (gpointer
) this, // client data
3050 0, // button used to activate it
3051 gs_timeLastClick
// the time of activation
3056 while (gtk_events_pending())
3057 gtk_main_iteration();
3063 #if wxUSE_DRAG_AND_DROP
3065 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3067 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3069 GtkWidget
*dnd_widget
= GetConnectWidget();
3071 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3073 if (m_dropTarget
) delete m_dropTarget
;
3074 m_dropTarget
= dropTarget
;
3076 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3079 #endif // wxUSE_DRAG_AND_DROP
3081 GtkWidget
* wxWindow::GetConnectWidget()
3083 GtkWidget
*connect_widget
= m_widget
;
3084 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3086 return connect_widget
;
3089 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3092 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3094 return (window
== m_widget
->window
);
3097 bool wxWindow::SetFont( const wxFont
&font
)
3099 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3101 if (!wxWindowBase::SetFont(font
))
3106 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3107 if ( sysbg
== m_backgroundColour
)
3109 m_backgroundColour
= wxNullColour
;
3111 m_backgroundColour
= sysbg
;
3121 void wxWindow::CaptureMouse()
3123 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3125 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3127 GdkWindow
*window
= (GdkWindow
*) NULL
;
3129 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3131 window
= GetConnectWidget()->window
;
3133 if (!window
) return;
3135 gdk_pointer_grab( window
, FALSE
,
3137 (GDK_BUTTON_PRESS_MASK
|
3138 GDK_BUTTON_RELEASE_MASK
|
3139 GDK_POINTER_MOTION_HINT_MASK
|
3140 GDK_POINTER_MOTION_MASK
),
3142 m_cursor
.GetCursor(),
3143 (guint32
)GDK_CURRENT_TIME
);
3144 g_captureWindow
= this;
3147 void wxWindow::ReleaseMouse()
3149 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3151 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3153 GdkWindow
*window
= (GdkWindow
*) NULL
;
3155 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3157 window
= GetConnectWidget()->window
;
3162 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3163 g_captureWindow
= (wxWindow
*) NULL
;
3166 bool wxWindow::IsRetained() const
3171 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3172 int range
, bool refresh
)
3174 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3176 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3178 m_hasScrolling
= TRUE
;
3180 if (orient
== wxHORIZONTAL
)
3182 float fpos
= (float)pos
;
3183 float frange
= (float)range
;
3184 float fthumb
= (float)thumbVisible
;
3185 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3186 if (fpos
< 0.0) fpos
= 0.0;
3188 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3189 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3191 SetScrollPos( orient
, pos
, refresh
);
3195 m_oldHorizontalPos
= fpos
;
3197 m_hAdjust
->lower
= 0.0;
3198 m_hAdjust
->upper
= frange
;
3199 m_hAdjust
->value
= fpos
;
3200 m_hAdjust
->step_increment
= 1.0;
3201 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3202 m_hAdjust
->page_size
= fthumb
;
3206 float fpos
= (float)pos
;
3207 float frange
= (float)range
;
3208 float fthumb
= (float)thumbVisible
;
3209 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3210 if (fpos
< 0.0) fpos
= 0.0;
3212 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3213 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3215 SetScrollPos( orient
, pos
, refresh
);
3219 m_oldVerticalPos
= fpos
;
3221 m_vAdjust
->lower
= 0.0;
3222 m_vAdjust
->upper
= frange
;
3223 m_vAdjust
->value
= fpos
;
3224 m_vAdjust
->step_increment
= 1.0;
3225 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3226 m_vAdjust
->page_size
= fthumb
;
3229 if (orient
== wxHORIZONTAL
)
3230 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3232 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3235 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3237 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3239 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3241 if (orient
== wxHORIZONTAL
)
3243 float fpos
= (float)pos
;
3244 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3245 if (fpos
< 0.0) fpos
= 0.0;
3246 m_oldHorizontalPos
= fpos
;
3248 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3249 m_hAdjust
->value
= fpos
;
3253 float fpos
= (float)pos
;
3254 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3255 if (fpos
< 0.0) fpos
= 0.0;
3256 m_oldVerticalPos
= fpos
;
3258 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3259 m_vAdjust
->value
= fpos
;
3266 if (m_wxwindow
->window
)
3268 if (orient
== wxHORIZONTAL
)
3269 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3271 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3278 int wxWindow::GetScrollThumb( int orient
) const
3280 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3282 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3284 if (orient
== wxHORIZONTAL
)
3285 return (int)(m_hAdjust
->page_size
+0.5);
3287 return (int)(m_vAdjust
->page_size
+0.5);
3290 int wxWindow::GetScrollPos( int orient
) const
3292 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3294 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3296 if (orient
== wxHORIZONTAL
)
3297 return (int)(m_hAdjust
->value
+0.5);
3299 return (int)(m_vAdjust
->value
+0.5);
3302 int wxWindow::GetScrollRange( int orient
) const
3304 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3306 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3308 if (orient
== wxHORIZONTAL
)
3309 return (int)(m_hAdjust
->upper
+0.5);
3311 return (int)(m_vAdjust
->upper
+0.5);
3314 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3316 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3318 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3320 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3325 m_scrollGC = gdk_gc_new( m_wxwindow->window );
3326 gdk_gc_set_exposures( m_scrollGC, TRUE );
3329 wxNode *node = m_children.First();
3332 wxWindow *child = (wxWindow*) node->Data();
3335 child->GetSize( &sx, &sy );
3336 child->SetSize( child->m_x + dx, child->m_y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
3337 node = node->Next();
3342 GetClientSize( &cw, &ch );
3343 int w = cw - abs(dx);
3344 int h = ch - abs(dy);
3346 if ((h < 0) || (w < 0))
3354 if (dx < 0) s_x = -dx;
3355 if (dy < 0) s_y = -dy;
3358 if (dx > 0) d_x = dx;
3359 if (dy > 0) d_y = dy;
3361 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
3362 m_wxwindow->window, s_x, s_y, w, h );
3365 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3366 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3367 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3368 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3370 Refresh( TRUE, &rect );
3375 void wxWindow::SetScrolling(bool scroll
)
3377 m_isScrolling
= g_blockEventsOnScroll
= scroll
;