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
);
252 #define DEBUG_MAIN_THREAD
255 //-----------------------------------------------------------------------------
256 // missing gdk functions
257 //-----------------------------------------------------------------------------
260 gdk_window_warp_pointer (GdkWindow
*window
,
264 GdkWindowPrivate
*priv
;
267 window
= (GdkWindow
*) &gdk_root_parent
;
269 priv
= (GdkWindowPrivate
*) window
;
271 if (!priv
->destroyed
)
273 XWarpPointer (priv
->xdisplay
,
274 None
, /* not source window -> move from anywhere */
275 priv
->xwindow
, /* dest window */
276 0, 0, 0, 0, /* not source window -> move from anywhere */
281 //-----------------------------------------------------------------------------
283 //-----------------------------------------------------------------------------
285 extern void wxapp_install_idle_handler();
286 extern bool g_isIdle
;
288 //-----------------------------------------------------------------------------
289 // local code (see below)
290 //-----------------------------------------------------------------------------
292 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
300 if (win
->HasScrolling())
302 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
303 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget
)->klass
);
306 GtkWidget *hscrollbar = scroll_window->hscrollbar;
307 GtkWidget *vscrollbar = scroll_window->vscrollbar;
309 we use this instead: range.slider_width = 11 + 2*2pts edge
312 if (scroll_window
->vscrollbar_visible
)
314 dw
+= 15; /* dw += vscrollbar->allocation.width; */
315 dw
+= scroll_class
->scrollbar_spacing
;
318 if (scroll_window
->hscrollbar_visible
)
320 dh
+= 15; /* dh += hscrollbar->allocation.height; */
321 dh
+= scroll_class
->scrollbar_spacing
;
327 if (GTK_WIDGET_NO_WINDOW (widget
))
329 dx
+= widget
->allocation
.x
;
330 dy
+= widget
->allocation
.y
;
333 if (win
->HasFlag(wxRAISED_BORDER
))
335 gtk_draw_shadow( widget
->style
,
340 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
344 if (win
->HasFlag(wxSUNKEN_BORDER
))
346 gtk_draw_shadow( widget
->style
,
351 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
355 if (win
->HasFlag(wxSIMPLE_BORDER
))
358 gc
= gdk_gc_new( widget
->window
);
359 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
360 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
362 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
368 //-----------------------------------------------------------------------------
369 // "expose_event" of m_widget
370 //-----------------------------------------------------------------------------
372 static void gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
374 if (gdk_event
->count
> 0) return;
375 draw_frame( widget
, win
);
378 //-----------------------------------------------------------------------------
379 // "draw" of m_widget
380 //-----------------------------------------------------------------------------
382 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
384 draw_frame( widget
, win
);
387 //-----------------------------------------------------------------------------
388 // key code mapping routines
389 //-----------------------------------------------------------------------------
391 static long map_to_unmodified_wx_keysym( KeySym keysym
)
398 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
400 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
406 case GDK_Super_R
: key_code
= WXK_ALT
; break;
407 case GDK_Menu
: key_code
= WXK_MENU
; break;
408 case GDK_Help
: key_code
= WXK_HELP
; break;
409 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
410 case GDK_ISO_Left_Tab
:
411 case GDK_Tab
: key_code
= WXK_TAB
; break;
412 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
413 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
414 case GDK_Return
: key_code
= WXK_RETURN
; break;
415 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
416 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
417 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
418 case GDK_Delete
: key_code
= WXK_DELETE
; break;
419 case GDK_Home
: key_code
= WXK_HOME
; break;
420 case GDK_Left
: key_code
= WXK_LEFT
; break;
421 case GDK_Up
: key_code
= WXK_UP
; break;
422 case GDK_Right
: key_code
= WXK_RIGHT
; break;
423 case GDK_Down
: key_code
= WXK_DOWN
; break;
424 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
425 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
426 case GDK_Next
: key_code
= WXK_NEXT
; break;
427 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
428 case GDK_End
: key_code
= WXK_END
; break;
429 case GDK_Begin
: key_code
= WXK_HOME
; break;
430 case GDK_Select
: key_code
= WXK_SELECT
; break;
431 case GDK_Print
: key_code
= WXK_PRINT
; break;
432 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
433 case GDK_Insert
: key_code
= WXK_INSERT
; break;
434 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
436 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
437 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
438 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
439 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
440 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
441 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
442 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
443 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
444 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
445 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
446 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
447 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
448 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
449 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
450 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
451 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
452 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
453 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
454 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
455 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
456 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
457 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
458 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
459 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
460 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
461 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
462 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
463 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
464 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
465 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
466 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
467 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
468 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
469 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
470 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
471 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
472 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
474 case GDK_F1
: key_code
= WXK_F1
; break;
475 case GDK_F2
: key_code
= WXK_F2
; break;
476 case GDK_F3
: key_code
= WXK_F3
; break;
477 case GDK_F4
: key_code
= WXK_F4
; break;
478 case GDK_F5
: key_code
= WXK_F5
; break;
479 case GDK_F6
: key_code
= WXK_F6
; break;
480 case GDK_F7
: key_code
= WXK_F7
; break;
481 case GDK_F8
: key_code
= WXK_F8
; break;
482 case GDK_F9
: key_code
= WXK_F9
; break;
483 case GDK_F10
: key_code
= WXK_F10
; break;
484 case GDK_F11
: key_code
= WXK_F11
; break;
485 case GDK_F12
: key_code
= WXK_F12
; break;
490 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
491 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
492 key_code
= (guint
)keysym
;
500 static long map_to_wx_keysym( KeySym keysym
)
506 case GDK_Menu
: key_code
= WXK_MENU
; break;
507 case GDK_Help
: key_code
= WXK_HELP
; break;
508 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
509 case GDK_ISO_Left_Tab
:
510 case GDK_Tab
: key_code
= WXK_TAB
; break;
511 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
512 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
513 case GDK_Return
: key_code
= WXK_RETURN
; break;
514 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
515 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
516 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
517 case GDK_Delete
: key_code
= WXK_DELETE
; break;
518 case GDK_Home
: key_code
= WXK_HOME
; break;
519 case GDK_Left
: key_code
= WXK_LEFT
; break;
520 case GDK_Up
: key_code
= WXK_UP
; break;
521 case GDK_Right
: key_code
= WXK_RIGHT
; break;
522 case GDK_Down
: key_code
= WXK_DOWN
; break;
523 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
524 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
525 case GDK_Next
: key_code
= WXK_NEXT
; break;
526 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
527 case GDK_End
: key_code
= WXK_END
; break;
528 case GDK_Begin
: key_code
= WXK_HOME
; break;
529 case GDK_Select
: key_code
= WXK_SELECT
; break;
530 case GDK_Print
: key_code
= WXK_PRINT
; break;
531 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
532 case GDK_Insert
: key_code
= WXK_INSERT
; break;
533 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
535 case GDK_KP_0
: key_code
= '0'; break;
536 case GDK_KP_1
: key_code
= '1'; break;
537 case GDK_KP_2
: key_code
= '2'; break;
538 case GDK_KP_3
: key_code
= '3'; break;
539 case GDK_KP_4
: key_code
= '4'; break;
540 case GDK_KP_5
: key_code
= '5'; break;
541 case GDK_KP_6
: key_code
= '6'; break;
542 case GDK_KP_7
: key_code
= '7'; break;
543 case GDK_KP_8
: key_code
= '8'; break;
544 case GDK_KP_9
: key_code
= '9'; break;
545 case GDK_KP_Space
: key_code
= ' '; break;
546 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
547 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
548 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
549 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
550 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
551 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
552 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
553 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
554 case GDK_KP_Up
: key_code
= WXK_UP
; break;
555 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
556 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
557 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
558 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
559 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
560 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
561 case GDK_KP_End
: key_code
= WXK_END
; break;
562 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
563 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
564 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
565 case GDK_KP_Equal
: key_code
= '='; break;
566 case GDK_KP_Multiply
: key_code
= '*'; break;
567 case GDK_KP_Add
: key_code
= '+'; break;
568 case GDK_KP_Separator
: key_code
= ','; break;
569 case GDK_KP_Subtract
: key_code
= '-'; break;
570 case GDK_KP_Decimal
: key_code
= '.'; break;
571 case GDK_KP_Divide
: key_code
= '/'; break;
573 case GDK_F1
: key_code
= WXK_F1
; break;
574 case GDK_F2
: key_code
= WXK_F2
; break;
575 case GDK_F3
: key_code
= WXK_F3
; break;
576 case GDK_F4
: key_code
= WXK_F4
; break;
577 case GDK_F5
: key_code
= WXK_F5
; break;
578 case GDK_F6
: key_code
= WXK_F6
; break;
579 case GDK_F7
: key_code
= WXK_F7
; break;
580 case GDK_F8
: key_code
= WXK_F8
; break;
581 case GDK_F9
: key_code
= WXK_F9
; break;
582 case GDK_F10
: key_code
= WXK_F10
; break;
583 case GDK_F11
: key_code
= WXK_F11
; break;
584 case GDK_F12
: key_code
= WXK_F12
; break;
589 key_code
= (guint
)keysym
;
597 //-----------------------------------------------------------------------------
598 // "expose_event" of m_wxwindow
599 //-----------------------------------------------------------------------------
601 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
608 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
610 gdk_event
->area
.width
,
611 gdk_event
->area
.height
);
614 wxPrintf( "OnExpose from " );
615 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
616 wxPrintf( win->GetClassInfo()->GetClassName() );
617 wxPrintf( " %d %d %d %d\n", (int)gdk_event->area.x,
618 (int)gdk_event->area.y,
619 (int)gdk_event->area.width,
620 (int)gdk_event->area.height );
623 if (gdk_event
->count
> 0)
626 wxEraseEvent
eevent( win
->GetId() );
627 eevent
.SetEventObject( win
);
628 win
->GetEventHandler()->ProcessEvent(eevent
);
630 wxPaintEvent
event( win
->GetId() );
631 event
.SetEventObject( win
);
632 win
->GetEventHandler()->ProcessEvent( event
);
634 win
->GetUpdateRegion().Clear();
637 //-----------------------------------------------------------------------------
638 // "draw" of m_wxwindow
639 //-----------------------------------------------------------------------------
641 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
),
642 GdkRectangle
*rect
, wxWindow
*win
)
647 wxapp_install_idle_handler();
652 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
,
653 rect
->width
, rect
->height
);
656 wxPrintf( "OnDraw from " );
657 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
658 printf( win->GetClassInfo()->GetClassName() );
659 wxPrintf( " %d %d %d %d\n", (int)rect->x,
665 wxEraseEvent
eevent( win
->GetId() );
666 eevent
.SetEventObject( win
);
667 win
->GetEventHandler()->ProcessEvent(eevent
);
669 wxPaintEvent
event( win
->GetId() );
670 event
.SetEventObject( win
);
671 win
->GetEventHandler()->ProcessEvent( event
);
673 win
->GetUpdateRegion().Clear();
676 //-----------------------------------------------------------------------------
677 // "key_press_event" from any window
678 //-----------------------------------------------------------------------------
680 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
685 wxapp_install_idle_handler();
687 if (!win
->m_hasVMT
) return FALSE
;
688 if (g_blockEventsOnDrag
) return FALSE
;
692 tmp += (char)gdk_event->keyval;
693 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
694 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
699 GdkModifierType state
;
700 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
704 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
705 /* sending unknown key events doesn't really make sense */
706 if (key_code
== 0) return FALSE
;
708 wxKeyEvent
event( wxEVT_KEY_DOWN
);
709 event
.SetTimestamp( gdk_event
->time
);
710 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
711 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
712 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
713 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
714 event
.m_keyCode
= key_code
;
715 event
.m_scanCode
= gdk_event
->keyval
;
718 event
.SetEventObject( win
);
719 ret
= win
->GetEventHandler()->ProcessEvent( event
);
724 wxWindow
*ancestor
= win
;
727 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
730 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
731 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
734 if (ancestor
->m_isFrame
)
736 ancestor
= ancestor
->GetParent();
739 #endif // wxUSE_ACCEL
741 /* wxMSW doesn't send char events with Alt pressed */
742 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
743 will only be sent if it is not in an accelerator table. */
744 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
749 wxKeyEvent
event2( wxEVT_CHAR
);
750 event2
.SetTimestamp( gdk_event
->time
);
751 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
752 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
753 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
754 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
755 event2
.m_keyCode
= key_code
;
756 event2
.m_scanCode
= gdk_event
->keyval
;
759 event2
.SetEventObject( win
);
760 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
763 /* win is a control: tab can be propagated up */
765 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
766 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
767 (win
->GetParent()) &&
768 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
770 wxNavigationKeyEvent new_event
;
771 new_event
.SetEventObject( win
);
772 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
773 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
774 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
775 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
776 new_event
.SetCurrentFocus( win
);
777 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
780 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
782 (gdk_event
->keyval
== GDK_Escape
) )
784 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
785 new_event
.SetEventObject( win
);
786 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
789 #if (GTK_MINOR_VERSION > 0)
790 /* Pressing F10 will activate the menu bar of the top frame. */
794 (gdk_event->keyval == GDK_F10) )
796 wxWindow *ancestor = win;
799 if (wxIsKindOf(ancestor,wxFrame))
801 wxFrame *frame = (wxFrame*) ancestor;
802 wxMenuBar *menubar = frame->GetMenuBar();
805 wxNode *node = menubar->GetMenus().First();
808 wxMenu *firstMenu = (wxMenu*) node->Data();
809 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
815 ancestor = ancestor->GetParent();
823 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
830 //-----------------------------------------------------------------------------
831 // "key_release_event" from any window
832 //-----------------------------------------------------------------------------
834 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
839 wxapp_install_idle_handler();
841 if (!win
->m_hasVMT
) return FALSE
;
842 if (g_blockEventsOnDrag
) return FALSE
;
845 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
846 if (gdk_event->state & GDK_SHIFT_MASK)
847 printf( "ShiftDown.\n" );
849 printf( "ShiftUp.\n" );
850 if (gdk_event->state & GDK_CONTROL_MASK)
851 printf( "ControlDown.\n" );
853 printf( "ControlUp.\n" );
857 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
859 /* sending unknown key events doesn't really make sense */
860 if (key_code
== 0) return FALSE
;
864 GdkModifierType state
;
865 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
867 wxKeyEvent
event( wxEVT_KEY_UP
);
868 event
.SetTimestamp( gdk_event
->time
);
869 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
870 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
871 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
872 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
873 event
.m_keyCode
= key_code
;
874 event
.m_scanCode
= gdk_event
->keyval
;
877 event
.SetEventObject( win
);
879 if (win
->GetEventHandler()->ProcessEvent( event
))
881 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
888 //-----------------------------------------------------------------------------
889 // "button_press_event"
890 //-----------------------------------------------------------------------------
892 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
897 wxapp_install_idle_handler();
900 wxPrintf( wxT("1) OnButtonPress from ") );
901 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
902 wxPrintf( win->GetClassInfo()->GetClassName() );
903 wxPrintf( wxT(".\n") );
905 if (!win
->m_hasVMT
) return FALSE
;
906 if (g_blockEventsOnDrag
) return TRUE
;
907 if (g_blockEventsOnScroll
) return TRUE
;
909 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
913 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
915 gtk_widget_grab_focus (win
->m_wxwindow
);
918 wxPrintf( wxT("GrabFocus from ") );
919 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
920 wxPrintf( win->GetClassInfo()->GetClassName() );
921 wxPrintf( wxT(".\n") );
927 wxEventType event_type
= wxEVT_LEFT_DOWN
;
929 if (gdk_event
->button
== 1)
931 switch (gdk_event
->type
)
933 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
934 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
938 else if (gdk_event
->button
== 2)
940 switch (gdk_event
->type
)
942 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
943 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
947 else if (gdk_event
->button
== 3)
949 switch (gdk_event
->type
)
951 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
952 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
957 wxMouseEvent
event( event_type
);
958 event
.SetTimestamp( gdk_event
->time
);
959 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
960 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
961 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
962 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
963 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
964 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
965 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
967 event
.m_x
= (wxCoord
)gdk_event
->x
;
968 event
.m_y
= (wxCoord
)gdk_event
->y
;
970 // Some control don't have their own X window and thus cannot get
973 if (!g_captureWindow
)
975 wxCoord x
= event
.m_x
;
976 wxCoord y
= event
.m_y
;
979 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
984 wxNode
*node
= win
->GetChildren().First();
987 wxWindow
*child
= (wxWindow
*)node
->Data();
990 if (!child
->IsShown())
993 if (child
->m_isStaticBox
)
995 // wxStaticBox is transparent in the box itself
996 int xx1
= child
->m_x
;
997 int yy1
= child
->m_y
;
998 int xx2
= child
->m_x
+ child
->m_width
;
999 int yy2
= child
->m_x
+ child
->m_height
;
1002 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1004 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1006 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1008 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1011 event
.m_x
-= child
->m_x
;
1012 event
.m_y
-= child
->m_y
;
1019 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1020 (child
->m_x
<= x
) &&
1021 (child
->m_y
<= y
) &&
1022 (child
->m_x
+child
->m_width
>= x
) &&
1023 (child
->m_y
+child
->m_height
>= y
))
1026 event
.m_x
-= child
->m_x
;
1027 event
.m_y
-= child
->m_y
;
1034 event
.SetEventObject( win
);
1036 gs_timeLastClick
= gdk_event
->time
;
1039 wxPrintf( wxT("2) OnButtonPress from ") );
1040 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1041 wxPrintf( win->GetClassInfo()->GetClassName() );
1042 wxPrintf( wxT(".\n") );
1045 if (win
->GetEventHandler()->ProcessEvent( event
))
1047 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1054 //-----------------------------------------------------------------------------
1055 // "button_release_event"
1056 //-----------------------------------------------------------------------------
1058 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1063 wxapp_install_idle_handler();
1065 if (!win
->m_hasVMT
) return FALSE
;
1066 if (g_blockEventsOnDrag
) return FALSE
;
1067 if (g_blockEventsOnScroll
) return FALSE
;
1069 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1072 printf( "OnButtonRelease from " );
1073 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1074 printf( win->GetClassInfo()->GetClassName() );
1078 wxEventType event_type
= wxEVT_NULL
;
1080 switch (gdk_event
->button
)
1082 case 1: event_type
= wxEVT_LEFT_UP
; break;
1083 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1084 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1087 wxMouseEvent
event( event_type
);
1088 event
.SetTimestamp( gdk_event
->time
);
1089 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1090 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1091 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1092 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1093 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1094 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1095 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1096 event
.m_x
= (wxCoord
)gdk_event
->x
;
1097 event
.m_y
= (wxCoord
)gdk_event
->y
;
1099 // Some control don't have their own X window and thus cannot get
1102 if (!g_captureWindow
)
1104 wxCoord x
= event
.m_x
;
1105 wxCoord y
= event
.m_y
;
1106 if (win
->m_wxwindow
)
1108 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1109 x
+= pizza
->xoffset
;
1110 y
+= pizza
->yoffset
;
1113 wxNode
*node
= win
->GetChildren().First();
1116 wxWindow
*child
= (wxWindow
*)node
->Data();
1118 node
= node
->Next();
1119 if (!child
->IsShown())
1122 if (child
->m_isStaticBox
)
1124 // wxStaticBox is transparent in the box itself
1125 int xx1
= child
->m_x
;
1126 int yy1
= child
->m_y
;
1127 int xx2
= child
->m_x
+ child
->m_width
;
1128 int yy2
= child
->m_x
+ child
->m_height
;
1131 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1133 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1135 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1137 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1140 event
.m_x
-= child
->m_x
;
1141 event
.m_y
-= child
->m_y
;
1148 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1149 (child
->m_x
<= x
) &&
1150 (child
->m_y
<= y
) &&
1151 (child
->m_x
+child
->m_width
>= x
) &&
1152 (child
->m_y
+child
->m_height
>= y
))
1155 event
.m_x
-= child
->m_x
;
1156 event
.m_y
-= child
->m_y
;
1163 event
.SetEventObject( win
);
1165 if (win
->GetEventHandler()->ProcessEvent( event
))
1167 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1174 //-----------------------------------------------------------------------------
1175 // "motion_notify_event"
1176 //-----------------------------------------------------------------------------
1178 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1183 wxapp_install_idle_handler();
1185 if (!win
->m_hasVMT
) return FALSE
;
1186 if (g_blockEventsOnDrag
) return FALSE
;
1187 if (g_blockEventsOnScroll
) return FALSE
;
1189 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1191 if (gdk_event
->is_hint
)
1195 GdkModifierType state
;
1196 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1202 printf( "OnMotion from " );
1203 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1204 printf( win->GetClassInfo()->GetClassName() );
1208 wxMouseEvent
event( wxEVT_MOTION
);
1209 event
.SetTimestamp( gdk_event
->time
);
1210 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1211 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1212 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1213 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1214 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1215 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1216 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1218 event
.m_x
= (wxCoord
)gdk_event
->x
;
1219 event
.m_y
= (wxCoord
)gdk_event
->y
;
1221 // Some control don't have their own X window and thus cannot get
1224 if (!g_captureWindow
)
1226 wxCoord x
= event
.m_x
;
1227 wxCoord y
= event
.m_y
;
1228 if (win
->m_wxwindow
)
1230 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1231 x
+= pizza
->xoffset
;
1232 y
+= pizza
->yoffset
;
1235 wxNode
*node
= win
->GetChildren().First();
1238 wxWindow
*child
= (wxWindow
*)node
->Data();
1240 node
= node
->Next();
1241 if (!child
->IsShown())
1244 if (child
->m_isStaticBox
)
1246 // wxStaticBox is transparent in the box itself
1247 int xx1
= child
->m_x
;
1248 int yy1
= child
->m_y
;
1249 int xx2
= child
->m_x
+ child
->m_width
;
1250 int yy2
= child
->m_x
+ child
->m_height
;
1253 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1255 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1257 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1259 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1262 event
.m_x
-= child
->m_x
;
1263 event
.m_y
-= child
->m_y
;
1270 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1271 (child
->m_x
<= x
) &&
1272 (child
->m_y
<= y
) &&
1273 (child
->m_x
+child
->m_width
>= x
) &&
1274 (child
->m_y
+child
->m_height
>= y
))
1277 event
.m_x
-= child
->m_x
;
1278 event
.m_y
-= child
->m_y
;
1285 event
.SetEventObject( win
);
1287 if (win
->GetEventHandler()->ProcessEvent( event
))
1289 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1296 //-----------------------------------------------------------------------------
1298 //-----------------------------------------------------------------------------
1300 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1305 wxapp_install_idle_handler();
1307 if (!win
->m_hasVMT
) return FALSE
;
1308 if (g_blockEventsOnDrag
) return FALSE
;
1310 switch ( g_sendActivateEvent
)
1313 // we've got focus from outside, synthtize wxActivateEvent
1314 g_sendActivateEvent
= 1;
1318 // another our window just lost focus, it was already ours before
1319 // - don't send any wxActivateEvent
1320 g_sendActivateEvent
= -1;
1324 g_focusWindow
= win
;
1327 printf( "OnSetFocus from " );
1328 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1329 printf( win->GetClassInfo()->GetClassName() );
1331 printf( WXSTRINGCAST win->GetLabel() );
1335 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1338 panel
->SetLastFocus(win
);
1343 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1346 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1347 event
.SetEventObject( win
);
1349 if (win
->GetEventHandler()->ProcessEvent( event
))
1351 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1358 //-----------------------------------------------------------------------------
1359 // "focus_out_event"
1360 //-----------------------------------------------------------------------------
1362 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1367 wxapp_install_idle_handler();
1369 if (!win
->m_hasVMT
) return FALSE
;
1370 if (g_blockEventsOnDrag
) return FALSE
;
1372 // if the focus goes out of our app alltogether, OnIdle() will send
1373 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1374 // g_sendActivateEvent to -1
1375 g_sendActivateEvent
= 0;
1377 g_focusWindow
= (wxWindow
*)NULL
;
1380 printf( "OnKillFocus from " );
1381 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1382 printf( win->GetClassInfo()->GetClassName() );
1391 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1392 event
.SetEventObject( win
);
1394 if (win
->GetEventHandler()->ProcessEvent( event
))
1396 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1403 //-----------------------------------------------------------------------------
1404 // "enter_notify_event"
1405 //-----------------------------------------------------------------------------
1407 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1412 wxapp_install_idle_handler();
1414 if (!win
->m_hasVMT
) return FALSE
;
1415 if (g_blockEventsOnDrag
) return FALSE
;
1417 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1419 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1420 #if (GTK_MINOR_VERSION > 0)
1421 event
.SetTimestamp( gdk_event
->time
);
1423 event
.SetEventObject( win
);
1427 GdkModifierType state
= (GdkModifierType
)0;
1429 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1431 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1432 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1433 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1434 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1435 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1436 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1437 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1442 if (win
->GetEventHandler()->ProcessEvent( event
))
1444 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1451 //-----------------------------------------------------------------------------
1452 // "leave_notify_event"
1453 //-----------------------------------------------------------------------------
1455 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1460 wxapp_install_idle_handler();
1462 if (!win
->m_hasVMT
) return FALSE
;
1463 if (g_blockEventsOnDrag
) return FALSE
;
1465 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1467 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1468 #if (GTK_MINOR_VERSION > 0)
1469 event
.SetTimestamp( gdk_event
->time
);
1471 event
.SetEventObject( win
);
1475 GdkModifierType state
= (GdkModifierType
)0;
1477 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1479 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1480 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1481 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1482 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1483 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1484 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1485 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1490 if (win
->GetEventHandler()->ProcessEvent( event
))
1492 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1499 //-----------------------------------------------------------------------------
1500 // "value_changed" from m_vAdjust
1501 //-----------------------------------------------------------------------------
1503 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1508 wxapp_install_idle_handler();
1510 if (g_blockEventsOnDrag
) return;
1512 if (!win
->m_hasVMT
) return;
1514 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1515 if (fabs(diff
) < 0.2) return;
1517 win
->m_oldVerticalPos
= adjust
->value
;
1519 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1520 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1522 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1523 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1524 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1525 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1526 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1528 int value
= (int)(adjust
->value
+0.5);
1530 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1531 event
.SetEventObject( win
);
1532 win
->GetEventHandler()->ProcessEvent( event
);
1535 //-----------------------------------------------------------------------------
1536 // "value_changed" from m_hAdjust
1537 //-----------------------------------------------------------------------------
1539 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1544 wxapp_install_idle_handler();
1546 if (g_blockEventsOnDrag
) return;
1547 if (!win
->m_hasVMT
) return;
1549 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1550 if (fabs(diff
) < 0.2) return;
1552 win
->m_oldHorizontalPos
= adjust
->value
;
1554 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1555 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1557 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1558 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1559 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1560 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1561 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1563 int value
= (int)(adjust
->value
+0.5);
1565 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1566 event
.SetEventObject( win
);
1567 win
->GetEventHandler()->ProcessEvent( event
);
1570 //-----------------------------------------------------------------------------
1571 // "changed" from m_vAdjust
1572 //-----------------------------------------------------------------------------
1574 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1579 wxapp_install_idle_handler();
1581 if (g_blockEventsOnDrag
) return;
1582 if (!win
->m_hasVMT
) return;
1584 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1585 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1587 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1588 event
.SetEventObject( win
);
1589 win
->GetEventHandler()->ProcessEvent( event
);
1592 //-----------------------------------------------------------------------------
1593 // "changed" from m_hAdjust
1594 //-----------------------------------------------------------------------------
1596 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1601 wxapp_install_idle_handler();
1603 if (g_blockEventsOnDrag
) return;
1604 if (!win
->m_hasVMT
) return;
1606 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1607 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1609 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1610 event
.SetEventObject( win
);
1611 win
->GetEventHandler()->ProcessEvent( event
);
1614 //-----------------------------------------------------------------------------
1615 // "button_press_event" from scrollbar
1616 //-----------------------------------------------------------------------------
1618 static gint
gtk_scrollbar_button_press_callback( GtkRange
*WXUNUSED(widget
),
1619 GdkEventButton
*WXUNUSED(gdk_event
),
1625 wxapp_install_idle_handler();
1627 // don't test here as we can release the mouse while being over
1628 // a different window than the slider
1630 // if (gdk_event->window != widget->slider) return FALSE;
1632 win
->SetScrolling( TRUE
);
1637 //-----------------------------------------------------------------------------
1638 // "button_release_event" from scrollbar
1639 //-----------------------------------------------------------------------------
1641 static gint
gtk_scrollbar_button_release_callback( GtkRange
*WXUNUSED(widget
),
1642 GdkEventButton
*WXUNUSED(gdk_event
),
1648 // don't test here as we can release the mouse while being over
1649 // a different window than the slider
1651 // if (gdk_event->window != widget->slider) return FALSE;
1653 win
->SetScrolling( FALSE
);
1658 // ----------------------------------------------------------------------------
1659 // this wxWindowBase function is implemented here (in platform-specific file)
1660 // because it is static and so couldn't be made virtual
1661 // ----------------------------------------------------------------------------
1663 wxWindow
*wxWindowBase::FindFocus()
1665 return g_focusWindow
;
1668 //-----------------------------------------------------------------------------
1669 // "realize" from m_widget
1670 //-----------------------------------------------------------------------------
1672 /* We cannot set colours and fonts before the widget has
1673 been realized, so we do this directly after realization. */
1676 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1681 wxapp_install_idle_handler();
1683 if (win
->m_delayedBackgroundColour
)
1684 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1686 if (win
->m_delayedForegroundColour
)
1687 win
->SetForegroundColour( win
->GetForegroundColour() );
1689 wxWindowCreateEvent
event( win
);
1690 event
.SetEventObject( win
);
1691 win
->GetEventHandler()->ProcessEvent( event
);
1696 //-----------------------------------------------------------------------------
1698 //-----------------------------------------------------------------------------
1701 #define WXUNUSED_UNLESS_XIM(param) param
1703 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1706 /* Resize XIM window */
1709 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1710 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1711 wxFrame
* WXUNUSED_UNLESS_XIM(win
) )
1714 wxapp_install_idle_handler();
1720 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1724 gdk_window_get_size (widget
->window
, &width
, &height
);
1725 win
->m_icattr
->preedit_area
.width
= width
;
1726 win
->m_icattr
->preedit_area
.height
= height
;
1727 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
1732 //-----------------------------------------------------------------------------
1733 // "realize" from m_wxwindow
1734 //-----------------------------------------------------------------------------
1736 /* Initialize XIM support */
1739 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1740 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1743 wxapp_install_idle_handler();
1746 if (win
->m_ic
) return FALSE
;
1747 if (!widget
) return FALSE
;
1748 if (!gdk_im_ready()) return FALSE
;
1750 win
->m_icattr
= gdk_ic_attr_new();
1751 if (!win
->m_icattr
) return FALSE
;
1755 GdkColormap
*colormap
;
1756 GdkICAttr
*attr
= win
->m_icattr
;
1757 unsigned attrmask
= GDK_IC_ALL_REQ
;
1759 GdkIMStyle supported_style
= (GdkIMStyle
)
1760 (GDK_IM_PREEDIT_NONE
|
1761 GDK_IM_PREEDIT_NOTHING
|
1762 GDK_IM_PREEDIT_POSITION
|
1763 GDK_IM_STATUS_NONE
|
1764 GDK_IM_STATUS_NOTHING
);
1766 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1767 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
1769 attr
->style
= style
= gdk_im_decide_style (supported_style
);
1770 attr
->client_window
= widget
->window
;
1772 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
1773 gtk_widget_get_default_colormap ())
1775 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
1776 attr
->preedit_colormap
= colormap
;
1779 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
1780 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
1781 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
1782 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
1784 switch (style
& GDK_IM_PREEDIT_MASK
)
1786 case GDK_IM_PREEDIT_POSITION
:
1787 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1789 g_warning ("over-the-spot style requires fontset");
1793 gdk_window_get_size (widget
->window
, &width
, &height
);
1795 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
1796 attr
->spot_location
.x
= 0;
1797 attr
->spot_location
.y
= height
;
1798 attr
->preedit_area
.x
= 0;
1799 attr
->preedit_area
.y
= 0;
1800 attr
->preedit_area
.width
= width
;
1801 attr
->preedit_area
.height
= height
;
1802 attr
->preedit_fontset
= widget
->style
->font
;
1807 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
1809 if (win
->m_ic
== NULL
)
1810 g_warning ("Can't create input context.");
1813 mask
= gdk_window_get_events (widget
->window
);
1814 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
1815 gdk_window_set_events (widget
->window
, mask
);
1817 if (GTK_WIDGET_HAS_FOCUS(widget
))
1818 gdk_im_begin (win
->m_ic
, widget
->window
);
1825 //-----------------------------------------------------------------------------
1826 // InsertChild for wxWindow.
1827 //-----------------------------------------------------------------------------
1829 /* Callback for wxWindow. This very strange beast has to be used because
1830 * C++ has no virtual methods in a constructor. We have to emulate a
1831 * virtual function here as wxNotebook requires a different way to insert
1832 * a child in it. I had opted for creating a wxNotebookPage window class
1833 * which would have made this superfluous (such in the MDI window system),
1834 * but no-one was listening to me... */
1836 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1838 /* the window might have been scrolled already, do we
1839 have to adapt the position */
1840 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
1841 child
->m_x
+= pizza
->xoffset
;
1842 child
->m_y
+= pizza
->yoffset
;
1844 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
1845 GTK_WIDGET(child
->m_widget
),
1852 //-----------------------------------------------------------------------------
1854 //-----------------------------------------------------------------------------
1856 wxWindow
* wxGetActiveWindow()
1858 return g_focusWindow
;
1861 //-----------------------------------------------------------------------------
1863 //-----------------------------------------------------------------------------
1865 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
1867 void wxWindow::Init()
1873 m_widget
= (GtkWidget
*) NULL
;
1874 m_wxwindow
= (GtkWidget
*) NULL
;
1884 m_needParent
= TRUE
;
1885 m_isBeingDeleted
= FALSE
;
1888 m_nativeSizeEvent
= FALSE
;
1890 m_hasScrolling
= FALSE
;
1891 m_isScrolling
= FALSE
;
1893 m_hAdjust
= (GtkAdjustment
*) NULL
;
1894 m_vAdjust
= (GtkAdjustment
*) NULL
;
1895 m_oldHorizontalPos
= 0.0;
1896 m_oldVerticalPos
= 0.0;
1899 m_widgetStyle
= (GtkStyle
*) NULL
;
1901 m_insertCallback
= (wxInsertChildFunction
) NULL
;
1903 m_isStaticBox
= FALSE
;
1904 m_isRadioButton
= FALSE
;
1906 m_acceptsFocus
= FALSE
;
1908 m_cursor
= *wxSTANDARD_CURSOR
;
1911 m_ic
= (GdkIC
*) NULL
;
1912 m_icattr
= (GdkICAttr
*) NULL
;
1916 wxWindow::wxWindow()
1921 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1922 const wxPoint
&pos
, const wxSize
&size
,
1923 long style
, const wxString
&name
)
1927 Create( parent
, id
, pos
, size
, style
, name
);
1930 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1931 const wxPoint
&pos
, const wxSize
&size
,
1932 long style
, const wxString
&name
)
1934 if (!PreCreation( parent
, pos
, size
) ||
1935 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
1937 wxFAIL_MSG( wxT("wxWindow creation failed") );
1941 m_insertCallback
= wxInsertChildInWindow
;
1943 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
1944 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1947 debug_focus_in( m_widget
, wxT("wxWindow::m_widget"), name
);
1950 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
1953 debug_focus_in( scrolledWindow
->hscrollbar
, wxT("wxWindow::hsrcollbar"), name
);
1954 debug_focus_in( scrolledWindow
->vscrollbar
, wxT("wxWindow::vsrcollbar"), name
);
1957 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1958 scroll_class
->scrollbar_spacing
= 0;
1960 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1962 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
1963 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
1965 m_wxwindow
= gtk_pizza_new();
1968 debug_focus_in( m_wxwindow
, wxT("wxWindow::m_wxwindow"), name
);
1971 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
1973 #if (GTK_MINOR_VERSION > 0)
1974 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
1976 if (HasFlag(wxRAISED_BORDER
))
1978 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
1980 else if (HasFlag(wxSUNKEN_BORDER
))
1982 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
1984 else if (HasFlag(wxSIMPLE_BORDER
))
1986 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
1990 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
1992 #else // GTK_MINOR_VERSION == 0
1993 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
1995 if (HasFlag(wxRAISED_BORDER
))
1997 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
1999 else if (HasFlag(wxSUNKEN_BORDER
))
2001 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2005 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2007 #endif // GTK_MINOR_VERSION
2009 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2010 m_acceptsFocus
= TRUE
;
2012 #if (GTK_MINOR_VERSION == 0)
2013 // shut the viewport up
2014 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2015 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2016 #endif // GTK_MINOR_VERSION == 0
2018 // I _really_ don't want scrollbars in the beginning
2019 m_vAdjust
->lower
= 0.0;
2020 m_vAdjust
->upper
= 1.0;
2021 m_vAdjust
->value
= 0.0;
2022 m_vAdjust
->step_increment
= 1.0;
2023 m_vAdjust
->page_increment
= 1.0;
2024 m_vAdjust
->page_size
= 5.0;
2025 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2026 m_hAdjust
->lower
= 0.0;
2027 m_hAdjust
->upper
= 1.0;
2028 m_hAdjust
->value
= 0.0;
2029 m_hAdjust
->step_increment
= 1.0;
2030 m_hAdjust
->page_increment
= 1.0;
2031 m_hAdjust
->page_size
= 5.0;
2032 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2034 // these handlers block mouse events to any window during scrolling such as
2035 // motion events and prevent GTK and wxWindows from fighting over where the
2038 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2039 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2041 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2042 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2044 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2045 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2047 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2048 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2050 // these handlers get notified when screen updates are required either when
2051 // scrolling or when the window size (and therefore scrollbar configuration)
2054 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2055 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2056 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2057 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2059 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
2060 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
2061 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
2062 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
2064 gtk_widget_show( m_wxwindow
);
2067 m_parent
->DoAddChild( this );
2076 wxWindow::~wxWindow()
2078 m_isBeingDeleted
= TRUE
;
2087 m_parent
->RemoveChild( this );
2091 gdk_ic_destroy (m_ic
);
2093 gdk_ic_attr_destroy (m_icattr
);
2098 gtk_style_unref( m_widgetStyle
);
2099 m_widgetStyle
= (GtkStyle
*) NULL
;
2104 gtk_widget_destroy( m_wxwindow
);
2105 m_wxwindow
= (GtkWidget
*) NULL
;
2110 gtk_widget_destroy( m_widget
);
2111 m_widget
= (GtkWidget
*) NULL
;
2115 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2117 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2119 /* this turns -1 into 20 so that a minimal window is
2120 visible even although -1,-1 has been given as the
2121 size of the window. the same trick is used in other
2122 ports and should make debugging easier */
2123 m_width
= WidthDefault(size
.x
);
2124 m_height
= HeightDefault(size
.y
);
2129 /* some reasonable defaults */
2134 m_x
= (gdk_screen_width () - m_width
) / 2;
2135 if (m_x
< 10) m_x
= 10;
2139 m_y
= (gdk_screen_height () - m_height
) / 2;
2140 if (m_y
< 10) m_y
= 10;
2147 void wxWindow::PostCreation()
2149 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2155 /* these get reported to wxWindows -> wxPaintEvent */
2156 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2157 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2159 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2160 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2163 #if (GTK_MINOR_VERSION > 0)
2164 /* these are called when the "sunken" or "raised" borders are drawn */
2165 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2166 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2168 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2169 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2173 if (m_wxwindow
&& m_needParent
)
2175 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2176 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2178 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2179 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2183 // For dialogs and frames, we are interested mainly in
2184 // m_widget's focus.
2186 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2187 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2189 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2190 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2193 GtkWidget
*connect_widget
= GetConnectWidget();
2195 ConnectWidget( connect_widget
);
2197 /* We cannot set colours, fonts and cursors before the widget has
2198 been realized, so we do this directly after realization */
2199 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2200 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2204 /* Initialize XIM support. */
2205 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2206 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2208 /* And resize XIM window. */
2209 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2210 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2216 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2218 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2219 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2221 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2222 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2224 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2225 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2227 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2228 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2230 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2231 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2233 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2234 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2236 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2237 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2240 bool wxWindow::Destroy()
2242 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2246 return wxWindowBase::Destroy();
2249 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2251 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2254 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2256 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2257 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2259 if (m_resizing
) return; /* I don't like recursions */
2262 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2264 /* don't set the size for children of wxNotebook, just take the values. */
2272 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2274 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2276 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2277 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2278 if (width
!= -1) m_width
= width
;
2279 if (height
!= -1) m_height
= height
;
2283 m_x
= x
+ pizza
->xoffset
;
2284 m_y
= y
+ pizza
->yoffset
;
2289 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2291 if (width
== -1) m_width
= 80;
2294 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2296 if (height
== -1) m_height
= 26;
2299 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2300 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2301 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2302 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2305 int bottom_border
= 0;
2307 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2309 /* the default button has a border around it */
2314 DoMoveWindow( m_x
-border
,
2317 m_height
+border
+bottom_border
);
2321 wxPrintf( "OnSize sent from " );
2322 if (GetClassInfo() && GetClassInfo()->GetClassName())
2323 wxPrintf( GetClassInfo()->GetClassName() );
2324 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2327 if (!m_nativeSizeEvent
)
2329 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2330 event
.SetEventObject( this );
2331 GetEventHandler()->ProcessEvent( event
);
2337 void wxWindow::OnInternalIdle()
2339 if ( g_sendActivateEvent
!= -1 )
2341 bool activate
= g_sendActivateEvent
!= 0;
2344 g_sendActivateEvent
= -1;
2346 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2347 event
.SetEventObject(this);
2349 (void)GetEventHandler()->ProcessEvent(event
);
2352 wxCursor cursor
= m_cursor
;
2353 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2357 /* I now set the cursor anew in every OnInternalIdle call
2358 as setting the cursor in a parent window also effects the
2359 windows above so that checking for the current cursor is
2364 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2366 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2368 if (!g_globalCursor
.Ok())
2369 cursor
= *wxSTANDARD_CURSOR
;
2371 window
= m_widget
->window
;
2372 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2373 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2379 GdkWindow
*window
= m_widget
->window
;
2380 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2381 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2389 void wxWindow::DoGetSize( int *width
, int *height
) const
2391 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2393 if (width
) (*width
) = m_width
;
2394 if (height
) (*height
) = m_height
;
2397 void wxWindow::DoSetClientSize( int width
, int height
)
2399 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2403 SetSize( width
, height
);
2410 #if (GTK_MINOR_VERSION == 0)
2411 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2415 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2416 #if 0 // unused - if this is ok, just remove this line (VZ)
2417 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2420 GtkWidget
*viewport
= scroll_window
->viewport
;
2421 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2423 dw
+= 2 * viewport_class
->xthickness
;
2424 dh
+= 2 * viewport_class
->ythickness
;
2428 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2430 /* when using GTK 1.2 we set the shadow border size to 2 */
2434 if (HasFlag(wxSIMPLE_BORDER
))
2436 /* when using GTK 1.2 we set the simple border size to 1 */
2445 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2446 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2448 we use this instead: range.slider_width = 11 + 2*2pts edge
2451 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2452 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2454 if (scroll_window
->vscrollbar_visible
)
2456 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2457 dw
+= scroll_class
->scrollbar_spacing
;
2460 if (scroll_window
->hscrollbar_visible
)
2462 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2463 dh
+= scroll_class
->scrollbar_spacing
;
2467 SetSize( width
+dw
, height
+dh
);
2471 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2473 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2477 if (width
) (*width
) = m_width
;
2478 if (height
) (*height
) = m_height
;
2485 #if (GTK_MINOR_VERSION == 0)
2486 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2490 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2491 #if 0 // unused - if this is ok, just remove this line (VZ)
2492 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2495 GtkWidget
*viewport
= scroll_window
->viewport
;
2496 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2498 dw
+= 2 * viewport_class
->xthickness
;
2499 dh
+= 2 * viewport_class
->ythickness
;
2503 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2505 /* when using GTK 1.2 we set the shadow border size to 2 */
2509 if (HasFlag(wxSIMPLE_BORDER
))
2511 /* when using GTK 1.2 we set the simple border size to 1 */
2519 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2520 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2522 we use this instead: range.slider_width = 11 + 2*2pts edge
2525 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2526 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2528 if (scroll_window
->vscrollbar_visible
)
2530 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2531 dw
+= scroll_class
->scrollbar_spacing
;
2534 if (scroll_window
->hscrollbar_visible
)
2536 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2537 dh
+= scroll_class
->scrollbar_spacing
;
2541 if (width
) (*width
) = m_width
- dw
;
2542 if (height
) (*height
) = m_height
- dh
;
2546 void wxWindow::DoGetPosition( int *x
, int *y
) const
2548 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2552 if (m_parent
&& m_parent
->m_wxwindow
)
2554 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2555 dx
= pizza
->xoffset
;
2556 dy
= pizza
->yoffset
;
2559 if (x
) (*x
) = m_x
- dx
;
2560 if (y
) (*y
) = m_y
- dy
;
2563 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2565 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2567 if (!m_widget
->window
) return;
2569 GdkWindow
*source
= (GdkWindow
*) NULL
;
2571 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2573 source
= m_widget
->window
;
2577 gdk_window_get_origin( source
, &org_x
, &org_y
);
2581 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2583 org_x
+= m_widget
->allocation
.x
;
2584 org_y
+= m_widget
->allocation
.y
;
2592 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2594 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2596 if (!m_widget
->window
) return;
2598 GdkWindow
*source
= (GdkWindow
*) NULL
;
2600 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2602 source
= m_widget
->window
;
2606 gdk_window_get_origin( source
, &org_x
, &org_y
);
2610 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2612 org_x
+= m_widget
->allocation
.x
;
2613 org_y
+= m_widget
->allocation
.y
;
2621 bool wxWindow::Show( bool show
)
2623 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2625 if (!wxWindowBase::Show(show
))
2632 gtk_widget_show( m_widget
);
2634 gtk_widget_hide( m_widget
);
2639 bool wxWindow::Enable( bool enable
)
2641 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2643 if (!wxWindowBase::Enable(enable
))
2649 gtk_widget_set_sensitive( m_widget
, enable
);
2651 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2656 int wxWindow::GetCharHeight() const
2658 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2660 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2662 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2664 return font
->ascent
+ font
->descent
;
2667 int wxWindow::GetCharWidth() const
2669 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2671 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2673 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2675 return gdk_string_width( font
, "H" );
2678 void wxWindow::GetTextExtent( const wxString
& string
,
2682 int *externalLeading
,
2683 const wxFont
*theFont
) const
2685 wxFont fontToUse
= m_font
;
2686 if (theFont
) fontToUse
= *theFont
;
2688 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2690 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2691 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2692 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2693 if (descent
) (*descent
) = font
->descent
;
2694 if (externalLeading
) (*externalLeading
) = 0; // ??
2697 void wxWindow::SetFocus()
2699 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2703 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2704 gtk_widget_grab_focus (m_wxwindow
);
2710 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2712 gtk_widget_grab_focus (m_widget
);
2714 else if (GTK_IS_CONTAINER(m_widget
))
2716 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2725 bool wxWindow::AcceptsFocus() const
2727 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2730 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2732 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2734 wxWindow
*oldParent
= m_parent
,
2735 *newParent
= (wxWindow
*)newParentBase
;
2737 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2739 if ( !wxWindowBase::Reparent(newParent
) )
2742 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2744 /* prevent GTK from deleting the widget arbitrarily */
2745 gtk_widget_ref( m_widget
);
2749 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2752 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2756 /* insert GTK representation */
2757 (*(newParent
->m_insertCallback
))(newParent
, this);
2760 /* reverse: prevent GTK from deleting the widget arbitrarily */
2761 gtk_widget_unref( m_widget
);
2766 void wxWindow::DoAddChild(wxWindow
*child
)
2768 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2770 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
2772 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
2777 /* insert GTK representation */
2778 (*m_insertCallback
)(this, child
);
2781 void wxWindow::Raise()
2783 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2785 if (!m_widget
->window
) return;
2787 gdk_window_raise( m_widget
->window
);
2790 void wxWindow::Lower()
2792 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2794 if (!m_widget
->window
) return;
2796 gdk_window_lower( m_widget
->window
);
2799 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2801 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2803 return wxWindowBase::SetCursor( cursor
);
2806 void wxWindow::WarpPointer( int x
, int y
)
2808 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2810 /* we provide this function ourselves as it is
2811 missing in GDK (top of this file) */
2813 GdkWindow
*window
= (GdkWindow
*) NULL
;
2815 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2817 window
= GetConnectWidget()->window
;
2820 gdk_window_warp_pointer( window
, x
, y
);
2823 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2825 if (!m_widget
) return;
2826 if (!m_widget
->window
) return;
2828 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2832 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
2834 rect
->width
, rect
->height
);
2838 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
2842 /* there is no GTK equivalent of "draw only, don't clear" so we
2843 invent our own in the GtkPizza widget */
2849 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2850 gboolean old_clear
= pizza
->clear_on_draw
;
2851 gtk_pizza_set_clear( pizza
, FALSE
);
2853 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2855 gtk_pizza_set_clear( pizza
, old_clear
);
2858 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2862 GdkRectangle gdk_rect
;
2863 gdk_rect
.x
= rect
->x
;
2864 gdk_rect
.y
= rect
->y
;
2865 gdk_rect
.width
= rect
->width
;
2866 gdk_rect
.height
= rect
->height
;
2870 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2871 gboolean old_clear
= pizza
->clear_on_draw
;
2872 gtk_pizza_set_clear( pizza
, FALSE
);
2874 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2876 gtk_pizza_set_clear( pizza
, old_clear
);
2879 gtk_widget_draw( m_widget
, &gdk_rect
);
2883 void wxWindow::Clear()
2885 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
2887 if (!m_widget
->window
) return;
2889 if (m_wxwindow
&& m_wxwindow
->window
)
2891 gdk_window_clear( m_wxwindow
->window
);
2896 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2898 wxWindowBase::DoSetToolTip(tip
);
2901 m_tooltip
->Apply( this );
2904 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2906 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
2908 #endif // wxUSE_TOOLTIPS
2910 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2912 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2914 if (!wxWindowBase::SetBackgroundColour(colour
))
2916 // don't leave if the GTK widget has just
2918 if (!m_delayedBackgroundColour
) return FALSE
;
2921 GdkWindow
*window
= (GdkWindow
*) NULL
;
2923 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2925 window
= GetConnectWidget()->window
;
2929 // indicate that a new style has been set
2930 // but it couldn't get applied as the
2931 // widget hasn't been realized yet.
2932 m_delayedBackgroundColour
= TRUE
;
2934 // pretend we have done something
2939 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
2941 /* wxMSW doesn't clear the window here. I don't do that either to
2942 provide compatibility. call Clear() to do the job. */
2944 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
2945 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
2953 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
2955 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2957 if (!wxWindowBase::SetForegroundColour(colour
))
2959 // don't leave if the GTK widget has just
2961 if (!m_delayedForegroundColour
) return FALSE
;
2964 GdkWindow
*window
= (GdkWindow
*) NULL
;
2966 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2968 window
= GetConnectWidget()->window
;
2972 // indicate that a new style has been set
2973 // but it couldn't get applied as the
2974 // widget hasn't been realized yet.
2975 m_delayedForegroundColour
= TRUE
;
2977 // pretend we have done something
2986 GtkStyle
*wxWindow::GetWidgetStyle()
2988 if (m_widgetStyle
) return m_widgetStyle
;
2990 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
2993 def
= gtk_widget_get_default_style();
2995 m_widgetStyle
= gtk_style_copy( def
);
2996 m_widgetStyle
->klass
= def
->klass
;
2998 return m_widgetStyle
;
3001 void wxWindow::SetWidgetStyle()
3003 GtkStyle
*style
= GetWidgetStyle();
3005 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3007 gdk_font_unref( style
->font
);
3008 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3011 if (m_foregroundColour
.Ok())
3013 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3014 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3016 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3017 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3018 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3022 if (m_backgroundColour
.Ok())
3024 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3025 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3027 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3028 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3029 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3030 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3031 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3032 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3033 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3034 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3039 void wxWindow::ApplyWidgetStyle()
3043 //-----------------------------------------------------------------------------
3044 // Pop-up menu stuff
3045 //-----------------------------------------------------------------------------
3047 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3049 *is_waiting
= FALSE
;
3052 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3054 menu
->SetInvokingWindow( win
);
3055 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3058 wxMenuItem
*menuitem
= node
->GetData();
3059 if (menuitem
->IsSubMenu())
3061 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3064 node
= node
->GetNext();
3068 static gint gs_pop_x
= 0;
3069 static gint gs_pop_y
= 0;
3071 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3075 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3080 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3082 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3084 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3086 SetInvokingWindow( menu
, this );
3093 bool is_waiting
= TRUE
;
3095 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3096 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3099 GTK_MENU(menu
->m_menu
),
3100 (GtkWidget
*) NULL
, // parent menu shell
3101 (GtkWidget
*) NULL
, // parent menu item
3102 (GtkMenuPositionFunc
) pop_pos_callback
,
3103 (gpointer
) this, // client data
3104 0, // button used to activate it
3105 gs_timeLastClick
// the time of activation
3110 while (gtk_events_pending())
3111 gtk_main_iteration();
3117 #if wxUSE_DRAG_AND_DROP
3119 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3121 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3123 GtkWidget
*dnd_widget
= GetConnectWidget();
3125 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3127 if (m_dropTarget
) delete m_dropTarget
;
3128 m_dropTarget
= dropTarget
;
3130 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3133 #endif // wxUSE_DRAG_AND_DROP
3135 GtkWidget
* wxWindow::GetConnectWidget()
3137 GtkWidget
*connect_widget
= m_widget
;
3138 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3140 return connect_widget
;
3143 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3146 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3148 return (window
== m_widget
->window
);
3151 bool wxWindow::SetFont( const wxFont
&font
)
3153 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3155 if (!wxWindowBase::SetFont(font
))
3160 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3161 if ( sysbg
== m_backgroundColour
)
3163 m_backgroundColour
= wxNullColour
;
3165 m_backgroundColour
= sysbg
;
3175 void wxWindow::CaptureMouse()
3177 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3179 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3181 GdkWindow
*window
= (GdkWindow
*) NULL
;
3183 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3185 window
= GetConnectWidget()->window
;
3187 if (!window
) return;
3189 gdk_pointer_grab( window
, FALSE
,
3191 (GDK_BUTTON_PRESS_MASK
|
3192 GDK_BUTTON_RELEASE_MASK
|
3193 GDK_POINTER_MOTION_HINT_MASK
|
3194 GDK_POINTER_MOTION_MASK
),
3196 m_cursor
.GetCursor(),
3197 (guint32
)GDK_CURRENT_TIME
);
3198 g_captureWindow
= this;
3201 void wxWindow::ReleaseMouse()
3203 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3205 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3207 GdkWindow
*window
= (GdkWindow
*) NULL
;
3209 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3211 window
= GetConnectWidget()->window
;
3216 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3217 g_captureWindow
= (wxWindow
*) NULL
;
3220 bool wxWindow::IsRetained() const
3225 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3226 int range
, bool refresh
)
3228 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3230 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3232 m_hasScrolling
= TRUE
;
3234 if (orient
== wxHORIZONTAL
)
3236 float fpos
= (float)pos
;
3237 float frange
= (float)range
;
3238 float fthumb
= (float)thumbVisible
;
3239 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3240 if (fpos
< 0.0) fpos
= 0.0;
3242 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3243 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3245 SetScrollPos( orient
, pos
, refresh
);
3249 m_oldHorizontalPos
= fpos
;
3251 m_hAdjust
->lower
= 0.0;
3252 m_hAdjust
->upper
= frange
;
3253 m_hAdjust
->value
= fpos
;
3254 m_hAdjust
->step_increment
= 1.0;
3255 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3256 m_hAdjust
->page_size
= fthumb
;
3260 float fpos
= (float)pos
;
3261 float frange
= (float)range
;
3262 float fthumb
= (float)thumbVisible
;
3263 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3264 if (fpos
< 0.0) fpos
= 0.0;
3266 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3267 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3269 SetScrollPos( orient
, pos
, refresh
);
3273 m_oldVerticalPos
= fpos
;
3275 m_vAdjust
->lower
= 0.0;
3276 m_vAdjust
->upper
= frange
;
3277 m_vAdjust
->value
= fpos
;
3278 m_vAdjust
->step_increment
= 1.0;
3279 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3280 m_vAdjust
->page_size
= fthumb
;
3283 if (orient
== wxHORIZONTAL
)
3284 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3286 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3289 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3291 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3293 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3295 if (orient
== wxHORIZONTAL
)
3297 float fpos
= (float)pos
;
3298 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3299 if (fpos
< 0.0) fpos
= 0.0;
3300 m_oldHorizontalPos
= fpos
;
3302 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3303 m_hAdjust
->value
= fpos
;
3307 float fpos
= (float)pos
;
3308 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3309 if (fpos
< 0.0) fpos
= 0.0;
3310 m_oldVerticalPos
= fpos
;
3312 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3313 m_vAdjust
->value
= fpos
;
3320 if (m_wxwindow
->window
)
3322 if (orient
== wxHORIZONTAL
)
3323 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3325 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3332 int wxWindow::GetScrollThumb( int orient
) const
3334 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3336 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3338 if (orient
== wxHORIZONTAL
)
3339 return (int)(m_hAdjust
->page_size
+0.5);
3341 return (int)(m_vAdjust
->page_size
+0.5);
3344 int wxWindow::GetScrollPos( int orient
) const
3346 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3348 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3350 if (orient
== wxHORIZONTAL
)
3351 return (int)(m_hAdjust
->value
+0.5);
3353 return (int)(m_vAdjust
->value
+0.5);
3356 int wxWindow::GetScrollRange( int orient
) const
3358 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3360 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3362 if (orient
== wxHORIZONTAL
)
3363 return (int)(m_hAdjust
->upper
+0.5);
3365 return (int)(m_vAdjust
->upper
+0.5);
3368 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3370 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3372 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3375 printf( "ScrollWindow: %d %d\n", dx, dy );
3378 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3383 m_scrollGC = gdk_gc_new( m_wxwindow->window );
3384 gdk_gc_set_exposures( m_scrollGC, TRUE );
3387 wxNode *node = m_children.First();
3390 wxWindow *child = (wxWindow*) node->Data();
3393 child->GetSize( &sx, &sy );
3394 child->SetSize( child->m_x + dx, child->m_y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
3395 node = node->Next();
3400 GetClientSize( &cw, &ch );
3401 int w = cw - abs(dx);
3402 int h = ch - abs(dy);
3404 if ((h < 0) || (w < 0))
3412 if (dx < 0) s_x = -dx;
3413 if (dy < 0) s_y = -dy;
3416 if (dx > 0) d_x = dx;
3417 if (dy > 0) d_y = dy;
3419 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
3420 m_wxwindow->window, s_x, s_y, w, h );
3423 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3424 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3425 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3426 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3428 Refresh( TRUE, &rect );
3433 void wxWindow::SetScrolling(bool scroll
)
3435 m_isScrolling
= g_blockEventsOnScroll
= scroll
;