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
) == 0))
744 wxNavigationKeyEvent new_event
;
745 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
746 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
747 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
748 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
749 new_event
.SetCurrentFocus( win
);
750 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
753 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
755 (gdk_event
->keyval
== GDK_Escape
) )
757 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
758 new_event
.SetEventObject( win
);
759 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
762 #if (GTK_MINOR_VERSION > 0)
763 /* Pressing F10 will activate the menu bar of the top frame. */
767 (gdk_event->keyval == GDK_F10) )
769 wxWindow *ancestor = win;
772 if (wxIsKindOf(ancestor,wxFrame))
774 wxFrame *frame = (wxFrame*) ancestor;
775 wxMenuBar *menubar = frame->GetMenuBar();
778 wxNode *node = menubar->GetMenus().First();
781 wxMenu *firstMenu = (wxMenu*) node->Data();
782 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
788 ancestor = ancestor->GetParent();
795 Damn, I forgot why this didn't work, but it didn't work.
797 // win is a panel: up can be propagated to the panel
798 if ((!ret) && (win->m_wxwindow) && (win->m_parent) && (win->m_parent->AcceptsFocus()) &&
799 (gdk_event->keyval == GDK_Up))
801 win->m_parent->SetFocus();
805 // win is a panel: left/right can be propagated to the panel
806 if ((!ret) && (win->m_wxwindow) &&
807 ((gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Left) ||
808 (gdk_event->keyval == GDK_Up) || (gdk_event->keyval == GDK_Down)))
810 wxNavigationKeyEvent new_event;
811 new_event.SetDirection( (gdk_event->keyval == GDK_Right) || (gdk_event->keyval == GDK_Down) );
812 new_event.SetCurrentFocus( win );
813 ret = win->GetEventHandler()->ProcessEvent( new_event );
819 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
826 //-----------------------------------------------------------------------------
827 // "key_release_event" from any window
828 //-----------------------------------------------------------------------------
830 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
833 wxapp_install_idle_handler();
835 if (!win
->m_hasVMT
) return FALSE
;
836 if (g_blockEventsOnDrag
) return FALSE
;
839 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
840 if (gdk_event->state & GDK_SHIFT_MASK)
841 printf( "ShiftDown.\n" );
843 printf( "ShiftUp.\n" );
844 if (gdk_event->state & GDK_CONTROL_MASK)
845 printf( "ControlDown.\n" );
847 printf( "ControlUp.\n" );
851 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
853 /* sending unknown key events doesn't really make sense */
854 if (key_code
== 0) return FALSE
;
858 GdkModifierType state
;
859 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
861 wxKeyEvent
event( wxEVT_KEY_UP
);
862 event
.SetTimestamp( gdk_event
->time
);
863 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
864 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
865 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
866 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
867 event
.m_keyCode
= key_code
;
868 event
.m_scanCode
= gdk_event
->keyval
;
871 event
.SetEventObject( win
);
873 if (win
->GetEventHandler()->ProcessEvent( event
))
875 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
882 //-----------------------------------------------------------------------------
883 // "button_press_event"
884 //-----------------------------------------------------------------------------
886 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
889 wxapp_install_idle_handler();
892 wxPrintf( wxT("1) OnButtonPress from ") );
893 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
894 wxPrintf( win->GetClassInfo()->GetClassName() );
895 wxPrintf( wxT(".\n") );
897 if (!win
->m_hasVMT
) return FALSE
;
898 if (g_blockEventsOnDrag
) return TRUE
;
899 if (g_blockEventsOnScroll
) return TRUE
;
901 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
905 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
907 gtk_widget_grab_focus (win
->m_wxwindow
);
910 wxPrintf( wxT("GrabFocus from ") );
911 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
912 wxPrintf( win->GetClassInfo()->GetClassName() );
913 wxPrintf( wxT(".\n") );
919 wxEventType event_type
= wxEVT_LEFT_DOWN
;
921 if (gdk_event
->button
== 1)
923 switch (gdk_event
->type
)
925 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
926 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
930 else if (gdk_event
->button
== 2)
932 switch (gdk_event
->type
)
934 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
935 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
939 else if (gdk_event
->button
== 3)
941 switch (gdk_event
->type
)
943 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
944 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
949 wxMouseEvent
event( event_type
);
950 event
.SetTimestamp( gdk_event
->time
);
951 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
952 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
953 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
954 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
955 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
956 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
957 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
959 event
.m_x
= (long)gdk_event
->x
;
960 event
.m_y
= (long)gdk_event
->y
;
962 // Some control don't have their own X window and thus cannot get
965 if (!g_captureWindow
)
971 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
976 wxNode
*node
= win
->GetChildren().First();
979 wxWindow
*child
= (wxWindow
*)node
->Data();
982 if (!child
->IsShown())
985 if (child
->m_isStaticBox
)
987 // wxStaticBox is transparent in the box itself
988 int xx1
= child
->m_x
;
989 int yy1
= child
->m_y
;
990 int xx2
= child
->m_x
+ child
->m_width
;
991 int yy2
= child
->m_x
+ child
->m_height
;
994 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
996 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
998 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1000 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1003 event
.m_x
-= child
->m_x
;
1004 event
.m_y
-= child
->m_y
;
1011 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1012 (child
->m_x
<= x
) &&
1013 (child
->m_y
<= y
) &&
1014 (child
->m_x
+child
->m_width
>= x
) &&
1015 (child
->m_y
+child
->m_height
>= y
))
1018 event
.m_x
-= child
->m_x
;
1019 event
.m_y
-= child
->m_y
;
1026 event
.SetEventObject( win
);
1028 gs_timeLastClick
= gdk_event
->time
;
1031 wxPrintf( wxT("2) OnButtonPress from ") );
1032 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1033 wxPrintf( win->GetClassInfo()->GetClassName() );
1034 wxPrintf( wxT(".\n") );
1037 if (win
->GetEventHandler()->ProcessEvent( event
))
1039 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1046 //-----------------------------------------------------------------------------
1047 // "button_release_event"
1048 //-----------------------------------------------------------------------------
1050 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1053 wxapp_install_idle_handler();
1055 if (!win
->m_hasVMT
) return FALSE
;
1056 if (g_blockEventsOnDrag
) return FALSE
;
1057 if (g_blockEventsOnScroll
) return FALSE
;
1059 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1062 printf( "OnButtonRelease from " );
1063 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1064 printf( win->GetClassInfo()->GetClassName() );
1068 wxEventType event_type
= wxEVT_NULL
;
1070 switch (gdk_event
->button
)
1072 case 1: event_type
= wxEVT_LEFT_UP
; break;
1073 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1074 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1077 wxMouseEvent
event( event_type
);
1078 event
.SetTimestamp( gdk_event
->time
);
1079 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1080 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1081 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1082 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1083 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1084 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1085 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1086 event
.m_x
= (long)gdk_event
->x
;
1087 event
.m_y
= (long)gdk_event
->y
;
1089 // Some control don't have their own X window and thus cannot get
1092 if (!g_captureWindow
)
1096 if (win
->m_wxwindow
)
1098 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1099 x
+= pizza
->xoffset
;
1100 y
+= pizza
->yoffset
;
1103 wxNode
*node
= win
->GetChildren().First();
1106 wxWindow
*child
= (wxWindow
*)node
->Data();
1108 node
= node
->Next();
1109 if (!child
->IsShown())
1112 if (child
->m_isStaticBox
)
1114 // wxStaticBox is transparent in the box itself
1115 int xx1
= child
->m_x
;
1116 int yy1
= child
->m_y
;
1117 int xx2
= child
->m_x
+ child
->m_width
;
1118 int yy2
= child
->m_x
+ child
->m_height
;
1121 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1123 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1125 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1127 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1130 event
.m_x
-= child
->m_x
;
1131 event
.m_y
-= child
->m_y
;
1138 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1139 (child
->m_x
<= x
) &&
1140 (child
->m_y
<= y
) &&
1141 (child
->m_x
+child
->m_width
>= x
) &&
1142 (child
->m_y
+child
->m_height
>= y
))
1145 event
.m_x
-= child
->m_x
;
1146 event
.m_y
-= child
->m_y
;
1153 event
.SetEventObject( win
);
1155 if (win
->GetEventHandler()->ProcessEvent( event
))
1157 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1164 //-----------------------------------------------------------------------------
1165 // "motion_notify_event"
1166 //-----------------------------------------------------------------------------
1168 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1171 wxapp_install_idle_handler();
1173 if (!win
->m_hasVMT
) return FALSE
;
1174 if (g_blockEventsOnDrag
) return FALSE
;
1175 if (g_blockEventsOnScroll
) return FALSE
;
1177 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1179 if (gdk_event
->is_hint
)
1183 GdkModifierType state
;
1184 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1190 printf( "OnMotion from " );
1191 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1192 printf( win->GetClassInfo()->GetClassName() );
1196 wxMouseEvent
event( wxEVT_MOTION
);
1197 event
.SetTimestamp( gdk_event
->time
);
1198 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1199 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1200 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1201 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1202 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1203 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1204 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1206 event
.m_x
= (long)gdk_event
->x
;
1207 event
.m_y
= (long)gdk_event
->y
;
1209 // Some control don't have their own X window and thus cannot get
1212 if (!g_captureWindow
)
1216 if (win
->m_wxwindow
)
1218 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1219 x
+= pizza
->xoffset
;
1220 y
+= pizza
->yoffset
;
1223 wxNode
*node
= win
->GetChildren().First();
1226 wxWindow
*child
= (wxWindow
*)node
->Data();
1228 node
= node
->Next();
1229 if (!child
->IsShown())
1232 if (child
->m_isStaticBox
)
1234 // wxStaticBox is transparent in the box itself
1235 int xx1
= child
->m_x
;
1236 int yy1
= child
->m_y
;
1237 int xx2
= child
->m_x
+ child
->m_width
;
1238 int yy2
= child
->m_x
+ child
->m_height
;
1241 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1243 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1245 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1247 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1250 event
.m_x
-= child
->m_x
;
1251 event
.m_y
-= child
->m_y
;
1258 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1259 (child
->m_x
<= x
) &&
1260 (child
->m_y
<= y
) &&
1261 (child
->m_x
+child
->m_width
>= x
) &&
1262 (child
->m_y
+child
->m_height
>= y
))
1265 event
.m_x
-= child
->m_x
;
1266 event
.m_y
-= child
->m_y
;
1273 event
.SetEventObject( win
);
1275 if (win
->GetEventHandler()->ProcessEvent( event
))
1277 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1284 //-----------------------------------------------------------------------------
1286 //-----------------------------------------------------------------------------
1288 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1291 wxapp_install_idle_handler();
1293 if (!win
->m_hasVMT
) return FALSE
;
1294 if (g_blockEventsOnDrag
) return FALSE
;
1296 g_focusWindow
= win
;
1298 if (win
->m_wxwindow
)
1300 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1302 GTK_WIDGET_SET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1304 printf( "SetFocus flag from " );
1305 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1306 printf( win->GetClassInfo()->GetClassName() );
1314 printf( "OnSetFocus from " );
1315 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1316 printf( win->GetClassInfo()->GetClassName() );
1318 printf( WXSTRINGCAST win->GetLabel() );
1322 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1323 event
.SetEventObject( win
);
1325 if (win
->GetEventHandler()->ProcessEvent( event
))
1327 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1334 //-----------------------------------------------------------------------------
1335 // "focus_out_event"
1336 //-----------------------------------------------------------------------------
1338 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1341 wxapp_install_idle_handler();
1343 if (!win
->m_hasVMT
) return FALSE
;
1344 if (g_blockEventsOnDrag
) return FALSE
;
1346 if (win
->m_wxwindow
)
1348 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
))
1349 GTK_WIDGET_UNSET_FLAGS (win
->m_wxwindow
, GTK_HAS_FOCUS
);
1353 printf( "OnKillFocus from " );
1354 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1355 printf( win->GetClassInfo()->GetClassName() );
1359 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1360 event
.SetEventObject( win
);
1362 if (win
->GetEventHandler()->ProcessEvent( event
))
1364 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1371 //-----------------------------------------------------------------------------
1372 // "enter_notify_event"
1373 //-----------------------------------------------------------------------------
1375 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1378 wxapp_install_idle_handler();
1380 if (!win
->m_hasVMT
) return FALSE
;
1381 if (g_blockEventsOnDrag
) return FALSE
;
1383 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1385 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1386 #if (GTK_MINOR_VERSION > 0)
1387 event
.SetTimestamp( gdk_event
->time
);
1389 event
.SetEventObject( win
);
1393 GdkModifierType state
= (GdkModifierType
)0;
1395 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1397 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1398 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1399 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1400 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1401 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1402 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1403 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1405 event
.m_x
= (long)x
;
1406 event
.m_y
= (long)y
;
1408 if (win
->GetEventHandler()->ProcessEvent( event
))
1410 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1417 //-----------------------------------------------------------------------------
1418 // "leave_notify_event"
1419 //-----------------------------------------------------------------------------
1421 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1424 wxapp_install_idle_handler();
1426 if (!win
->m_hasVMT
) return FALSE
;
1427 if (g_blockEventsOnDrag
) return FALSE
;
1429 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1431 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1432 #if (GTK_MINOR_VERSION > 0)
1433 event
.SetTimestamp( gdk_event
->time
);
1435 event
.SetEventObject( win
);
1439 GdkModifierType state
= (GdkModifierType
)0;
1441 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1443 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1444 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1445 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1446 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1447 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1448 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1449 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1451 event
.m_x
= (long)x
;
1452 event
.m_y
= (long)y
;
1454 if (win
->GetEventHandler()->ProcessEvent( event
))
1456 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1463 //-----------------------------------------------------------------------------
1464 // "value_changed" from m_vAdjust
1465 //-----------------------------------------------------------------------------
1467 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1470 wxapp_install_idle_handler();
1472 if (g_blockEventsOnDrag
) return;
1474 if (!win
->m_hasVMT
) return;
1476 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1477 if (fabs(diff
) < 0.2) return;
1479 win
->m_oldVerticalPos
= adjust
->value
;
1481 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1482 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1484 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1485 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1486 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1487 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1488 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1490 int value
= (int)(adjust
->value
+0.5);
1492 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1493 event
.SetEventObject( win
);
1494 win
->GetEventHandler()->ProcessEvent( event
);
1497 //-----------------------------------------------------------------------------
1498 // "value_changed" from m_hAdjust
1499 //-----------------------------------------------------------------------------
1501 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1504 wxapp_install_idle_handler();
1506 if (g_blockEventsOnDrag
) return;
1507 if (!win
->m_hasVMT
) return;
1509 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1510 if (fabs(diff
) < 0.2) return;
1512 win
->m_oldHorizontalPos
= adjust
->value
;
1514 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1515 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1517 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1518 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1519 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1520 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1521 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1523 int value
= (int)(adjust
->value
+0.5);
1525 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1526 event
.SetEventObject( win
);
1527 win
->GetEventHandler()->ProcessEvent( event
);
1530 //-----------------------------------------------------------------------------
1531 // "changed" from m_vAdjust
1532 //-----------------------------------------------------------------------------
1534 static void gtk_window_vscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1537 wxapp_install_idle_handler();
1539 if (g_blockEventsOnDrag
) return;
1540 if (!win
->m_hasVMT
) return;
1542 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1543 int value
= (int)(win
->m_vAdjust
->value
+0.5);
1545 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1546 event
.SetEventObject( win
);
1547 win
->GetEventHandler()->ProcessEvent( event
);
1550 //-----------------------------------------------------------------------------
1551 // "changed" from m_hAdjust
1552 //-----------------------------------------------------------------------------
1554 static void gtk_window_hscroll_change_callback( GtkWidget
*WXUNUSED(widget
), wxWindow
*win
)
1557 wxapp_install_idle_handler();
1559 if (g_blockEventsOnDrag
) return;
1560 if (!win
->m_hasVMT
) return;
1562 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1563 int value
= (int)(win
->m_hAdjust
->value
+0.5);
1565 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1566 event
.SetEventObject( win
);
1567 win
->GetEventHandler()->ProcessEvent( event
);
1570 //-----------------------------------------------------------------------------
1571 // "button_press_event" from scrollbar
1572 //-----------------------------------------------------------------------------
1574 static gint
gtk_scrollbar_button_press_callback( GtkRange
*WXUNUSED(widget
),
1575 GdkEventButton
*WXUNUSED(gdk_event
),
1579 wxapp_install_idle_handler();
1581 // don't test here as we can release the mouse while being over
1582 // a different window than the slider
1584 // if (gdk_event->window != widget->slider) return FALSE;
1586 win
->SetScrolling( TRUE
);
1591 //-----------------------------------------------------------------------------
1592 // "button_release_event" from scrollbar
1593 //-----------------------------------------------------------------------------
1595 static gint
gtk_scrollbar_button_release_callback( GtkRange
*WXUNUSED(widget
),
1596 GdkEventButton
*WXUNUSED(gdk_event
),
1600 // don't test here as we can release the mouse while being over
1601 // a different window than the slider
1603 // if (gdk_event->window != widget->slider) return FALSE;
1605 win
->SetScrolling( FALSE
);
1610 // ----------------------------------------------------------------------------
1611 // this wxWindowBase function is implemented here (in platform-specific file)
1612 // because it is static and so couldn't be made virtual
1613 // ----------------------------------------------------------------------------
1615 wxWindow
*wxWindowBase::FindFocus()
1617 return g_focusWindow
;
1620 //-----------------------------------------------------------------------------
1621 // "realize" from m_widget
1622 //-----------------------------------------------------------------------------
1624 /* we cannot set colours and fonts before the widget has
1625 been realized, so we do this directly after realization */
1628 gtk_window_realized_callback( GtkWidget
* WXUNUSED(widget
), wxWindow
*win
)
1631 wxapp_install_idle_handler();
1633 if (win
->m_delayedFont
)
1634 win
->SetFont( win
->GetFont() );
1636 if (win
->m_delayedBackgroundColour
)
1637 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1639 if (win
->m_delayedForegroundColour
)
1640 win
->SetForegroundColour( win
->GetForegroundColour() );
1642 wxWindowCreateEvent
event( win
);
1643 event
.SetEventObject( win
);
1644 win
->GetEventHandler()->ProcessEvent( event
);
1649 //-----------------------------------------------------------------------------
1650 // InsertChild for wxWindow.
1651 //-----------------------------------------------------------------------------
1653 /* Callback for wxWindow. This very strange beast has to be used because
1654 * C++ has no virtual methods in a constructor. We have to emulate a
1655 * virtual function here as wxNotebook requires a different way to insert
1656 * a child in it. I had opted for creating a wxNotebookPage window class
1657 * which would have made this superfluous (such in the MDI window system),
1658 * but no-one was listening to me... */
1660 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
1662 /* the window might have been scrolled already, do we
1663 have to adapt the position */
1664 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
1665 child
->m_x
+= pizza
->xoffset
;
1666 child
->m_y
+= pizza
->yoffset
;
1668 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
1669 GTK_WIDGET(child
->m_widget
),
1675 if (parent
->HasFlag(wxTAB_TRAVERSAL
))
1677 /* we now allow a window to get the focus as long as it
1678 doesn't have any children. */
1679 GTK_WIDGET_UNSET_FLAGS( parent
->m_wxwindow
, GTK_CAN_FOCUS
);
1683 //-----------------------------------------------------------------------------
1685 //-----------------------------------------------------------------------------
1687 wxWindow
* wxGetActiveWindow()
1689 return g_focusWindow
;
1692 //-----------------------------------------------------------------------------
1694 //-----------------------------------------------------------------------------
1696 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
1698 void wxWindow::Init()
1704 m_widget
= (GtkWidget
*) NULL
;
1705 m_wxwindow
= (GtkWidget
*) NULL
;
1715 m_needParent
= TRUE
;
1716 m_isBeingDeleted
= FALSE
;
1719 m_nativeSizeEvent
= FALSE
;
1721 m_hasScrolling
= FALSE
;
1722 m_isScrolling
= FALSE
;
1724 m_hAdjust
= (GtkAdjustment
*) NULL
;
1725 m_vAdjust
= (GtkAdjustment
*) NULL
;
1726 m_oldHorizontalPos
= 0.0;
1727 m_oldVerticalPos
= 0.0;
1730 m_widgetStyle
= (GtkStyle
*) NULL
;
1732 m_insertCallback
= (wxInsertChildFunction
) NULL
;
1734 m_isStaticBox
= FALSE
;
1735 m_isRadioButton
= FALSE
;
1737 m_acceptsFocus
= FALSE
;
1739 m_cursor
= *wxSTANDARD_CURSOR
;
1742 wxWindow::wxWindow()
1747 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
1748 const wxPoint
&pos
, const wxSize
&size
,
1749 long style
, const wxString
&name
)
1753 Create( parent
, id
, pos
, size
, style
, name
);
1756 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
1757 const wxPoint
&pos
, const wxSize
&size
,
1758 long style
, const wxString
&name
)
1760 if (!PreCreation( parent
, pos
, size
) ||
1761 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
1763 wxFAIL_MSG( wxT("wxWindow creation failed") );
1767 m_insertCallback
= wxInsertChildInWindow
;
1769 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
1770 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
1773 debug_focus_in( m_widget
, wxT("wxWindow::m_widget"), name
);
1776 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
1779 debug_focus_in( scrolledWindow
->hscrollbar
, wxT("wxWindow::hsrcollbar"), name
);
1780 debug_focus_in( scrolledWindow
->vscrollbar
, wxT("wxWindow::vsrcollbar"), name
);
1783 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
1784 scroll_class
->scrollbar_spacing
= 0;
1786 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1788 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
1789 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
1791 m_wxwindow
= gtk_pizza_new();
1794 debug_focus_in( m_wxwindow
, wxT("wxWindow::m_wxwindow"), name
);
1797 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
1799 #if (GTK_MINOR_VERSION > 0)
1800 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
1802 if (HasFlag(wxRAISED_BORDER
))
1804 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
1806 else if (HasFlag(wxSUNKEN_BORDER
))
1808 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
1810 else if (HasFlag(wxSIMPLE_BORDER
))
1812 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
1816 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
1818 #else // GTK_MINOR_VERSION == 0
1819 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
1821 if (HasFlag(wxRAISED_BORDER
))
1823 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
1825 else if (HasFlag(wxSUNKEN_BORDER
))
1827 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
1831 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
1833 #endif // GTK_MINOR_VERSION
1835 if (HasFlag(wxTAB_TRAVERSAL
))
1837 /* we now allow a window to get the focus as long as it
1838 doesn't have any children. */
1839 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1840 m_acceptsFocus
= FALSE
;
1844 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
1845 m_acceptsFocus
= TRUE
;
1848 #if (GTK_MINOR_VERSION == 0)
1849 // shut the viewport up
1850 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1851 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
1852 #endif // GTK_MINOR_VERSION == 0
1854 // I _really_ don't want scrollbars in the beginning
1855 m_vAdjust
->lower
= 0.0;
1856 m_vAdjust
->upper
= 1.0;
1857 m_vAdjust
->value
= 0.0;
1858 m_vAdjust
->step_increment
= 1.0;
1859 m_vAdjust
->page_increment
= 1.0;
1860 m_vAdjust
->page_size
= 5.0;
1861 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
1862 m_hAdjust
->lower
= 0.0;
1863 m_hAdjust
->upper
= 1.0;
1864 m_hAdjust
->value
= 0.0;
1865 m_hAdjust
->step_increment
= 1.0;
1866 m_hAdjust
->page_increment
= 1.0;
1867 m_hAdjust
->page_size
= 5.0;
1868 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
1870 // these handlers block mouse events to any window during scrolling such as
1871 // motion events and prevent GTK and wxWindows from fighting over where the
1874 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
1875 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1877 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
1878 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
1880 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
1881 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1883 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
1884 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
1886 // these handlers get notified when screen updates are required either when
1887 // scrolling or when the window size (and therefore scrollbar configuration)
1890 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
1891 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
1892 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
1893 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
1895 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "changed",
1896 (GtkSignalFunc
) gtk_window_hscroll_change_callback
, (gpointer
) this );
1897 gtk_signal_connect(GTK_OBJECT(m_vAdjust
), "changed",
1898 (GtkSignalFunc
) gtk_window_vscroll_change_callback
, (gpointer
) this );
1900 gtk_widget_show( m_wxwindow
);
1903 m_parent
->DoAddChild( this );
1912 wxWindow::~wxWindow()
1914 m_isBeingDeleted
= TRUE
;
1923 m_parent
->RemoveChild( this );
1927 gtk_style_unref( m_widgetStyle
);
1928 m_widgetStyle
= (GtkStyle
*) NULL
;
1933 gtk_widget_destroy( m_wxwindow
);
1934 m_wxwindow
= (GtkWidget
*) NULL
;
1939 gtk_widget_destroy( m_widget
);
1940 m_widget
= (GtkWidget
*) NULL
;
1944 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
1946 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
1948 /* this turns -1 into 20 so that a minimal window is
1949 visible even although -1,-1 has been given as the
1950 size of the window. the same trick is used in other
1951 ports and should make debugging easier */
1952 m_width
= WidthDefault(size
.x
);
1953 m_height
= HeightDefault(size
.y
);
1958 /* some reasonable defaults */
1963 m_x
= (gdk_screen_width () - m_width
) / 2;
1964 if (m_x
< 10) m_x
= 10;
1968 m_y
= (gdk_screen_height () - m_height
) / 2;
1969 if (m_y
< 10) m_y
= 10;
1976 void wxWindow::PostCreation()
1978 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
1984 /* these get reported to wxWindows -> wxPaintEvent */
1985 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
1986 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
1988 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
1989 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
1992 #if (GTK_MINOR_VERSION > 0)
1993 /* these are called when the "sunken" or "raised" borders are drawn */
1994 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
1995 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
1997 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
1998 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2002 GtkWidget
*connect_widget
= GetConnectWidget();
2004 ConnectWidget( connect_widget
);
2006 /* we cannot set colours, fonts and cursors before the widget has
2007 been realized, so we do this directly after realization */
2008 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2009 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2014 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2016 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2017 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2019 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2020 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2022 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2023 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2025 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2026 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2028 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2029 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2031 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
2032 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2034 gtk_signal_connect( GTK_OBJECT(widget
), "focus_out_event",
2035 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2037 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2038 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2040 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2041 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2044 bool wxWindow::Destroy()
2046 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2050 return wxWindowBase::Destroy();
2053 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2055 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2056 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2058 if (m_resizing
) return; /* I don't like recursions */
2061 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2063 /* don't set the size for children of wxNotebook, just take the values. */
2071 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2073 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2075 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2076 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2077 if (width
!= -1) m_width
= width
;
2078 if (height
!= -1) m_height
= height
;
2082 m_x
= x
+ pizza
->xoffset
;
2083 m_y
= y
+ pizza
->yoffset
;
2088 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2090 if (width
== -1) m_width
= 80;
2093 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2095 if (height
== -1) m_height
= 26;
2098 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2099 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2100 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2101 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2104 int bottom_border
= 0;
2106 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2108 /* the default button has a border around it */
2113 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
),
2118 m_height
+border
+bottom_border
);
2122 wxPrintf( "OnSize sent from " );
2123 if (GetClassInfo() && GetClassInfo()->GetClassName())
2124 wxPrintf( GetClassInfo()->GetClassName() );
2125 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2128 if (!m_nativeSizeEvent
)
2130 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2131 event
.SetEventObject( this );
2132 GetEventHandler()->ProcessEvent( event
);
2138 void wxWindow::OnInternalIdle()
2140 wxCursor cursor
= m_cursor
;
2141 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2145 /* I now set the cursor anew in every OnInternalIdle call
2146 as setting the cursor in a parent window also effects the
2147 windows above so that checking for the current cursor is
2152 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2154 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2156 if (!g_globalCursor
.Ok())
2157 cursor
= *wxSTANDARD_CURSOR
;
2159 window
= m_widget
->window
;
2160 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2161 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2167 GdkWindow
*window
= m_widget
->window
;
2168 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2169 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2177 void wxWindow::DoGetSize( int *width
, int *height
) const
2179 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2181 if (width
) (*width
) = m_width
;
2182 if (height
) (*height
) = m_height
;
2185 void wxWindow::DoSetClientSize( int width
, int height
)
2187 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2191 SetSize( width
, height
);
2198 #if (GTK_MINOR_VERSION == 0)
2199 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2203 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2204 #if 0 // unused - if this is ok, just remove this line (VZ)
2205 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2208 GtkWidget
*viewport
= scroll_window
->viewport
;
2209 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2211 dw
+= 2 * viewport_class
->xthickness
;
2212 dh
+= 2 * viewport_class
->ythickness
;
2216 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2218 /* when using GTK 1.2 we set the shadow border size to 2 */
2222 if (HasFlag(wxSIMPLE_BORDER
))
2224 /* when using GTK 1.2 we set the simple border size to 1 */
2233 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2234 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2236 we use this instead: range.slider_width = 11 + 2*2pts edge
2239 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2240 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2242 if (scroll_window
->vscrollbar_visible
)
2244 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2245 dw
+= scroll_class
->scrollbar_spacing
;
2248 if (scroll_window
->hscrollbar_visible
)
2250 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2251 dh
+= scroll_class
->scrollbar_spacing
;
2255 SetSize( width
+dw
, height
+dh
);
2259 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2261 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2265 if (width
) (*width
) = m_width
;
2266 if (height
) (*height
) = m_height
;
2273 #if (GTK_MINOR_VERSION == 0)
2274 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2278 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2279 #if 0 // unused - if this is ok, just remove this line (VZ)
2280 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2283 GtkWidget
*viewport
= scroll_window
->viewport
;
2284 GtkStyleClass
*viewport_class
= viewport
->style
->klass
;
2286 dw
+= 2 * viewport_class
->xthickness
;
2287 dh
+= 2 * viewport_class
->ythickness
;
2291 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2293 /* when using GTK 1.2 we set the shadow border size to 2 */
2297 if (HasFlag(wxSIMPLE_BORDER
))
2299 /* when using GTK 1.2 we set the simple border size to 1 */
2307 GtkWidget *hscrollbar = scroll_window->hscrollbar;
2308 GtkWidget *vscrollbar = scroll_window->vscrollbar;
2310 we use this instead: range.slider_width = 11 + 2*2pts edge
2313 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2314 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2316 if (scroll_window
->vscrollbar_visible
)
2318 dw
+= 15; /* dw += vscrollbar->allocation.width; */
2319 dw
+= scroll_class
->scrollbar_spacing
;
2322 if (scroll_window
->hscrollbar_visible
)
2324 dh
+= 15; /* dh += hscrollbar->allocation.height; */
2325 dh
+= scroll_class
->scrollbar_spacing
;
2329 if (width
) (*width
) = m_width
- dw
;
2330 if (height
) (*height
) = m_height
- dh
;
2334 void wxWindow::DoGetPosition( int *x
, int *y
) const
2336 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2340 if (m_parent
&& m_parent
->m_wxwindow
)
2342 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2343 dx
= pizza
->xoffset
;
2344 dy
= pizza
->yoffset
;
2347 if (x
) (*x
) = m_x
- dx
;
2348 if (y
) (*y
) = m_y
- dy
;
2351 void wxWindow::DoClientToScreen( 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 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2382 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2384 if (!m_widget
->window
) return;
2386 GdkWindow
*source
= (GdkWindow
*) NULL
;
2388 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2390 source
= m_widget
->window
;
2394 gdk_window_get_origin( source
, &org_x
, &org_y
);
2398 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2400 org_x
+= m_widget
->allocation
.x
;
2401 org_y
+= m_widget
->allocation
.y
;
2409 bool wxWindow::Show( bool show
)
2411 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2413 if (!wxWindowBase::Show(show
))
2420 gtk_widget_show( m_widget
);
2422 gtk_widget_hide( m_widget
);
2427 bool wxWindow::Enable( bool enable
)
2429 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2431 if (!wxWindowBase::Enable(enable
))
2437 gtk_widget_set_sensitive( m_widget
, enable
);
2439 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2444 int wxWindow::GetCharHeight() const
2446 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2448 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2450 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2452 return font
->ascent
+ font
->descent
;
2455 int wxWindow::GetCharWidth() const
2457 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2459 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2461 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2463 return gdk_string_width( font
, "H" );
2466 void wxWindow::GetTextExtent( const wxString
& string
,
2470 int *externalLeading
,
2471 const wxFont
*theFont
) const
2473 wxFont fontToUse
= m_font
;
2474 if (theFont
) fontToUse
= *theFont
;
2476 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2478 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2479 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2480 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2481 if (descent
) (*descent
) = font
->descent
;
2482 if (externalLeading
) (*externalLeading
) = 0; // ??
2485 void wxWindow::SetFocus()
2487 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2489 wxNode
*node
= m_children
.First();
2492 wxWindow
*child
= (wxWindow
*) node
->Data();
2493 if (child
->AcceptsFocus())
2498 node
= node
->Next();
2503 gtk_widget_grab_focus (m_wxwindow
);
2509 if (GTK_WIDGET_CAN_FOCUS(m_widget
) /*&& !GTK_WIDGET_HAS_FOCUS (connect_widget)*/ )
2511 gtk_widget_grab_focus (m_widget
);
2513 else if (GTK_IS_CONTAINER(m_widget
))
2515 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2524 bool wxWindow::AcceptsFocus() const
2526 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2529 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2531 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2533 wxWindow
*oldParent
= m_parent
,
2534 *newParent
= (wxWindow
*)newParentBase
;
2536 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2538 if ( !wxWindowBase::Reparent(newParent
) )
2541 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2543 /* prevent GTK from deleting the widget arbitrarily */
2544 gtk_widget_ref( m_widget
);
2548 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2551 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2555 /* insert GTK representation */
2556 (*(newParent
->m_insertCallback
))(newParent
, this);
2559 /* reverse: prevent GTK from deleting the widget arbitrarily */
2560 gtk_widget_unref( m_widget
);
2565 void wxWindow::DoAddChild(wxWindow
*child
)
2567 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2569 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
2571 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
2576 /* insert GTK representation */
2577 (*m_insertCallback
)(this, child
);
2580 void wxWindow::Raise()
2582 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2584 if (!m_widget
->window
) return;
2586 gdk_window_raise( m_widget
->window
);
2589 void wxWindow::Lower()
2591 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2593 if (!m_widget
->window
) return;
2595 gdk_window_lower( m_widget
->window
);
2598 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2600 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2602 return wxWindowBase::SetCursor( cursor
);
2605 void wxWindow::WarpPointer( int x
, int y
)
2607 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2609 /* we provide this function ourselves as it is
2610 missing in GDK (top of this file) */
2612 GdkWindow
*window
= (GdkWindow
*) NULL
;
2614 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2616 window
= GetConnectWidget()->window
;
2619 gdk_window_warp_pointer( window
, x
, y
);
2622 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
2624 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2626 if (!m_widget
->window
) return;
2628 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
2632 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
2634 rect
->width
, rect
->height
);
2638 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
2642 /* there is no GTK equivalent of "draw only, don't clear" so we
2643 invent our own in the GtkPizza widget */
2649 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2650 gboolean old_clear
= pizza
->clear_on_draw
;
2651 gtk_pizza_set_clear( pizza
, FALSE
);
2653 gtk_widget_draw( m_wxwindow
, (GdkRectangle
*) NULL
);
2655 gtk_pizza_set_clear( pizza
, old_clear
);
2658 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
2662 GdkRectangle gdk_rect
;
2663 gdk_rect
.x
= rect
->x
;
2664 gdk_rect
.y
= rect
->y
;
2665 gdk_rect
.width
= rect
->width
;
2666 gdk_rect
.height
= rect
->height
;
2670 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2671 gboolean old_clear
= pizza
->clear_on_draw
;
2672 gtk_pizza_set_clear( pizza
, FALSE
);
2674 gtk_widget_draw( m_wxwindow
, &gdk_rect
);
2676 gtk_pizza_set_clear( pizza
, old_clear
);
2679 gtk_widget_draw( m_widget
, &gdk_rect
);
2683 void wxWindow::Clear()
2685 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
2687 if (!m_widget
->window
) return;
2689 if (m_wxwindow
&& m_wxwindow
->window
)
2691 gdk_window_clear( m_wxwindow
->window
);
2696 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
2698 wxWindowBase::DoSetToolTip(tip
);
2701 m_tooltip
->Apply( this );
2704 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
2706 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
2708 #endif // wxUSE_TOOLTIPS
2710 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
2712 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2714 if (!wxWindowBase::SetBackgroundColour(colour
))
2716 // don't leave if the GTK widget has just
2718 if (!m_delayedBackgroundColour
) return FALSE
;
2721 GdkWindow
*window
= (GdkWindow
*) NULL
;
2723 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2725 window
= GetConnectWidget()->window
;
2729 // indicate that a new style has been set
2730 // but it couldn't get applied as the
2731 // widget hasn't been realized yet.
2732 m_delayedBackgroundColour
= TRUE
;
2734 // pretend we have done something
2740 /* wxMSW doesn't clear the window here. I don't do that either to
2741 provide compatibility. call Clear() to do the job. */
2743 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
2744 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
2747 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2748 if (sysbg
== m_backgroundColour
)
2750 m_backgroundColour
= wxNullColour
;
2752 m_backgroundColour
= sysbg
;
2762 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
2764 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2766 if (!wxWindowBase::SetForegroundColour(colour
))
2768 // don't leave if the GTK widget has just
2770 if (!m_delayedForegroundColour
) return FALSE
;
2773 GdkWindow
*window
= (GdkWindow
*) NULL
;
2775 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2777 window
= GetConnectWidget()->window
;
2781 // indicate that a new style has been set
2782 // but it couldn't get applied as the
2783 // widget hasn't been realized yet.
2784 m_delayedForegroundColour
= TRUE
;
2786 // pretend we have done something
2790 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2791 if ( sysbg
== m_backgroundColour
)
2793 m_backgroundColour
= wxNullColour
;
2795 m_backgroundColour
= sysbg
;
2805 GtkStyle
*wxWindow::GetWidgetStyle()
2807 if (m_widgetStyle
) gtk_style_unref( m_widgetStyle
);
2809 m_widgetStyle
= gtk_style_copy( gtk_widget_get_style( m_widget
) );
2811 return m_widgetStyle
;
2814 void wxWindow::SetWidgetStyle()
2816 GtkStyle
*style
= GetWidgetStyle();
2818 gdk_font_unref( style
->font
);
2819 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
2821 if (m_foregroundColour
.Ok())
2823 m_foregroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2824 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
2825 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
2826 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
2829 if (m_backgroundColour
.Ok())
2831 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( m_widget
->window
) );
2832 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2833 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
2834 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2835 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
2836 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2837 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
2838 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2839 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
2843 void wxWindow::ApplyWidgetStyle()
2847 //-----------------------------------------------------------------------------
2848 // Pop-up menu stuff
2849 //-----------------------------------------------------------------------------
2851 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
2853 *is_waiting
= FALSE
;
2856 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
2858 menu
->SetInvokingWindow( win
);
2859 wxNode
*node
= menu
->GetItems().First();
2862 wxMenuItem
*menuitem
= (wxMenuItem
*)node
->Data();
2863 if (menuitem
->IsSubMenu())
2865 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
2867 node
= node
->Next();
2871 static gint gs_pop_x
= 0;
2872 static gint gs_pop_y
= 0;
2874 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
2878 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
2883 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
2885 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2887 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
2889 SetInvokingWindow( menu
, this );
2896 bool is_waiting
= TRUE
;
2898 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
2899 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
2902 GTK_MENU(menu
->m_menu
),
2903 (GtkWidget
*) NULL
, // parent menu shell
2904 (GtkWidget
*) NULL
, // parent menu item
2905 (GtkMenuPositionFunc
) pop_pos_callback
,
2906 (gpointer
) this, // client data
2907 0, // button used to activate it
2908 gs_timeLastClick
// the time of activation
2913 while (gtk_events_pending())
2914 gtk_main_iteration();
2920 #if wxUSE_DRAG_AND_DROP
2922 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
2924 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
2926 GtkWidget
*dnd_widget
= GetConnectWidget();
2928 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
2930 if (m_dropTarget
) delete m_dropTarget
;
2931 m_dropTarget
= dropTarget
;
2933 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
2936 #endif // wxUSE_DRAG_AND_DROP
2938 GtkWidget
* wxWindow::GetConnectWidget()
2940 GtkWidget
*connect_widget
= m_widget
;
2941 if (m_wxwindow
) connect_widget
= m_wxwindow
;
2943 return connect_widget
;
2946 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
2949 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
2951 return (window
== m_widget
->window
);
2954 bool wxWindow::SetFont( const wxFont
&font
)
2956 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
2958 if (!wxWindowBase::SetFont(font
))
2960 // don't leave if the GTK widget has just
2962 if (!m_delayedFont
) return FALSE
;
2965 GdkWindow
*window
= (GdkWindow
*) NULL
;
2967 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2969 window
= GetConnectWidget()->window
;
2973 // indicate that a new style has been set
2974 // but it couldn't get applied as the
2975 // widget hasn't been realized yet.
2976 m_delayedFont
= TRUE
;
2978 // pretend we have done something
2982 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
2983 if ( sysbg
== m_backgroundColour
)
2985 m_backgroundColour
= wxNullColour
;
2987 m_backgroundColour
= sysbg
;
2997 void wxWindow::CaptureMouse()
2999 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3001 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3003 GdkWindow
*window
= (GdkWindow
*) NULL
;
3005 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3007 window
= GetConnectWidget()->window
;
3009 if (!window
) return;
3011 gdk_pointer_grab( window
, FALSE
,
3013 (GDK_BUTTON_PRESS_MASK
|
3014 GDK_BUTTON_RELEASE_MASK
|
3015 GDK_POINTER_MOTION_HINT_MASK
|
3016 GDK_POINTER_MOTION_MASK
),
3018 m_cursor
.GetCursor(),
3020 g_captureWindow
= this;
3023 void wxWindow::ReleaseMouse()
3025 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3027 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3029 GdkWindow
*window
= (GdkWindow
*) NULL
;
3031 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3033 window
= GetConnectWidget()->window
;
3035 if (!window
) return;
3037 gdk_pointer_ungrab ( GDK_CURRENT_TIME
);
3038 g_captureWindow
= (wxWindow
*) NULL
;
3041 bool wxWindow::IsRetained() const
3046 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3047 int range
, bool refresh
)
3049 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3051 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3053 m_hasScrolling
= TRUE
;
3055 if (orient
== wxHORIZONTAL
)
3057 float fpos
= (float)pos
;
3058 float frange
= (float)range
;
3059 float fthumb
= (float)thumbVisible
;
3060 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3061 if (fpos
< 0.0) fpos
= 0.0;
3063 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3064 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3066 SetScrollPos( orient
, pos
, refresh
);
3070 m_oldHorizontalPos
= fpos
;
3072 m_hAdjust
->lower
= 0.0;
3073 m_hAdjust
->upper
= frange
;
3074 m_hAdjust
->value
= fpos
;
3075 m_hAdjust
->step_increment
= 1.0;
3076 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3077 m_hAdjust
->page_size
= fthumb
;
3081 float fpos
= (float)pos
;
3082 float frange
= (float)range
;
3083 float fthumb
= (float)thumbVisible
;
3084 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3085 if (fpos
< 0.0) fpos
= 0.0;
3087 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3088 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3090 SetScrollPos( orient
, pos
, refresh
);
3094 m_oldVerticalPos
= fpos
;
3096 m_vAdjust
->lower
= 0.0;
3097 m_vAdjust
->upper
= frange
;
3098 m_vAdjust
->value
= fpos
;
3099 m_vAdjust
->step_increment
= 1.0;
3100 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3101 m_vAdjust
->page_size
= fthumb
;
3104 if (orient
== wxHORIZONTAL
)
3105 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3107 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3110 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3112 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3114 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3116 if (orient
== wxHORIZONTAL
)
3118 float fpos
= (float)pos
;
3119 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3120 if (fpos
< 0.0) fpos
= 0.0;
3121 m_oldHorizontalPos
= fpos
;
3123 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3124 m_hAdjust
->value
= fpos
;
3128 float fpos
= (float)pos
;
3129 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3130 if (fpos
< 0.0) fpos
= 0.0;
3131 m_oldVerticalPos
= fpos
;
3133 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3134 m_vAdjust
->value
= fpos
;
3141 if (m_wxwindow
->window
)
3143 if (orient
== wxHORIZONTAL
)
3144 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3146 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3153 int wxWindow::GetScrollThumb( int orient
) const
3155 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3157 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3159 if (orient
== wxHORIZONTAL
)
3160 return (int)(m_hAdjust
->page_size
+0.5);
3162 return (int)(m_vAdjust
->page_size
+0.5);
3165 int wxWindow::GetScrollPos( int orient
) const
3167 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3169 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3171 if (orient
== wxHORIZONTAL
)
3172 return (int)(m_hAdjust
->value
+0.5);
3174 return (int)(m_vAdjust
->value
+0.5);
3177 int wxWindow::GetScrollRange( int orient
) const
3179 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3181 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3183 if (orient
== wxHORIZONTAL
)
3184 return (int)(m_hAdjust
->upper
+0.5);
3186 return (int)(m_vAdjust
->upper
+0.5);
3189 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3191 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3193 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3195 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3200 m_scrollGC = gdk_gc_new( m_wxwindow->window );
3201 gdk_gc_set_exposures( m_scrollGC, TRUE );
3204 wxNode *node = m_children.First();
3207 wxWindow *child = (wxWindow*) node->Data();
3210 child->GetSize( &sx, &sy );
3211 child->SetSize( child->m_x + dx, child->m_y + dy, sx, sy, wxSIZE_ALLOW_MINUS_ONE );
3212 node = node->Next();
3217 GetClientSize( &cw, &ch );
3218 int w = cw - abs(dx);
3219 int h = ch - abs(dy);
3221 if ((h < 0) || (w < 0))
3229 if (dx < 0) s_x = -dx;
3230 if (dy < 0) s_y = -dy;
3233 if (dx > 0) d_x = dx;
3234 if (dy > 0) d_y = dy;
3236 gdk_window_copy_area( m_wxwindow->window, m_scrollGC, d_x, d_y,
3237 m_wxwindow->window, s_x, s_y, w, h );
3240 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3241 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3242 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3243 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3245 Refresh( TRUE, &rect );
3250 void wxWindow::SetScrolling(bool scroll
)
3252 m_isScrolling
= g_blockEventsOnScroll
= scroll
;