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 //-----------------------------------------------------------------------------
214 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
216 # define DEBUG_MAIN_THREAD
219 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
220 GdkEvent
*WXUNUSED(event
),
221 const wxChar
*WXUNUSED(name
) )
224 static bool s_done = FALSE;
227 wxLog::AddTraceMask("focus");
230 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
236 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
238 // suppress warnings about gtk_debug_focus_in_callback being unused with
243 tmp
+= wxT(" FROM ");
246 wxChar
*s
= new wxChar
[tmp
.Length()+1];
250 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
251 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
256 #define DEBUG_MAIN_THREAD
259 //-----------------------------------------------------------------------------
260 // missing gdk functions
261 //-----------------------------------------------------------------------------
264 gdk_window_warp_pointer (GdkWindow
*window
,
268 GdkWindowPrivate
*priv
;
271 window
= (GdkWindow
*) &gdk_root_parent
;
273 priv
= (GdkWindowPrivate
*) window
;
275 if (!priv
->destroyed
)
277 XWarpPointer (priv
->xdisplay
,
278 None
, /* not source window -> move from anywhere */
279 priv
->xwindow
, /* dest window */
280 0, 0, 0, 0, /* not source window -> move from anywhere */
285 //-----------------------------------------------------------------------------
287 //-----------------------------------------------------------------------------
289 extern void wxapp_install_idle_handler();
290 extern bool g_isIdle
;
292 //-----------------------------------------------------------------------------
293 // local code (see below)
294 //-----------------------------------------------------------------------------
296 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
304 if (win
->HasScrolling())
306 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
307 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget
)->klass
);
310 GtkWidget *hscrollbar = scroll_window->hscrollbar;
311 GtkWidget *vscrollbar = scroll_window->vscrollbar;
313 we use this instead: range.slider_width = 11 + 2*2pts edge
316 if (scroll_window
->vscrollbar_visible
)
318 dw
+= 15; /* dw += vscrollbar->allocation.width; */
319 dw
+= scroll_class
->scrollbar_spacing
;
322 if (scroll_window
->hscrollbar_visible
)
324 dh
+= 15; /* dh += hscrollbar->allocation.height; */
325 dh
+= scroll_class
->scrollbar_spacing
;
331 if (GTK_WIDGET_NO_WINDOW (widget
))
333 dx
+= widget
->allocation
.x
;
334 dy
+= widget
->allocation
.y
;
337 if (win
->HasFlag(wxRAISED_BORDER
))
339 gtk_draw_shadow( widget
->style
,
344 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
348 if (win
->HasFlag(wxSUNKEN_BORDER
))
350 gtk_draw_shadow( widget
->style
,
355 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
359 if (win
->HasFlag(wxSIMPLE_BORDER
))
362 gc
= gdk_gc_new( widget
->window
);
363 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
364 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
366 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
372 //-----------------------------------------------------------------------------
373 // "expose_event" of m_widget
374 //-----------------------------------------------------------------------------
376 static void gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
378 if (gdk_event
->count
> 0) return;
379 draw_frame( widget
, win
);
382 //-----------------------------------------------------------------------------
383 // "draw" of m_widget
384 //-----------------------------------------------------------------------------
386 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
388 draw_frame( widget
, win
);
391 //-----------------------------------------------------------------------------
392 // key code mapping routines
393 //-----------------------------------------------------------------------------
395 static long map_to_unmodified_wx_keysym( KeySym keysym
)
402 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
404 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
410 case GDK_Super_R
: key_code
= WXK_ALT
; break;
411 case GDK_Menu
: key_code
= WXK_MENU
; break;
412 case GDK_Help
: key_code
= WXK_HELP
; break;
413 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
414 case GDK_ISO_Left_Tab
:
415 case GDK_Tab
: key_code
= WXK_TAB
; break;
416 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
417 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
418 case GDK_Return
: key_code
= WXK_RETURN
; break;
419 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
420 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
421 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
422 case GDK_Delete
: key_code
= WXK_DELETE
; break;
423 case GDK_Home
: key_code
= WXK_HOME
; break;
424 case GDK_Left
: key_code
= WXK_LEFT
; break;
425 case GDK_Up
: key_code
= WXK_UP
; break;
426 case GDK_Right
: key_code
= WXK_RIGHT
; break;
427 case GDK_Down
: key_code
= WXK_DOWN
; break;
428 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
429 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
430 case GDK_Next
: key_code
= WXK_NEXT
; break;
431 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
432 case GDK_End
: key_code
= WXK_END
; break;
433 case GDK_Begin
: key_code
= WXK_HOME
; break;
434 case GDK_Select
: key_code
= WXK_SELECT
; break;
435 case GDK_Print
: key_code
= WXK_PRINT
; break;
436 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
437 case GDK_Insert
: key_code
= WXK_INSERT
; break;
438 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
440 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
441 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
442 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
443 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
444 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
445 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
446 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
447 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
448 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
449 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
450 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
451 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
452 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
453 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
454 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
455 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
456 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
457 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
458 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
459 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
460 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
461 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
462 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
463 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
464 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
465 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
466 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
467 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
468 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
469 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
470 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
471 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
472 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
473 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
474 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
475 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
476 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
478 case GDK_F1
: key_code
= WXK_F1
; break;
479 case GDK_F2
: key_code
= WXK_F2
; break;
480 case GDK_F3
: key_code
= WXK_F3
; break;
481 case GDK_F4
: key_code
= WXK_F4
; break;
482 case GDK_F5
: key_code
= WXK_F5
; break;
483 case GDK_F6
: key_code
= WXK_F6
; break;
484 case GDK_F7
: key_code
= WXK_F7
; break;
485 case GDK_F8
: key_code
= WXK_F8
; break;
486 case GDK_F9
: key_code
= WXK_F9
; break;
487 case GDK_F10
: key_code
= WXK_F10
; break;
488 case GDK_F11
: key_code
= WXK_F11
; break;
489 case GDK_F12
: key_code
= WXK_F12
; break;
494 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
495 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
496 key_code
= (guint
)keysym
;
504 static long map_to_wx_keysym( KeySym keysym
)
510 case GDK_Menu
: key_code
= WXK_MENU
; break;
511 case GDK_Help
: key_code
= WXK_HELP
; break;
512 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
513 case GDK_ISO_Left_Tab
:
514 case GDK_Tab
: key_code
= WXK_TAB
; break;
515 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
516 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
517 case GDK_Return
: key_code
= WXK_RETURN
; break;
518 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
519 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
520 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
521 case GDK_Delete
: key_code
= WXK_DELETE
; break;
522 case GDK_Home
: key_code
= WXK_HOME
; break;
523 case GDK_Left
: key_code
= WXK_LEFT
; break;
524 case GDK_Up
: key_code
= WXK_UP
; break;
525 case GDK_Right
: key_code
= WXK_RIGHT
; break;
526 case GDK_Down
: key_code
= WXK_DOWN
; break;
527 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
528 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
529 case GDK_Next
: key_code
= WXK_NEXT
; break;
530 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
531 case GDK_End
: key_code
= WXK_END
; break;
532 case GDK_Begin
: key_code
= WXK_HOME
; break;
533 case GDK_Select
: key_code
= WXK_SELECT
; break;
534 case GDK_Print
: key_code
= WXK_PRINT
; break;
535 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
536 case GDK_Insert
: key_code
= WXK_INSERT
; break;
537 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
539 case GDK_KP_0
: key_code
= '0'; break;
540 case GDK_KP_1
: key_code
= '1'; break;
541 case GDK_KP_2
: key_code
= '2'; break;
542 case GDK_KP_3
: key_code
= '3'; break;
543 case GDK_KP_4
: key_code
= '4'; break;
544 case GDK_KP_5
: key_code
= '5'; break;
545 case GDK_KP_6
: key_code
= '6'; break;
546 case GDK_KP_7
: key_code
= '7'; break;
547 case GDK_KP_8
: key_code
= '8'; break;
548 case GDK_KP_9
: key_code
= '9'; break;
549 case GDK_KP_Space
: key_code
= ' '; break;
550 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
551 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
552 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
553 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
554 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
555 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
556 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
557 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
558 case GDK_KP_Up
: key_code
= WXK_UP
; break;
559 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
560 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
561 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
562 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
563 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
564 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
565 case GDK_KP_End
: key_code
= WXK_END
; break;
566 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
567 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
568 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
569 case GDK_KP_Equal
: key_code
= '='; break;
570 case GDK_KP_Multiply
: key_code
= '*'; break;
571 case GDK_KP_Add
: key_code
= '+'; break;
572 case GDK_KP_Separator
: key_code
= ','; break;
573 case GDK_KP_Subtract
: key_code
= '-'; break;
574 case GDK_KP_Decimal
: key_code
= '.'; break;
575 case GDK_KP_Divide
: key_code
= '/'; break;
577 case GDK_F1
: key_code
= WXK_F1
; break;
578 case GDK_F2
: key_code
= WXK_F2
; break;
579 case GDK_F3
: key_code
= WXK_F3
; break;
580 case GDK_F4
: key_code
= WXK_F4
; break;
581 case GDK_F5
: key_code
= WXK_F5
; break;
582 case GDK_F6
: key_code
= WXK_F6
; break;
583 case GDK_F7
: key_code
= WXK_F7
; break;
584 case GDK_F8
: key_code
= WXK_F8
; break;
585 case GDK_F9
: key_code
= WXK_F9
; break;
586 case GDK_F10
: key_code
= WXK_F10
; break;
587 case GDK_F11
: key_code
= WXK_F11
; break;
588 case GDK_F12
: key_code
= WXK_F12
; break;
593 key_code
= (guint
)keysym
;
601 //-----------------------------------------------------------------------------
602 // "expose_event" of m_wxwindow
603 //-----------------------------------------------------------------------------
605 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
612 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
614 gdk_event
->area
.width
,
615 gdk_event
->area
.height
);
618 wxPrintf( "OnExpose from " );
619 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
620 wxPrintf( win->GetClassInfo()->GetClassName() );
621 wxPrintf( " %d %d %d %d\n", (int)gdk_event->area.x,
622 (int)gdk_event->area.y,
623 (int)gdk_event->area.width,
624 (int)gdk_event->area.height );
627 if (gdk_event
->count
> 0)
630 wxEraseEvent
eevent( win
->GetId() );
631 eevent
.SetEventObject( win
);
632 win
->GetEventHandler()->ProcessEvent(eevent
);
634 wxPaintEvent
event( win
->GetId() );
635 event
.SetEventObject( win
);
636 win
->GetEventHandler()->ProcessEvent( event
);
638 win
->GetUpdateRegion().Clear();
641 //-----------------------------------------------------------------------------
642 // "draw" of m_wxwindow
643 //-----------------------------------------------------------------------------
645 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
),
646 GdkRectangle
*rect
, wxWindow
*win
)
651 wxapp_install_idle_handler();
656 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
,
657 rect
->width
, rect
->height
);
660 wxPrintf( "OnDraw from " );
661 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
662 printf( win->GetClassInfo()->GetClassName() );
663 wxPrintf( " %d %d %d %d\n", (int)rect->x,
669 wxEraseEvent
eevent( win
->GetId() );
670 eevent
.SetEventObject( win
);
671 win
->GetEventHandler()->ProcessEvent(eevent
);
673 wxPaintEvent
event( win
->GetId() );
674 event
.SetEventObject( win
);
675 win
->GetEventHandler()->ProcessEvent( event
);
677 win
->GetUpdateRegion().Clear();
680 //-----------------------------------------------------------------------------
681 // "key_press_event" from any window
682 //-----------------------------------------------------------------------------
684 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
689 wxapp_install_idle_handler();
691 if (!win
->m_hasVMT
) return FALSE
;
692 if (g_blockEventsOnDrag
) return FALSE
;
696 tmp += (char)gdk_event->keyval;
697 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
698 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
703 GdkModifierType state
;
704 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
708 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
709 /* sending unknown key events doesn't really make sense */
710 if (key_code
== 0) return FALSE
;
712 wxKeyEvent
event( wxEVT_KEY_DOWN
);
713 event
.SetTimestamp( gdk_event
->time
);
714 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
715 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
716 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
717 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
718 event
.m_keyCode
= key_code
;
719 event
.m_scanCode
= gdk_event
->keyval
;
722 event
.SetEventObject( win
);
723 ret
= win
->GetEventHandler()->ProcessEvent( event
);
728 wxWindow
*ancestor
= win
;
731 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
734 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
735 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
738 if (ancestor
->m_isFrame
)
740 ancestor
= ancestor
->GetParent();
743 #endif // wxUSE_ACCEL
745 /* wxMSW doesn't send char events with Alt pressed */
746 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
747 will only be sent if it is not in an accelerator table. */
748 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
753 wxKeyEvent
event2( wxEVT_CHAR
);
754 event2
.SetTimestamp( gdk_event
->time
);
755 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
756 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
757 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
758 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
759 event2
.m_keyCode
= key_code
;
760 event2
.m_scanCode
= gdk_event
->keyval
;
763 event2
.SetEventObject( win
);
764 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
767 /* win is a control: tab can be propagated up */
769 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
770 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
771 (win
->GetParent()) &&
772 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
774 wxNavigationKeyEvent new_event
;
775 new_event
.SetEventObject( win
);
776 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
777 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
778 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
779 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
780 new_event
.SetCurrentFocus( win
);
781 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
784 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
786 (gdk_event
->keyval
== GDK_Escape
) )
788 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
789 new_event
.SetEventObject( win
);
790 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
793 #if (GTK_MINOR_VERSION > 0)
794 /* Pressing F10 will activate the menu bar of the top frame. */
798 (gdk_event->keyval == GDK_F10) )
800 wxWindow *ancestor = win;
803 if (wxIsKindOf(ancestor,wxFrame))
805 wxFrame *frame = (wxFrame*) ancestor;
806 wxMenuBar *menubar = frame->GetMenuBar();
809 wxNode *node = menubar->GetMenus().First();
812 wxMenu *firstMenu = (wxMenu*) node->Data();
813 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
819 ancestor = ancestor->GetParent();
827 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
834 //-----------------------------------------------------------------------------
835 // "key_release_event" from any window
836 //-----------------------------------------------------------------------------
838 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
843 wxapp_install_idle_handler();
845 if (!win
->m_hasVMT
) return FALSE
;
846 if (g_blockEventsOnDrag
) return FALSE
;
849 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
850 if (gdk_event->state & GDK_SHIFT_MASK)
851 printf( "ShiftDown.\n" );
853 printf( "ShiftUp.\n" );
854 if (gdk_event->state & GDK_CONTROL_MASK)
855 printf( "ControlDown.\n" );
857 printf( "ControlUp.\n" );
861 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
863 /* sending unknown key events doesn't really make sense */
864 if (key_code
== 0) return FALSE
;
868 GdkModifierType state
;
869 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
871 wxKeyEvent
event( wxEVT_KEY_UP
);
872 event
.SetTimestamp( gdk_event
->time
);
873 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
874 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
875 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
876 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
877 event
.m_keyCode
= key_code
;
878 event
.m_scanCode
= gdk_event
->keyval
;
881 event
.SetEventObject( win
);
883 if (win
->GetEventHandler()->ProcessEvent( event
))
885 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
892 //-----------------------------------------------------------------------------
893 // "button_press_event"
894 //-----------------------------------------------------------------------------
896 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
901 wxapp_install_idle_handler();
904 wxPrintf( wxT("1) OnButtonPress from ") );
905 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
906 wxPrintf( win->GetClassInfo()->GetClassName() );
907 wxPrintf( wxT(".\n") );
909 if (!win
->m_hasVMT
) return FALSE
;
910 if (g_blockEventsOnDrag
) return TRUE
;
911 if (g_blockEventsOnScroll
) return TRUE
;
913 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
917 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
919 gtk_widget_grab_focus (win
->m_wxwindow
);
922 wxPrintf( wxT("GrabFocus from ") );
923 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
924 wxPrintf( win->GetClassInfo()->GetClassName() );
925 wxPrintf( wxT(".\n") );
931 wxEventType event_type
= wxEVT_LEFT_DOWN
;
933 if (gdk_event
->button
== 1)
935 switch (gdk_event
->type
)
937 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
938 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
942 else if (gdk_event
->button
== 2)
944 switch (gdk_event
->type
)
946 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
947 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
951 else if (gdk_event
->button
== 3)
953 switch (gdk_event
->type
)
955 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
956 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
961 wxMouseEvent
event( event_type
);
962 event
.SetTimestamp( gdk_event
->time
);
963 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
964 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
965 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
966 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
967 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
968 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
969 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
971 event
.m_x
= (wxCoord
)gdk_event
->x
;
972 event
.m_y
= (wxCoord
)gdk_event
->y
;
974 // Some control don't have their own X window and thus cannot get
977 if (!g_captureWindow
)
979 wxCoord x
= event
.m_x
;
980 wxCoord y
= event
.m_y
;
983 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
988 wxNode
*node
= win
->GetChildren().First();
991 wxWindow
*child
= (wxWindow
*)node
->Data();
994 if (!child
->IsShown())
997 if (child
->m_isStaticBox
)
999 // wxStaticBox is transparent in the box itself
1000 int xx1
= child
->m_x
;
1001 int yy1
= child
->m_y
;
1002 int xx2
= child
->m_x
+ child
->m_width
;
1003 int yy2
= child
->m_x
+ child
->m_height
;
1006 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1008 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1010 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1012 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1015 event
.m_x
-= child
->m_x
;
1016 event
.m_y
-= child
->m_y
;
1023 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1024 (child
->m_x
<= x
) &&
1025 (child
->m_y
<= y
) &&
1026 (child
->m_x
+child
->m_width
>= x
) &&
1027 (child
->m_y
+child
->m_height
>= y
))
1030 event
.m_x
-= child
->m_x
;
1031 event
.m_y
-= child
->m_y
;
1038 event
.SetEventObject( win
);
1040 gs_timeLastClick
= gdk_event
->time
;
1043 wxPrintf( wxT("2) OnButtonPress from ") );
1044 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1045 wxPrintf( win->GetClassInfo()->GetClassName() );
1046 wxPrintf( wxT(".\n") );
1049 if (win
->GetEventHandler()->ProcessEvent( event
))
1051 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1058 //-----------------------------------------------------------------------------
1059 // "button_release_event"
1060 //-----------------------------------------------------------------------------
1062 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1067 wxapp_install_idle_handler();
1069 if (!win
->m_hasVMT
) return FALSE
;
1070 if (g_blockEventsOnDrag
) return FALSE
;
1071 if (g_blockEventsOnScroll
) return FALSE
;
1073 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1076 printf( "OnButtonRelease from " );
1077 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1078 printf( win->GetClassInfo()->GetClassName() );
1082 wxEventType event_type
= wxEVT_NULL
;
1084 switch (gdk_event
->button
)
1086 case 1: event_type
= wxEVT_LEFT_UP
; break;
1087 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1088 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1091 wxMouseEvent
event( event_type
);
1092 event
.SetTimestamp( gdk_event
->time
);
1093 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1094 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1095 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1096 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1097 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1098 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1099 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1100 event
.m_x
= (wxCoord
)gdk_event
->x
;
1101 event
.m_y
= (wxCoord
)gdk_event
->y
;
1103 // Some control don't have their own X window and thus cannot get
1106 if (!g_captureWindow
)
1108 wxCoord x
= event
.m_x
;
1109 wxCoord y
= event
.m_y
;
1110 if (win
->m_wxwindow
)
1112 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1113 x
+= pizza
->xoffset
;
1114 y
+= pizza
->yoffset
;
1117 wxNode
*node
= win
->GetChildren().First();
1120 wxWindow
*child
= (wxWindow
*)node
->Data();
1122 node
= node
->Next();
1123 if (!child
->IsShown())
1126 if (child
->m_isStaticBox
)
1128 // wxStaticBox is transparent in the box itself
1129 int xx1
= child
->m_x
;
1130 int yy1
= child
->m_y
;
1131 int xx2
= child
->m_x
+ child
->m_width
;
1132 int yy2
= child
->m_x
+ child
->m_height
;
1135 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1137 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1139 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1141 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1144 event
.m_x
-= child
->m_x
;
1145 event
.m_y
-= child
->m_y
;
1152 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1153 (child
->m_x
<= x
) &&
1154 (child
->m_y
<= y
) &&
1155 (child
->m_x
+child
->m_width
>= x
) &&
1156 (child
->m_y
+child
->m_height
>= y
))
1159 event
.m_x
-= child
->m_x
;
1160 event
.m_y
-= child
->m_y
;
1167 event
.SetEventObject( win
);
1169 if (win
->GetEventHandler()->ProcessEvent( event
))
1171 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1178 //-----------------------------------------------------------------------------
1179 // "motion_notify_event"
1180 //-----------------------------------------------------------------------------
1182 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1187 wxapp_install_idle_handler();
1189 if (!win
->m_hasVMT
) return FALSE
;
1190 if (g_blockEventsOnDrag
) return FALSE
;
1191 if (g_blockEventsOnScroll
) return FALSE
;
1193 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1195 if (gdk_event
->is_hint
)
1199 GdkModifierType state
;
1200 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1206 printf( "OnMotion from " );
1207 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1208 printf( win->GetClassInfo()->GetClassName() );
1212 wxMouseEvent
event( wxEVT_MOTION
);
1213 event
.SetTimestamp( gdk_event
->time
);
1214 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1215 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1216 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1217 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1218 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1219 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1220 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1222 event
.m_x
= (wxCoord
)gdk_event
->x
;
1223 event
.m_y
= (wxCoord
)gdk_event
->y
;
1225 // Some control don't have their own X window and thus cannot get
1228 if (!g_captureWindow
)
1230 wxCoord x
= event
.m_x
;
1231 wxCoord y
= event
.m_y
;
1232 if (win
->m_wxwindow
)
1234 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1235 x
+= pizza
->xoffset
;
1236 y
+= pizza
->yoffset
;
1239 wxNode
*node
= win
->GetChildren().First();
1242 wxWindow
*child
= (wxWindow
*)node
->Data();
1244 node
= node
->Next();
1245 if (!child
->IsShown())
1248 if (child
->m_isStaticBox
)
1250 // wxStaticBox is transparent in the box itself
1251 int xx1
= child
->m_x
;
1252 int yy1
= child
->m_y
;
1253 int xx2
= child
->m_x
+ child
->m_width
;
1254 int yy2
= child
->m_x
+ child
->m_height
;
1257 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1259 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1261 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1263 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1266 event
.m_x
-= child
->m_x
;
1267 event
.m_y
-= child
->m_y
;
1274 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1275 (child
->m_x
<= x
) &&
1276 (child
->m_y
<= y
) &&
1277 (child
->m_x
+child
->m_width
>= x
) &&
1278 (child
->m_y
+child
->m_height
>= y
))
1281 event
.m_x
-= child
->m_x
;
1282 event
.m_y
-= child
->m_y
;
1289 event
.SetEventObject( win
);
1291 if (win
->GetEventHandler()->ProcessEvent( event
))
1293 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1300 //-----------------------------------------------------------------------------
1302 //-----------------------------------------------------------------------------
1304 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1309 wxapp_install_idle_handler();
1311 if (!win
->m_hasVMT
) return FALSE
;
1312 if (g_blockEventsOnDrag
) return FALSE
;
1314 switch ( g_sendActivateEvent
)
1317 // we've got focus from outside, synthtize wxActivateEvent
1318 g_sendActivateEvent
= 1;
1322 // another our window just lost focus, it was already ours before
1323 // - don't send any wxActivateEvent
1324 g_sendActivateEvent
= -1;
1328 g_focusWindow
= win
;
1331 printf( "OnSetFocus from " );
1332 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1333 printf( win->GetClassInfo()->GetClassName() );
1335 printf( WXSTRINGCAST win->GetLabel() );
1339 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1342 panel
->SetLastFocus(win
);
1347 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1350 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1351 event
.SetEventObject( win
);
1353 if (win
->GetEventHandler()->ProcessEvent( event
))
1355 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1362 //-----------------------------------------------------------------------------
1363 // "focus_out_event"
1364 //-----------------------------------------------------------------------------
1366 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1371 wxapp_install_idle_handler();
1373 if (!win
->m_hasVMT
) return FALSE
;
1374 if (g_blockEventsOnDrag
) return FALSE
;
1376 // if the focus goes out of our app alltogether, OnIdle() will send
1377 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1378 // g_sendActivateEvent to -1
1379 g_sendActivateEvent
= 0;
1381 g_focusWindow
= (wxWindow
*)NULL
;
1384 printf( "OnKillFocus from " );
1385 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1386 printf( win->GetClassInfo()->GetClassName() );
1395 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1396 event
.SetEventObject( win
);
1398 if (win
->GetEventHandler()->ProcessEvent( event
))
1400 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1407 //-----------------------------------------------------------------------------
1408 // "enter_notify_event"
1409 //-----------------------------------------------------------------------------
1411 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1416 wxapp_install_idle_handler();
1418 if (!win
->m_hasVMT
) return FALSE
;
1419 if (g_blockEventsOnDrag
) return FALSE
;
1421 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1423 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1424 #if (GTK_MINOR_VERSION > 0)
1425 event
.SetTimestamp( gdk_event
->time
);
1427 event
.SetEventObject( win
);
1431 GdkModifierType state
= (GdkModifierType
)0;
1433 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1435 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1436 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1437 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1438 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1439 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1440 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1441 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1446 if (win
->GetEventHandler()->ProcessEvent( event
))
1448 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1455 //-----------------------------------------------------------------------------
1456 // "leave_notify_event"
1457 //-----------------------------------------------------------------------------
1459 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1464 wxapp_install_idle_handler();
1466 if (!win
->m_hasVMT
) return FALSE
;
1467 if (g_blockEventsOnDrag
) return FALSE
;
1469 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1471 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1472 #if (GTK_MINOR_VERSION > 0)
1473 event
.SetTimestamp( gdk_event
->time
);
1475 event
.SetEventObject( win
);
1479 GdkModifierType state
= (GdkModifierType
)0;
1481 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1483 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1484 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1485 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1486 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1487 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1488 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1489 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1494 if (win
->GetEventHandler()->ProcessEvent( event
))
1496 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1503 //-----------------------------------------------------------------------------
1504 // "value_changed" from m_vAdjust
1505 //-----------------------------------------------------------------------------
1507 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1512 wxapp_install_idle_handler();
1514 if (g_blockEventsOnDrag
) return;
1516 if (!win
->m_hasVMT
) return;
1518 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1519 if (fabs(diff
) < 0.2) return;
1521 win
->m_oldVerticalPos
= adjust
->value
;
1523 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1524 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1526 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1527 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1528 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1529 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1530 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1532 int value
= (int)(adjust
->value
+0.5);
1534 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1535 event
.SetEventObject( win
);
1536 win
->GetEventHandler()->ProcessEvent( event
);
1539 //-----------------------------------------------------------------------------
1540 // "value_changed" from m_hAdjust
1541 //-----------------------------------------------------------------------------
1543 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1548 wxapp_install_idle_handler();
1550 if (g_blockEventsOnDrag
) return;
1551 if (!win
->m_hasVMT
) return;
1553 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1554 if (fabs(diff
) < 0.2) return;
1556 win
->m_oldHorizontalPos
= adjust
->value
;
1558 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1559 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1561 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1562 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1563 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1564 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1565 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1567 int value
= (int)(adjust
->value
+0.5);
1569 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1570 event
.SetEventObject( win
);
1571 win
->GetEventHandler()->ProcessEvent( event
);
1574 //-----------------------------------------------------------------------------
1575 // "changed" from m_vAdjust
1576 //-----------------------------------------------------------------------------
1578 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1583 wxapp_install_idle_handler();
1585 if (g_blockEventsOnDrag
) return;
1586 if (!win
->m_hasVMT
) return;
1588 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1589 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1591 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1592 event
.SetEventObject( win
);
1593 win
->GetEventHandler()->ProcessEvent( event
);
1596 //-----------------------------------------------------------------------------
1597 // "changed" from m_hAdjust
1598 //-----------------------------------------------------------------------------
1600 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1605 wxapp_install_idle_handler();
1607 if (g_blockEventsOnDrag
) return;
1608 if (!win
->m_hasVMT
) return;
1610 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1611 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1613 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1614 event
.SetEventObject( win
);
1615 win
->GetEventHandler()->ProcessEvent( event
);
1618 //-----------------------------------------------------------------------------
1619 // "button_press_event" from scrollbar
1620 //-----------------------------------------------------------------------------
1622 static gint
gtk_scrollbar_button_press_callback( GtkRange
*WXUNUSED(widget
),
1623 GdkEventButton
*WXUNUSED(gdk_event
),
1629 wxapp_install_idle_handler();
1631 // don't test here as we can release the mouse while being over
1632 // a different window than the slider
1634 // if (gdk_event->window != widget->slider) return FALSE;
1636 win
->SetScrolling( TRUE
);
1641 //-----------------------------------------------------------------------------
1642 // "button_release_event" from scrollbar
1643 //-----------------------------------------------------------------------------
1645 static gint
gtk_scrollbar_button_release_callback( GtkRange
*WXUNUSED(widget
),
1646 GdkEventButton
*WXUNUSED(gdk_event
),
1652 // don't test here as we can release the mouse while being over
1653 // a different window than the slider
1655 // if (gdk_event->window != widget->slider) return FALSE;
1657 win
->SetScrolling( FALSE
);
1662 // ----------------------------------------------------------------------------
1663 // this wxWindowBase function is implemented here (in platform-specific file)
1664 // because it is static and so couldn't be made virtual
1665 // ----------------------------------------------------------------------------
1667 wxWindow
*wxWindowBase::FindFocus()
1669 return g_focusWindow
;
1672 //-----------------------------------------------------------------------------
1673 // "realize" from m_widget
1674 //-----------------------------------------------------------------------------
1676 /* We cannot set colours and fonts before the widget has
1677 been realized, so we do this directly after realization. */
1680 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1685 wxapp_install_idle_handler();
1687 if (win
->m_delayedBackgroundColour
)
1688 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1690 if (win
->m_delayedForegroundColour
)
1691 win
->SetForegroundColour( win
->GetForegroundColour() );
1693 wxWindowCreateEvent
event( win
);
1694 event
.SetEventObject( win
);
1695 win
->GetEventHandler()->ProcessEvent( event
);
1700 //-----------------------------------------------------------------------------
1702 //-----------------------------------------------------------------------------
1705 #define WXUNUSED_UNLESS_XIM(param) param
1707 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1710 /* Resize XIM window */
1713 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1714 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1715 wxFrame
* WXUNUSED_UNLESS_XIM(win
) )
1718 wxapp_install_idle_handler();
1724 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1728 gdk_window_get_size (widget
->window
, &width
, &height
);
1729 win
->m_icattr
->preedit_area
.width
= width
;
1730 win
->m_icattr
->preedit_area
.height
= height
;
1731 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
1736 //-----------------------------------------------------------------------------
1737 // "realize" from m_wxwindow
1738 //-----------------------------------------------------------------------------
1740 /* Initialize XIM support */
1743 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1744 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1747 wxapp_install_idle_handler();
1750 if (win
->m_ic
) return FALSE
;
1751 if (!widget
) return FALSE
;
1752 if (!gdk_im_ready()) return FALSE
;
1754 win
->m_icattr
= gdk_ic_attr_new();
1755 if (!win
->m_icattr
) return FALSE
;
1759 GdkColormap
*colormap
;
1760 GdkICAttr
*attr
= win
->m_icattr
;
1761 unsigned attrmask
= GDK_IC_ALL_REQ
;
1763 GdkIMStyle supported_style
= (GdkIMStyle
)
1764 (GDK_IM_PREEDIT_NONE
|
1765 GDK_IM_PREEDIT_NOTHING
|
1766 GDK_IM_PREEDIT_POSITION
|
1767 GDK_IM_STATUS_NONE
|
1768 GDK_IM_STATUS_NOTHING
);
1770 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1771 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
1773 attr
->style
= style
= gdk_im_decide_style (supported_style
);
1774 attr
->client_window
= widget
->window
;
1776 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
1777 gtk_widget_get_default_colormap ())
1779 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
1780 attr
->preedit_colormap
= colormap
;
1783 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
1784 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
1785 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
1786 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
1788 switch (style
& GDK_IM_PREEDIT_MASK
)
1790 case GDK_IM_PREEDIT_POSITION
:
1791 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1793 g_warning ("over-the-spot style requires fontset");
1797 gdk_window_get_size (widget
->window
, &width
, &height
);
1799 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
1800 attr
->spot_location
.x
= 0;
1801 attr
->spot_location
.y
= height
;
1802 attr
->preedit_area
.x
= 0;
1803 attr
->preedit_area
.y
= 0;
1804 attr
->preedit_area
.width
= width
;
1805 attr
->preedit_area
.height
= height
;
1806 attr
->preedit_fontset
= widget
->style
->font
;
1811 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
1813 if (win
->m_ic
== NULL
)
1814 g_warning ("Can't create input context.");
1817 mask
= gdk_window_get_events (widget
->window
);
1818 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
1819 gdk_window_set_events (widget
->window
, mask
);
1821 if (GTK_WIDGET_HAS_FOCUS(widget
))
1822 gdk_im_begin (win
->m_ic
, widget
->window
);
1829 //-----------------------------------------------------------------------------
1830 // InsertChild for wxWindow.
1831 //-----------------------------------------------------------------------------
1833 /* Callback for wxWindow. This very strange beast has to be used because
1834 * C++ has no virtual methods in a constructor. We have to emulate a
1835 * virtual function here as wxNotebook requires a different way to insert
1836 * a child in it. I had opted for creating a wxNotebookPage window class
1837 * which would have made this superfluous (such in the MDI window system),
1838 * but no-one was listening to me... */
1840 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1842 /* the window might have been scrolled already, do we
1843 have to adapt the position */
1844 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
1845 child
->m_x
+= pizza
->xoffset
;
1846 child
->m_y
+= pizza
->yoffset
;
1848 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
1849 GTK_WIDGET(child
->m_widget
),
1856 //-----------------------------------------------------------------------------
1858 //-----------------------------------------------------------------------------
1860 wxWindow
* wxGetActiveWindow()
1862 return g_focusWindow
;
1865 //-----------------------------------------------------------------------------
1867 //-----------------------------------------------------------------------------
1869 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
1871 void wxWindow::Init()
1877 m_widget
= (GtkWidget
*) NULL
;
1878 m_wxwindow
= (GtkWidget
*) NULL
;
1888 m_needParent
= TRUE
;
1889 m_isBeingDeleted
= FALSE
;
1892 m_nativeSizeEvent
= FALSE
;
1894 m_hasScrolling
= FALSE
;
1895 m_isScrolling
= FALSE
;
1897 m_hAdjust
= (GtkAdjustment
*) NULL
;
1898 m_vAdjust
= (GtkAdjustment
*) NULL
;
1899 m_oldHorizontalPos
= 0.0;
1900 m_oldVerticalPos
= 0.0;
1903 m_widgetStyle
= (GtkStyle
*) NULL
;
1905 m_insertCallback
= (wxInsertChildFunction
) NULL
;
1907 m_isStaticBox
= FALSE
;
1908 m_isRadioButton
= FALSE
;
1910 m_acceptsFocus
= FALSE
;
1912 m_cursor
= *wxSTANDARD_CURSOR
;
1915 m_ic
= (GdkIC
*) NULL
;
1916 m_icattr
= (GdkICAttr
*) NULL
;
1920 wxWindow::wxWindow()
1925 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1926 const wxPoint
&pos
, const wxSize
&size
,
1927 long style
, const wxString
&name
)
1931 Create( parent
, id
, pos
, size
, style
, name
);
1934 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1935 const wxPoint
&pos
, const wxSize
&size
,
1936 long style
, const wxString
&name
)
1938 if (!PreCreation( parent
, pos
, size
) ||
1939 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
1941 wxFAIL_MSG( wxT("wxWindow creation failed") );
1945 m_insertCallback
= wxInsertChildInWindow
;
1947 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
1948 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1951 debug_focus_in( m_widget
, wxT("wxWindow::m_widget"), name
);
1954 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
1957 debug_focus_in( scrolledWindow
->hscrollbar
, wxT("wxWindow::hsrcollbar"), name
);
1958 debug_focus_in( scrolledWindow
->vscrollbar
, wxT("wxWindow::vsrcollbar"), name
);
1961 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1962 scroll_class
->scrollbar_spacing
= 0;
1964 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1966 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
1967 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
1969 m_wxwindow
= gtk_pizza_new();
1972 debug_focus_in( m_wxwindow
, wxT("wxWindow::m_wxwindow"), name
);
1975 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
1977 #if (GTK_MINOR_VERSION > 0)
1978 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
1980 if (HasFlag(wxRAISED_BORDER
))
1982 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
1984 else if (HasFlag(wxSUNKEN_BORDER
))
1986 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
1988 else if (HasFlag(wxSIMPLE_BORDER
))
1990 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
1994 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
1996 #else // GTK_MINOR_VERSION == 0
1997 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
1999 if (HasFlag(wxRAISED_BORDER
))
2001 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2003 else if (HasFlag(wxSUNKEN_BORDER
))
2005 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2009 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2011 #endif // GTK_MINOR_VERSION
2013 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2014 m_acceptsFocus
= TRUE
;
2016 #if (GTK_MINOR_VERSION == 0)
2017 // shut the viewport up
2018 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2019 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2020 #endif // GTK_MINOR_VERSION == 0
2022 // I _really_ don't want scrollbars in the beginning
2023 m_vAdjust
->lower
= 0.0;
2024 m_vAdjust
->upper
= 1.0;
2025 m_vAdjust
->value
= 0.0;
2026 m_vAdjust
->step_increment
= 1.0;
2027 m_vAdjust
->page_increment
= 1.0;
2028 m_vAdjust
->page_size
= 5.0;
2029 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2030 m_hAdjust
->lower
= 0.0;
2031 m_hAdjust
->upper
= 1.0;
2032 m_hAdjust
->value
= 0.0;
2033 m_hAdjust
->step_increment
= 1.0;
2034 m_hAdjust
->page_increment
= 1.0;
2035 m_hAdjust
->page_size
= 5.0;
2036 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2038 // these handlers block mouse events to any window during scrolling such as
2039 // motion events and prevent GTK and wxWindows from fighting over where the
2042 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2043 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2045 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2046 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2048 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2049 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2051 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2052 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2054 // these handlers get notified when screen updates are required either when
2055 // scrolling or when the window size (and therefore scrollbar configuration)
2058 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2059 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2060 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2061 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2063 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
2064 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
2065 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
2066 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
2068 gtk_widget_show( m_wxwindow
);
2071 m_parent
->DoAddChild( this );
2080 wxWindow::~wxWindow()
2082 m_isBeingDeleted
= TRUE
;
2091 m_parent
->RemoveChild( this );
2095 gdk_ic_destroy (m_ic
);
2097 gdk_ic_attr_destroy (m_icattr
);
2102 gtk_style_unref( m_widgetStyle
);
2103 m_widgetStyle
= (GtkStyle
*) NULL
;
2108 gtk_widget_destroy( m_wxwindow
);
2109 m_wxwindow
= (GtkWidget
*) NULL
;
2114 gtk_widget_destroy( m_widget
);
2115 m_widget
= (GtkWidget
*) NULL
;
2119 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2121 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2123 /* this turns -1 into 20 so that a minimal window is
2124 visible even although -1,-1 has been given as the
2125 size of the window. the same trick is used in other
2126 ports and should make debugging easier */
2127 m_width
= WidthDefault(size
.x
);
2128 m_height
= HeightDefault(size
.y
);
2133 /* some reasonable defaults */
2138 m_x
= (gdk_screen_width () - m_width
) / 2;
2139 if (m_x
< 10) m_x
= 10;
2143 m_y
= (gdk_screen_height () - m_height
) / 2;
2144 if (m_y
< 10) m_y
= 10;
2151 void wxWindow::PostCreation()
2153 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2159 /* these get reported to wxWindows -> wxPaintEvent */
2160 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2161 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2163 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2164 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2167 #if (GTK_MINOR_VERSION > 0)
2168 /* these are called when the "sunken" or "raised" borders are drawn */
2169 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2170 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2172 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2173 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2177 if (m_wxwindow
&& m_needParent
)
2179 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2180 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2182 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2183 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2187 // For dialogs and frames, we are interested mainly in
2188 // m_widget's focus.
2190 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2191 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2193 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2194 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2197 GtkWidget
*connect_widget
= GetConnectWidget();
2199 ConnectWidget( connect_widget
);
2201 /* We cannot set colours, fonts and cursors before the widget has
2202 been realized, so we do this directly after realization */
2203 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2204 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2208 /* Initialize XIM support. */
2209 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2210 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2212 /* And resize XIM window. */
2213 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2214 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2220 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2222 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2223 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2225 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2226 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2228 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2229 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2231 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2232 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2234 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2235 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2237 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2238 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2240 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2241 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2244 bool wxWindow::Destroy()
2246 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2250 return wxWindowBase::Destroy();
2253 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2255 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2258 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2260 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2261 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2263 if (m_resizing
) return; /* I don't like recursions */
2266 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2268 /* don't set the size for children of wxNotebook, just take the values. */
2276 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2278 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2280 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2281 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2282 if (width
!= -1) m_width
= width
;
2283 if (height
!= -1) m_height
= height
;
2287 m_x
= x
+ pizza
->xoffset
;
2288 m_y
= y
+ pizza
->yoffset
;
2293 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2295 if (width
== -1) m_width
= 80;
2298 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2300 if (height
== -1) m_height
= 26;
2303 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2304 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2305 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2306 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2309 int bottom_border
= 0;
2311 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2313 /* the default button has a border around it */
2318 DoMoveWindow( m_x
-border
,
2321 m_height
+border
+bottom_border
);
2325 wxPrintf( "OnSize sent from " );
2326 if (GetClassInfo() && GetClassInfo()->GetClassName())
2327 wxPrintf( GetClassInfo()->GetClassName() );
2328 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2331 if (!m_nativeSizeEvent
)
2333 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2334 event
.SetEventObject( this );
2335 GetEventHandler()->ProcessEvent( event
);
2341 void wxWindow::OnInternalIdle()
2343 if ( g_sendActivateEvent
!= -1 )
2345 bool activate
= g_sendActivateEvent
!= 0;
2348 g_sendActivateEvent
= -1;
2350 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2351 event
.SetEventObject(this);
2353 (void)GetEventHandler()->ProcessEvent(event
);
2356 wxCursor cursor
= m_cursor
;
2357 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2361 /* I now set the cursor anew in every OnInternalIdle call
2362 as setting the cursor in a parent window also effects the
2363 windows above so that checking for the current cursor is
2368 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2370 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2372 if (!g_globalCursor
.Ok())
2373 cursor
= *wxSTANDARD_CURSOR
;
2375 window
= m_widget
->window
;
2376 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2377 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2383 GdkWindow
*window
= m_widget
->window
;
2384 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2385 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2393 void wxWindow::DoGetSize( int *width
, int *height
) const
2395 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2397 if (width
) (*width
) = m_width
;
2398 if (height
) (*height
) = m_height
;
2401 void wxWindow::DoSetClientSize( int width
, int height
)
2403 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2407 SetSize( width
, height
);
2414 #if (GTK_MINOR_VERSION == 0)
2415 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2419 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2420 #if 0 // unused - if this is ok, just remove this line (VZ)
2421 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2424 GtkWidget
*viewport
= scroll_window
->viewport
;
2425 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2427 dw
+= 2 * viewport_class
->xthickness
;
2428 dh
+= 2 * viewport_class
->ythickness
;
2432 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2434 /* when using GTK 1.2 we set the shadow border size to 2 */
2438 if (HasFlag(wxSIMPLE_BORDER
))
2440 /* when using GTK 1.2 we set the simple border size to 1 */
2449 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2450 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2452 we use this instead: range.slider_width = 11 + 2*2pts edge
2455 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2456 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2458 if (scroll_window
->vscrollbar_visible
)
2460 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2461 dw
+= scroll_class
->scrollbar_spacing
;
2464 if (scroll_window
->hscrollbar_visible
)
2466 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2467 dh
+= scroll_class
->scrollbar_spacing
;
2471 SetSize( width
+dw
, height
+dh
);
2475 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2477 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2481 if (width
) (*width
) = m_width
;
2482 if (height
) (*height
) = m_height
;
2489 #if (GTK_MINOR_VERSION == 0)
2490 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2494 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2495 #if 0 // unused - if this is ok, just remove this line (VZ)
2496 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2499 GtkWidget
*viewport
= scroll_window
->viewport
;
2500 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2502 dw
+= 2 * viewport_class
->xthickness
;
2503 dh
+= 2 * viewport_class
->ythickness
;
2507 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2509 /* when using GTK 1.2 we set the shadow border size to 2 */
2513 if (HasFlag(wxSIMPLE_BORDER
))
2515 /* when using GTK 1.2 we set the simple border size to 1 */
2523 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2524 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2526 we use this instead: range.slider_width = 11 + 2*2pts edge
2529 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2530 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2532 if (scroll_window
->vscrollbar_visible
)
2534 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2535 dw
+= scroll_class
->scrollbar_spacing
;
2538 if (scroll_window
->hscrollbar_visible
)
2540 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2541 dh
+= scroll_class
->scrollbar_spacing
;
2545 if (width
) (*width
) = m_width
- dw
;
2546 if (height
) (*height
) = m_height
- dh
;
2550 void wxWindow::DoGetPosition( int *x
, int *y
) const
2552 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2556 if (m_parent
&& m_parent
->m_wxwindow
)
2558 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2559 dx
= pizza
->xoffset
;
2560 dy
= pizza
->yoffset
;
2563 if (x
) (*x
) = m_x
- dx
;
2564 if (y
) (*y
) = m_y
- dy
;
2567 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2569 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2571 if (!m_widget
->window
) return;
2573 GdkWindow
*source
= (GdkWindow
*) NULL
;
2575 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2577 source
= m_widget
->window
;
2581 gdk_window_get_origin( source
, &org_x
, &org_y
);
2585 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2587 org_x
+= m_widget
->allocation
.x
;
2588 org_y
+= m_widget
->allocation
.y
;
2596 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2598 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2600 if (!m_widget
->window
) return;
2602 GdkWindow
*source
= (GdkWindow
*) NULL
;
2604 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2606 source
= m_widget
->window
;
2610 gdk_window_get_origin( source
, &org_x
, &org_y
);
2614 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2616 org_x
+= m_widget
->allocation
.x
;
2617 org_y
+= m_widget
->allocation
.y
;
2625 bool wxWindow::Show( bool show
)
2627 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2629 if (!wxWindowBase::Show(show
))
2636 gtk_widget_show( m_widget
);
2638 gtk_widget_hide( m_widget
);
2643 bool wxWindow::Enable( bool enable
)
2645 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2647 if (!wxWindowBase::Enable(enable
))
2653 gtk_widget_set_sensitive( m_widget
, enable
);
2655 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2660 int wxWindow::GetCharHeight() const
2662 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2664 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2666 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2668 return font
->ascent
+ font
->descent
;
2671 int wxWindow::GetCharWidth() const
2673 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2675 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2677 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2679 return gdk_string_width( font
, "H" );
2682 void wxWindow::GetTextExtent( const wxString
& string
,
2686 int *externalLeading
,
2687 const wxFont
*theFont
) const
2689 wxFont fontToUse
= m_font
;
2690 if (theFont
) fontToUse
= *theFont
;
2692 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2694 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2695 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2696 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2697 if (descent
) (*descent
) = font
->descent
;
2698 if (externalLeading
) (*externalLeading
) = 0; // ??
2701 void wxWindow::SetFocus()
2703 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2707 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2708 gtk_widget_grab_focus (m_wxwindow
);
2714 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2716 gtk_widget_grab_focus (m_widget
);
2718 else if (GTK_IS_CONTAINER(m_widget
))
2720 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2729 bool wxWindow::AcceptsFocus() const
2731 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2734 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2736 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2738 wxWindow
*oldParent
= m_parent
,
2739 *newParent
= (wxWindow
*)newParentBase
;
2741 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2743 if ( !wxWindowBase::Reparent(newParent
) )
2746 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2748 /* prevent GTK from deleting the widget arbitrarily */
2749 gtk_widget_ref( m_widget
);
2753 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2756 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2760 /* insert GTK representation */
2761 (*(newParent
->m_insertCallback
))(newParent
, this);
2764 /* reverse: prevent GTK from deleting the widget arbitrarily */
2765 gtk_widget_unref( m_widget
);
2770 void wxWindow::DoAddChild(wxWindow
*child
)
2772 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2774 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
2776 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
2781 /* insert GTK representation */
2782 (*m_insertCallback
)(this, child
);
2785 void wxWindow::Raise()
2787 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2789 if (!m_widget
->window
) return;
2791 gdk_window_raise( m_widget
->window
);
2794 void wxWindow::Lower()
2796 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2798 if (!m_widget
->window
) return;
2800 gdk_window_lower( m_widget
->window
);
2803 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2805 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2807 return wxWindowBase::SetCursor( cursor
);
2810 void wxWindow::WarpPointer( int x
, int y
)
2812 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2814 /* we provide this function ourselves as it is
2815 missing in GDK (top of this file) */
2817 GdkWindow
*window
= (GdkWindow
*) NULL
;
2819 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2821 window
= GetConnectWidget()->window
;
2824 gdk_window_warp_pointer( window
, x
, y
);
2827 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2829 if (!m_widget
) return;
2830 if (!m_widget
->window
) return;
2832 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2836 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
2838 rect
->width
, rect
->height
);
2842 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
2846 /* there is no GTK equivalent of "draw only, don't clear" so we
2847 invent our own in the GtkPizza widget */
2853 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2854 gboolean old_clear
= pizza
->clear_on_draw
;
2855 gtk_pizza_set_clear( pizza
, FALSE
);
2857 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2859 gtk_pizza_set_clear( pizza
, old_clear
);
2862 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2866 GdkRectangle gdk_rect
;
2867 gdk_rect
.x
= rect
->x
;
2868 gdk_rect
.y
= rect
->y
;
2869 gdk_rect
.width
= rect
->width
;
2870 gdk_rect
.height
= rect
->height
;
2874 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2875 gboolean old_clear
= pizza
->clear_on_draw
;
2876 gtk_pizza_set_clear( pizza
, FALSE
);
2878 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2880 gtk_pizza_set_clear( pizza
, old_clear
);
2883 gtk_widget_draw( m_widget
, &gdk_rect
);
2887 void wxWindow::Clear()
2889 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
2891 if (!m_widget
->window
) return;
2893 if (m_wxwindow
&& m_wxwindow
->window
)
2895 gdk_window_clear( m_wxwindow
->window
);
2900 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2902 wxWindowBase::DoSetToolTip(tip
);
2905 m_tooltip
->Apply( this );
2908 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2910 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
2912 #endif // wxUSE_TOOLTIPS
2914 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2916 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2918 if (!wxWindowBase::SetBackgroundColour(colour
))
2920 // don't leave if the GTK widget has just
2922 if (!m_delayedBackgroundColour
) return FALSE
;
2925 GdkWindow
*window
= (GdkWindow
*) NULL
;
2927 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2929 window
= GetConnectWidget()->window
;
2933 // indicate that a new style has been set
2934 // but it couldn't get applied as the
2935 // widget hasn't been realized yet.
2936 m_delayedBackgroundColour
= TRUE
;
2938 // pretend we have done something
2943 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
2945 /* wxMSW doesn't clear the window here. I don't do that either to
2946 provide compatibility. call Clear() to do the job. */
2948 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
2949 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
2957 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
2959 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2961 if (!wxWindowBase::SetForegroundColour(colour
))
2963 // don't leave if the GTK widget has just
2965 if (!m_delayedForegroundColour
) return FALSE
;
2968 GdkWindow
*window
= (GdkWindow
*) NULL
;
2970 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2972 window
= GetConnectWidget()->window
;
2976 // indicate that a new style has been set
2977 // but it couldn't get applied as the
2978 // widget hasn't been realized yet.
2979 m_delayedForegroundColour
= TRUE
;
2981 // pretend we have done something
2990 GtkStyle
*wxWindow::GetWidgetStyle()
2992 if (m_widgetStyle
) return m_widgetStyle
;
2994 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
2997 def
= gtk_widget_get_default_style();
2999 m_widgetStyle
= gtk_style_copy( def
);
3000 m_widgetStyle
->klass
= def
->klass
;
3002 return m_widgetStyle
;
3005 void wxWindow::SetWidgetStyle()
3007 GtkStyle
*style
= GetWidgetStyle();
3009 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3011 gdk_font_unref( style
->font
);
3012 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3015 if (m_foregroundColour
.Ok())
3017 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3018 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3020 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3021 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3022 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3026 if (m_backgroundColour
.Ok())
3028 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3029 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3031 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3032 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3033 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3034 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3035 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3036 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3037 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3038 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3043 void wxWindow::ApplyWidgetStyle()
3047 //-----------------------------------------------------------------------------
3048 // Pop-up menu stuff
3049 //-----------------------------------------------------------------------------
3051 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3053 *is_waiting
= FALSE
;
3056 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3058 menu
->SetInvokingWindow( win
);
3059 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3062 wxMenuItem
*menuitem
= node
->GetData();
3063 if (menuitem
->IsSubMenu())
3065 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3068 node
= node
->GetNext();
3072 static gint gs_pop_x
= 0;
3073 static gint gs_pop_y
= 0;
3075 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3079 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3084 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3086 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3088 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3090 SetInvokingWindow( menu
, this );
3097 bool is_waiting
= TRUE
;
3099 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3100 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3103 GTK_MENU(menu
->m_menu
),
3104 (GtkWidget
*) NULL
, // parent menu shell
3105 (GtkWidget
*) NULL
, // parent menu item
3106 (GtkMenuPositionFunc
) pop_pos_callback
,
3107 (gpointer
) this, // client data
3108 0, // button used to activate it
3109 gs_timeLastClick
// the time of activation
3114 while (gtk_events_pending())
3115 gtk_main_iteration();
3121 #if wxUSE_DRAG_AND_DROP
3123 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3125 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3127 GtkWidget
*dnd_widget
= GetConnectWidget();
3129 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3131 if (m_dropTarget
) delete m_dropTarget
;
3132 m_dropTarget
= dropTarget
;
3134 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3137 #endif // wxUSE_DRAG_AND_DROP
3139 GtkWidget
* wxWindow::GetConnectWidget()
3141 GtkWidget
*connect_widget
= m_widget
;
3142 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3144 return connect_widget
;
3147 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3150 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3152 return (window
== m_widget
->window
);
3155 bool wxWindow::SetFont( const wxFont
&font
)
3157 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3159 if (!wxWindowBase::SetFont(font
))
3164 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3165 if ( sysbg
== m_backgroundColour
)
3167 m_backgroundColour
= wxNullColour
;
3169 m_backgroundColour
= sysbg
;
3179 void wxWindow::CaptureMouse()
3181 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3183 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3185 GdkWindow
*window
= (GdkWindow
*) NULL
;
3187 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3189 window
= GetConnectWidget()->window
;
3191 if (!window
) return;
3193 gdk_pointer_grab( window
, FALSE
,
3195 (GDK_BUTTON_PRESS_MASK
|
3196 GDK_BUTTON_RELEASE_MASK
|
3197 GDK_POINTER_MOTION_HINT_MASK
|
3198 GDK_POINTER_MOTION_MASK
),
3200 m_cursor
.GetCursor(),
3201 (guint32
)GDK_CURRENT_TIME
);
3202 g_captureWindow
= this;
3205 void wxWindow::ReleaseMouse()
3207 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3209 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3211 GdkWindow
*window
= (GdkWindow
*) NULL
;
3213 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3215 window
= GetConnectWidget()->window
;
3220 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3221 g_captureWindow
= (wxWindow
*) NULL
;
3224 bool wxWindow::IsRetained() const
3229 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3230 int range
, bool refresh
)
3232 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3234 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3236 m_hasScrolling
= TRUE
;
3238 if (orient
== wxHORIZONTAL
)
3240 float fpos
= (float)pos
;
3241 float frange
= (float)range
;
3242 float fthumb
= (float)thumbVisible
;
3243 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3244 if (fpos
< 0.0) fpos
= 0.0;
3246 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3247 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3249 SetScrollPos( orient
, pos
, refresh
);
3253 m_oldHorizontalPos
= fpos
;
3255 m_hAdjust
->lower
= 0.0;
3256 m_hAdjust
->upper
= frange
;
3257 m_hAdjust
->value
= fpos
;
3258 m_hAdjust
->step_increment
= 1.0;
3259 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3260 m_hAdjust
->page_size
= fthumb
;
3264 float fpos
= (float)pos
;
3265 float frange
= (float)range
;
3266 float fthumb
= (float)thumbVisible
;
3267 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3268 if (fpos
< 0.0) fpos
= 0.0;
3270 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3271 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3273 SetScrollPos( orient
, pos
, refresh
);
3277 m_oldVerticalPos
= fpos
;
3279 m_vAdjust
->lower
= 0.0;
3280 m_vAdjust
->upper
= frange
;
3281 m_vAdjust
->value
= fpos
;
3282 m_vAdjust
->step_increment
= 1.0;
3283 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3284 m_vAdjust
->page_size
= fthumb
;
3287 if (orient
== wxHORIZONTAL
)
3288 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3290 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3293 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3295 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3297 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3299 if (orient
== wxHORIZONTAL
)
3301 float fpos
= (float)pos
;
3302 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3303 if (fpos
< 0.0) fpos
= 0.0;
3304 m_oldHorizontalPos
= fpos
;
3306 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3307 m_hAdjust
->value
= fpos
;
3311 float fpos
= (float)pos
;
3312 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3313 if (fpos
< 0.0) fpos
= 0.0;
3314 m_oldVerticalPos
= fpos
;
3316 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3317 m_vAdjust
->value
= fpos
;
3324 if (m_wxwindow
->window
)
3326 if (orient
== wxHORIZONTAL
)
3327 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3329 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3336 int wxWindow::GetScrollThumb( int orient
) const
3338 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3340 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3342 if (orient
== wxHORIZONTAL
)
3343 return (int)(m_hAdjust
->page_size
+0.5);
3345 return (int)(m_vAdjust
->page_size
+0.5);
3348 int wxWindow::GetScrollPos( int orient
) const
3350 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3352 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3354 if (orient
== wxHORIZONTAL
)
3355 return (int)(m_hAdjust
->value
+0.5);
3357 return (int)(m_vAdjust
->value
+0.5);
3360 int wxWindow::GetScrollRange( int orient
) const
3362 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3364 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3366 if (orient
== wxHORIZONTAL
)
3367 return (int)(m_hAdjust
->upper
+0.5);
3369 return (int)(m_vAdjust
->upper
+0.5);
3372 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3374 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3376 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3379 printf( "ScrollWindow: %d %d\n", dx, dy );
3382 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3387 m_scrollGC = gdk_gc_new( m_wxwindow->window );
3388 gdk_gc_set_exposures( m_scrollGC, TRUE );
3391 wxNode *node = m_children.First();
3394 wxWindow *child = (wxWindow*) node->Data();
3397 child->GetSize( &sx, &sy );
3398 child->SetSize( child->m_x + dx, child->m_y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
3399 node = node->Next();
3404 GetClientSize( &cw, &ch );
3405 int w = cw - abs(dx);
3406 int h = ch - abs(dy);
3408 if ((h < 0) || (w < 0))
3416 if (dx < 0) s_x = -dx;
3417 if (dy < 0) s_y = -dy;
3420 if (dx > 0) d_x = dx;
3421 if (dy > 0) d_y = dy;
3423 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
3424 m_wxwindow->window, s_x, s_y, w, h );
3427 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3428 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3429 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3430 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3432 Refresh( TRUE, &rect );
3437 void wxWindow::SetScrolling(bool scroll
)
3439 m_isScrolling
= g_blockEventsOnScroll
= scroll
;