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 extern wxWindow
*g_focusWindow
= (wxWindow
*) NULL
;
190 // if we detect that the app has got/lost the focus, we set this variable to
191 // either TRUE or FALSE and an activate event will be sent during the next
192 // OnIdle() call and it is reset to -1: this value means that we shouldn't
193 // send any activate events at all
194 static int g_sendActivateEvent
= -1;
196 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
197 the last click here */
198 static guint32 gs_timeLastClick
= 0;
200 //-----------------------------------------------------------------------------
202 //-----------------------------------------------------------------------------
206 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
207 GdkEvent
*WXUNUSED(event
),
208 const wxChar
*WXUNUSED(name
) )
211 static bool s_done = FALSE;
214 wxLog::AddTraceMask("focus");
217 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
223 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
226 tmp
+= wxT(" FROM ");
229 wxChar
*s
= new wxChar
[tmp
.Length()+1];
233 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
234 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
239 //-----------------------------------------------------------------------------
240 // missing gdk functions
241 //-----------------------------------------------------------------------------
244 gdk_window_warp_pointer (GdkWindow
*window
,
248 GdkWindowPrivate
*priv
;
251 window
= (GdkWindow
*) &gdk_root_parent
;
253 priv
= (GdkWindowPrivate
*) window
;
255 if (!priv
->destroyed
)
257 XWarpPointer (priv
->xdisplay
,
258 None
, /* not source window -> move from anywhere */
259 priv
->xwindow
, /* dest window */
260 0, 0, 0, 0, /* not source window -> move from anywhere */
265 //-----------------------------------------------------------------------------
267 //-----------------------------------------------------------------------------
269 extern void wxapp_install_idle_handler();
270 extern bool g_isIdle
;
272 //-----------------------------------------------------------------------------
273 // local code (see below)
274 //-----------------------------------------------------------------------------
276 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
284 if (win
->HasScrolling())
286 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
287 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget
)->klass
);
290 GtkWidget *hscrollbar = scroll_window->hscrollbar;
291 GtkWidget *vscrollbar = scroll_window->vscrollbar;
293 we use this instead: range.slider_width = 11 + 2*2pts edge
296 if (scroll_window
->vscrollbar_visible
)
298 dw
+= 15; /* dw += vscrollbar->allocation.width; */
299 dw
+= scroll_class
->scrollbar_spacing
;
302 if (scroll_window
->hscrollbar_visible
)
304 dh
+= 15; /* dh += hscrollbar->allocation.height; */
305 dh
+= scroll_class
->scrollbar_spacing
;
311 if (GTK_WIDGET_NO_WINDOW (widget
))
313 dx
+= widget
->allocation
.x
;
314 dy
+= widget
->allocation
.y
;
317 if (win
->HasFlag(wxRAISED_BORDER
))
319 gtk_draw_shadow( widget
->style
,
324 win
->m_width
-dw
, win
->m_height
-dh
);
328 if (win
->HasFlag(wxSUNKEN_BORDER
))
330 gtk_draw_shadow( widget
->style
,
335 win
->m_width
-dw
, win
->m_height
-dh
);
339 if (win
->HasFlag(wxSIMPLE_BORDER
))
342 gc
= gdk_gc_new( widget
->window
);
343 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
344 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
346 win
->m_width
-dw
-1, win
->m_height
-dh
-1 );
352 //-----------------------------------------------------------------------------
353 // "expose_event" of m_widget
354 //-----------------------------------------------------------------------------
356 static void gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
358 if (gdk_event
->count
> 0) return;
359 draw_frame( widget
, win
);
362 //-----------------------------------------------------------------------------
363 // "draw" of m_widget
364 //-----------------------------------------------------------------------------
366 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
368 draw_frame( widget
, win
);
371 //-----------------------------------------------------------------------------
372 // key code mapping routines
373 //-----------------------------------------------------------------------------
375 static long map_to_unmodified_wx_keysym( KeySym keysym
)
382 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
384 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
390 case GDK_Super_R
: key_code
= WXK_ALT
; break;
391 case GDK_Menu
: key_code
= WXK_MENU
; break;
392 case GDK_Help
: key_code
= WXK_HELP
; break;
393 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
394 case GDK_ISO_Left_Tab
:
395 case GDK_Tab
: key_code
= WXK_TAB
; break;
396 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
397 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
398 case GDK_Return
: key_code
= WXK_RETURN
; break;
399 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
400 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
401 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
402 case GDK_Delete
: key_code
= WXK_DELETE
; break;
403 case GDK_Home
: key_code
= WXK_HOME
; break;
404 case GDK_Left
: key_code
= WXK_LEFT
; break;
405 case GDK_Up
: key_code
= WXK_UP
; break;
406 case GDK_Right
: key_code
= WXK_RIGHT
; break;
407 case GDK_Down
: key_code
= WXK_DOWN
; break;
408 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
409 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
410 case GDK_Next
: key_code
= WXK_NEXT
; break;
411 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
412 case GDK_End
: key_code
= WXK_END
; break;
413 case GDK_Begin
: key_code
= WXK_HOME
; break;
414 case GDK_Select
: key_code
= WXK_SELECT
; break;
415 case GDK_Print
: key_code
= WXK_PRINT
; break;
416 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
417 case GDK_Insert
: key_code
= WXK_INSERT
; break;
418 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
420 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
421 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
422 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
423 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
424 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
425 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
426 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
427 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
428 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
429 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
430 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
431 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
432 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
433 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
434 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
435 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
436 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
437 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
438 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
439 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
440 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
441 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
442 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
443 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
444 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
445 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
446 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
447 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
448 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
449 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
450 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
451 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
452 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
453 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
454 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
455 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
456 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
458 case GDK_F1
: key_code
= WXK_F1
; break;
459 case GDK_F2
: key_code
= WXK_F2
; break;
460 case GDK_F3
: key_code
= WXK_F3
; break;
461 case GDK_F4
: key_code
= WXK_F4
; break;
462 case GDK_F5
: key_code
= WXK_F5
; break;
463 case GDK_F6
: key_code
= WXK_F6
; break;
464 case GDK_F7
: key_code
= WXK_F7
; break;
465 case GDK_F8
: key_code
= WXK_F8
; break;
466 case GDK_F9
: key_code
= WXK_F9
; break;
467 case GDK_F10
: key_code
= WXK_F10
; break;
468 case GDK_F11
: key_code
= WXK_F11
; break;
469 case GDK_F12
: key_code
= WXK_F12
; break;
474 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
475 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
476 key_code
= (guint
)keysym
;
484 static long map_to_wx_keysym( KeySym keysym
)
490 case GDK_Menu
: key_code
= WXK_MENU
; break;
491 case GDK_Help
: key_code
= WXK_HELP
; break;
492 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
493 case GDK_ISO_Left_Tab
:
494 case GDK_Tab
: key_code
= WXK_TAB
; break;
495 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
496 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
497 case GDK_Return
: key_code
= WXK_RETURN
; break;
498 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
499 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
500 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
501 case GDK_Delete
: key_code
= WXK_DELETE
; break;
502 case GDK_Home
: key_code
= WXK_HOME
; break;
503 case GDK_Left
: key_code
= WXK_LEFT
; break;
504 case GDK_Up
: key_code
= WXK_UP
; break;
505 case GDK_Right
: key_code
= WXK_RIGHT
; break;
506 case GDK_Down
: key_code
= WXK_DOWN
; break;
507 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
508 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
509 case GDK_Next
: key_code
= WXK_NEXT
; break;
510 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
511 case GDK_End
: key_code
= WXK_END
; break;
512 case GDK_Begin
: key_code
= WXK_HOME
; break;
513 case GDK_Select
: key_code
= WXK_SELECT
; break;
514 case GDK_Print
: key_code
= WXK_PRINT
; break;
515 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
516 case GDK_Insert
: key_code
= WXK_INSERT
; break;
517 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
519 case GDK_KP_0
: key_code
= '0'; break;
520 case GDK_KP_1
: key_code
= '1'; break;
521 case GDK_KP_2
: key_code
= '2'; break;
522 case GDK_KP_3
: key_code
= '3'; break;
523 case GDK_KP_4
: key_code
= '4'; break;
524 case GDK_KP_5
: key_code
= '5'; break;
525 case GDK_KP_6
: key_code
= '6'; break;
526 case GDK_KP_7
: key_code
= '7'; break;
527 case GDK_KP_8
: key_code
= '8'; break;
528 case GDK_KP_9
: key_code
= '9'; break;
529 case GDK_KP_Space
: key_code
= ' '; break;
530 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
531 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
532 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
533 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
534 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
535 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
536 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
537 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
538 case GDK_KP_Up
: key_code
= WXK_UP
; break;
539 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
540 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
541 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
542 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
543 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
544 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
545 case GDK_KP_End
: key_code
= WXK_END
; break;
546 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
547 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
548 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
549 case GDK_KP_Equal
: key_code
= '='; break;
550 case GDK_KP_Multiply
: key_code
= '*'; break;
551 case GDK_KP_Add
: key_code
= '+'; break;
552 case GDK_KP_Separator
: key_code
= ','; break;
553 case GDK_KP_Subtract
: key_code
= '-'; break;
554 case GDK_KP_Decimal
: key_code
= '.'; break;
555 case GDK_KP_Divide
: key_code
= '/'; break;
557 case GDK_F1
: key_code
= WXK_F1
; break;
558 case GDK_F2
: key_code
= WXK_F2
; break;
559 case GDK_F3
: key_code
= WXK_F3
; break;
560 case GDK_F4
: key_code
= WXK_F4
; break;
561 case GDK_F5
: key_code
= WXK_F5
; break;
562 case GDK_F6
: key_code
= WXK_F6
; break;
563 case GDK_F7
: key_code
= WXK_F7
; break;
564 case GDK_F8
: key_code
= WXK_F8
; break;
565 case GDK_F9
: key_code
= WXK_F9
; break;
566 case GDK_F10
: key_code
= WXK_F10
; break;
567 case GDK_F11
: key_code
= WXK_F11
; break;
568 case GDK_F12
: key_code
= WXK_F12
; break;
573 key_code
= (guint
)keysym
;
581 //-----------------------------------------------------------------------------
582 // "expose_event" of m_wxwindow
583 //-----------------------------------------------------------------------------
585 static void gtk_window_expose_callback( GtkWidget
*WXUNUSED(widget
), GdkEventExpose
*gdk_event
, wxWindow
*win
)
590 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
592 gdk_event
->area
.width
,
593 gdk_event
->area
.height
);
595 if (gdk_event
->count
> 0)
599 wxPrintf( "OnExpose from " );
600 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
601 wxPrintf( win->GetClassInfo()->GetClassName() );
602 wxPrintf( " %d %d %d %d\n", (int)gdk_event->area.x,
603 (int)gdk_event->area.y,
604 (int)gdk_event->area.width,
605 (int)gdk_event->area.height );
608 wxEraseEvent
eevent( win
->GetId() );
609 eevent
.SetEventObject( win
);
610 win
->GetEventHandler()->ProcessEvent(eevent
);
612 wxPaintEvent
event( win
->GetId() );
613 event
.SetEventObject( win
);
614 win
->GetEventHandler()->ProcessEvent( event
);
616 win
->GetUpdateRegion().Clear();
619 //-----------------------------------------------------------------------------
620 // "draw" of m_wxwindow
621 //-----------------------------------------------------------------------------
623 static void gtk_window_draw_callback( GtkWidget
*WXUNUSED(widget
),
624 GdkRectangle
*rect
, wxWindow
*win
)
627 wxapp_install_idle_handler();
632 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
,
633 rect
->width
, rect
->height
);
636 wxPrintf( "OnDraw from " );
637 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
638 printf( win->GetClassInfo()->GetClassName() );
639 wxPrintf( " %d %d %d %d\n", (int)rect->x,
645 wxEraseEvent
eevent( win
->GetId() );
646 eevent
.SetEventObject( win
);
647 win
->GetEventHandler()->ProcessEvent(eevent
);
649 wxPaintEvent
event( win
->GetId() );
650 event
.SetEventObject( win
);
651 win
->GetEventHandler()->ProcessEvent( event
);
653 win
->GetUpdateRegion().Clear();
656 //-----------------------------------------------------------------------------
657 // "key_press_event" from any window
658 //-----------------------------------------------------------------------------
660 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
663 wxapp_install_idle_handler();
665 if (!win
->m_hasVMT
) return FALSE
;
666 if (g_blockEventsOnDrag
) return FALSE
;
669 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
670 if (gdk_event->state & GDK_SHIFT_MASK)
671 printf( "ShiftDown.\n" );
673 printf( "ShiftUp.\n" );
674 if (gdk_event->state & GDK_CONTROL_MASK)
675 printf( "ControlDown.\n" );
677 printf( "ControlUp.\n" );
682 GdkModifierType state
;
683 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
687 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
688 /* sending unknown key events doesn't really make sense */
689 if (key_code
== 0) return FALSE
;
691 wxKeyEvent
event( wxEVT_KEY_DOWN
);
692 event
.SetTimestamp( gdk_event
->time
);
693 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
694 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
695 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
696 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
697 event
.m_keyCode
= key_code
;
698 event
.m_scanCode
= gdk_event
->keyval
;
701 event
.SetEventObject( win
);
702 ret
= win
->GetEventHandler()->ProcessEvent( event
);
707 wxWindow
*ancestor
= win
;
710 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
713 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
714 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
717 if (ancestor
->m_isFrame
)
719 ancestor
= ancestor
->GetParent();
722 #endif // wxUSE_ACCEL
724 /* wxMSW doesn't send char events with Alt pressed */
725 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
726 will only be sent if it is not in an accelerator table. */
727 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
732 wxKeyEvent
event2( wxEVT_CHAR
);
733 event2
.SetTimestamp( gdk_event
->time
);
734 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
735 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
736 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
737 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
738 event2
.m_keyCode
= key_code
;
739 event2
.m_scanCode
= gdk_event
->keyval
;
742 event2
.SetEventObject( win
);
743 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
746 /* win is a control: tab can be propagated up */
748 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
749 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
750 (win
->GetParent()) &&
751 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
753 wxNavigationKeyEvent new_event
;
754 new_event
.SetEventObject( win
);
755 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
756 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
757 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
758 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
759 new_event
.SetCurrentFocus( win
);
760 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
763 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
765 (gdk_event
->keyval
== GDK_Escape
) )
767 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
768 new_event
.SetEventObject( win
);
769 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
772 #if (GTK_MINOR_VERSION > 0)
773 /* Pressing F10 will activate the menu bar of the top frame. */
777 (gdk_event->keyval == GDK_F10) )
779 wxWindow *ancestor = win;
782 if (wxIsKindOf(ancestor,wxFrame))
784 wxFrame *frame = (wxFrame*) ancestor;
785 wxMenuBar *menubar = frame->GetMenuBar();
788 wxNode *node = menubar->GetMenus().First();
791 wxMenu *firstMenu = (wxMenu*) node->Data();
792 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
798 ancestor = ancestor->GetParent();
806 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
813 //-----------------------------------------------------------------------------
814 // "key_release_event" from any window
815 //-----------------------------------------------------------------------------
817 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
820 wxapp_install_idle_handler();
822 if (!win
->m_hasVMT
) return FALSE
;
823 if (g_blockEventsOnDrag
) return FALSE
;
826 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
827 if (gdk_event->state & GDK_SHIFT_MASK)
828 printf( "ShiftDown.\n" );
830 printf( "ShiftUp.\n" );
831 if (gdk_event->state & GDK_CONTROL_MASK)
832 printf( "ControlDown.\n" );
834 printf( "ControlUp.\n" );
838 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
840 /* sending unknown key events doesn't really make sense */
841 if (key_code
== 0) return FALSE
;
845 GdkModifierType state
;
846 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
848 wxKeyEvent
event( wxEVT_KEY_UP
);
849 event
.SetTimestamp( gdk_event
->time
);
850 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
851 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
852 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
853 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
854 event
.m_keyCode
= key_code
;
855 event
.m_scanCode
= gdk_event
->keyval
;
858 event
.SetEventObject( win
);
860 if (win
->GetEventHandler()->ProcessEvent( event
))
862 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
869 //-----------------------------------------------------------------------------
870 // "button_press_event"
871 //-----------------------------------------------------------------------------
873 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
876 wxapp_install_idle_handler();
879 wxPrintf( wxT("1) OnButtonPress from ") );
880 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
881 wxPrintf( win->GetClassInfo()->GetClassName() );
882 wxPrintf( wxT(".\n") );
884 if (!win
->m_hasVMT
) return FALSE
;
885 if (g_blockEventsOnDrag
) return TRUE
;
886 if (g_blockEventsOnScroll
) return TRUE
;
888 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
892 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
894 gtk_widget_grab_focus (win
->m_wxwindow
);
897 wxPrintf( wxT("GrabFocus from ") );
898 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
899 wxPrintf( win->GetClassInfo()->GetClassName() );
900 wxPrintf( wxT(".\n") );
906 wxEventType event_type
= wxEVT_LEFT_DOWN
;
908 if (gdk_event
->button
== 1)
910 switch (gdk_event
->type
)
912 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
913 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
917 else if (gdk_event
->button
== 2)
919 switch (gdk_event
->type
)
921 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
922 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
926 else if (gdk_event
->button
== 3)
928 switch (gdk_event
->type
)
930 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
931 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
936 wxMouseEvent
event( event_type
);
937 event
.SetTimestamp( gdk_event
->time
);
938 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
939 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
940 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
941 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
942 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
943 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
944 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
946 event
.m_x
= (long)gdk_event
->x
;
947 event
.m_y
= (long)gdk_event
->y
;
949 // Some control don't have their own X window and thus cannot get
952 if (!g_captureWindow
)
954 wxCoord x
= event
.m_x
;
955 wxCoord y
= event
.m_y
;
958 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
963 wxNode
*node
= win
->GetChildren().First();
966 wxWindow
*child
= (wxWindow
*)node
->Data();
969 if (!child
->IsShown())
972 if (child
->m_isStaticBox
)
974 // wxStaticBox is transparent in the box itself
975 int xx1
= child
->m_x
;
976 int yy1
= child
->m_y
;
977 int xx2
= child
->m_x
+ child
->m_width
;
978 int yy2
= child
->m_x
+ child
->m_height
;
981 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
983 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
985 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
987 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
990 event
.m_x
-= child
->m_x
;
991 event
.m_y
-= child
->m_y
;
998 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1000 (child
->m_y
<= y
) &&
1001 (child
->m_x
+child
->m_width
>= x
) &&
1002 (child
->m_y
+child
->m_height
>= y
))
1005 event
.m_x
-= child
->m_x
;
1006 event
.m_y
-= child
->m_y
;
1013 event
.SetEventObject( win
);
1015 gs_timeLastClick
= gdk_event
->time
;
1018 wxPrintf( wxT("2) OnButtonPress from ") );
1019 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1020 wxPrintf( win->GetClassInfo()->GetClassName() );
1021 wxPrintf( wxT(".\n") );
1024 if (win
->GetEventHandler()->ProcessEvent( event
))
1026 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1033 //-----------------------------------------------------------------------------
1034 // "button_release_event"
1035 //-----------------------------------------------------------------------------
1037 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1040 wxapp_install_idle_handler();
1042 if (!win
->m_hasVMT
) return FALSE
;
1043 if (g_blockEventsOnDrag
) return FALSE
;
1044 if (g_blockEventsOnScroll
) return FALSE
;
1046 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1049 printf( "OnButtonRelease from " );
1050 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1051 printf( win->GetClassInfo()->GetClassName() );
1055 wxEventType event_type
= wxEVT_NULL
;
1057 switch (gdk_event
->button
)
1059 case 1: event_type
= wxEVT_LEFT_UP
; break;
1060 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1061 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1064 wxMouseEvent
event( event_type
);
1065 event
.SetTimestamp( gdk_event
->time
);
1066 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1067 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1068 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1069 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1070 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1071 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1072 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1073 event
.m_x
= (long)gdk_event
->x
;
1074 event
.m_y
= (long)gdk_event
->y
;
1076 // Some control don't have their own X window and thus cannot get
1079 if (!g_captureWindow
)
1081 wxCoord x
= event
.m_x
;
1082 wxCoord y
= event
.m_y
;
1083 if (win
->m_wxwindow
)
1085 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1086 x
+= pizza
->xoffset
;
1087 y
+= pizza
->yoffset
;
1090 wxNode
*node
= win
->GetChildren().First();
1093 wxWindow
*child
= (wxWindow
*)node
->Data();
1095 node
= node
->Next();
1096 if (!child
->IsShown())
1099 if (child
->m_isStaticBox
)
1101 // wxStaticBox is transparent in the box itself
1102 int xx1
= child
->m_x
;
1103 int yy1
= child
->m_y
;
1104 int xx2
= child
->m_x
+ child
->m_width
;
1105 int yy2
= child
->m_x
+ child
->m_height
;
1108 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1110 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1112 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1114 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1117 event
.m_x
-= child
->m_x
;
1118 event
.m_y
-= child
->m_y
;
1125 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1126 (child
->m_x
<= x
) &&
1127 (child
->m_y
<= y
) &&
1128 (child
->m_x
+child
->m_width
>= x
) &&
1129 (child
->m_y
+child
->m_height
>= y
))
1132 event
.m_x
-= child
->m_x
;
1133 event
.m_y
-= child
->m_y
;
1140 event
.SetEventObject( win
);
1142 if (win
->GetEventHandler()->ProcessEvent( event
))
1144 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1151 //-----------------------------------------------------------------------------
1152 // "motion_notify_event"
1153 //-----------------------------------------------------------------------------
1155 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1158 wxapp_install_idle_handler();
1160 if (!win
->m_hasVMT
) return FALSE
;
1161 if (g_blockEventsOnDrag
) return FALSE
;
1162 if (g_blockEventsOnScroll
) return FALSE
;
1164 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1166 if (gdk_event
->is_hint
)
1170 GdkModifierType state
;
1171 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1177 printf( "OnMotion from " );
1178 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1179 printf( win->GetClassInfo()->GetClassName() );
1183 wxMouseEvent
event( wxEVT_MOTION
);
1184 event
.SetTimestamp( gdk_event
->time
);
1185 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1186 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1187 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1188 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1189 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1190 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1191 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1193 event
.m_x
= (long)gdk_event
->x
;
1194 event
.m_y
= (long)gdk_event
->y
;
1196 // Some control don't have their own X window and thus cannot get
1199 if (!g_captureWindow
)
1201 wxCoord x
= event
.m_x
;
1202 wxCoord y
= event
.m_y
;
1203 if (win
->m_wxwindow
)
1205 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1206 x
+= pizza
->xoffset
;
1207 y
+= pizza
->yoffset
;
1210 wxNode
*node
= win
->GetChildren().First();
1213 wxWindow
*child
= (wxWindow
*)node
->Data();
1215 node
= node
->Next();
1216 if (!child
->IsShown())
1219 if (child
->m_isStaticBox
)
1221 // wxStaticBox is transparent in the box itself
1222 int xx1
= child
->m_x
;
1223 int yy1
= child
->m_y
;
1224 int xx2
= child
->m_x
+ child
->m_width
;
1225 int yy2
= child
->m_x
+ child
->m_height
;
1228 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1230 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1232 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1234 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1237 event
.m_x
-= child
->m_x
;
1238 event
.m_y
-= child
->m_y
;
1245 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1246 (child
->m_x
<= x
) &&
1247 (child
->m_y
<= y
) &&
1248 (child
->m_x
+child
->m_width
>= x
) &&
1249 (child
->m_y
+child
->m_height
>= y
))
1252 event
.m_x
-= child
->m_x
;
1253 event
.m_y
-= child
->m_y
;
1260 event
.SetEventObject( win
);
1262 if (win
->GetEventHandler()->ProcessEvent( event
))
1264 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1271 //-----------------------------------------------------------------------------
1273 //-----------------------------------------------------------------------------
1275 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1278 wxapp_install_idle_handler();
1280 if (!win
->m_hasVMT
) return FALSE
;
1281 if (g_blockEventsOnDrag
) return FALSE
;
1283 switch ( g_sendActivateEvent
)
1286 // we've got focus from outside, synthtize wxActivateEvent
1287 g_sendActivateEvent
= 1;
1291 // another our window just lost focus, it was already ours before
1292 // - don't send any wxActivateEvent
1293 g_sendActivateEvent
= -1;
1297 g_focusWindow
= win
;
1300 printf( "OnSetFocus from " );
1301 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1302 printf( win->GetClassInfo()->GetClassName() );
1304 printf( WXSTRINGCAST win->GetLabel() );
1308 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1311 panel
->SetLastFocus(win
);
1314 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1315 event
.SetEventObject( win
);
1317 if (win
->GetEventHandler()->ProcessEvent( event
))
1319 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1326 //-----------------------------------------------------------------------------
1327 // "focus_out_event"
1328 //-----------------------------------------------------------------------------
1330 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1333 wxapp_install_idle_handler();
1335 if (!win
->m_hasVMT
) return FALSE
;
1336 if (g_blockEventsOnDrag
) return FALSE
;
1338 // if the focus goes out of our app alltogether, OnIdle() will send
1339 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1340 // g_sendActivateEvent to -1
1341 g_sendActivateEvent
= 0;
1343 g_focusWindow
= (wxWindow
*)NULL
;
1346 printf( "OnKillFocus from " );
1347 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1348 printf( win->GetClassInfo()->GetClassName() );
1352 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1353 event
.SetEventObject( win
);
1355 if (win
->GetEventHandler()->ProcessEvent( event
))
1357 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1364 //-----------------------------------------------------------------------------
1365 // "enter_notify_event"
1366 //-----------------------------------------------------------------------------
1368 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1371 wxapp_install_idle_handler();
1373 if (!win
->m_hasVMT
) return FALSE
;
1374 if (g_blockEventsOnDrag
) return FALSE
;
1376 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1378 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1379 #if (GTK_MINOR_VERSION > 0)
1380 event
.SetTimestamp( gdk_event
->time
);
1382 event
.SetEventObject( win
);
1386 GdkModifierType state
= (GdkModifierType
)0;
1388 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1390 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1391 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1392 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1393 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1394 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1395 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1396 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1398 event
.m_x
= (long)x
;
1399 event
.m_y
= (long)y
;
1401 if (win
->GetEventHandler()->ProcessEvent( event
))
1403 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1410 //-----------------------------------------------------------------------------
1411 // "leave_notify_event"
1412 //-----------------------------------------------------------------------------
1414 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1417 wxapp_install_idle_handler();
1419 if (!win
->m_hasVMT
) return FALSE
;
1420 if (g_blockEventsOnDrag
) return FALSE
;
1422 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1424 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1425 #if (GTK_MINOR_VERSION > 0)
1426 event
.SetTimestamp( gdk_event
->time
);
1428 event
.SetEventObject( win
);
1432 GdkModifierType state
= (GdkModifierType
)0;
1434 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1436 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1437 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1438 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1439 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1440 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1441 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1442 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1444 event
.m_x
= (long)x
;
1445 event
.m_y
= (long)y
;
1447 if (win
->GetEventHandler()->ProcessEvent( event
))
1449 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1456 //-----------------------------------------------------------------------------
1457 // "value_changed" from m_vAdjust
1458 //-----------------------------------------------------------------------------
1460 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1463 wxapp_install_idle_handler();
1465 if (g_blockEventsOnDrag
) return;
1467 if (!win
->m_hasVMT
) return;
1469 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1470 if (fabs(diff
) < 0.2) return;
1472 win
->m_oldVerticalPos
= adjust
->value
;
1474 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1475 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1477 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1478 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1479 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1480 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1481 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1483 int value
= (int)(adjust
->value
+0.5);
1485 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1486 event
.SetEventObject( win
);
1487 win
->GetEventHandler()->ProcessEvent( event
);
1490 //-----------------------------------------------------------------------------
1491 // "value_changed" from m_hAdjust
1492 //-----------------------------------------------------------------------------
1494 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1497 wxapp_install_idle_handler();
1499 if (g_blockEventsOnDrag
) return;
1500 if (!win
->m_hasVMT
) return;
1502 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1503 if (fabs(diff
) < 0.2) return;
1505 win
->m_oldHorizontalPos
= adjust
->value
;
1507 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1508 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1510 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1511 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1512 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1513 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1514 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1516 int value
= (int)(adjust
->value
+0.5);
1518 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1519 event
.SetEventObject( win
);
1520 win
->GetEventHandler()->ProcessEvent( event
);
1523 //-----------------------------------------------------------------------------
1524 // "changed" from m_vAdjust
1525 //-----------------------------------------------------------------------------
1527 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1530 wxapp_install_idle_handler();
1532 if (g_blockEventsOnDrag
) return;
1533 if (!win
->m_hasVMT
) return;
1535 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1536 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1538 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1539 event
.SetEventObject( win
);
1540 win
->GetEventHandler()->ProcessEvent( event
);
1543 //-----------------------------------------------------------------------------
1544 // "changed" from m_hAdjust
1545 //-----------------------------------------------------------------------------
1547 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1550 wxapp_install_idle_handler();
1552 if (g_blockEventsOnDrag
) return;
1553 if (!win
->m_hasVMT
) return;
1555 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1556 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1558 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1559 event
.SetEventObject( win
);
1560 win
->GetEventHandler()->ProcessEvent( event
);
1563 //-----------------------------------------------------------------------------
1564 // "button_press_event" from scrollbar
1565 //-----------------------------------------------------------------------------
1567 static gint
gtk_scrollbar_button_press_callback( GtkRange
*WXUNUSED(widget
),
1568 GdkEventButton
*WXUNUSED(gdk_event
),
1572 wxapp_install_idle_handler();
1574 // don't test here as we can release the mouse while being over
1575 // a different window than the slider
1577 // if (gdk_event->window != widget->slider) return FALSE;
1579 win
->SetScrolling( TRUE
);
1584 //-----------------------------------------------------------------------------
1585 // "button_release_event" from scrollbar
1586 //-----------------------------------------------------------------------------
1588 static gint
gtk_scrollbar_button_release_callback( GtkRange
*WXUNUSED(widget
),
1589 GdkEventButton
*WXUNUSED(gdk_event
),
1593 // don't test here as we can release the mouse while being over
1594 // a different window than the slider
1596 // if (gdk_event->window != widget->slider) return FALSE;
1598 win
->SetScrolling( FALSE
);
1603 // ----------------------------------------------------------------------------
1604 // this wxWindowBase function is implemented here (in platform-specific file)
1605 // because it is static and so couldn't be made virtual
1606 // ----------------------------------------------------------------------------
1608 wxWindow
*wxWindowBase::FindFocus()
1610 return g_focusWindow
;
1613 //-----------------------------------------------------------------------------
1614 // "realize" from m_widget
1615 //-----------------------------------------------------------------------------
1617 /* we cannot set colours and fonts before the widget has
1618 been realized, so we do this directly after realization */
1621 gtk_window_realized_callback( GtkWidget
* WXUNUSED(widget
), wxWindow
*win
)
1624 wxapp_install_idle_handler();
1626 if (win
->m_delayedFont
)
1627 win
->SetFont( win
->GetFont() );
1629 if (win
->m_delayedBackgroundColour
)
1630 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1632 if (win
->m_delayedForegroundColour
)
1633 win
->SetForegroundColour( win
->GetForegroundColour() );
1635 wxWindowCreateEvent
event( win
);
1636 event
.SetEventObject( win
);
1637 win
->GetEventHandler()->ProcessEvent( event
);
1642 //-----------------------------------------------------------------------------
1643 // InsertChild for wxWindow.
1644 //-----------------------------------------------------------------------------
1646 /* Callback for wxWindow. This very strange beast has to be used because
1647 * C++ has no virtual methods in a constructor. We have to emulate a
1648 * virtual function here as wxNotebook requires a different way to insert
1649 * a child in it. I had opted for creating a wxNotebookPage window class
1650 * which would have made this superfluous (such in the MDI window system),
1651 * but no-one was listening to me... */
1653 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1655 /* the window might have been scrolled already, do we
1656 have to adapt the position */
1657 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
1658 child
->m_x
+= pizza
->xoffset
;
1659 child
->m_y
+= pizza
->yoffset
;
1661 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
1662 GTK_WIDGET(child
->m_widget
),
1669 //-----------------------------------------------------------------------------
1671 //-----------------------------------------------------------------------------
1673 wxWindow
* wxGetActiveWindow()
1675 return g_focusWindow
;
1678 //-----------------------------------------------------------------------------
1680 //-----------------------------------------------------------------------------
1682 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
1684 void wxWindow::Init()
1690 m_widget
= (GtkWidget
*) NULL
;
1691 m_wxwindow
= (GtkWidget
*) NULL
;
1701 m_needParent
= TRUE
;
1702 m_isBeingDeleted
= FALSE
;
1705 m_nativeSizeEvent
= FALSE
;
1707 m_hasScrolling
= FALSE
;
1708 m_isScrolling
= FALSE
;
1710 m_hAdjust
= (GtkAdjustment
*) NULL
;
1711 m_vAdjust
= (GtkAdjustment
*) NULL
;
1712 m_oldHorizontalPos
= 0.0;
1713 m_oldVerticalPos
= 0.0;
1716 m_widgetStyle
= (GtkStyle
*) NULL
;
1718 m_insertCallback
= (wxInsertChildFunction
) NULL
;
1720 m_isStaticBox
= FALSE
;
1721 m_isRadioButton
= FALSE
;
1723 m_acceptsFocus
= FALSE
;
1725 m_cursor
= *wxSTANDARD_CURSOR
;
1728 wxWindow::wxWindow()
1733 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1734 const wxPoint
&pos
, const wxSize
&size
,
1735 long style
, const wxString
&name
)
1739 Create( parent
, id
, pos
, size
, style
, name
);
1742 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1743 const wxPoint
&pos
, const wxSize
&size
,
1744 long style
, const wxString
&name
)
1746 if (!PreCreation( parent
, pos
, size
) ||
1747 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
1749 wxFAIL_MSG( wxT("wxWindow creation failed") );
1753 m_insertCallback
= wxInsertChildInWindow
;
1755 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
1756 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1759 debug_focus_in( m_widget
, wxT("wxWindow::m_widget"), name
);
1762 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
1765 debug_focus_in( scrolledWindow
->hscrollbar
, wxT("wxWindow::hsrcollbar"), name
);
1766 debug_focus_in( scrolledWindow
->vscrollbar
, wxT("wxWindow::vsrcollbar"), name
);
1769 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1770 scroll_class
->scrollbar_spacing
= 0;
1772 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1774 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
1775 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
1777 m_wxwindow
= gtk_pizza_new();
1780 debug_focus_in( m_wxwindow
, wxT("wxWindow::m_wxwindow"), name
);
1783 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
1785 #if (GTK_MINOR_VERSION > 0)
1786 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
1788 if (HasFlag(wxRAISED_BORDER
))
1790 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
1792 else if (HasFlag(wxSUNKEN_BORDER
))
1794 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
1796 else if (HasFlag(wxSIMPLE_BORDER
))
1798 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
1802 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
1804 #else // GTK_MINOR_VERSION == 0
1805 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
1807 if (HasFlag(wxRAISED_BORDER
))
1809 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
1811 else if (HasFlag(wxSUNKEN_BORDER
))
1813 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
1817 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
1819 #endif // GTK_MINOR_VERSION
1821 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1822 m_acceptsFocus
= TRUE
;
1824 #if (GTK_MINOR_VERSION == 0)
1825 // shut the viewport up
1826 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1827 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1828 #endif // GTK_MINOR_VERSION == 0
1830 // I _really_ don't want scrollbars in the beginning
1831 m_vAdjust
->lower
= 0.0;
1832 m_vAdjust
->upper
= 1.0;
1833 m_vAdjust
->value
= 0.0;
1834 m_vAdjust
->step_increment
= 1.0;
1835 m_vAdjust
->page_increment
= 1.0;
1836 m_vAdjust
->page_size
= 5.0;
1837 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
1838 m_hAdjust
->lower
= 0.0;
1839 m_hAdjust
->upper
= 1.0;
1840 m_hAdjust
->value
= 0.0;
1841 m_hAdjust
->step_increment
= 1.0;
1842 m_hAdjust
->page_increment
= 1.0;
1843 m_hAdjust
->page_size
= 5.0;
1844 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1846 // these handlers block mouse events to any window during scrolling such as
1847 // motion events and prevent GTK and wxWindows from fighting over where the
1850 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
1851 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1853 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
1854 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1856 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
1857 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1859 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
1860 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1862 // these handlers get notified when screen updates are required either when
1863 // scrolling or when the window size (and therefore scrollbar configuration)
1866 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
1867 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
1868 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
1869 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
1871 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
1872 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
1873 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
1874 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
1876 gtk_widget_show( m_wxwindow
);
1879 m_parent
->DoAddChild( this );
1888 wxWindow::~wxWindow()
1890 m_isBeingDeleted
= TRUE
;
1899 m_parent
->RemoveChild( this );
1903 gtk_style_unref( m_widgetStyle
);
1904 m_widgetStyle
= (GtkStyle
*) NULL
;
1909 gtk_widget_destroy( m_wxwindow
);
1910 m_wxwindow
= (GtkWidget
*) NULL
;
1915 gtk_widget_destroy( m_widget
);
1916 m_widget
= (GtkWidget
*) NULL
;
1920 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
1922 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
1924 /* this turns -1 into 20 so that a minimal window is
1925 visible even although -1,-1 has been given as the
1926 size of the window. the same trick is used in other
1927 ports and should make debugging easier */
1928 m_width
= WidthDefault(size
.x
);
1929 m_height
= HeightDefault(size
.y
);
1934 /* some reasonable defaults */
1939 m_x
= (gdk_screen_width () - m_width
) / 2;
1940 if (m_x
< 10) m_x
= 10;
1944 m_y
= (gdk_screen_height () - m_height
) / 2;
1945 if (m_y
< 10) m_y
= 10;
1952 void wxWindow::PostCreation()
1954 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
1960 /* these get reported to wxWindows -> wxPaintEvent */
1961 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1962 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1964 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1965 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1968 #if (GTK_MINOR_VERSION > 0)
1969 /* these are called when the "sunken" or "raised" borders are drawn */
1970 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
1971 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
1973 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
1974 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
1978 GtkWidget
*connect_widget
= GetConnectWidget();
1980 ConnectWidget( connect_widget
);
1982 /* we cannot set colours, fonts and cursors before the widget has
1983 been realized, so we do this directly after realization */
1984 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
1985 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
1990 void wxWindow::ConnectWidget( GtkWidget
*widget
)
1992 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
1993 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
1995 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
1996 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
1998 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
1999 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2001 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2002 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2004 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2005 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2007 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
2008 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2010 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
2011 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2013 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2014 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2016 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2017 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2020 bool wxWindow::Destroy()
2022 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2026 return wxWindowBase::Destroy();
2029 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2031 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2032 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2034 if (m_resizing
) return; /* I don't like recursions */
2037 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2039 /* don't set the size for children of wxNotebook, just take the values. */
2047 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2049 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2051 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2052 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2053 if (width
!= -1) m_width
= width
;
2054 if (height
!= -1) m_height
= height
;
2058 m_x
= x
+ pizza
->xoffset
;
2059 m_y
= y
+ pizza
->yoffset
;
2064 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2066 if (width
== -1) m_width
= 80;
2069 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2071 if (height
== -1) m_height
= 26;
2074 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2075 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2076 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2077 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2080 int bottom_border
= 0;
2082 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2084 /* the default button has a border around it */
2089 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
),
2094 m_height
+border
+bottom_border
);
2098 wxPrintf( "OnSize sent from " );
2099 if (GetClassInfo() && GetClassInfo()->GetClassName())
2100 wxPrintf( GetClassInfo()->GetClassName() );
2101 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2104 if (!m_nativeSizeEvent
)
2106 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2107 event
.SetEventObject( this );
2108 GetEventHandler()->ProcessEvent( event
);
2114 void wxWindow::OnInternalIdle()
2116 if ( g_sendActivateEvent
!= -1 )
2118 bool activate
= g_sendActivateEvent
!= 0;
2121 g_sendActivateEvent
= -1;
2123 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2124 event
.SetEventObject(this);
2126 (void)GetEventHandler()->ProcessEvent(event
);
2129 wxCursor cursor
= m_cursor
;
2130 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2134 /* I now set the cursor anew in every OnInternalIdle call
2135 as setting the cursor in a parent window also effects the
2136 windows above so that checking for the current cursor is
2141 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2143 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2145 if (!g_globalCursor
.Ok())
2146 cursor
= *wxSTANDARD_CURSOR
;
2148 window
= m_widget
->window
;
2149 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2150 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2156 GdkWindow
*window
= m_widget
->window
;
2157 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2158 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2166 void wxWindow::DoGetSize( int *width
, int *height
) const
2168 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2170 if (width
) (*width
) = m_width
;
2171 if (height
) (*height
) = m_height
;
2174 void wxWindow::DoSetClientSize( int width
, int height
)
2176 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2180 SetSize( width
, height
);
2187 #if (GTK_MINOR_VERSION == 0)
2188 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2192 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2193 #if 0 // unused - if this is ok, just remove this line (VZ)
2194 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2197 GtkWidget
*viewport
= scroll_window
->viewport
;
2198 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2200 dw
+= 2 * viewport_class
->xthickness
;
2201 dh
+= 2 * viewport_class
->ythickness
;
2205 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2207 /* when using GTK 1.2 we set the shadow border size to 2 */
2211 if (HasFlag(wxSIMPLE_BORDER
))
2213 /* when using GTK 1.2 we set the simple border size to 1 */
2222 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2223 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2225 we use this instead: range.slider_width = 11 + 2*2pts edge
2228 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2229 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2231 if (scroll_window
->vscrollbar_visible
)
2233 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2234 dw
+= scroll_class
->scrollbar_spacing
;
2237 if (scroll_window
->hscrollbar_visible
)
2239 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2240 dh
+= scroll_class
->scrollbar_spacing
;
2244 SetSize( width
+dw
, height
+dh
);
2248 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2250 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2254 if (width
) (*width
) = m_width
;
2255 if (height
) (*height
) = m_height
;
2262 #if (GTK_MINOR_VERSION == 0)
2263 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2267 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2268 #if 0 // unused - if this is ok, just remove this line (VZ)
2269 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2272 GtkWidget
*viewport
= scroll_window
->viewport
;
2273 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2275 dw
+= 2 * viewport_class
->xthickness
;
2276 dh
+= 2 * viewport_class
->ythickness
;
2280 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2282 /* when using GTK 1.2 we set the shadow border size to 2 */
2286 if (HasFlag(wxSIMPLE_BORDER
))
2288 /* when using GTK 1.2 we set the simple border size to 1 */
2296 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2297 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2299 we use this instead: range.slider_width = 11 + 2*2pts edge
2302 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2303 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2305 if (scroll_window
->vscrollbar_visible
)
2307 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2308 dw
+= scroll_class
->scrollbar_spacing
;
2311 if (scroll_window
->hscrollbar_visible
)
2313 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2314 dh
+= scroll_class
->scrollbar_spacing
;
2318 if (width
) (*width
) = m_width
- dw
;
2319 if (height
) (*height
) = m_height
- dh
;
2323 void wxWindow::DoGetPosition( int *x
, int *y
) const
2325 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2329 if (m_parent
&& m_parent
->m_wxwindow
)
2331 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2332 dx
= pizza
->xoffset
;
2333 dy
= pizza
->yoffset
;
2336 if (x
) (*x
) = m_x
- dx
;
2337 if (y
) (*y
) = m_y
- dy
;
2340 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2342 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2344 if (!m_widget
->window
) return;
2346 GdkWindow
*source
= (GdkWindow
*) NULL
;
2348 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2350 source
= m_widget
->window
;
2354 gdk_window_get_origin( source
, &org_x
, &org_y
);
2358 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2360 org_x
+= m_widget
->allocation
.x
;
2361 org_y
+= m_widget
->allocation
.y
;
2369 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2371 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2373 if (!m_widget
->window
) return;
2375 GdkWindow
*source
= (GdkWindow
*) NULL
;
2377 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2379 source
= m_widget
->window
;
2383 gdk_window_get_origin( source
, &org_x
, &org_y
);
2387 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2389 org_x
+= m_widget
->allocation
.x
;
2390 org_y
+= m_widget
->allocation
.y
;
2398 bool wxWindow::Show( bool show
)
2400 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2402 if (!wxWindowBase::Show(show
))
2409 gtk_widget_show( m_widget
);
2411 gtk_widget_hide( m_widget
);
2416 bool wxWindow::Enable( bool enable
)
2418 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2420 if (!wxWindowBase::Enable(enable
))
2426 gtk_widget_set_sensitive( m_widget
, enable
);
2428 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2433 int wxWindow::GetCharHeight() const
2435 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2437 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2439 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2441 return font
->ascent
+ font
->descent
;
2444 int wxWindow::GetCharWidth() const
2446 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2448 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2450 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2452 return gdk_string_width( font
, "H" );
2455 void wxWindow::GetTextExtent( const wxString
& string
,
2459 int *externalLeading
,
2460 const wxFont
*theFont
) const
2462 wxFont fontToUse
= m_font
;
2463 if (theFont
) fontToUse
= *theFont
;
2465 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2467 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2468 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2469 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2470 if (descent
) (*descent
) = font
->descent
;
2471 if (externalLeading
) (*externalLeading
) = 0; // ??
2474 void wxWindow::SetFocus()
2476 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2480 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2481 gtk_widget_grab_focus (m_wxwindow
);
2487 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2489 gtk_widget_grab_focus (m_widget
);
2491 else if (GTK_IS_CONTAINER(m_widget
))
2493 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2502 bool wxWindow::AcceptsFocus() const
2504 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2507 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2509 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2511 wxWindow
*oldParent
= m_parent
,
2512 *newParent
= (wxWindow
*)newParentBase
;
2514 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2516 if ( !wxWindowBase::Reparent(newParent
) )
2519 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2521 /* prevent GTK from deleting the widget arbitrarily */
2522 gtk_widget_ref( m_widget
);
2526 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2529 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2533 /* insert GTK representation */
2534 (*(newParent
->m_insertCallback
))(newParent
, this);
2537 /* reverse: prevent GTK from deleting the widget arbitrarily */
2538 gtk_widget_unref( m_widget
);
2543 void wxWindow::DoAddChild(wxWindow
*child
)
2545 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2547 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
2549 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
2554 /* insert GTK representation */
2555 (*m_insertCallback
)(this, child
);
2558 void wxWindow::Raise()
2560 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2562 if (!m_widget
->window
) return;
2564 gdk_window_raise( m_widget
->window
);
2567 void wxWindow::Lower()
2569 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2571 if (!m_widget
->window
) return;
2573 gdk_window_lower( m_widget
->window
);
2576 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2578 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2580 return wxWindowBase::SetCursor( cursor
);
2583 void wxWindow::WarpPointer( int x
, int y
)
2585 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2587 /* we provide this function ourselves as it is
2588 missing in GDK (top of this file) */
2590 GdkWindow
*window
= (GdkWindow
*) NULL
;
2592 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2594 window
= GetConnectWidget()->window
;
2597 gdk_window_warp_pointer( window
, x
, y
);
2600 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2602 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2604 if (!m_widget
->window
) return;
2606 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2610 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
2612 rect
->width
, rect
->height
);
2616 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
2620 /* there is no GTK equivalent of "draw only, don't clear" so we
2621 invent our own in the GtkPizza widget */
2627 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2628 gboolean old_clear
= pizza
->clear_on_draw
;
2629 gtk_pizza_set_clear( pizza
, FALSE
);
2631 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2633 gtk_pizza_set_clear( pizza
, old_clear
);
2636 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2640 GdkRectangle gdk_rect
;
2641 gdk_rect
.x
= rect
->x
;
2642 gdk_rect
.y
= rect
->y
;
2643 gdk_rect
.width
= rect
->width
;
2644 gdk_rect
.height
= rect
->height
;
2648 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2649 gboolean old_clear
= pizza
->clear_on_draw
;
2650 gtk_pizza_set_clear( pizza
, FALSE
);
2652 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2654 gtk_pizza_set_clear( pizza
, old_clear
);
2657 gtk_widget_draw( m_widget
, &gdk_rect
);
2661 void wxWindow::Clear()
2663 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
2665 if (!m_widget
->window
) return;
2667 if (m_wxwindow
&& m_wxwindow
->window
)
2669 gdk_window_clear( m_wxwindow
->window
);
2674 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2676 wxWindowBase::DoSetToolTip(tip
);
2679 m_tooltip
->Apply( this );
2682 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2684 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
2686 #endif // wxUSE_TOOLTIPS
2688 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2690 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2692 if (!wxWindowBase::SetBackgroundColour(colour
))
2694 // don't leave if the GTK widget has just
2696 if (!m_delayedBackgroundColour
) return FALSE
;
2699 GdkWindow
*window
= (GdkWindow
*) NULL
;
2701 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2703 window
= GetConnectWidget()->window
;
2707 // indicate that a new style has been set
2708 // but it couldn't get applied as the
2709 // widget hasn't been realized yet.
2710 m_delayedBackgroundColour
= TRUE
;
2712 // pretend we have done something
2718 /* wxMSW doesn't clear the window here. I don't do that either to
2719 provide compatibility. call Clear() to do the job. */
2721 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
2722 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
2725 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2726 if (sysbg
== m_backgroundColour
)
2728 m_backgroundColour
= wxNullColour
;
2730 m_backgroundColour
= sysbg
;
2740 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
2742 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2744 if (!wxWindowBase::SetForegroundColour(colour
))
2746 // don't leave if the GTK widget has just
2748 if (!m_delayedForegroundColour
) return FALSE
;
2751 GdkWindow
*window
= (GdkWindow
*) NULL
;
2753 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2755 window
= GetConnectWidget()->window
;
2759 // indicate that a new style has been set
2760 // but it couldn't get applied as the
2761 // widget hasn't been realized yet.
2762 m_delayedForegroundColour
= TRUE
;
2764 // pretend we have done something
2768 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2769 if ( sysbg
== m_backgroundColour
)
2771 m_backgroundColour
= wxNullColour
;
2773 m_backgroundColour
= sysbg
;
2783 GtkStyle
*wxWindow::GetWidgetStyle()
2785 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
2787 m_widgetStyle
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
2789 return m_widgetStyle
;
2792 void wxWindow::SetWidgetStyle()
2794 GtkStyle
*style
= GetWidgetStyle();
2796 gdk_font_unref( style
->font
);
2797 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2799 if (m_foregroundColour
.Ok())
2801 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
2802 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
2803 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
2804 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
2807 if (m_backgroundColour
.Ok())
2809 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
2810 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2811 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2812 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2813 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2814 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2815 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2816 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2817 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2821 void wxWindow::ApplyWidgetStyle()
2825 //-----------------------------------------------------------------------------
2826 // Pop-up menu stuff
2827 //-----------------------------------------------------------------------------
2829 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
2831 *is_waiting
= FALSE
;
2834 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2836 menu
->SetInvokingWindow( win
);
2837 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
2840 wxMenuItem
*menuitem
= node
->GetData();
2841 if (menuitem
->IsSubMenu())
2843 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2846 node
= node
->GetNext();
2850 static gint gs_pop_x
= 0;
2851 static gint gs_pop_y
= 0;
2853 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
2857 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
2862 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
2864 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2866 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
2868 SetInvokingWindow( menu
, this );
2875 bool is_waiting
= TRUE
;
2877 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
2878 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
2881 GTK_MENU(menu
->m_menu
),
2882 (GtkWidget
*) NULL
, // parent menu shell
2883 (GtkWidget
*) NULL
, // parent menu item
2884 (GtkMenuPositionFunc
) pop_pos_callback
,
2885 (gpointer
) this, // client data
2886 0, // button used to activate it
2887 gs_timeLastClick
// the time of activation
2892 while (gtk_events_pending())
2893 gtk_main_iteration();
2899 #if wxUSE_DRAG_AND_DROP
2901 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2903 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
2905 GtkWidget
*dnd_widget
= GetConnectWidget();
2907 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
2909 if (m_dropTarget
) delete m_dropTarget
;
2910 m_dropTarget
= dropTarget
;
2912 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
2915 #endif // wxUSE_DRAG_AND_DROP
2917 GtkWidget
* wxWindow::GetConnectWidget()
2919 GtkWidget
*connect_widget
= m_widget
;
2920 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2922 return connect_widget
;
2925 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2928 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
2930 return (window
== m_widget
->window
);
2933 bool wxWindow::SetFont( const wxFont
&font
)
2935 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2937 if (!wxWindowBase::SetFont(font
))
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(),
2979 (guint32
)GDK_CURRENT_TIME
);
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
;
2998 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
2999 g_captureWindow
= (wxWindow
*) NULL
;
3002 bool wxWindow::IsRetained() const
3007 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3008 int range
, bool refresh
)
3010 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3012 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3014 m_hasScrolling
= TRUE
;
3016 if (orient
== wxHORIZONTAL
)
3018 float fpos
= (float)pos
;
3019 float frange
= (float)range
;
3020 float fthumb
= (float)thumbVisible
;
3021 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3022 if (fpos
< 0.0) fpos
= 0.0;
3024 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3025 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3027 SetScrollPos( orient
, pos
, refresh
);
3031 m_oldHorizontalPos
= fpos
;
3033 m_hAdjust
->lower
= 0.0;
3034 m_hAdjust
->upper
= frange
;
3035 m_hAdjust
->value
= fpos
;
3036 m_hAdjust
->step_increment
= 1.0;
3037 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3038 m_hAdjust
->page_size
= fthumb
;
3042 float fpos
= (float)pos
;
3043 float frange
= (float)range
;
3044 float fthumb
= (float)thumbVisible
;
3045 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3046 if (fpos
< 0.0) fpos
= 0.0;
3048 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3049 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3051 SetScrollPos( orient
, pos
, refresh
);
3055 m_oldVerticalPos
= fpos
;
3057 m_vAdjust
->lower
= 0.0;
3058 m_vAdjust
->upper
= frange
;
3059 m_vAdjust
->value
= fpos
;
3060 m_vAdjust
->step_increment
= 1.0;
3061 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3062 m_vAdjust
->page_size
= fthumb
;
3065 if (orient
== wxHORIZONTAL
)
3066 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3068 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3071 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3073 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3075 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3077 if (orient
== wxHORIZONTAL
)
3079 float fpos
= (float)pos
;
3080 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3081 if (fpos
< 0.0) fpos
= 0.0;
3082 m_oldHorizontalPos
= fpos
;
3084 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3085 m_hAdjust
->value
= fpos
;
3089 float fpos
= (float)pos
;
3090 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3091 if (fpos
< 0.0) fpos
= 0.0;
3092 m_oldVerticalPos
= fpos
;
3094 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3095 m_vAdjust
->value
= fpos
;
3102 if (m_wxwindow
->window
)
3104 if (orient
== wxHORIZONTAL
)
3105 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3107 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3114 int wxWindow::GetScrollThumb( int orient
) const
3116 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3118 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3120 if (orient
== wxHORIZONTAL
)
3121 return (int)(m_hAdjust
->page_size
+0.5);
3123 return (int)(m_vAdjust
->page_size
+0.5);
3126 int wxWindow::GetScrollPos( int orient
) const
3128 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3130 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3132 if (orient
== wxHORIZONTAL
)
3133 return (int)(m_hAdjust
->value
+0.5);
3135 return (int)(m_vAdjust
->value
+0.5);
3138 int wxWindow::GetScrollRange( int orient
) const
3140 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3142 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3144 if (orient
== wxHORIZONTAL
)
3145 return (int)(m_hAdjust
->upper
+0.5);
3147 return (int)(m_vAdjust
->upper
+0.5);
3150 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3152 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3154 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3156 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3161 m_scrollGC = gdk_gc_new( m_wxwindow->window );
3162 gdk_gc_set_exposures( m_scrollGC, TRUE );
3165 wxNode *node = m_children.First();
3168 wxWindow *child = (wxWindow*) node->Data();
3171 child->GetSize( &sx, &sy );
3172 child->SetSize( child->m_x + dx, child->m_y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
3173 node = node->Next();
3178 GetClientSize( &cw, &ch );
3179 int w = cw - abs(dx);
3180 int h = ch - abs(dy);
3182 if ((h < 0) || (w < 0))
3190 if (dx < 0) s_x = -dx;
3191 if (dy < 0) s_y = -dy;
3194 if (dx > 0) d_x = dx;
3195 if (dy > 0) d_y = dy;
3197 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
3198 m_wxwindow->window, s_x, s_y, w, h );
3201 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3202 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3203 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3204 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3206 Refresh( TRUE, &rect );
3211 void wxWindow::SetScrolling(bool scroll
)
3213 m_isScrolling
= g_blockEventsOnScroll
= scroll
;