1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #include "wx/window.h"
20 #include "wx/layout.h"
22 #include "wx/dialog.h"
23 #include "wx/msgdlg.h"
25 #if wxUSE_DRAG_AND_DROP
30 #include "wx/tooltip.h"
34 #include "wx/statusbr.h"
36 #include "wx/settings.h"
43 #include "gdk/gdkprivate.h"
44 #include "gdk/gdkkeysyms.h"
45 #include "wx/gtk/win_gtk.h"
49 //-----------------------------------------------------------------------------
50 // documentation on internals
51 //-----------------------------------------------------------------------------
54 I have been asked several times about writing some documentation about
55 the GTK port of wxWindows, especially its internal structures. Obviously,
56 you cannot understand wxGTK without knowing a little about the GTK, but
57 some more information about what the wxWindow, which is the base class
58 for all other window classes, does seems required as well.
62 What does wxWindow do? It contains the common interface for the following
63 jobs of its descendants:
65 1) Define the rudimentary behaviour common to all window classes, such as
66 resizing, intercepting user input (so as to make it possible to use these
67 events for special purposes in a derived class), window names etc.
69 2) Provide the possibility to contain and manage children, if the derived
70 class is allowed to contain children, which holds true for those window
71 classes which do not display a native GTK widget. To name them, these
72 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
73 work classes are a special case and are handled a bit differently from
74 the rest. The same holds true for the wxNotebook class.
76 3) Provide the possibility to draw into a client area of a window. This,
77 too, only holds true for classes that do not display a native GTK widget
80 4) Provide the entire mechanism for scrolling widgets. This actual inter-
81 face for this is usually in wxScrolledWindow, but the GTK implementation
84 5) A multitude of helper or extra methods for special purposes, such as
85 Drag'n'Drop, managing validators etc.
87 6) Display a border (sunken, raised, simple or none).
89 Normally one might expect, that one wxWindows window would always correspond
90 to one GTK widget. Under GTK, there is no such allround widget that has all
91 the functionality. Moreover, the GTK defines a client area as a different
92 widget from the actual widget you are handling. Last but not least some
93 special classes (e.g. wxFrame) handle different categories of widgets and
94 still have the possibility to draw something in the client area.
95 It was therefore required to write a special purpose GTK widget, that would
96 represent a client area in the sense of wxWindows capable to do the jobs
97 2), 3) and 4). I have written this class and it resides in win_gtk.c of
100 All windows must have a widget, with which they interact with other under-
101 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
102 thw wxWindow class has a member variable called m_widget which holds a
103 pointer to this widget. When the window class represents a GTK native widget,
104 this is (in most cases) the only GTK widget the class manages. E.g. the
105 wxStatitText class handles only a GtkLabel widget a pointer to which you
106 can find in m_widget (defined in wxWindow)
108 When the class has a client area for drawing into and for containing children
109 it has to handle the client area widget (of the type GtkPizza, defined in
110 win_gtk.c), but there could be any number of widgets, handled by a class
111 The common rule for all windows is only, that the widget that interacts with
112 the rest of GTK must be referenced in m_widget and all other widgets must be
113 children of this widget on the GTK level. The top-most widget, which also
114 represents the client area, must be in the m_wxwindow field and must be of
117 As I said, the window classes that display a GTK native widget only have
118 one widget, so in the case of e.g. the wxButton class m_widget holds a
119 pointer to a GtkButton widget. But windows with client areas (for drawing
120 and children) have a m_widget field that is a pointer to a GtkScrolled-
121 Window and a m_wxwindow field that is pointer to a GtkPizza and this
122 one is (in the GTK sense) a child of the GtkScrolledWindow.
124 If the m_wxwindow field is set, then all input to this widget is inter-
125 cepted and sent to the wxWindows class. If not, all input to the widget
126 that gets pointed to by m_widget gets intercepted and sent to the class.
130 The design of scrolling in wxWindows is markedly different from that offered
131 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
132 clicking on a scrollbar belonging to scrolled window will inevitably move
133 the window. In wxWindows, the scrollbar will only emit an event, send this
134 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
135 which actually moves the window and its subchildren. Note that GtkPizza
136 memorizes how much it has been scrolled but that wxWindows forgets this
137 so that the two coordinates systems have to be kept in synch. This is done
138 in various places using the pizza->xoffset and pizza->yoffset values.
142 Singularily the most broken code in GTK is the code that is supposes to
143 inform subwindows (child windows) about new positions. Very often, duplicate
144 events are sent without changes in size or position, equally often no
145 events are sent at all (All this is due to a bug in the GtkContainer code
146 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
147 GTK's own system and it simply waits for size events for toplevel windows
148 and then iterates down the respective size events to all window. This has
149 the disadvantage, that windows might get size events before the GTK widget
150 actually has the reported size. This doesn't normally pose any problem, but
151 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
152 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
153 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
154 window that is used for OpenGl output really has that size (as reported by
159 If someone at some point of time feels the immense desire to have a look at,
160 change or attempt to optimse the Refresh() logic, this person will need an
161 intimate understanding of what a "draw" and what an "expose" events are and
162 what there are used for, in particular when used in connection with GTK's
163 own windowless widgets. Beware.
167 Cursors, too, have been a constant source of pleasure. The main difficulty
168 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
169 for the parent. To prevent this from doing too much harm, I use idle time
170 to set the cursor over and over again, starting from the toplevel windows
171 and ending with the youngest generation (speaking of parent and child windows).
172 Also don't forget that cursors (like much else) are connected to GdkWindows,
173 not GtkWidgets and that the "window" field of a GtkWidget might very well
174 point to the GdkWindow of the parent widget (-> "window less widget") and
175 that the two obviously have very different meanings.
179 //-----------------------------------------------------------------------------
181 //-----------------------------------------------------------------------------
183 extern wxList wxPendingDelete
;
184 extern bool g_blockEventsOnDrag
;
185 extern bool g_blockEventsOnScroll
;
186 extern wxCursor g_globalCursor
;
187 static wxWindow
*g_captureWindow
= (wxWindow
*) NULL
;
188 wxWindow
*g_focusWindow
= (wxWindow
*) NULL
;
190 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
191 the last click here */
192 static guint32 gs_timeLastClick
= 0;
194 //-----------------------------------------------------------------------------
196 //-----------------------------------------------------------------------------
200 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
201 GdkEvent
*WXUNUSED(event
),
202 const wxChar
*WXUNUSED(name
) )
205 static bool s_done = FALSE;
208 wxLog::AddTraceMask("focus");
211 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
217 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
220 tmp
+= wxT(" FROM ");
223 wxChar
*s
= new wxChar
[tmp
.Length()+1];
227 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
228 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
233 //-----------------------------------------------------------------------------
234 // missing gdk functions
235 //-----------------------------------------------------------------------------
238 gdk_window_warp_pointer (GdkWindow
*window
,
242 GdkWindowPrivate
*priv
;
245 window
= (GdkWindow
*) &gdk_root_parent
;
247 priv
= (GdkWindowPrivate
*) window
;
249 if (!priv
->destroyed
)
251 XWarpPointer (priv
->xdisplay
,
252 None
, /* not source window -> move from anywhere */
253 priv
->xwindow
, /* dest window */
254 0, 0, 0, 0, /* not source window -> move from anywhere */
259 //-----------------------------------------------------------------------------
261 //-----------------------------------------------------------------------------
263 extern void wxapp_install_idle_handler();
264 extern bool g_isIdle
;
266 //-----------------------------------------------------------------------------
267 // local code (see below)
268 //-----------------------------------------------------------------------------
270 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
278 if (win
->HasScrolling())
280 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
281 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget
)->klass
);
284 GtkWidget *hscrollbar = scroll_window->hscrollbar;
285 GtkWidget *vscrollbar = scroll_window->vscrollbar;
287 we use this instead: range.slider_width = 11 + 2*2pts edge
290 if (scroll_window
->vscrollbar_visible
)
292 dw
+= 15; /* dw += vscrollbar->allocation.width; */
293 dw
+= scroll_class
->scrollbar_spacing
;
296 if (scroll_window
->hscrollbar_visible
)
298 dh
+= 15; /* dh += hscrollbar->allocation.height; */
299 dh
+= scroll_class
->scrollbar_spacing
;
305 if (GTK_WIDGET_NO_WINDOW (widget
))
307 dx
+= widget
->allocation
.x
;
308 dy
+= widget
->allocation
.y
;
311 if (win
->HasFlag(wxRAISED_BORDER
))
313 gtk_draw_shadow( widget
->style
,
318 win
->m_width
-dw
, win
->m_height
-dh
);
322 if (win
->HasFlag(wxSUNKEN_BORDER
))
324 gtk_draw_shadow( widget
->style
,
329 win
->m_width
-dw
, win
->m_height
-dh
);
333 if (win
->HasFlag(wxSIMPLE_BORDER
))
336 gc
= gdk_gc_new( widget
->window
);
337 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
338 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
340 win
->m_width
-dw
-1, win
->m_height
-dh
-1 );
346 //-----------------------------------------------------------------------------
347 // "expose_event" of m_widget
348 //-----------------------------------------------------------------------------
350 static void gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
352 if (gdk_event
->count
> 0) return;
353 draw_frame( widget
, win
);
356 //-----------------------------------------------------------------------------
357 // "draw" of m_widget
358 //-----------------------------------------------------------------------------
360 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
362 draw_frame( widget
, win
);
365 //-----------------------------------------------------------------------------
366 // key code mapping routines
367 //-----------------------------------------------------------------------------
369 static long map_to_unmodified_wx_keysym( KeySym keysym
)
376 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
378 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
384 case GDK_Super_R
: key_code
= WXK_ALT
; break;
385 case GDK_Menu
: key_code
= WXK_MENU
; break;
386 case GDK_Help
: key_code
= WXK_HELP
; break;
387 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
388 case GDK_ISO_Left_Tab
:
389 case GDK_Tab
: key_code
= WXK_TAB
; break;
390 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
391 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
392 case GDK_Return
: key_code
= WXK_RETURN
; break;
393 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
394 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
395 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
396 case GDK_Delete
: key_code
= WXK_DELETE
; break;
397 case GDK_Home
: key_code
= WXK_HOME
; break;
398 case GDK_Left
: key_code
= WXK_LEFT
; break;
399 case GDK_Up
: key_code
= WXK_UP
; break;
400 case GDK_Right
: key_code
= WXK_RIGHT
; break;
401 case GDK_Down
: key_code
= WXK_DOWN
; break;
402 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
403 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
404 case GDK_Next
: key_code
= WXK_NEXT
; break;
405 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
406 case GDK_End
: key_code
= WXK_END
; break;
407 case GDK_Begin
: key_code
= WXK_HOME
; break;
408 case GDK_Select
: key_code
= WXK_SELECT
; break;
409 case GDK_Print
: key_code
= WXK_PRINT
; break;
410 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
411 case GDK_Insert
: key_code
= WXK_INSERT
; break;
412 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
414 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
415 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
416 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
417 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
418 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
419 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
420 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
421 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
422 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
423 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
424 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
425 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
426 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
427 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
428 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
429 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
430 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
431 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
432 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
433 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
434 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
435 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
436 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
437 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
438 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
439 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
440 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
441 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
442 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
443 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
444 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
445 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
446 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
447 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
448 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
449 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
450 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
452 case GDK_F1
: key_code
= WXK_F1
; break;
453 case GDK_F2
: key_code
= WXK_F2
; break;
454 case GDK_F3
: key_code
= WXK_F3
; break;
455 case GDK_F4
: key_code
= WXK_F4
; break;
456 case GDK_F5
: key_code
= WXK_F5
; break;
457 case GDK_F6
: key_code
= WXK_F6
; break;
458 case GDK_F7
: key_code
= WXK_F7
; break;
459 case GDK_F8
: key_code
= WXK_F8
; break;
460 case GDK_F9
: key_code
= WXK_F9
; break;
461 case GDK_F10
: key_code
= WXK_F10
; break;
462 case GDK_F11
: key_code
= WXK_F11
; break;
463 case GDK_F12
: key_code
= WXK_F12
; break;
468 guint upper
= gdk_keyval_to_upper( keysym
);
469 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
478 static long map_to_wx_keysym( KeySym keysym
)
484 case GDK_Menu
: key_code
= WXK_MENU
; break;
485 case GDK_Help
: key_code
= WXK_HELP
; break;
486 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
487 case GDK_ISO_Left_Tab
:
488 case GDK_Tab
: key_code
= WXK_TAB
; break;
489 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
490 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
491 case GDK_Return
: key_code
= WXK_RETURN
; break;
492 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
493 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
494 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
495 case GDK_Delete
: key_code
= WXK_DELETE
; break;
496 case GDK_Home
: key_code
= WXK_HOME
; break;
497 case GDK_Left
: key_code
= WXK_LEFT
; break;
498 case GDK_Up
: key_code
= WXK_UP
; break;
499 case GDK_Right
: key_code
= WXK_RIGHT
; break;
500 case GDK_Down
: key_code
= WXK_DOWN
; break;
501 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
502 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
503 case GDK_Next
: key_code
= WXK_NEXT
; break;
504 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
505 case GDK_End
: key_code
= WXK_END
; break;
506 case GDK_Begin
: key_code
= WXK_HOME
; break;
507 case GDK_Select
: key_code
= WXK_SELECT
; break;
508 case GDK_Print
: key_code
= WXK_PRINT
; break;
509 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
510 case GDK_Insert
: key_code
= WXK_INSERT
; break;
511 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
513 case GDK_KP_0
: key_code
= '0'; break;
514 case GDK_KP_1
: key_code
= '1'; break;
515 case GDK_KP_2
: key_code
= '2'; break;
516 case GDK_KP_3
: key_code
= '3'; break;
517 case GDK_KP_4
: key_code
= '4'; break;
518 case GDK_KP_5
: key_code
= '5'; break;
519 case GDK_KP_6
: key_code
= '6'; break;
520 case GDK_KP_7
: key_code
= '7'; break;
521 case GDK_KP_8
: key_code
= '8'; break;
522 case GDK_KP_9
: key_code
= '9'; break;
523 case GDK_KP_Space
: key_code
= ' '; break;
524 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
525 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
526 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
527 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
528 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
529 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
530 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
531 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
532 case GDK_KP_Up
: key_code
= WXK_UP
; break;
533 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
534 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
535 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
536 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
537 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
538 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
539 case GDK_KP_End
: key_code
= WXK_END
; break;
540 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
541 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
542 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
543 case GDK_KP_Equal
: key_code
= '='; break;
544 case GDK_KP_Multiply
: key_code
= '*'; break;
545 case GDK_KP_Add
: key_code
= '+'; break;
546 case GDK_KP_Separator
: key_code
= ','; break;
547 case GDK_KP_Subtract
: key_code
= '-'; break;
548 case GDK_KP_Decimal
: key_code
= '.'; break;
549 case GDK_KP_Divide
: key_code
= '/'; break;
551 case GDK_F1
: key_code
= WXK_F1
; break;
552 case GDK_F2
: key_code
= WXK_F2
; break;
553 case GDK_F3
: key_code
= WXK_F3
; break;
554 case GDK_F4
: key_code
= WXK_F4
; break;
555 case GDK_F5
: key_code
= WXK_F5
; break;
556 case GDK_F6
: key_code
= WXK_F6
; break;
557 case GDK_F7
: key_code
= WXK_F7
; break;
558 case GDK_F8
: key_code
= WXK_F8
; break;
559 case GDK_F9
: key_code
= WXK_F9
; break;
560 case GDK_F10
: key_code
= WXK_F10
; break;
561 case GDK_F11
: key_code
= WXK_F11
; break;
562 case GDK_F12
: key_code
= WXK_F12
; break;
575 //-----------------------------------------------------------------------------
576 // "expose_event" of m_wxwindow
577 //-----------------------------------------------------------------------------
579 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
584 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
586 gdk_event
->area
.width
,
587 gdk_event
->area
.height
);
589 if (gdk_event
->count
> 0)
593 wxPrintf( "OnExpose from " );
594 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
595 wxPrintf( win->GetClassInfo()->GetClassName() );
596 wxPrintf( " %d %d %d %d\n", (int)gdk_event->area.x,
597 (int)gdk_event->area.y,
598 (int)gdk_event->area.width,
599 (int)gdk_event->area.height );
602 wxEraseEvent
eevent( win
->GetId() );
603 eevent
.SetEventObject( win
);
604 win
->GetEventHandler()->ProcessEvent(eevent
);
606 wxPaintEvent
event( win
->GetId() );
607 event
.SetEventObject( win
);
608 win
->GetEventHandler()->ProcessEvent( event
);
610 win
->GetUpdateRegion().Clear();
613 //-----------------------------------------------------------------------------
614 // "draw" of m_wxwindow
615 //-----------------------------------------------------------------------------
617 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
620 wxapp_install_idle_handler();
625 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
,
626 rect
->width
, rect
->height
);
629 wxPrintf( "OnDraw from " );
630 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
631 printf( win->GetClassInfo()->GetClassName() );
632 wxPrintf( " %d %d %d %d\n", (int)rect->x,
638 wxEraseEvent
eevent( win
->GetId() );
639 eevent
.SetEventObject( win
);
640 win
->GetEventHandler()->ProcessEvent(eevent
);
642 wxPaintEvent
event( win
->GetId() );
643 event
.SetEventObject( win
);
644 win
->GetEventHandler()->ProcessEvent( event
);
646 win
->GetUpdateRegion().Clear();
649 //-----------------------------------------------------------------------------
650 // "key_press_event" from any window
651 //-----------------------------------------------------------------------------
653 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
656 wxapp_install_idle_handler();
658 if (!win
->m_hasVMT
) return FALSE
;
659 if (g_blockEventsOnDrag
) return FALSE
;
662 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
663 if (gdk_event->state & GDK_SHIFT_MASK)
664 printf( "ShiftDown.\n" );
666 printf( "ShiftUp.\n" );
667 if (gdk_event->state & GDK_CONTROL_MASK)
668 printf( "ControlDown.\n" );
670 printf( "ControlUp.\n" );
675 GdkModifierType state
;
676 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
680 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
681 /* sending unknown key events doesn't really make sense */
682 if (key_code
== 0) return FALSE
;
684 wxKeyEvent
event( wxEVT_KEY_DOWN
);
685 event
.SetTimestamp( gdk_event
->time
);
686 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
687 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
688 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
689 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
690 event
.m_keyCode
= key_code
;
691 event
.m_scanCode
= gdk_event
->keyval
;
694 event
.SetEventObject( win
);
695 ret
= win
->GetEventHandler()->ProcessEvent( event
);
700 wxWindow
*ancestor
= win
;
703 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
706 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
707 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
710 if (ancestor
->m_isFrame
)
712 ancestor
= ancestor
->GetParent();
715 #endif // wxUSE_ACCEL
717 /* wxMSW doesn't send char events with Alt pressed */
718 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
719 will only be sent if it is not in an accelerator table. */
720 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
725 wxKeyEvent
event2( wxEVT_CHAR
);
726 event2
.SetTimestamp( gdk_event
->time
);
727 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
728 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
729 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
730 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
731 event2
.m_keyCode
= key_code
;
732 event2
.m_scanCode
= gdk_event
->keyval
;
735 event2
.SetEventObject( win
);
736 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
739 /* win is a control: tab can be propagated up */
741 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
742 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
743 (win
->GetParent()) &&
744 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
746 wxNavigationKeyEvent new_event
;
747 new_event
.SetEventObject( win
);
748 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
749 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
750 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
751 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
752 new_event
.SetCurrentFocus( win
);
753 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
756 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
758 (gdk_event
->keyval
== GDK_Escape
) )
760 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
761 new_event
.SetEventObject( win
);
762 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
765 #if (GTK_MINOR_VERSION > 0)
766 /* Pressing F10 will activate the menu bar of the top frame. */
770 (gdk_event->keyval == GDK_F10) )
772 wxWindow *ancestor = win;
775 if (wxIsKindOf(ancestor,wxFrame))
777 wxFrame *frame = (wxFrame*) ancestor;
778 wxMenuBar *menubar = frame->GetMenuBar();
781 wxNode *node = menubar->GetMenus().First();
784 wxMenu *firstMenu = (wxMenu*) node->Data();
785 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
791 ancestor = ancestor->GetParent();
798 Damn, I forgot why this didn't work, but it didn't work.
800 // win is a panel: up can be propagated to the panel
801 if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
802 (gdk_event->keyval == GDK_Up))
804 win->m_parent->SetFocus();
808 // win is a panel: left/right can be propagated to the panel
809 if ((!ret) && (win->m_wxwindow) &&
810 ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
811 (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
813 wxNavigationKeyEvent new_event;
814 new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
815 new_event.SetCurrentFocus( win );
816 ret = win->GetEventHandler()->ProcessEvent( new_event );
822 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
829 //-----------------------------------------------------------------------------
830 // "key_release_event" from any window
831 //-----------------------------------------------------------------------------
833 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
836 wxapp_install_idle_handler();
838 if (!win
->m_hasVMT
) return FALSE
;
839 if (g_blockEventsOnDrag
) return FALSE
;
842 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
843 if (gdk_event->state & GDK_SHIFT_MASK)
844 printf( "ShiftDown.\n" );
846 printf( "ShiftUp.\n" );
847 if (gdk_event->state & GDK_CONTROL_MASK)
848 printf( "ControlDown.\n" );
850 printf( "ControlUp.\n" );
854 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
856 /* sending unknown key events doesn't really make sense */
857 if (key_code
== 0) return FALSE
;
861 GdkModifierType state
;
862 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
864 wxKeyEvent
event( wxEVT_KEY_UP
);
865 event
.SetTimestamp( gdk_event
->time
);
866 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
867 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
868 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
869 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
870 event
.m_keyCode
= key_code
;
871 event
.m_scanCode
= gdk_event
->keyval
;
874 event
.SetEventObject( win
);
876 if (win
->GetEventHandler()->ProcessEvent( event
))
878 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
885 //-----------------------------------------------------------------------------
886 // "button_press_event"
887 //-----------------------------------------------------------------------------
889 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
892 wxapp_install_idle_handler();
895 wxPrintf( wxT("1) OnButtonPress from ") );
896 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
897 wxPrintf( win->GetClassInfo()->GetClassName() );
898 wxPrintf( wxT(".\n") );
900 if (!win
->m_hasVMT
) return FALSE
;
901 if (g_blockEventsOnDrag
) return TRUE
;
902 if (g_blockEventsOnScroll
) return TRUE
;
904 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
908 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
910 gtk_widget_grab_focus (win
->m_wxwindow
);
913 wxPrintf( wxT("GrabFocus from ") );
914 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
915 wxPrintf( win->GetClassInfo()->GetClassName() );
916 wxPrintf( wxT(".\n") );
922 wxEventType event_type
= wxEVT_LEFT_DOWN
;
924 if (gdk_event
->button
== 1)
926 switch (gdk_event
->type
)
928 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
929 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
933 else if (gdk_event
->button
== 2)
935 switch (gdk_event
->type
)
937 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
938 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
942 else if (gdk_event
->button
== 3)
944 switch (gdk_event
->type
)
946 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
947 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
952 wxMouseEvent
event( event_type
);
953 event
.SetTimestamp( gdk_event
->time
);
954 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
955 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
956 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
957 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
958 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
959 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
960 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
962 event
.m_x
= (long)gdk_event
->x
;
963 event
.m_y
= (long)gdk_event
->y
;
965 // Some control don't have their own X window and thus cannot get
968 if (!g_captureWindow
)
974 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
979 wxNode
*node
= win
->GetChildren().First();
982 wxWindow
*child
= (wxWindow
*)node
->Data();
985 if (!child
->IsShown())
988 if (child
->m_isStaticBox
)
990 // wxStaticBox is transparent in the box itself
991 int xx1
= child
->m_x
;
992 int yy1
= child
->m_y
;
993 int xx2
= child
->m_x
+ child
->m_width
;
994 int yy2
= child
->m_x
+ child
->m_height
;
997 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
999 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1001 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1003 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1006 event
.m_x
-= child
->m_x
;
1007 event
.m_y
-= child
->m_y
;
1014 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1015 (child
->m_x
<= x
) &&
1016 (child
->m_y
<= y
) &&
1017 (child
->m_x
+child
->m_width
>= x
) &&
1018 (child
->m_y
+child
->m_height
>= y
))
1021 event
.m_x
-= child
->m_x
;
1022 event
.m_y
-= child
->m_y
;
1029 event
.SetEventObject( win
);
1031 gs_timeLastClick
= gdk_event
->time
;
1034 wxPrintf( wxT("2) OnButtonPress from ") );
1035 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1036 wxPrintf( win->GetClassInfo()->GetClassName() );
1037 wxPrintf( wxT(".\n") );
1040 if (win
->GetEventHandler()->ProcessEvent( event
))
1042 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1049 //-----------------------------------------------------------------------------
1050 // "button_release_event"
1051 //-----------------------------------------------------------------------------
1053 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1056 wxapp_install_idle_handler();
1058 if (!win
->m_hasVMT
) return FALSE
;
1059 if (g_blockEventsOnDrag
) return FALSE
;
1060 if (g_blockEventsOnScroll
) return FALSE
;
1062 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1065 printf( "OnButtonRelease from " );
1066 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1067 printf( win->GetClassInfo()->GetClassName() );
1071 wxEventType event_type
= wxEVT_NULL
;
1073 switch (gdk_event
->button
)
1075 case 1: event_type
= wxEVT_LEFT_UP
; break;
1076 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1077 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1080 wxMouseEvent
event( event_type
);
1081 event
.SetTimestamp( gdk_event
->time
);
1082 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1083 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1084 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1085 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1086 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1087 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1088 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1089 event
.m_x
= (long)gdk_event
->x
;
1090 event
.m_y
= (long)gdk_event
->y
;
1092 // Some control don't have their own X window and thus cannot get
1095 if (!g_captureWindow
)
1099 if (win
->m_wxwindow
)
1101 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1102 x
+= pizza
->xoffset
;
1103 y
+= pizza
->yoffset
;
1106 wxNode
*node
= win
->GetChildren().First();
1109 wxWindow
*child
= (wxWindow
*)node
->Data();
1111 node
= node
->Next();
1112 if (!child
->IsShown())
1115 if (child
->m_isStaticBox
)
1117 // wxStaticBox is transparent in the box itself
1118 int xx1
= child
->m_x
;
1119 int yy1
= child
->m_y
;
1120 int xx2
= child
->m_x
+ child
->m_width
;
1121 int yy2
= child
->m_x
+ child
->m_height
;
1124 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1126 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1128 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1130 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1133 event
.m_x
-= child
->m_x
;
1134 event
.m_y
-= child
->m_y
;
1141 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1142 (child
->m_x
<= x
) &&
1143 (child
->m_y
<= y
) &&
1144 (child
->m_x
+child
->m_width
>= x
) &&
1145 (child
->m_y
+child
->m_height
>= y
))
1148 event
.m_x
-= child
->m_x
;
1149 event
.m_y
-= child
->m_y
;
1156 event
.SetEventObject( win
);
1158 if (win
->GetEventHandler()->ProcessEvent( event
))
1160 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1167 //-----------------------------------------------------------------------------
1168 // "motion_notify_event"
1169 //-----------------------------------------------------------------------------
1171 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1174 wxapp_install_idle_handler();
1176 if (!win
->m_hasVMT
) return FALSE
;
1177 if (g_blockEventsOnDrag
) return FALSE
;
1178 if (g_blockEventsOnScroll
) return FALSE
;
1180 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1182 if (gdk_event
->is_hint
)
1186 GdkModifierType state
;
1187 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1193 printf( "OnMotion from " );
1194 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1195 printf( win->GetClassInfo()->GetClassName() );
1199 wxMouseEvent
event( wxEVT_MOTION
);
1200 event
.SetTimestamp( gdk_event
->time
);
1201 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1202 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1203 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1204 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1205 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1206 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1207 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1209 event
.m_x
= (long)gdk_event
->x
;
1210 event
.m_y
= (long)gdk_event
->y
;
1212 // Some control don't have their own X window and thus cannot get
1215 if (!g_captureWindow
)
1219 if (win
->m_wxwindow
)
1221 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1222 x
+= pizza
->xoffset
;
1223 y
+= pizza
->yoffset
;
1226 wxNode
*node
= win
->GetChildren().First();
1229 wxWindow
*child
= (wxWindow
*)node
->Data();
1231 node
= node
->Next();
1232 if (!child
->IsShown())
1235 if (child
->m_isStaticBox
)
1237 // wxStaticBox is transparent in the box itself
1238 int xx1
= child
->m_x
;
1239 int yy1
= child
->m_y
;
1240 int xx2
= child
->m_x
+ child
->m_width
;
1241 int yy2
= child
->m_x
+ child
->m_height
;
1244 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1246 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1248 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1250 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1253 event
.m_x
-= child
->m_x
;
1254 event
.m_y
-= child
->m_y
;
1261 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1262 (child
->m_x
<= x
) &&
1263 (child
->m_y
<= y
) &&
1264 (child
->m_x
+child
->m_width
>= x
) &&
1265 (child
->m_y
+child
->m_height
>= y
))
1268 event
.m_x
-= child
->m_x
;
1269 event
.m_y
-= child
->m_y
;
1276 event
.SetEventObject( win
);
1278 if (win
->GetEventHandler()->ProcessEvent( event
))
1280 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1287 //-----------------------------------------------------------------------------
1289 //-----------------------------------------------------------------------------
1291 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1294 wxapp_install_idle_handler();
1296 if (!win
->m_hasVMT
) return FALSE
;
1297 if (g_blockEventsOnDrag
) return FALSE
;
1299 g_focusWindow
= win
;
1302 printf( "OnSetFocus from " );
1303 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1304 printf( win->GetClassInfo()->GetClassName() );
1306 printf( WXSTRINGCAST win->GetLabel() );
1310 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1313 panel
->SetLastFocus(win
);
1316 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1317 event
.SetEventObject( win
);
1319 if (win
->GetEventHandler()->ProcessEvent( event
))
1321 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1328 //-----------------------------------------------------------------------------
1329 // "focus_out_event"
1330 //-----------------------------------------------------------------------------
1332 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1335 wxapp_install_idle_handler();
1337 if (!win
->m_hasVMT
) return FALSE
;
1338 if (g_blockEventsOnDrag
) return FALSE
;
1341 printf( "OnKillFocus from " );
1342 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1343 printf( win->GetClassInfo()->GetClassName() );
1347 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1348 event
.SetEventObject( win
);
1350 if (win
->GetEventHandler()->ProcessEvent( event
))
1352 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1359 //-----------------------------------------------------------------------------
1360 // "enter_notify_event"
1361 //-----------------------------------------------------------------------------
1363 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1366 wxapp_install_idle_handler();
1368 if (!win
->m_hasVMT
) return FALSE
;
1369 if (g_blockEventsOnDrag
) return FALSE
;
1371 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1373 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1374 #if (GTK_MINOR_VERSION > 0)
1375 event
.SetTimestamp( gdk_event
->time
);
1377 event
.SetEventObject( win
);
1381 GdkModifierType state
= (GdkModifierType
)0;
1383 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1385 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1386 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1387 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1388 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1389 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1390 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1391 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1393 event
.m_x
= (long)x
;
1394 event
.m_y
= (long)y
;
1396 if (win
->GetEventHandler()->ProcessEvent( event
))
1398 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1405 //-----------------------------------------------------------------------------
1406 // "leave_notify_event"
1407 //-----------------------------------------------------------------------------
1409 static gint
gtk_window_leave_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_LEAVE_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
);
1439 event
.m_x
= (long)x
;
1440 event
.m_y
= (long)y
;
1442 if (win
->GetEventHandler()->ProcessEvent( event
))
1444 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1451 //-----------------------------------------------------------------------------
1452 // "value_changed" from m_vAdjust
1453 //-----------------------------------------------------------------------------
1455 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1458 wxapp_install_idle_handler();
1460 if (g_blockEventsOnDrag
) return;
1462 if (!win
->m_hasVMT
) return;
1464 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1465 if (fabs(diff
) < 0.2) return;
1467 win
->m_oldVerticalPos
= adjust
->value
;
1469 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1470 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1472 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1473 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1474 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1475 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1476 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1478 int value
= (int)(adjust
->value
+0.5);
1480 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1481 event
.SetEventObject( win
);
1482 win
->GetEventHandler()->ProcessEvent( event
);
1485 //-----------------------------------------------------------------------------
1486 // "value_changed" from m_hAdjust
1487 //-----------------------------------------------------------------------------
1489 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1492 wxapp_install_idle_handler();
1494 if (g_blockEventsOnDrag
) return;
1495 if (!win
->m_hasVMT
) return;
1497 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1498 if (fabs(diff
) < 0.2) return;
1500 win
->m_oldHorizontalPos
= adjust
->value
;
1502 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1503 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1505 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1506 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1507 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1508 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1509 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1511 int value
= (int)(adjust
->value
+0.5);
1513 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1514 event
.SetEventObject( win
);
1515 win
->GetEventHandler()->ProcessEvent( event
);
1518 //-----------------------------------------------------------------------------
1519 // "changed" from m_vAdjust
1520 //-----------------------------------------------------------------------------
1522 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1525 wxapp_install_idle_handler();
1527 if (g_blockEventsOnDrag
) return;
1528 if (!win
->m_hasVMT
) return;
1530 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1531 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1533 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1534 event
.SetEventObject( win
);
1535 win
->GetEventHandler()->ProcessEvent( event
);
1538 //-----------------------------------------------------------------------------
1539 // "changed" from m_hAdjust
1540 //-----------------------------------------------------------------------------
1542 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1545 wxapp_install_idle_handler();
1547 if (g_blockEventsOnDrag
) return;
1548 if (!win
->m_hasVMT
) return;
1550 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1551 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1553 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1554 event
.SetEventObject( win
);
1555 win
->GetEventHandler()->ProcessEvent( event
);
1558 //-----------------------------------------------------------------------------
1559 // "button_press_event" from scrollbar
1560 //-----------------------------------------------------------------------------
1562 static gint
gtk_scrollbar_button_press_callback( GtkRange
*WXUNUSED(widget
),
1563 GdkEventButton
*WXUNUSED(gdk_event
),
1567 wxapp_install_idle_handler();
1569 // don't test here as we can release the mouse while being over
1570 // a different window than the slider
1572 // if (gdk_event->window != widget->slider) return FALSE;
1574 win
->SetScrolling( TRUE
);
1579 //-----------------------------------------------------------------------------
1580 // "button_release_event" from scrollbar
1581 //-----------------------------------------------------------------------------
1583 static gint
gtk_scrollbar_button_release_callback( GtkRange
*WXUNUSED(widget
),
1584 GdkEventButton
*WXUNUSED(gdk_event
),
1588 // don't test here as we can release the mouse while being over
1589 // a different window than the slider
1591 // if (gdk_event->window != widget->slider) return FALSE;
1593 win
->SetScrolling( FALSE
);
1598 // ----------------------------------------------------------------------------
1599 // this wxWindowBase function is implemented here (in platform-specific file)
1600 // because it is static and so couldn't be made virtual
1601 // ----------------------------------------------------------------------------
1603 wxWindow
*wxWindowBase::FindFocus()
1605 return g_focusWindow
;
1608 //-----------------------------------------------------------------------------
1609 // "realize" from m_widget
1610 //-----------------------------------------------------------------------------
1612 /* we cannot set colours and fonts before the widget has
1613 been realized, so we do this directly after realization */
1616 gtk_window_realized_callback( GtkWidget
* WXUNUSED(widget
), wxWindow
*win
)
1619 wxapp_install_idle_handler();
1621 if (win
->m_delayedFont
)
1622 win
->SetFont( win
->GetFont() );
1624 if (win
->m_delayedBackgroundColour
)
1625 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1627 if (win
->m_delayedForegroundColour
)
1628 win
->SetForegroundColour( win
->GetForegroundColour() );
1630 wxWindowCreateEvent
event( win
);
1631 event
.SetEventObject( win
);
1632 win
->GetEventHandler()->ProcessEvent( event
);
1637 //-----------------------------------------------------------------------------
1638 // InsertChild for wxWindow.
1639 //-----------------------------------------------------------------------------
1641 /* Callback for wxWindow. This very strange beast has to be used because
1642 * C++ has no virtual methods in a constructor. We have to emulate a
1643 * virtual function here as wxNotebook requires a different way to insert
1644 * a child in it. I had opted for creating a wxNotebookPage window class
1645 * which would have made this superfluous (such in the MDI window system),
1646 * but no-one was listening to me... */
1648 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1650 /* the window might have been scrolled already, do we
1651 have to adapt the position */
1652 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
1653 child
->m_x
+= pizza
->xoffset
;
1654 child
->m_y
+= pizza
->yoffset
;
1656 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
1657 GTK_WIDGET(child
->m_widget
),
1664 //-----------------------------------------------------------------------------
1666 //-----------------------------------------------------------------------------
1668 wxWindow
* wxGetActiveWindow()
1670 return g_focusWindow
;
1673 //-----------------------------------------------------------------------------
1675 //-----------------------------------------------------------------------------
1677 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
1679 void wxWindow::Init()
1685 m_widget
= (GtkWidget
*) NULL
;
1686 m_wxwindow
= (GtkWidget
*) NULL
;
1696 m_needParent
= TRUE
;
1697 m_isBeingDeleted
= FALSE
;
1700 m_nativeSizeEvent
= FALSE
;
1702 m_hasScrolling
= FALSE
;
1703 m_isScrolling
= FALSE
;
1705 m_hAdjust
= (GtkAdjustment
*) NULL
;
1706 m_vAdjust
= (GtkAdjustment
*) NULL
;
1707 m_oldHorizontalPos
= 0.0;
1708 m_oldVerticalPos
= 0.0;
1711 m_widgetStyle
= (GtkStyle
*) NULL
;
1713 m_insertCallback
= (wxInsertChildFunction
) NULL
;
1715 m_isStaticBox
= FALSE
;
1716 m_isRadioButton
= FALSE
;
1718 m_acceptsFocus
= FALSE
;
1720 m_cursor
= *wxSTANDARD_CURSOR
;
1723 wxWindow::wxWindow()
1728 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1729 const wxPoint
&pos
, const wxSize
&size
,
1730 long style
, const wxString
&name
)
1734 Create( parent
, id
, pos
, size
, style
, name
);
1737 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1738 const wxPoint
&pos
, const wxSize
&size
,
1739 long style
, const wxString
&name
)
1741 if (!PreCreation( parent
, pos
, size
) ||
1742 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
1744 wxFAIL_MSG( wxT("wxWindow creation failed") );
1748 m_insertCallback
= wxInsertChildInWindow
;
1750 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
1751 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1754 debug_focus_in( m_widget
, wxT("wxWindow::m_widget"), name
);
1757 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
1760 debug_focus_in( scrolledWindow
->hscrollbar
, wxT("wxWindow::hsrcollbar"), name
);
1761 debug_focus_in( scrolledWindow
->vscrollbar
, wxT("wxWindow::vsrcollbar"), name
);
1764 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1765 scroll_class
->scrollbar_spacing
= 0;
1767 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1769 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
1770 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
1772 m_wxwindow
= gtk_pizza_new();
1775 debug_focus_in( m_wxwindow
, wxT("wxWindow::m_wxwindow"), name
);
1778 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
1780 #if (GTK_MINOR_VERSION > 0)
1781 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
1783 if (HasFlag(wxRAISED_BORDER
))
1785 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
1787 else if (HasFlag(wxSUNKEN_BORDER
))
1789 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
1791 else if (HasFlag(wxSIMPLE_BORDER
))
1793 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
1797 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
1799 #else // GTK_MINOR_VERSION == 0
1800 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
1802 if (HasFlag(wxRAISED_BORDER
))
1804 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
1806 else if (HasFlag(wxSUNKEN_BORDER
))
1808 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
1812 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
1814 #endif // GTK_MINOR_VERSION
1816 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1817 m_acceptsFocus
= TRUE
;
1819 #if (GTK_MINOR_VERSION == 0)
1820 // shut the viewport up
1821 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1822 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1823 #endif // GTK_MINOR_VERSION == 0
1825 // I _really_ don't want scrollbars in the beginning
1826 m_vAdjust
->lower
= 0.0;
1827 m_vAdjust
->upper
= 1.0;
1828 m_vAdjust
->value
= 0.0;
1829 m_vAdjust
->step_increment
= 1.0;
1830 m_vAdjust
->page_increment
= 1.0;
1831 m_vAdjust
->page_size
= 5.0;
1832 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
1833 m_hAdjust
->lower
= 0.0;
1834 m_hAdjust
->upper
= 1.0;
1835 m_hAdjust
->value
= 0.0;
1836 m_hAdjust
->step_increment
= 1.0;
1837 m_hAdjust
->page_increment
= 1.0;
1838 m_hAdjust
->page_size
= 5.0;
1839 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1841 // these handlers block mouse events to any window during scrolling such as
1842 // motion events and prevent GTK and wxWindows from fighting over where the
1845 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
1846 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1848 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
1849 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1851 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
1852 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1854 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
1855 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1857 // these handlers get notified when screen updates are required either when
1858 // scrolling or when the window size (and therefore scrollbar configuration)
1861 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
1862 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
1863 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
1864 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
1866 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
1867 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
1868 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
1869 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
1871 gtk_widget_show( m_wxwindow
);
1874 m_parent
->DoAddChild( this );
1883 wxWindow::~wxWindow()
1885 m_isBeingDeleted
= TRUE
;
1894 m_parent
->RemoveChild( this );
1898 gtk_style_unref( m_widgetStyle
);
1899 m_widgetStyle
= (GtkStyle
*) NULL
;
1904 gtk_widget_destroy( m_wxwindow
);
1905 m_wxwindow
= (GtkWidget
*) NULL
;
1910 gtk_widget_destroy( m_widget
);
1911 m_widget
= (GtkWidget
*) NULL
;
1915 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
1917 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
1919 /* this turns -1 into 20 so that a minimal window is
1920 visible even although -1,-1 has been given as the
1921 size of the window. the same trick is used in other
1922 ports and should make debugging easier */
1923 m_width
= WidthDefault(size
.x
);
1924 m_height
= HeightDefault(size
.y
);
1929 /* some reasonable defaults */
1934 m_x
= (gdk_screen_width () - m_width
) / 2;
1935 if (m_x
< 10) m_x
= 10;
1939 m_y
= (gdk_screen_height () - m_height
) / 2;
1940 if (m_y
< 10) m_y
= 10;
1947 void wxWindow::PostCreation()
1949 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
1955 /* these get reported to wxWindows -> wxPaintEvent */
1956 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1957 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1959 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1960 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1963 #if (GTK_MINOR_VERSION > 0)
1964 /* these are called when the "sunken" or "raised" borders are drawn */
1965 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
1966 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
1968 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
1969 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
1973 GtkWidget
*connect_widget
= GetConnectWidget();
1975 ConnectWidget( connect_widget
);
1977 /* we cannot set colours, fonts and cursors before the widget has
1978 been realized, so we do this directly after realization */
1979 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
1980 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
1985 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1987 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1988 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1990 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
1991 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
1993 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1994 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
1996 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
1997 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
1999 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2000 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2002 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
2003 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2005 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
2006 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2008 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2009 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2011 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2012 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2015 bool wxWindow::Destroy()
2017 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2021 return wxWindowBase::Destroy();
2024 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2026 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2027 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2029 if (m_resizing
) return; /* I don't like recursions */
2032 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2034 /* don't set the size for children of wxNotebook, just take the values. */
2042 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2044 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2046 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2047 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2048 if (width
!= -1) m_width
= width
;
2049 if (height
!= -1) m_height
= height
;
2053 m_x
= x
+ pizza
->xoffset
;
2054 m_y
= y
+ pizza
->yoffset
;
2059 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2061 if (width
== -1) m_width
= 80;
2064 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2066 if (height
== -1) m_height
= 26;
2069 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2070 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2071 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2072 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2075 int bottom_border
= 0;
2077 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2079 /* the default button has a border around it */
2084 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
),
2089 m_height
+border
+bottom_border
);
2093 wxPrintf( "OnSize sent from " );
2094 if (GetClassInfo() && GetClassInfo()->GetClassName())
2095 wxPrintf( GetClassInfo()->GetClassName() );
2096 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2099 if (!m_nativeSizeEvent
)
2101 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2102 event
.SetEventObject( this );
2103 GetEventHandler()->ProcessEvent( event
);
2109 void wxWindow::OnInternalIdle()
2111 wxCursor cursor
= m_cursor
;
2112 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2116 /* I now set the cursor anew in every OnInternalIdle call
2117 as setting the cursor in a parent window also effects the
2118 windows above so that checking for the current cursor is
2123 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2125 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2127 if (!g_globalCursor
.Ok())
2128 cursor
= *wxSTANDARD_CURSOR
;
2130 window
= m_widget
->window
;
2131 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2132 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2138 GdkWindow
*window
= m_widget
->window
;
2139 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2140 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2148 void wxWindow::DoGetSize( int *width
, int *height
) const
2150 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2152 if (width
) (*width
) = m_width
;
2153 if (height
) (*height
) = m_height
;
2156 void wxWindow::DoSetClientSize( int width
, int height
)
2158 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2162 SetSize( width
, height
);
2169 #if (GTK_MINOR_VERSION == 0)
2170 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2174 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2175 #if 0 // unused - if this is ok, just remove this line (VZ)
2176 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2179 GtkWidget
*viewport
= scroll_window
->viewport
;
2180 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2182 dw
+= 2 * viewport_class
->xthickness
;
2183 dh
+= 2 * viewport_class
->ythickness
;
2187 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2189 /* when using GTK 1.2 we set the shadow border size to 2 */
2193 if (HasFlag(wxSIMPLE_BORDER
))
2195 /* when using GTK 1.2 we set the simple border size to 1 */
2204 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2205 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2207 we use this instead: range.slider_width = 11 + 2*2pts edge
2210 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2211 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2213 if (scroll_window
->vscrollbar_visible
)
2215 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2216 dw
+= scroll_class
->scrollbar_spacing
;
2219 if (scroll_window
->hscrollbar_visible
)
2221 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2222 dh
+= scroll_class
->scrollbar_spacing
;
2226 SetSize( width
+dw
, height
+dh
);
2230 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2232 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2236 if (width
) (*width
) = m_width
;
2237 if (height
) (*height
) = m_height
;
2244 #if (GTK_MINOR_VERSION == 0)
2245 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2249 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2250 #if 0 // unused - if this is ok, just remove this line (VZ)
2251 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2254 GtkWidget
*viewport
= scroll_window
->viewport
;
2255 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2257 dw
+= 2 * viewport_class
->xthickness
;
2258 dh
+= 2 * viewport_class
->ythickness
;
2262 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2264 /* when using GTK 1.2 we set the shadow border size to 2 */
2268 if (HasFlag(wxSIMPLE_BORDER
))
2270 /* when using GTK 1.2 we set the simple border size to 1 */
2278 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2279 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2281 we use this instead: range.slider_width = 11 + 2*2pts edge
2284 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2285 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2287 if (scroll_window
->vscrollbar_visible
)
2289 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2290 dw
+= scroll_class
->scrollbar_spacing
;
2293 if (scroll_window
->hscrollbar_visible
)
2295 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2296 dh
+= scroll_class
->scrollbar_spacing
;
2300 if (width
) (*width
) = m_width
- dw
;
2301 if (height
) (*height
) = m_height
- dh
;
2305 void wxWindow::DoGetPosition( int *x
, int *y
) const
2307 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2311 if (m_parent
&& m_parent
->m_wxwindow
)
2313 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2314 dx
= pizza
->xoffset
;
2315 dy
= pizza
->yoffset
;
2318 if (x
) (*x
) = m_x
- dx
;
2319 if (y
) (*y
) = m_y
- dy
;
2322 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2324 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2326 if (!m_widget
->window
) return;
2328 GdkWindow
*source
= (GdkWindow
*) NULL
;
2330 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2332 source
= m_widget
->window
;
2336 gdk_window_get_origin( source
, &org_x
, &org_y
);
2340 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2342 org_x
+= m_widget
->allocation
.x
;
2343 org_y
+= m_widget
->allocation
.y
;
2351 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2353 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2355 if (!m_widget
->window
) return;
2357 GdkWindow
*source
= (GdkWindow
*) NULL
;
2359 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2361 source
= m_widget
->window
;
2365 gdk_window_get_origin( source
, &org_x
, &org_y
);
2369 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2371 org_x
+= m_widget
->allocation
.x
;
2372 org_y
+= m_widget
->allocation
.y
;
2380 bool wxWindow::Show( bool show
)
2382 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2384 if (!wxWindowBase::Show(show
))
2391 gtk_widget_show( m_widget
);
2393 gtk_widget_hide( m_widget
);
2398 bool wxWindow::Enable( bool enable
)
2400 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2402 if (!wxWindowBase::Enable(enable
))
2408 gtk_widget_set_sensitive( m_widget
, enable
);
2410 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2415 int wxWindow::GetCharHeight() const
2417 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2419 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2421 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2423 return font
->ascent
+ font
->descent
;
2426 int wxWindow::GetCharWidth() const
2428 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2430 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2432 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2434 return gdk_string_width( font
, "H" );
2437 void wxWindow::GetTextExtent( const wxString
& string
,
2441 int *externalLeading
,
2442 const wxFont
*theFont
) const
2444 wxFont fontToUse
= m_font
;
2445 if (theFont
) fontToUse
= *theFont
;
2447 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2449 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2450 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2451 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2452 if (descent
) (*descent
) = font
->descent
;
2453 if (externalLeading
) (*externalLeading
) = 0; // ??
2456 void wxWindow::SetFocus()
2458 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2462 gtk_widget_grab_focus (m_wxwindow
);
2468 if (GTK_WIDGET_CAN_FOCUS(m_widget
) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
2470 gtk_widget_grab_focus (m_widget
);
2472 else if (GTK_IS_CONTAINER(m_widget
))
2474 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2483 bool wxWindow::AcceptsFocus() const
2485 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2488 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2490 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2492 wxWindow
*oldParent
= m_parent
,
2493 *newParent
= (wxWindow
*)newParentBase
;
2495 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2497 if ( !wxWindowBase::Reparent(newParent
) )
2500 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2502 /* prevent GTK from deleting the widget arbitrarily */
2503 gtk_widget_ref( m_widget
);
2507 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2510 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2514 /* insert GTK representation */
2515 (*(newParent
->m_insertCallback
))(newParent
, this);
2518 /* reverse: prevent GTK from deleting the widget arbitrarily */
2519 gtk_widget_unref( m_widget
);
2524 void wxWindow::DoAddChild(wxWindow
*child
)
2526 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2528 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
2530 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
2535 /* insert GTK representation */
2536 (*m_insertCallback
)(this, child
);
2539 void wxWindow::Raise()
2541 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2543 if (!m_widget
->window
) return;
2545 gdk_window_raise( m_widget
->window
);
2548 void wxWindow::Lower()
2550 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2552 if (!m_widget
->window
) return;
2554 gdk_window_lower( m_widget
->window
);
2557 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2559 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2561 return wxWindowBase::SetCursor( cursor
);
2564 void wxWindow::WarpPointer( int x
, int y
)
2566 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2568 /* we provide this function ourselves as it is
2569 missing in GDK (top of this file) */
2571 GdkWindow
*window
= (GdkWindow
*) NULL
;
2573 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2575 window
= GetConnectWidget()->window
;
2578 gdk_window_warp_pointer( window
, x
, y
);
2581 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2583 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2585 if (!m_widget
->window
) return;
2587 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2591 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
2593 rect
->width
, rect
->height
);
2597 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
2601 /* there is no GTK equivalent of "draw only, don't clear" so we
2602 invent our own in the GtkPizza widget */
2608 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2609 gboolean old_clear
= pizza
->clear_on_draw
;
2610 gtk_pizza_set_clear( pizza
, FALSE
);
2612 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2614 gtk_pizza_set_clear( pizza
, old_clear
);
2617 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2621 GdkRectangle gdk_rect
;
2622 gdk_rect
.x
= rect
->x
;
2623 gdk_rect
.y
= rect
->y
;
2624 gdk_rect
.width
= rect
->width
;
2625 gdk_rect
.height
= rect
->height
;
2629 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2630 gboolean old_clear
= pizza
->clear_on_draw
;
2631 gtk_pizza_set_clear( pizza
, FALSE
);
2633 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2635 gtk_pizza_set_clear( pizza
, old_clear
);
2638 gtk_widget_draw( m_widget
, &gdk_rect
);
2642 void wxWindow::Clear()
2644 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
2646 if (!m_widget
->window
) return;
2648 if (m_wxwindow
&& m_wxwindow
->window
)
2650 gdk_window_clear( m_wxwindow
->window
);
2655 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2657 wxWindowBase::DoSetToolTip(tip
);
2660 m_tooltip
->Apply( this );
2663 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2665 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
2667 #endif // wxUSE_TOOLTIPS
2669 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2671 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2673 if (!wxWindowBase::SetBackgroundColour(colour
))
2675 // don't leave if the GTK widget has just
2677 if (!m_delayedBackgroundColour
) return FALSE
;
2680 GdkWindow
*window
= (GdkWindow
*) NULL
;
2682 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2684 window
= GetConnectWidget()->window
;
2688 // indicate that a new style has been set
2689 // but it couldn't get applied as the
2690 // widget hasn't been realized yet.
2691 m_delayedBackgroundColour
= TRUE
;
2693 // pretend we have done something
2699 /* wxMSW doesn't clear the window here. I don't do that either to
2700 provide compatibility. call Clear() to do the job. */
2702 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
2703 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
2706 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2707 if (sysbg
== m_backgroundColour
)
2709 m_backgroundColour
= wxNullColour
;
2711 m_backgroundColour
= sysbg
;
2721 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
2723 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2725 if (!wxWindowBase::SetForegroundColour(colour
))
2727 // don't leave if the GTK widget has just
2729 if (!m_delayedForegroundColour
) return FALSE
;
2732 GdkWindow
*window
= (GdkWindow
*) NULL
;
2734 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2736 window
= GetConnectWidget()->window
;
2740 // indicate that a new style has been set
2741 // but it couldn't get applied as the
2742 // widget hasn't been realized yet.
2743 m_delayedForegroundColour
= TRUE
;
2745 // pretend we have done something
2749 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2750 if ( sysbg
== m_backgroundColour
)
2752 m_backgroundColour
= wxNullColour
;
2754 m_backgroundColour
= sysbg
;
2764 GtkStyle
*wxWindow::GetWidgetStyle()
2766 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
2768 m_widgetStyle
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
2770 return m_widgetStyle
;
2773 void wxWindow::SetWidgetStyle()
2775 GtkStyle
*style
= GetWidgetStyle();
2777 gdk_font_unref( style
->font
);
2778 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2780 if (m_foregroundColour
.Ok())
2782 m_foregroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2783 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
2784 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
2785 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
2788 if (m_backgroundColour
.Ok())
2790 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2791 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2792 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2793 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2794 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2795 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2796 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2797 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2798 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2802 void wxWindow::ApplyWidgetStyle()
2806 //-----------------------------------------------------------------------------
2807 // Pop-up menu stuff
2808 //-----------------------------------------------------------------------------
2810 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
2812 *is_waiting
= FALSE
;
2815 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2817 menu
->SetInvokingWindow( win
);
2818 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
2821 wxMenuItem
*menuitem
= node
->GetData();
2822 if (menuitem
->IsSubMenu())
2824 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2827 node
= node
->GetNext();
2831 static gint gs_pop_x
= 0;
2832 static gint gs_pop_y
= 0;
2834 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
2838 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
2843 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
2845 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2847 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
2849 SetInvokingWindow( menu
, this );
2856 bool is_waiting
= TRUE
;
2858 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
2859 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
2862 GTK_MENU(menu
->m_menu
),
2863 (GtkWidget
*) NULL
, // parent menu shell
2864 (GtkWidget
*) NULL
, // parent menu item
2865 (GtkMenuPositionFunc
) pop_pos_callback
,
2866 (gpointer
) this, // client data
2867 0, // button used to activate it
2868 gs_timeLastClick
// the time of activation
2873 while (gtk_events_pending())
2874 gtk_main_iteration();
2880 #if wxUSE_DRAG_AND_DROP
2882 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2884 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
2886 GtkWidget
*dnd_widget
= GetConnectWidget();
2888 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
2890 if (m_dropTarget
) delete m_dropTarget
;
2891 m_dropTarget
= dropTarget
;
2893 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
2896 #endif // wxUSE_DRAG_AND_DROP
2898 GtkWidget
* wxWindow::GetConnectWidget()
2900 GtkWidget
*connect_widget
= m_widget
;
2901 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2903 return connect_widget
;
2906 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2909 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
2911 return (window
== m_widget
->window
);
2914 bool wxWindow::SetFont( const wxFont
&font
)
2916 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2918 if (!wxWindowBase::SetFont(font
))
2920 // don't leave if the GTK widget has just
2922 if (!m_delayedFont
) 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_delayedFont
= TRUE
;
2938 // pretend we have done something
2942 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2943 if ( sysbg
== m_backgroundColour
)
2945 m_backgroundColour
= wxNullColour
;
2947 m_backgroundColour
= sysbg
;
2957 void wxWindow::CaptureMouse()
2959 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
2961 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
2963 GdkWindow
*window
= (GdkWindow
*) NULL
;
2965 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2967 window
= GetConnectWidget()->window
;
2969 if (!window
) return;
2971 gdk_pointer_grab( window
, FALSE
,
2973 (GDK_BUTTON_PRESS_MASK
|
2974 GDK_BUTTON_RELEASE_MASK
|
2975 GDK_POINTER_MOTION_HINT_MASK
|
2976 GDK_POINTER_MOTION_MASK
),
2978 m_cursor
.GetCursor(),
2980 g_captureWindow
= this;
2983 void wxWindow::ReleaseMouse()
2985 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
2987 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
2989 GdkWindow
*window
= (GdkWindow
*) NULL
;
2991 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2993 window
= GetConnectWidget()->window
;
2995 if (!window
) return;
2997 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
2998 g_captureWindow
= (wxWindow
*) NULL
;
3001 bool wxWindow::IsRetained() const
3006 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3007 int range
, bool refresh
)
3009 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3011 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3013 m_hasScrolling
= TRUE
;
3015 if (orient
== wxHORIZONTAL
)
3017 float fpos
= (float)pos
;
3018 float frange
= (float)range
;
3019 float fthumb
= (float)thumbVisible
;
3020 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3021 if (fpos
< 0.0) fpos
= 0.0;
3023 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3024 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3026 SetScrollPos( orient
, pos
, refresh
);
3030 m_oldHorizontalPos
= fpos
;
3032 m_hAdjust
->lower
= 0.0;
3033 m_hAdjust
->upper
= frange
;
3034 m_hAdjust
->value
= fpos
;
3035 m_hAdjust
->step_increment
= 1.0;
3036 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3037 m_hAdjust
->page_size
= fthumb
;
3041 float fpos
= (float)pos
;
3042 float frange
= (float)range
;
3043 float fthumb
= (float)thumbVisible
;
3044 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3045 if (fpos
< 0.0) fpos
= 0.0;
3047 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3048 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3050 SetScrollPos( orient
, pos
, refresh
);
3054 m_oldVerticalPos
= fpos
;
3056 m_vAdjust
->lower
= 0.0;
3057 m_vAdjust
->upper
= frange
;
3058 m_vAdjust
->value
= fpos
;
3059 m_vAdjust
->step_increment
= 1.0;
3060 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3061 m_vAdjust
->page_size
= fthumb
;
3064 if (orient
== wxHORIZONTAL
)
3065 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3067 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3070 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3072 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3074 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3076 if (orient
== wxHORIZONTAL
)
3078 float fpos
= (float)pos
;
3079 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3080 if (fpos
< 0.0) fpos
= 0.0;
3081 m_oldHorizontalPos
= fpos
;
3083 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3084 m_hAdjust
->value
= fpos
;
3088 float fpos
= (float)pos
;
3089 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3090 if (fpos
< 0.0) fpos
= 0.0;
3091 m_oldVerticalPos
= fpos
;
3093 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3094 m_vAdjust
->value
= fpos
;
3101 if (m_wxwindow
->window
)
3103 if (orient
== wxHORIZONTAL
)
3104 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3106 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3113 int wxWindow::GetScrollThumb( int orient
) const
3115 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3117 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3119 if (orient
== wxHORIZONTAL
)
3120 return (int)(m_hAdjust
->page_size
+0.5);
3122 return (int)(m_vAdjust
->page_size
+0.5);
3125 int wxWindow::GetScrollPos( int orient
) const
3127 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3129 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3131 if (orient
== wxHORIZONTAL
)
3132 return (int)(m_hAdjust
->value
+0.5);
3134 return (int)(m_vAdjust
->value
+0.5);
3137 int wxWindow::GetScrollRange( int orient
) const
3139 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3141 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3143 if (orient
== wxHORIZONTAL
)
3144 return (int)(m_hAdjust
->upper
+0.5);
3146 return (int)(m_vAdjust
->upper
+0.5);
3149 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3151 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3153 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3155 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3160 m_scrollGC = gdk_gc_new( m_wxwindow->window );
3161 gdk_gc_set_exposures( m_scrollGC, TRUE );
3164 wxNode *node = m_children.First();
3167 wxWindow *child = (wxWindow*) node->Data();
3170 child->GetSize( &sx, &sy );
3171 child->SetSize( child->m_x + dx, child->m_y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
3172 node = node->Next();
3177 GetClientSize( &cw, &ch );
3178 int w = cw - abs(dx);
3179 int h = ch - abs(dy);
3181 if ((h < 0) || (w < 0))
3189 if (dx < 0) s_x = -dx;
3190 if (dy < 0) s_y = -dy;
3193 if (dx > 0) d_x = dx;
3194 if (dy > 0) d_y = dy;
3196 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
3197 m_wxwindow->window, s_x, s_y, w, h );
3200 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3201 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3202 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3203 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3205 Refresh( TRUE, &rect );
3210 void wxWindow::SetScrolling(bool scroll
)
3212 m_isScrolling
= g_blockEventsOnScroll
= scroll
;