1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #include "wx/window.h"
20 #include "wx/layout.h"
22 #include "wx/dialog.h"
23 #include "wx/msgdlg.h"
25 #if wxUSE_DRAG_AND_DROP
30 #include "wx/tooltip.h"
34 #include "wx/statusbr.h"
36 #include "wx/settings.h"
40 #include "wx/thread.h"
47 #include <gdk/gdkprivate.h>
48 #include <gdk/gdkkeysyms.h>
49 #include <wx/gtk/win_gtk.h>
53 //-----------------------------------------------------------------------------
54 // documentation on internals
55 //-----------------------------------------------------------------------------
58 I have been asked several times about writing some documentation about
59 the GTK port of wxWindows, especially its internal structures. Obviously,
60 you cannot understand wxGTK without knowing a little about the GTK, but
61 some more information about what the wxWindow, which is the base class
62 for all other window classes, does seems required as well.
66 What does wxWindow do? It contains the common interface for the following
67 jobs of its descendants:
69 1) Define the rudimentary behaviour common to all window classes, such as
70 resizing, intercepting user input (so as to make it possible to use these
71 events for special purposes in a derived class), window names etc.
73 2) Provide the possibility to contain and manage children, if the derived
74 class is allowed to contain children, which holds true for those window
75 classes which do not display a native GTK widget. To name them, these
76 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
77 work classes are a special case and are handled a bit differently from
78 the rest. The same holds true for the wxNotebook class.
80 3) Provide the possibility to draw into a client area of a window. This,
81 too, only holds true for classes that do not display a native GTK widget
84 4) Provide the entire mechanism for scrolling widgets. This actual inter-
85 face for this is usually in wxScrolledWindow, but the GTK implementation
88 5) A multitude of helper or extra methods for special purposes, such as
89 Drag'n'Drop, managing validators etc.
91 6) Display a border (sunken, raised, simple or none).
93 Normally one might expect, that one wxWindows window would always correspond
94 to one GTK widget. Under GTK, there is no such allround widget that has all
95 the functionality. Moreover, the GTK defines a client area as a different
96 widget from the actual widget you are handling. Last but not least some
97 special classes (e.g. wxFrame) handle different categories of widgets and
98 still have the possibility to draw something in the client area.
99 It was therefore required to write a special purpose GTK widget, that would
100 represent a client area in the sense of wxWindows capable to do the jobs
101 2), 3) and 4). I have written this class and it resides in win_gtk.c of
104 All windows must have a widget, with which they interact with other under-
105 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
106 thw wxWindow class has a member variable called m_widget which holds a
107 pointer to this widget. When the window class represents a GTK native widget,
108 this is (in most cases) the only GTK widget the class manages. E.g. the
109 wxStatitText class handles only a GtkLabel widget a pointer to which you
110 can find in m_widget (defined in wxWindow)
112 When the class has a client area for drawing into and for containing children
113 it has to handle the client area widget (of the type GtkPizza, defined in
114 win_gtk.c), but there could be any number of widgets, handled by a class
115 The common rule for all windows is only, that the widget that interacts with
116 the rest of GTK must be referenced in m_widget and all other widgets must be
117 children of this widget on the GTK level. The top-most widget, which also
118 represents the client area, must be in the m_wxwindow field and must be of
121 As I said, the window classes that display a GTK native widget only have
122 one widget, so in the case of e.g. the wxButton class m_widget holds a
123 pointer to a GtkButton widget. But windows with client areas (for drawing
124 and children) have a m_widget field that is a pointer to a GtkScrolled-
125 Window and a m_wxwindow field that is pointer to a GtkPizza and this
126 one is (in the GTK sense) a child of the GtkScrolledWindow.
128 If the m_wxwindow field is set, then all input to this widget is inter-
129 cepted and sent to the wxWindows class. If not, all input to the widget
130 that gets pointed to by m_widget gets intercepted and sent to the class.
134 The design of scrolling in wxWindows is markedly different from that offered
135 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
136 clicking on a scrollbar belonging to scrolled window will inevitably move
137 the window. In wxWindows, the scrollbar will only emit an event, send this
138 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
139 which actually moves the window and its subchildren. Note that GtkPizza
140 memorizes how much it has been scrolled but that wxWindows forgets this
141 so that the two coordinates systems have to be kept in synch. This is done
142 in various places using the pizza->xoffset and pizza->yoffset values.
146 Singularily the most broken code in GTK is the code that is supposes to
147 inform subwindows (child windows) about new positions. Very often, duplicate
148 events are sent without changes in size or position, equally often no
149 events are sent at all (All this is due to a bug in the GtkContainer code
150 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
151 GTK's own system and it simply waits for size events for toplevel windows
152 and then iterates down the respective size events to all window. This has
153 the disadvantage, that windows might get size events before the GTK widget
154 actually has the reported size. This doesn't normally pose any problem, but
155 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
156 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
157 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
158 window that is used for OpenGl output really has that size (as reported by
163 If someone at some point of time feels the immense desire to have a look at,
164 change or attempt to optimse the Refresh() logic, this person will need an
165 intimate understanding of what a "draw" and what an "expose" events are and
166 what there are used for, in particular when used in connection with GTK's
167 own windowless widgets. Beware.
171 Cursors, too, have been a constant source of pleasure. The main difficulty
172 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
173 for the parent. To prevent this from doing too much harm, I use idle time
174 to set the cursor over and over again, starting from the toplevel windows
175 and ending with the youngest generation (speaking of parent and child windows).
176 Also don't forget that cursors (like much else) are connected to GdkWindows,
177 not GtkWidgets and that the "window" field of a GtkWidget might very well
178 point to the GdkWindow of the parent widget (-> "window less widget") and
179 that the two obviously have very different meanings.
183 //-----------------------------------------------------------------------------
185 //-----------------------------------------------------------------------------
187 extern wxList wxPendingDelete
;
188 extern bool g_blockEventsOnDrag
;
189 extern bool g_blockEventsOnScroll
;
190 extern wxCursor g_globalCursor
;
191 static wxWindow
*g_captureWindow
= (wxWindow
*) NULL
;
193 /* extern */ wxWindow
*g_focusWindow
= (wxWindow
*) NULL
;
195 // if we detect that the app has got/lost the focus, we set this variable to
196 // either TRUE or FALSE and an activate event will be sent during the next
197 // OnIdle() call and it is reset to -1: this value means that we shouldn't
198 // send any activate events at all
199 static int g_sendActivateEvent
= -1;
201 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
202 the last click here */
203 static guint32 gs_timeLastClick
= 0;
205 extern bool g_mainThreadLocked
;
207 //-----------------------------------------------------------------------------
209 //-----------------------------------------------------------------------------
213 #define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
215 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
216 GdkEvent
*WXUNUSED(event
),
217 const wxChar
*WXUNUSED(name
) )
220 static bool s_done = FALSE;
223 wxLog::AddTraceMask("focus");
226 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
232 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
234 // suppress warnings about gtk_debug_focus_in_callback being unused with
239 tmp
+= wxT(" FROM ");
242 wxChar
*s
= new wxChar
[tmp
.Length()+1];
246 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
247 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
253 //-----------------------------------------------------------------------------
254 // missing gdk functions
255 //-----------------------------------------------------------------------------
258 gdk_window_warp_pointer (GdkWindow
*window
,
262 GdkWindowPrivate
*priv
;
265 window
= (GdkWindow
*) &gdk_root_parent
;
267 priv
= (GdkWindowPrivate
*) window
;
269 if (!priv
->destroyed
)
271 XWarpPointer (priv
->xdisplay
,
272 None
, /* not source window -> move from anywhere */
273 priv
->xwindow
, /* dest window */
274 0, 0, 0, 0, /* not source window -> move from anywhere */
279 //-----------------------------------------------------------------------------
281 //-----------------------------------------------------------------------------
283 extern void wxapp_install_idle_handler();
284 extern bool g_isIdle
;
286 //-----------------------------------------------------------------------------
287 // local code (see below)
288 //-----------------------------------------------------------------------------
290 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
298 if (win
->HasScrolling())
300 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
301 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget
)->klass
);
304 GtkWidget *hscrollbar = scroll_window->hscrollbar;
305 GtkWidget *vscrollbar = scroll_window->vscrollbar;
307 we use this instead: range.slider_width = 11 + 2*2pts edge
310 if (scroll_window
->vscrollbar_visible
)
312 dw
+= 15; /* dw += vscrollbar->allocation.width; */
313 dw
+= scroll_class
->scrollbar_spacing
;
316 if (scroll_window
->hscrollbar_visible
)
318 dh
+= 15; /* dh += hscrollbar->allocation.height; */
319 dh
+= scroll_class
->scrollbar_spacing
;
325 if (GTK_WIDGET_NO_WINDOW (widget
))
327 dx
+= widget
->allocation
.x
;
328 dy
+= widget
->allocation
.y
;
331 if (win
->HasFlag(wxRAISED_BORDER
))
333 gtk_draw_shadow( widget
->style
,
338 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
342 if (win
->HasFlag(wxSUNKEN_BORDER
))
344 gtk_draw_shadow( widget
->style
,
349 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
353 if (win
->HasFlag(wxSIMPLE_BORDER
))
356 gc
= gdk_gc_new( widget
->window
);
357 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
358 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
360 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
366 //-----------------------------------------------------------------------------
367 // "expose_event" of m_widget
368 //-----------------------------------------------------------------------------
370 static void gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
372 if (gdk_event
->count
> 0) return;
373 draw_frame( widget
, win
);
376 //-----------------------------------------------------------------------------
377 // "draw" of m_widget
378 //-----------------------------------------------------------------------------
380 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
382 draw_frame( widget
, win
);
385 //-----------------------------------------------------------------------------
386 // key code mapping routines
387 //-----------------------------------------------------------------------------
389 static long map_to_unmodified_wx_keysym( KeySym keysym
)
396 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
398 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
404 case GDK_Super_R
: key_code
= WXK_ALT
; break;
405 case GDK_Menu
: key_code
= WXK_MENU
; break;
406 case GDK_Help
: key_code
= WXK_HELP
; break;
407 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
408 case GDK_ISO_Left_Tab
:
409 case GDK_Tab
: key_code
= WXK_TAB
; break;
410 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
411 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
412 case GDK_Return
: key_code
= WXK_RETURN
; break;
413 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
414 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
415 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
416 case GDK_Delete
: key_code
= WXK_DELETE
; break;
417 case GDK_Home
: key_code
= WXK_HOME
; break;
418 case GDK_Left
: key_code
= WXK_LEFT
; break;
419 case GDK_Up
: key_code
= WXK_UP
; break;
420 case GDK_Right
: key_code
= WXK_RIGHT
; break;
421 case GDK_Down
: key_code
= WXK_DOWN
; break;
422 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
423 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
424 case GDK_Next
: key_code
= WXK_NEXT
; break;
425 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
426 case GDK_End
: key_code
= WXK_END
; break;
427 case GDK_Begin
: key_code
= WXK_HOME
; break;
428 case GDK_Select
: key_code
= WXK_SELECT
; break;
429 case GDK_Print
: key_code
= WXK_PRINT
; break;
430 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
431 case GDK_Insert
: key_code
= WXK_INSERT
; break;
432 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
434 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
435 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
436 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
437 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
438 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
439 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
440 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
441 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
442 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
443 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
444 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
445 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
446 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
447 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
448 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
449 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
450 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
451 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
452 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
453 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
454 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
455 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
456 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
457 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
458 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
459 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
460 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
461 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
462 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
463 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
464 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
465 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
466 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
467 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
468 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
469 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
470 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
472 case GDK_F1
: key_code
= WXK_F1
; break;
473 case GDK_F2
: key_code
= WXK_F2
; break;
474 case GDK_F3
: key_code
= WXK_F3
; break;
475 case GDK_F4
: key_code
= WXK_F4
; break;
476 case GDK_F5
: key_code
= WXK_F5
; break;
477 case GDK_F6
: key_code
= WXK_F6
; break;
478 case GDK_F7
: key_code
= WXK_F7
; break;
479 case GDK_F8
: key_code
= WXK_F8
; break;
480 case GDK_F9
: key_code
= WXK_F9
; break;
481 case GDK_F10
: key_code
= WXK_F10
; break;
482 case GDK_F11
: key_code
= WXK_F11
; break;
483 case GDK_F12
: key_code
= WXK_F12
; break;
488 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
489 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
490 key_code
= (guint
)keysym
;
498 static long map_to_wx_keysym( KeySym keysym
)
504 case GDK_Menu
: key_code
= WXK_MENU
; break;
505 case GDK_Help
: key_code
= WXK_HELP
; break;
506 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
507 case GDK_ISO_Left_Tab
:
508 case GDK_Tab
: key_code
= WXK_TAB
; break;
509 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
510 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
511 case GDK_Return
: key_code
= WXK_RETURN
; break;
512 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
513 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
514 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
515 case GDK_Delete
: key_code
= WXK_DELETE
; break;
516 case GDK_Home
: key_code
= WXK_HOME
; break;
517 case GDK_Left
: key_code
= WXK_LEFT
; break;
518 case GDK_Up
: key_code
= WXK_UP
; break;
519 case GDK_Right
: key_code
= WXK_RIGHT
; break;
520 case GDK_Down
: key_code
= WXK_DOWN
; break;
521 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
522 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
523 case GDK_Next
: key_code
= WXK_NEXT
; break;
524 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
525 case GDK_End
: key_code
= WXK_END
; break;
526 case GDK_Begin
: key_code
= WXK_HOME
; break;
527 case GDK_Select
: key_code
= WXK_SELECT
; break;
528 case GDK_Print
: key_code
= WXK_PRINT
; break;
529 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
530 case GDK_Insert
: key_code
= WXK_INSERT
; break;
531 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
533 case GDK_KP_0
: key_code
= '0'; break;
534 case GDK_KP_1
: key_code
= '1'; break;
535 case GDK_KP_2
: key_code
= '2'; break;
536 case GDK_KP_3
: key_code
= '3'; break;
537 case GDK_KP_4
: key_code
= '4'; break;
538 case GDK_KP_5
: key_code
= '5'; break;
539 case GDK_KP_6
: key_code
= '6'; break;
540 case GDK_KP_7
: key_code
= '7'; break;
541 case GDK_KP_8
: key_code
= '8'; break;
542 case GDK_KP_9
: key_code
= '9'; break;
543 case GDK_KP_Space
: key_code
= ' '; break;
544 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
545 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
546 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
547 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
548 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
549 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
550 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
551 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
552 case GDK_KP_Up
: key_code
= WXK_UP
; break;
553 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
554 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
555 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
556 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
557 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
558 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
559 case GDK_KP_End
: key_code
= WXK_END
; break;
560 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
561 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
562 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
563 case GDK_KP_Equal
: key_code
= '='; break;
564 case GDK_KP_Multiply
: key_code
= '*'; break;
565 case GDK_KP_Add
: key_code
= '+'; break;
566 case GDK_KP_Separator
: key_code
= ','; break;
567 case GDK_KP_Subtract
: key_code
= '-'; break;
568 case GDK_KP_Decimal
: key_code
= '.'; break;
569 case GDK_KP_Divide
: key_code
= '/'; break;
571 case GDK_F1
: key_code
= WXK_F1
; break;
572 case GDK_F2
: key_code
= WXK_F2
; break;
573 case GDK_F3
: key_code
= WXK_F3
; break;
574 case GDK_F4
: key_code
= WXK_F4
; break;
575 case GDK_F5
: key_code
= WXK_F5
; break;
576 case GDK_F6
: key_code
= WXK_F6
; break;
577 case GDK_F7
: key_code
= WXK_F7
; break;
578 case GDK_F8
: key_code
= WXK_F8
; break;
579 case GDK_F9
: key_code
= WXK_F9
; break;
580 case GDK_F10
: key_code
= WXK_F10
; break;
581 case GDK_F11
: key_code
= WXK_F11
; break;
582 case GDK_F12
: key_code
= WXK_F12
; break;
587 key_code
= (guint
)keysym
;
595 //-----------------------------------------------------------------------------
596 // "expose_event" of m_wxwindow
597 //-----------------------------------------------------------------------------
599 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
606 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
608 gdk_event
->area
.width
,
609 gdk_event
->area
.height
);
612 wxPrintf( "OnExpose from " );
613 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
614 wxPrintf( win->GetClassInfo()->GetClassName() );
615 wxPrintf( " %d %d %d %d\n", (int)gdk_event->area.x,
616 (int)gdk_event->area.y,
617 (int)gdk_event->area.width,
618 (int)gdk_event->area.height );
621 if (gdk_event
->count
> 0)
624 wxEraseEvent
eevent( win
->GetId() );
625 eevent
.SetEventObject( win
);
626 win
->GetEventHandler()->ProcessEvent(eevent
);
628 wxPaintEvent
event( win
->GetId() );
629 event
.SetEventObject( win
);
630 win
->GetEventHandler()->ProcessEvent( event
);
632 win
->GetUpdateRegion().Clear();
635 //-----------------------------------------------------------------------------
636 // "draw" of m_wxwindow
637 //-----------------------------------------------------------------------------
639 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
),
640 GdkRectangle
*rect
, wxWindow
*win
)
645 wxapp_install_idle_handler();
650 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
,
651 rect
->width
, rect
->height
);
654 wxPrintf( "OnDraw from " );
655 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
656 printf( win->GetClassInfo()->GetClassName() );
657 wxPrintf( " %d %d %d %d\n", (int)rect->x,
663 wxEraseEvent
eevent( win
->GetId() );
664 eevent
.SetEventObject( win
);
665 win
->GetEventHandler()->ProcessEvent(eevent
);
667 wxPaintEvent
event( win
->GetId() );
668 event
.SetEventObject( win
);
669 win
->GetEventHandler()->ProcessEvent( event
);
671 win
->GetUpdateRegion().Clear();
674 //-----------------------------------------------------------------------------
675 // "key_press_event" from any window
676 //-----------------------------------------------------------------------------
678 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
683 wxapp_install_idle_handler();
685 if (!win
->m_hasVMT
) return FALSE
;
686 if (g_blockEventsOnDrag
) return FALSE
;
690 tmp += (char)gdk_event->keyval;
691 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
692 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
697 GdkModifierType state
;
698 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
702 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
703 /* sending unknown key events doesn't really make sense */
704 if (key_code
== 0) return FALSE
;
706 wxKeyEvent
event( wxEVT_KEY_DOWN
);
707 event
.SetTimestamp( gdk_event
->time
);
708 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
709 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
710 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
711 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
712 event
.m_keyCode
= key_code
;
713 event
.m_scanCode
= gdk_event
->keyval
;
716 event
.SetEventObject( win
);
717 ret
= win
->GetEventHandler()->ProcessEvent( event
);
722 wxWindow
*ancestor
= win
;
725 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
728 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
729 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
732 if (ancestor
->m_isFrame
)
734 ancestor
= ancestor
->GetParent();
737 #endif // wxUSE_ACCEL
739 /* wxMSW doesn't send char events with Alt pressed */
740 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
741 will only be sent if it is not in an accelerator table. */
742 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
747 wxKeyEvent
event2( wxEVT_CHAR
);
748 event2
.SetTimestamp( gdk_event
->time
);
749 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
750 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
751 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
752 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
753 event2
.m_keyCode
= key_code
;
754 event2
.m_scanCode
= gdk_event
->keyval
;
757 event2
.SetEventObject( win
);
758 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
761 /* win is a control: tab can be propagated up */
763 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
764 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
765 (win
->GetParent()) &&
766 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
768 wxNavigationKeyEvent new_event
;
769 new_event
.SetEventObject( win
);
770 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
771 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
772 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
773 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
774 new_event
.SetCurrentFocus( win
);
775 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
778 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
780 (gdk_event
->keyval
== GDK_Escape
) )
782 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
783 new_event
.SetEventObject( win
);
784 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
787 #if (GTK_MINOR_VERSION > 0)
788 /* Pressing F10 will activate the menu bar of the top frame. */
792 (gdk_event->keyval == GDK_F10) )
794 wxWindow *ancestor = win;
797 if (wxIsKindOf(ancestor,wxFrame))
799 wxFrame *frame = (wxFrame*) ancestor;
800 wxMenuBar *menubar = frame->GetMenuBar();
803 wxNode *node = menubar->GetMenus().First();
806 wxMenu *firstMenu = (wxMenu*) node->Data();
807 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
813 ancestor = ancestor->GetParent();
821 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
828 //-----------------------------------------------------------------------------
829 // "key_release_event" from any window
830 //-----------------------------------------------------------------------------
832 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
837 wxapp_install_idle_handler();
839 if (!win
->m_hasVMT
) return FALSE
;
840 if (g_blockEventsOnDrag
) return FALSE
;
843 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
844 if (gdk_event->state & GDK_SHIFT_MASK)
845 printf( "ShiftDown.\n" );
847 printf( "ShiftUp.\n" );
848 if (gdk_event->state & GDK_CONTROL_MASK)
849 printf( "ControlDown.\n" );
851 printf( "ControlUp.\n" );
855 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
857 /* sending unknown key events doesn't really make sense */
858 if (key_code
== 0) return FALSE
;
862 GdkModifierType state
;
863 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
865 wxKeyEvent
event( wxEVT_KEY_UP
);
866 event
.SetTimestamp( gdk_event
->time
);
867 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
868 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
869 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
870 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
871 event
.m_keyCode
= key_code
;
872 event
.m_scanCode
= gdk_event
->keyval
;
875 event
.SetEventObject( win
);
877 if (win
->GetEventHandler()->ProcessEvent( event
))
879 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
886 //-----------------------------------------------------------------------------
887 // "button_press_event"
888 //-----------------------------------------------------------------------------
890 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
895 wxapp_install_idle_handler();
898 wxPrintf( wxT("1) OnButtonPress from ") );
899 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
900 wxPrintf( win->GetClassInfo()->GetClassName() );
901 wxPrintf( wxT(".\n") );
903 if (!win
->m_hasVMT
) return FALSE
;
904 if (g_blockEventsOnDrag
) return TRUE
;
905 if (g_blockEventsOnScroll
) return TRUE
;
907 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
911 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
913 gtk_widget_grab_focus (win
->m_wxwindow
);
916 wxPrintf( wxT("GrabFocus from ") );
917 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
918 wxPrintf( win->GetClassInfo()->GetClassName() );
919 wxPrintf( wxT(".\n") );
925 wxEventType event_type
= wxEVT_LEFT_DOWN
;
927 if (gdk_event
->button
== 1)
929 switch (gdk_event
->type
)
931 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
932 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
936 else if (gdk_event
->button
== 2)
938 switch (gdk_event
->type
)
940 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
941 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
945 else if (gdk_event
->button
== 3)
947 switch (gdk_event
->type
)
949 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
950 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
955 wxMouseEvent
event( event_type
);
956 event
.SetTimestamp( gdk_event
->time
);
957 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
958 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
959 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
960 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
961 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
962 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
963 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
965 event
.m_x
= (wxCoord
)gdk_event
->x
;
966 event
.m_y
= (wxCoord
)gdk_event
->y
;
968 // Some control don't have their own X window and thus cannot get
971 if (!g_captureWindow
)
973 wxCoord x
= event
.m_x
;
974 wxCoord y
= event
.m_y
;
977 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
982 wxNode
*node
= win
->GetChildren().First();
985 wxWindow
*child
= (wxWindow
*)node
->Data();
988 if (!child
->IsShown())
991 if (child
->m_isStaticBox
)
993 // wxStaticBox is transparent in the box itself
994 int xx1
= child
->m_x
;
995 int yy1
= child
->m_y
;
996 int xx2
= child
->m_x
+ child
->m_width
;
997 int yy2
= child
->m_x
+ child
->m_height
;
1000 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1002 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1004 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1006 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1009 event
.m_x
-= child
->m_x
;
1010 event
.m_y
-= child
->m_y
;
1017 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1018 (child
->m_x
<= x
) &&
1019 (child
->m_y
<= y
) &&
1020 (child
->m_x
+child
->m_width
>= x
) &&
1021 (child
->m_y
+child
->m_height
>= y
))
1024 event
.m_x
-= child
->m_x
;
1025 event
.m_y
-= child
->m_y
;
1032 event
.SetEventObject( win
);
1034 gs_timeLastClick
= gdk_event
->time
;
1037 wxPrintf( wxT("2) OnButtonPress from ") );
1038 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1039 wxPrintf( win->GetClassInfo()->GetClassName() );
1040 wxPrintf( wxT(".\n") );
1043 if (win
->GetEventHandler()->ProcessEvent( event
))
1045 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1052 //-----------------------------------------------------------------------------
1053 // "button_release_event"
1054 //-----------------------------------------------------------------------------
1056 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1061 wxapp_install_idle_handler();
1063 if (!win
->m_hasVMT
) return FALSE
;
1064 if (g_blockEventsOnDrag
) return FALSE
;
1065 if (g_blockEventsOnScroll
) return FALSE
;
1067 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1070 printf( "OnButtonRelease from " );
1071 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1072 printf( win->GetClassInfo()->GetClassName() );
1076 wxEventType event_type
= wxEVT_NULL
;
1078 switch (gdk_event
->button
)
1080 case 1: event_type
= wxEVT_LEFT_UP
; break;
1081 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1082 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1085 wxMouseEvent
event( event_type
);
1086 event
.SetTimestamp( gdk_event
->time
);
1087 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1088 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1089 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1090 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1091 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1092 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1093 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1094 event
.m_x
= (wxCoord
)gdk_event
->x
;
1095 event
.m_y
= (wxCoord
)gdk_event
->y
;
1097 // Some control don't have their own X window and thus cannot get
1100 if (!g_captureWindow
)
1102 wxCoord x
= event
.m_x
;
1103 wxCoord y
= event
.m_y
;
1104 if (win
->m_wxwindow
)
1106 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1107 x
+= pizza
->xoffset
;
1108 y
+= pizza
->yoffset
;
1111 wxNode
*node
= win
->GetChildren().First();
1114 wxWindow
*child
= (wxWindow
*)node
->Data();
1116 node
= node
->Next();
1117 if (!child
->IsShown())
1120 if (child
->m_isStaticBox
)
1122 // wxStaticBox is transparent in the box itself
1123 int xx1
= child
->m_x
;
1124 int yy1
= child
->m_y
;
1125 int xx2
= child
->m_x
+ child
->m_width
;
1126 int yy2
= child
->m_x
+ child
->m_height
;
1129 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1131 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1133 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1135 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1138 event
.m_x
-= child
->m_x
;
1139 event
.m_y
-= child
->m_y
;
1146 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1147 (child
->m_x
<= x
) &&
1148 (child
->m_y
<= y
) &&
1149 (child
->m_x
+child
->m_width
>= x
) &&
1150 (child
->m_y
+child
->m_height
>= y
))
1153 event
.m_x
-= child
->m_x
;
1154 event
.m_y
-= child
->m_y
;
1161 event
.SetEventObject( win
);
1163 if (win
->GetEventHandler()->ProcessEvent( event
))
1165 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1172 //-----------------------------------------------------------------------------
1173 // "motion_notify_event"
1174 //-----------------------------------------------------------------------------
1176 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1181 wxapp_install_idle_handler();
1183 if (!win
->m_hasVMT
) return FALSE
;
1184 if (g_blockEventsOnDrag
) return FALSE
;
1185 if (g_blockEventsOnScroll
) return FALSE
;
1187 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1189 if (gdk_event
->is_hint
)
1193 GdkModifierType state
;
1194 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1200 printf( "OnMotion from " );
1201 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1202 printf( win->GetClassInfo()->GetClassName() );
1206 wxMouseEvent
event( wxEVT_MOTION
);
1207 event
.SetTimestamp( gdk_event
->time
);
1208 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1209 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1210 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1211 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1212 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1213 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1214 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1216 event
.m_x
= (wxCoord
)gdk_event
->x
;
1217 event
.m_y
= (wxCoord
)gdk_event
->y
;
1219 // Some control don't have their own X window and thus cannot get
1222 if (!g_captureWindow
)
1224 wxCoord x
= event
.m_x
;
1225 wxCoord y
= event
.m_y
;
1226 if (win
->m_wxwindow
)
1228 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1229 x
+= pizza
->xoffset
;
1230 y
+= pizza
->yoffset
;
1233 wxNode
*node
= win
->GetChildren().First();
1236 wxWindow
*child
= (wxWindow
*)node
->Data();
1238 node
= node
->Next();
1239 if (!child
->IsShown())
1242 if (child
->m_isStaticBox
)
1244 // wxStaticBox is transparent in the box itself
1245 int xx1
= child
->m_x
;
1246 int yy1
= child
->m_y
;
1247 int xx2
= child
->m_x
+ child
->m_width
;
1248 int yy2
= child
->m_x
+ child
->m_height
;
1251 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1253 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1255 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1257 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1260 event
.m_x
-= child
->m_x
;
1261 event
.m_y
-= child
->m_y
;
1268 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1269 (child
->m_x
<= x
) &&
1270 (child
->m_y
<= y
) &&
1271 (child
->m_x
+child
->m_width
>= x
) &&
1272 (child
->m_y
+child
->m_height
>= y
))
1275 event
.m_x
-= child
->m_x
;
1276 event
.m_y
-= child
->m_y
;
1283 event
.SetEventObject( win
);
1285 if (win
->GetEventHandler()->ProcessEvent( event
))
1287 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1294 //-----------------------------------------------------------------------------
1296 //-----------------------------------------------------------------------------
1298 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1303 wxapp_install_idle_handler();
1305 if (!win
->m_hasVMT
) return FALSE
;
1306 if (g_blockEventsOnDrag
) return FALSE
;
1308 switch ( g_sendActivateEvent
)
1311 // we've got focus from outside, synthtize wxActivateEvent
1312 g_sendActivateEvent
= 1;
1316 // another our window just lost focus, it was already ours before
1317 // - don't send any wxActivateEvent
1318 g_sendActivateEvent
= -1;
1322 g_focusWindow
= win
;
1325 printf( "OnSetFocus from " );
1326 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1327 printf( win->GetClassInfo()->GetClassName() );
1329 printf( WXSTRINGCAST win->GetLabel() );
1333 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1336 panel
->SetLastFocus(win
);
1341 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1344 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1345 event
.SetEventObject( win
);
1347 if (win
->GetEventHandler()->ProcessEvent( event
))
1349 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1356 //-----------------------------------------------------------------------------
1357 // "focus_out_event"
1358 //-----------------------------------------------------------------------------
1360 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1365 wxapp_install_idle_handler();
1367 if (!win
->m_hasVMT
) return FALSE
;
1368 if (g_blockEventsOnDrag
) return FALSE
;
1370 // if the focus goes out of our app alltogether, OnIdle() will send
1371 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1372 // g_sendActivateEvent to -1
1373 g_sendActivateEvent
= 0;
1375 g_focusWindow
= (wxWindow
*)NULL
;
1378 printf( "OnKillFocus from " );
1379 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1380 printf( win->GetClassInfo()->GetClassName() );
1389 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1390 event
.SetEventObject( win
);
1392 if (win
->GetEventHandler()->ProcessEvent( event
))
1394 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1401 //-----------------------------------------------------------------------------
1402 // "enter_notify_event"
1403 //-----------------------------------------------------------------------------
1405 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1410 wxapp_install_idle_handler();
1412 if (!win
->m_hasVMT
) return FALSE
;
1413 if (g_blockEventsOnDrag
) return FALSE
;
1415 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1417 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1418 #if (GTK_MINOR_VERSION > 0)
1419 event
.SetTimestamp( gdk_event
->time
);
1421 event
.SetEventObject( win
);
1425 GdkModifierType state
= (GdkModifierType
)0;
1427 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1429 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1430 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1431 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1432 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1433 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1434 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1435 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1440 if (win
->GetEventHandler()->ProcessEvent( event
))
1442 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1449 //-----------------------------------------------------------------------------
1450 // "leave_notify_event"
1451 //-----------------------------------------------------------------------------
1453 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1458 wxapp_install_idle_handler();
1460 if (!win
->m_hasVMT
) return FALSE
;
1461 if (g_blockEventsOnDrag
) return FALSE
;
1463 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1465 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1466 #if (GTK_MINOR_VERSION > 0)
1467 event
.SetTimestamp( gdk_event
->time
);
1469 event
.SetEventObject( win
);
1473 GdkModifierType state
= (GdkModifierType
)0;
1475 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1477 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1478 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1479 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1480 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1481 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1482 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1483 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1488 if (win
->GetEventHandler()->ProcessEvent( event
))
1490 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1497 //-----------------------------------------------------------------------------
1498 // "value_changed" from m_vAdjust
1499 //-----------------------------------------------------------------------------
1501 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1506 wxapp_install_idle_handler();
1508 if (g_blockEventsOnDrag
) return;
1510 if (!win
->m_hasVMT
) return;
1512 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1513 if (fabs(diff
) < 0.2) return;
1515 win
->m_oldVerticalPos
= adjust
->value
;
1517 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1518 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1520 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1521 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1522 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1523 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1524 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1526 int value
= (int)(adjust
->value
+0.5);
1528 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1529 event
.SetEventObject( win
);
1530 win
->GetEventHandler()->ProcessEvent( event
);
1533 //-----------------------------------------------------------------------------
1534 // "value_changed" from m_hAdjust
1535 //-----------------------------------------------------------------------------
1537 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1542 wxapp_install_idle_handler();
1544 if (g_blockEventsOnDrag
) return;
1545 if (!win
->m_hasVMT
) return;
1547 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1548 if (fabs(diff
) < 0.2) return;
1550 win
->m_oldHorizontalPos
= adjust
->value
;
1552 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1553 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1555 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1556 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1557 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1558 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1559 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1561 int value
= (int)(adjust
->value
+0.5);
1563 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1564 event
.SetEventObject( win
);
1565 win
->GetEventHandler()->ProcessEvent( event
);
1568 //-----------------------------------------------------------------------------
1569 // "changed" from m_vAdjust
1570 //-----------------------------------------------------------------------------
1572 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1577 wxapp_install_idle_handler();
1579 if (g_blockEventsOnDrag
) return;
1580 if (!win
->m_hasVMT
) return;
1582 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1583 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1585 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1586 event
.SetEventObject( win
);
1587 win
->GetEventHandler()->ProcessEvent( event
);
1590 //-----------------------------------------------------------------------------
1591 // "changed" from m_hAdjust
1592 //-----------------------------------------------------------------------------
1594 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1599 wxapp_install_idle_handler();
1601 if (g_blockEventsOnDrag
) return;
1602 if (!win
->m_hasVMT
) return;
1604 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1605 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1607 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1608 event
.SetEventObject( win
);
1609 win
->GetEventHandler()->ProcessEvent( event
);
1612 //-----------------------------------------------------------------------------
1613 // "button_press_event" from scrollbar
1614 //-----------------------------------------------------------------------------
1616 static gint
gtk_scrollbar_button_press_callback( GtkRange
*WXUNUSED(widget
),
1617 GdkEventButton
*WXUNUSED(gdk_event
),
1623 wxapp_install_idle_handler();
1625 // don't test here as we can release the mouse while being over
1626 // a different window than the slider
1628 // if (gdk_event->window != widget->slider) return FALSE;
1630 win
->SetScrolling( TRUE
);
1635 //-----------------------------------------------------------------------------
1636 // "button_release_event" from scrollbar
1637 //-----------------------------------------------------------------------------
1639 static gint
gtk_scrollbar_button_release_callback( GtkRange
*WXUNUSED(widget
),
1640 GdkEventButton
*WXUNUSED(gdk_event
),
1646 // don't test here as we can release the mouse while being over
1647 // a different window than the slider
1649 // if (gdk_event->window != widget->slider) return FALSE;
1651 win
->SetScrolling( FALSE
);
1656 // ----------------------------------------------------------------------------
1657 // this wxWindowBase function is implemented here (in platform-specific file)
1658 // because it is static and so couldn't be made virtual
1659 // ----------------------------------------------------------------------------
1661 wxWindow
*wxWindowBase::FindFocus()
1663 return g_focusWindow
;
1666 //-----------------------------------------------------------------------------
1667 // "realize" from m_widget
1668 //-----------------------------------------------------------------------------
1670 /* We cannot set colours and fonts before the widget has
1671 been realized, so we do this directly after realization. */
1674 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1679 wxapp_install_idle_handler();
1681 if (win
->m_delayedBackgroundColour
)
1682 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1684 if (win
->m_delayedForegroundColour
)
1685 win
->SetForegroundColour( win
->GetForegroundColour() );
1687 wxWindowCreateEvent
event( win
);
1688 event
.SetEventObject( win
);
1689 win
->GetEventHandler()->ProcessEvent( event
);
1694 //-----------------------------------------------------------------------------
1696 //-----------------------------------------------------------------------------
1699 #define WXUNUSED_UNLESS_XIM(param) param
1701 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1704 /* Resize XIM window */
1707 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1708 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1709 wxFrame
* WXUNUSED_UNLESS_XIM(win
) )
1712 wxapp_install_idle_handler();
1718 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1722 gdk_window_get_size (widget
->window
, &width
, &height
);
1723 win
->m_icattr
->preedit_area
.width
= width
;
1724 win
->m_icattr
->preedit_area
.height
= height
;
1725 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
1730 //-----------------------------------------------------------------------------
1731 // "realize" from m_wxwindow
1732 //-----------------------------------------------------------------------------
1734 /* Initialize XIM support */
1737 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1738 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1741 wxapp_install_idle_handler();
1744 if (win
->m_ic
) return FALSE
;
1745 if (!widget
) return FALSE
;
1746 if (!gdk_im_ready()) return FALSE
;
1748 win
->m_icattr
= gdk_ic_attr_new();
1749 if (!win
->m_icattr
) return FALSE
;
1753 GdkColormap
*colormap
;
1754 GdkICAttr
*attr
= win
->m_icattr
;
1755 unsigned attrmask
= GDK_IC_ALL_REQ
;
1757 GdkIMStyle supported_style
= (GdkIMStyle
)
1758 (GDK_IM_PREEDIT_NONE
|
1759 GDK_IM_PREEDIT_NOTHING
|
1760 GDK_IM_PREEDIT_POSITION
|
1761 GDK_IM_STATUS_NONE
|
1762 GDK_IM_STATUS_NOTHING
);
1764 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1765 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
1767 attr
->style
= style
= gdk_im_decide_style (supported_style
);
1768 attr
->client_window
= widget
->window
;
1770 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
1771 gtk_widget_get_default_colormap ())
1773 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
1774 attr
->preedit_colormap
= colormap
;
1777 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
1778 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
1779 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
1780 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
1782 switch (style
& GDK_IM_PREEDIT_MASK
)
1784 case GDK_IM_PREEDIT_POSITION
:
1785 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1787 g_warning ("over-the-spot style requires fontset");
1791 gdk_window_get_size (widget
->window
, &width
, &height
);
1793 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
1794 attr
->spot_location
.x
= 0;
1795 attr
->spot_location
.y
= height
;
1796 attr
->preedit_area
.x
= 0;
1797 attr
->preedit_area
.y
= 0;
1798 attr
->preedit_area
.width
= width
;
1799 attr
->preedit_area
.height
= height
;
1800 attr
->preedit_fontset
= widget
->style
->font
;
1805 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
1807 if (win
->m_ic
== NULL
)
1808 g_warning ("Can't create input context.");
1811 mask
= gdk_window_get_events (widget
->window
);
1812 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
1813 gdk_window_set_events (widget
->window
, mask
);
1815 if (GTK_WIDGET_HAS_FOCUS(widget
))
1816 gdk_im_begin (win
->m_ic
, widget
->window
);
1823 //-----------------------------------------------------------------------------
1824 // InsertChild for wxWindow.
1825 //-----------------------------------------------------------------------------
1827 /* Callback for wxWindow. This very strange beast has to be used because
1828 * C++ has no virtual methods in a constructor. We have to emulate a
1829 * virtual function here as wxNotebook requires a different way to insert
1830 * a child in it. I had opted for creating a wxNotebookPage window class
1831 * which would have made this superfluous (such in the MDI window system),
1832 * but no-one was listening to me... */
1834 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1836 /* the window might have been scrolled already, do we
1837 have to adapt the position */
1838 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
1839 child
->m_x
+= pizza
->xoffset
;
1840 child
->m_y
+= pizza
->yoffset
;
1842 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
1843 GTK_WIDGET(child
->m_widget
),
1850 //-----------------------------------------------------------------------------
1852 //-----------------------------------------------------------------------------
1854 wxWindow
* wxGetActiveWindow()
1856 return g_focusWindow
;
1859 //-----------------------------------------------------------------------------
1861 //-----------------------------------------------------------------------------
1863 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
1865 void wxWindow::Init()
1871 m_widget
= (GtkWidget
*) NULL
;
1872 m_wxwindow
= (GtkWidget
*) NULL
;
1882 m_needParent
= TRUE
;
1883 m_isBeingDeleted
= FALSE
;
1886 m_nativeSizeEvent
= FALSE
;
1888 m_hasScrolling
= FALSE
;
1889 m_isScrolling
= FALSE
;
1891 m_hAdjust
= (GtkAdjustment
*) NULL
;
1892 m_vAdjust
= (GtkAdjustment
*) NULL
;
1893 m_oldHorizontalPos
= 0.0;
1894 m_oldVerticalPos
= 0.0;
1897 m_widgetStyle
= (GtkStyle
*) NULL
;
1899 m_insertCallback
= (wxInsertChildFunction
) NULL
;
1901 m_isStaticBox
= FALSE
;
1902 m_isRadioButton
= FALSE
;
1904 m_acceptsFocus
= FALSE
;
1906 m_cursor
= *wxSTANDARD_CURSOR
;
1909 m_ic
= (GdkIC
*) NULL
;
1910 m_icattr
= (GdkICAttr
*) NULL
;
1914 wxWindow::wxWindow()
1919 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1920 const wxPoint
&pos
, const wxSize
&size
,
1921 long style
, const wxString
&name
)
1925 Create( parent
, id
, pos
, size
, style
, name
);
1928 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1929 const wxPoint
&pos
, const wxSize
&size
,
1930 long style
, const wxString
&name
)
1932 if (!PreCreation( parent
, pos
, size
) ||
1933 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
1935 wxFAIL_MSG( wxT("wxWindow creation failed") );
1939 m_insertCallback
= wxInsertChildInWindow
;
1941 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
1942 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1945 debug_focus_in( m_widget
, wxT("wxWindow::m_widget"), name
);
1948 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
1951 debug_focus_in( scrolledWindow
->hscrollbar
, wxT("wxWindow::hsrcollbar"), name
);
1952 debug_focus_in( scrolledWindow
->vscrollbar
, wxT("wxWindow::vsrcollbar"), name
);
1955 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1956 scroll_class
->scrollbar_spacing
= 0;
1958 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1960 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
1961 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
1963 m_wxwindow
= gtk_pizza_new();
1966 debug_focus_in( m_wxwindow
, wxT("wxWindow::m_wxwindow"), name
);
1969 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
1971 #if (GTK_MINOR_VERSION > 0)
1972 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
1974 if (HasFlag(wxRAISED_BORDER
))
1976 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
1978 else if (HasFlag(wxSUNKEN_BORDER
))
1980 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
1982 else if (HasFlag(wxSIMPLE_BORDER
))
1984 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
1988 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
1990 #else // GTK_MINOR_VERSION == 0
1991 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
1993 if (HasFlag(wxRAISED_BORDER
))
1995 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
1997 else if (HasFlag(wxSUNKEN_BORDER
))
1999 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2003 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2005 #endif // GTK_MINOR_VERSION
2007 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2008 m_acceptsFocus
= TRUE
;
2010 #if (GTK_MINOR_VERSION == 0)
2011 // shut the viewport up
2012 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2013 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2014 #endif // GTK_MINOR_VERSION == 0
2016 // I _really_ don't want scrollbars in the beginning
2017 m_vAdjust
->lower
= 0.0;
2018 m_vAdjust
->upper
= 1.0;
2019 m_vAdjust
->value
= 0.0;
2020 m_vAdjust
->step_increment
= 1.0;
2021 m_vAdjust
->page_increment
= 1.0;
2022 m_vAdjust
->page_size
= 5.0;
2023 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2024 m_hAdjust
->lower
= 0.0;
2025 m_hAdjust
->upper
= 1.0;
2026 m_hAdjust
->value
= 0.0;
2027 m_hAdjust
->step_increment
= 1.0;
2028 m_hAdjust
->page_increment
= 1.0;
2029 m_hAdjust
->page_size
= 5.0;
2030 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2032 // these handlers block mouse events to any window during scrolling such as
2033 // motion events and prevent GTK and wxWindows from fighting over where the
2036 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2037 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2039 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2040 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2042 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2043 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2045 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2046 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2048 // these handlers get notified when screen updates are required either when
2049 // scrolling or when the window size (and therefore scrollbar configuration)
2052 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2053 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2054 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2055 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2057 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
2058 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
2059 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
2060 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
2062 gtk_widget_show( m_wxwindow
);
2065 m_parent
->DoAddChild( this );
2074 wxWindow::~wxWindow()
2076 m_isBeingDeleted
= TRUE
;
2085 m_parent
->RemoveChild( this );
2089 gdk_ic_destroy (m_ic
);
2091 gdk_ic_attr_destroy (m_icattr
);
2096 gtk_style_unref( m_widgetStyle
);
2097 m_widgetStyle
= (GtkStyle
*) NULL
;
2102 gtk_widget_destroy( m_wxwindow
);
2103 m_wxwindow
= (GtkWidget
*) NULL
;
2108 gtk_widget_destroy( m_widget
);
2109 m_widget
= (GtkWidget
*) NULL
;
2113 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2115 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2117 /* this turns -1 into 20 so that a minimal window is
2118 visible even although -1,-1 has been given as the
2119 size of the window. the same trick is used in other
2120 ports and should make debugging easier */
2121 m_width
= WidthDefault(size
.x
);
2122 m_height
= HeightDefault(size
.y
);
2127 /* some reasonable defaults */
2132 m_x
= (gdk_screen_width () - m_width
) / 2;
2133 if (m_x
< 10) m_x
= 10;
2137 m_y
= (gdk_screen_height () - m_height
) / 2;
2138 if (m_y
< 10) m_y
= 10;
2145 void wxWindow::PostCreation()
2147 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2153 /* these get reported to wxWindows -> wxPaintEvent */
2154 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2155 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2157 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2158 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2161 #if (GTK_MINOR_VERSION > 0)
2162 /* these are called when the "sunken" or "raised" borders are drawn */
2163 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2164 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2166 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2167 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2171 if (m_wxwindow
&& m_needParent
)
2173 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2174 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2176 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2177 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2181 // For dialogs and frames, we are interested mainly in
2182 // m_widget's focus.
2184 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2185 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2187 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2188 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2191 GtkWidget
*connect_widget
= GetConnectWidget();
2193 ConnectWidget( connect_widget
);
2195 /* We cannot set colours, fonts and cursors before the widget has
2196 been realized, so we do this directly after realization */
2197 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2198 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2202 /* Initialize XIM support. */
2203 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2204 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2206 /* And resize XIM window. */
2207 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2208 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2214 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2216 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2217 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2219 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2220 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2222 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2223 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2225 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2226 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2228 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2229 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2231 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2232 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2234 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2235 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2238 bool wxWindow::Destroy()
2240 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2244 return wxWindowBase::Destroy();
2247 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2249 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2252 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2254 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2255 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2257 if (m_resizing
) return; /* I don't like recursions */
2260 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2262 /* don't set the size for children of wxNotebook, just take the values. */
2270 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2272 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2274 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2275 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2276 if (width
!= -1) m_width
= width
;
2277 if (height
!= -1) m_height
= height
;
2281 m_x
= x
+ pizza
->xoffset
;
2282 m_y
= y
+ pizza
->yoffset
;
2287 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2289 if (width
== -1) m_width
= 80;
2292 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2294 if (height
== -1) m_height
= 26;
2297 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2298 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2299 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2300 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2303 int bottom_border
= 0;
2305 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2307 /* the default button has a border around it */
2312 DoMoveWindow( m_x
-border
,
2315 m_height
+border
+bottom_border
);
2319 wxPrintf( "OnSize sent from " );
2320 if (GetClassInfo() && GetClassInfo()->GetClassName())
2321 wxPrintf( GetClassInfo()->GetClassName() );
2322 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2325 if (!m_nativeSizeEvent
)
2327 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2328 event
.SetEventObject( this );
2329 GetEventHandler()->ProcessEvent( event
);
2335 void wxWindow::OnInternalIdle()
2337 if ( g_sendActivateEvent
!= -1 )
2339 bool activate
= g_sendActivateEvent
!= 0;
2342 g_sendActivateEvent
= -1;
2344 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2345 event
.SetEventObject(this);
2347 (void)GetEventHandler()->ProcessEvent(event
);
2350 wxCursor cursor
= m_cursor
;
2351 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2355 /* I now set the cursor anew in every OnInternalIdle call
2356 as setting the cursor in a parent window also effects the
2357 windows above so that checking for the current cursor is
2362 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2364 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2366 if (!g_globalCursor
.Ok())
2367 cursor
= *wxSTANDARD_CURSOR
;
2369 window
= m_widget
->window
;
2370 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2371 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2377 GdkWindow
*window
= m_widget
->window
;
2378 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2379 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2387 void wxWindow::DoGetSize( int *width
, int *height
) const
2389 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2391 if (width
) (*width
) = m_width
;
2392 if (height
) (*height
) = m_height
;
2395 void wxWindow::DoSetClientSize( int width
, int height
)
2397 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2401 SetSize( width
, height
);
2408 #if (GTK_MINOR_VERSION == 0)
2409 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2413 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2414 #if 0 // unused - if this is ok, just remove this line (VZ)
2415 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2418 GtkWidget
*viewport
= scroll_window
->viewport
;
2419 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2421 dw
+= 2 * viewport_class
->xthickness
;
2422 dh
+= 2 * viewport_class
->ythickness
;
2426 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2428 /* when using GTK 1.2 we set the shadow border size to 2 */
2432 if (HasFlag(wxSIMPLE_BORDER
))
2434 /* when using GTK 1.2 we set the simple border size to 1 */
2443 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2444 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2446 we use this instead: range.slider_width = 11 + 2*2pts edge
2449 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2450 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2452 if (scroll_window
->vscrollbar_visible
)
2454 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2455 dw
+= scroll_class
->scrollbar_spacing
;
2458 if (scroll_window
->hscrollbar_visible
)
2460 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2461 dh
+= scroll_class
->scrollbar_spacing
;
2465 SetSize( width
+dw
, height
+dh
);
2469 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2471 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2475 if (width
) (*width
) = m_width
;
2476 if (height
) (*height
) = m_height
;
2483 #if (GTK_MINOR_VERSION == 0)
2484 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2488 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2489 #if 0 // unused - if this is ok, just remove this line (VZ)
2490 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2493 GtkWidget
*viewport
= scroll_window
->viewport
;
2494 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2496 dw
+= 2 * viewport_class
->xthickness
;
2497 dh
+= 2 * viewport_class
->ythickness
;
2501 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2503 /* when using GTK 1.2 we set the shadow border size to 2 */
2507 if (HasFlag(wxSIMPLE_BORDER
))
2509 /* when using GTK 1.2 we set the simple border size to 1 */
2517 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2518 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2520 we use this instead: range.slider_width = 11 + 2*2pts edge
2523 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2524 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2526 if (scroll_window
->vscrollbar_visible
)
2528 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2529 dw
+= scroll_class
->scrollbar_spacing
;
2532 if (scroll_window
->hscrollbar_visible
)
2534 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2535 dh
+= scroll_class
->scrollbar_spacing
;
2539 if (width
) (*width
) = m_width
- dw
;
2540 if (height
) (*height
) = m_height
- dh
;
2544 void wxWindow::DoGetPosition( int *x
, int *y
) const
2546 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2550 if (m_parent
&& m_parent
->m_wxwindow
)
2552 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2553 dx
= pizza
->xoffset
;
2554 dy
= pizza
->yoffset
;
2557 if (x
) (*x
) = m_x
- dx
;
2558 if (y
) (*y
) = m_y
- dy
;
2561 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2563 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2565 if (!m_widget
->window
) return;
2567 GdkWindow
*source
= (GdkWindow
*) NULL
;
2569 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2571 source
= m_widget
->window
;
2575 gdk_window_get_origin( source
, &org_x
, &org_y
);
2579 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2581 org_x
+= m_widget
->allocation
.x
;
2582 org_y
+= m_widget
->allocation
.y
;
2590 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2592 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2594 if (!m_widget
->window
) return;
2596 GdkWindow
*source
= (GdkWindow
*) NULL
;
2598 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2600 source
= m_widget
->window
;
2604 gdk_window_get_origin( source
, &org_x
, &org_y
);
2608 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2610 org_x
+= m_widget
->allocation
.x
;
2611 org_y
+= m_widget
->allocation
.y
;
2619 bool wxWindow::Show( bool show
)
2621 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2623 if (!wxWindowBase::Show(show
))
2630 gtk_widget_show( m_widget
);
2632 gtk_widget_hide( m_widget
);
2637 bool wxWindow::Enable( bool enable
)
2639 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2641 if (!wxWindowBase::Enable(enable
))
2647 gtk_widget_set_sensitive( m_widget
, enable
);
2649 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2654 int wxWindow::GetCharHeight() const
2656 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2658 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2660 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2662 return font
->ascent
+ font
->descent
;
2665 int wxWindow::GetCharWidth() const
2667 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2669 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2671 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2673 return gdk_string_width( font
, "H" );
2676 void wxWindow::GetTextExtent( const wxString
& string
,
2680 int *externalLeading
,
2681 const wxFont
*theFont
) const
2683 wxFont fontToUse
= m_font
;
2684 if (theFont
) fontToUse
= *theFont
;
2686 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2688 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2689 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2690 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2691 if (descent
) (*descent
) = font
->descent
;
2692 if (externalLeading
) (*externalLeading
) = 0; // ??
2695 void wxWindow::SetFocus()
2697 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2701 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2702 gtk_widget_grab_focus (m_wxwindow
);
2708 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2710 gtk_widget_grab_focus (m_widget
);
2712 else if (GTK_IS_CONTAINER(m_widget
))
2714 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2723 bool wxWindow::AcceptsFocus() const
2725 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2728 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2730 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2732 wxWindow
*oldParent
= m_parent
,
2733 *newParent
= (wxWindow
*)newParentBase
;
2735 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2737 if ( !wxWindowBase::Reparent(newParent
) )
2740 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2742 /* prevent GTK from deleting the widget arbitrarily */
2743 gtk_widget_ref( m_widget
);
2747 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2750 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2754 /* insert GTK representation */
2755 (*(newParent
->m_insertCallback
))(newParent
, this);
2758 /* reverse: prevent GTK from deleting the widget arbitrarily */
2759 gtk_widget_unref( m_widget
);
2764 void wxWindow::DoAddChild(wxWindow
*child
)
2766 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2768 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
2770 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
2775 /* insert GTK representation */
2776 (*m_insertCallback
)(this, child
);
2779 void wxWindow::Raise()
2781 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2783 if (!m_widget
->window
) return;
2785 gdk_window_raise( m_widget
->window
);
2788 void wxWindow::Lower()
2790 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2792 if (!m_widget
->window
) return;
2794 gdk_window_lower( m_widget
->window
);
2797 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2799 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2801 return wxWindowBase::SetCursor( cursor
);
2804 void wxWindow::WarpPointer( int x
, int y
)
2806 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2808 /* we provide this function ourselves as it is
2809 missing in GDK (top of this file) */
2811 GdkWindow
*window
= (GdkWindow
*) NULL
;
2813 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2815 window
= GetConnectWidget()->window
;
2818 gdk_window_warp_pointer( window
, x
, y
);
2821 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2823 if (!m_widget
) return;
2824 if (!m_widget
->window
) return;
2826 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2830 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
2832 rect
->width
, rect
->height
);
2836 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
2840 /* there is no GTK equivalent of "draw only, don't clear" so we
2841 invent our own in the GtkPizza widget */
2847 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2848 gboolean old_clear
= pizza
->clear_on_draw
;
2849 gtk_pizza_set_clear( pizza
, FALSE
);
2851 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2853 gtk_pizza_set_clear( pizza
, old_clear
);
2856 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2860 GdkRectangle gdk_rect
;
2861 gdk_rect
.x
= rect
->x
;
2862 gdk_rect
.y
= rect
->y
;
2863 gdk_rect
.width
= rect
->width
;
2864 gdk_rect
.height
= rect
->height
;
2868 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2869 gboolean old_clear
= pizza
->clear_on_draw
;
2870 gtk_pizza_set_clear( pizza
, FALSE
);
2872 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2874 gtk_pizza_set_clear( pizza
, old_clear
);
2877 gtk_widget_draw( m_widget
, &gdk_rect
);
2881 void wxWindow::Clear()
2883 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
2885 if (!m_widget
->window
) return;
2887 if (m_wxwindow
&& m_wxwindow
->window
)
2889 gdk_window_clear( m_wxwindow
->window
);
2894 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2896 wxWindowBase::DoSetToolTip(tip
);
2899 m_tooltip
->Apply( this );
2902 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2904 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
2906 #endif // wxUSE_TOOLTIPS
2908 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2910 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2912 if (!wxWindowBase::SetBackgroundColour(colour
))
2914 // don't leave if the GTK widget has just
2916 if (!m_delayedBackgroundColour
) return FALSE
;
2919 GdkWindow
*window
= (GdkWindow
*) NULL
;
2921 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2923 window
= GetConnectWidget()->window
;
2927 // indicate that a new style has been set
2928 // but it couldn't get applied as the
2929 // widget hasn't been realized yet.
2930 m_delayedBackgroundColour
= TRUE
;
2932 // pretend we have done something
2937 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
2939 /* wxMSW doesn't clear the window here. I don't do that either to
2940 provide compatibility. call Clear() to do the job. */
2942 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
2943 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
2951 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
2953 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2955 if (!wxWindowBase::SetForegroundColour(colour
))
2957 // don't leave if the GTK widget has just
2959 if (!m_delayedForegroundColour
) return FALSE
;
2962 GdkWindow
*window
= (GdkWindow
*) NULL
;
2964 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2966 window
= GetConnectWidget()->window
;
2970 // indicate that a new style has been set
2971 // but it couldn't get applied as the
2972 // widget hasn't been realized yet.
2973 m_delayedForegroundColour
= TRUE
;
2975 // pretend we have done something
2984 GtkStyle
*wxWindow::GetWidgetStyle()
2986 if (m_widgetStyle
) return m_widgetStyle
;
2988 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
2991 def
= gtk_widget_get_default_style();
2993 m_widgetStyle
= gtk_style_copy( def
);
2994 m_widgetStyle
->klass
= def
->klass
;
2996 return m_widgetStyle
;
2999 void wxWindow::SetWidgetStyle()
3001 GtkStyle
*style
= GetWidgetStyle();
3003 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3005 gdk_font_unref( style
->font
);
3006 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3009 if (m_foregroundColour
.Ok())
3011 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3012 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3014 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3015 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3016 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3020 if (m_backgroundColour
.Ok())
3022 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3023 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3025 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3026 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3027 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3028 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3029 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3030 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3031 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3032 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3037 void wxWindow::ApplyWidgetStyle()
3041 //-----------------------------------------------------------------------------
3042 // Pop-up menu stuff
3043 //-----------------------------------------------------------------------------
3045 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3047 *is_waiting
= FALSE
;
3050 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3052 menu
->SetInvokingWindow( win
);
3053 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3056 wxMenuItem
*menuitem
= node
->GetData();
3057 if (menuitem
->IsSubMenu())
3059 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3062 node
= node
->GetNext();
3066 static gint gs_pop_x
= 0;
3067 static gint gs_pop_y
= 0;
3069 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3073 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3078 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3080 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3082 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3084 SetInvokingWindow( menu
, this );
3091 bool is_waiting
= TRUE
;
3093 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3094 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3097 GTK_MENU(menu
->m_menu
),
3098 (GtkWidget
*) NULL
, // parent menu shell
3099 (GtkWidget
*) NULL
, // parent menu item
3100 (GtkMenuPositionFunc
) pop_pos_callback
,
3101 (gpointer
) this, // client data
3102 0, // button used to activate it
3103 gs_timeLastClick
// the time of activation
3108 while (gtk_events_pending())
3109 gtk_main_iteration();
3115 #if wxUSE_DRAG_AND_DROP
3117 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3119 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3121 GtkWidget
*dnd_widget
= GetConnectWidget();
3123 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3125 if (m_dropTarget
) delete m_dropTarget
;
3126 m_dropTarget
= dropTarget
;
3128 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3131 #endif // wxUSE_DRAG_AND_DROP
3133 GtkWidget
* wxWindow::GetConnectWidget()
3135 GtkWidget
*connect_widget
= m_widget
;
3136 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3138 return connect_widget
;
3141 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3144 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3146 return (window
== m_widget
->window
);
3149 bool wxWindow::SetFont( const wxFont
&font
)
3151 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3153 if (!wxWindowBase::SetFont(font
))
3158 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3159 if ( sysbg
== m_backgroundColour
)
3161 m_backgroundColour
= wxNullColour
;
3163 m_backgroundColour
= sysbg
;
3173 void wxWindow::CaptureMouse()
3175 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3177 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3179 GdkWindow
*window
= (GdkWindow
*) NULL
;
3181 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3183 window
= GetConnectWidget()->window
;
3185 if (!window
) return;
3187 gdk_pointer_grab( window
, FALSE
,
3189 (GDK_BUTTON_PRESS_MASK
|
3190 GDK_BUTTON_RELEASE_MASK
|
3191 GDK_POINTER_MOTION_HINT_MASK
|
3192 GDK_POINTER_MOTION_MASK
),
3194 m_cursor
.GetCursor(),
3195 (guint32
)GDK_CURRENT_TIME
);
3196 g_captureWindow
= this;
3199 void wxWindow::ReleaseMouse()
3201 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3203 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3205 GdkWindow
*window
= (GdkWindow
*) NULL
;
3207 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3209 window
= GetConnectWidget()->window
;
3214 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3215 g_captureWindow
= (wxWindow
*) NULL
;
3218 bool wxWindow::IsRetained() const
3223 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3224 int range
, bool refresh
)
3226 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3228 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3230 m_hasScrolling
= TRUE
;
3232 if (orient
== wxHORIZONTAL
)
3234 float fpos
= (float)pos
;
3235 float frange
= (float)range
;
3236 float fthumb
= (float)thumbVisible
;
3237 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3238 if (fpos
< 0.0) fpos
= 0.0;
3240 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3241 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3243 SetScrollPos( orient
, pos
, refresh
);
3247 m_oldHorizontalPos
= fpos
;
3249 m_hAdjust
->lower
= 0.0;
3250 m_hAdjust
->upper
= frange
;
3251 m_hAdjust
->value
= fpos
;
3252 m_hAdjust
->step_increment
= 1.0;
3253 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3254 m_hAdjust
->page_size
= fthumb
;
3258 float fpos
= (float)pos
;
3259 float frange
= (float)range
;
3260 float fthumb
= (float)thumbVisible
;
3261 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3262 if (fpos
< 0.0) fpos
= 0.0;
3264 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3265 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3267 SetScrollPos( orient
, pos
, refresh
);
3271 m_oldVerticalPos
= fpos
;
3273 m_vAdjust
->lower
= 0.0;
3274 m_vAdjust
->upper
= frange
;
3275 m_vAdjust
->value
= fpos
;
3276 m_vAdjust
->step_increment
= 1.0;
3277 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3278 m_vAdjust
->page_size
= fthumb
;
3281 if (orient
== wxHORIZONTAL
)
3282 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3284 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3287 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3289 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3291 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3293 if (orient
== wxHORIZONTAL
)
3295 float fpos
= (float)pos
;
3296 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3297 if (fpos
< 0.0) fpos
= 0.0;
3298 m_oldHorizontalPos
= fpos
;
3300 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3301 m_hAdjust
->value
= fpos
;
3305 float fpos
= (float)pos
;
3306 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3307 if (fpos
< 0.0) fpos
= 0.0;
3308 m_oldVerticalPos
= fpos
;
3310 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3311 m_vAdjust
->value
= fpos
;
3318 if (m_wxwindow
->window
)
3320 if (orient
== wxHORIZONTAL
)
3321 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3323 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3330 int wxWindow::GetScrollThumb( int orient
) const
3332 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3334 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3336 if (orient
== wxHORIZONTAL
)
3337 return (int)(m_hAdjust
->page_size
+0.5);
3339 return (int)(m_vAdjust
->page_size
+0.5);
3342 int wxWindow::GetScrollPos( int orient
) const
3344 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3346 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3348 if (orient
== wxHORIZONTAL
)
3349 return (int)(m_hAdjust
->value
+0.5);
3351 return (int)(m_vAdjust
->value
+0.5);
3354 int wxWindow::GetScrollRange( int orient
) const
3356 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3358 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3360 if (orient
== wxHORIZONTAL
)
3361 return (int)(m_hAdjust
->upper
+0.5);
3363 return (int)(m_vAdjust
->upper
+0.5);
3366 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3368 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3370 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3373 printf( "ScrollWindow: %d %d\n", dx, dy );
3376 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3381 m_scrollGC = gdk_gc_new( m_wxwindow->window );
3382 gdk_gc_set_exposures( m_scrollGC, TRUE );
3385 wxNode *node = m_children.First();
3388 wxWindow *child = (wxWindow*) node->Data();
3391 child->GetSize( &sx, &sy );
3392 child->SetSize( child->m_x + dx, child->m_y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
3393 node = node->Next();
3398 GetClientSize( &cw, &ch );
3399 int w = cw - abs(dx);
3400 int h = ch - abs(dy);
3402 if ((h < 0) || (w < 0))
3410 if (dx < 0) s_x = -dx;
3411 if (dy < 0) s_y = -dy;
3414 if (dx > 0) d_x = dx;
3415 if (dy > 0) d_y = dy;
3417 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
3418 m_wxwindow->window, s_x, s_y, w, h );
3421 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3422 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3423 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3424 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3426 Refresh( TRUE, &rect );
3431 void wxWindow::SetScrolling(bool scroll
)
3433 m_isScrolling
= g_blockEventsOnScroll
= scroll
;