1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/window.cpp
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #define XWarpPointer XWARPPOINTER
20 #include "wx/window.h"
24 #include "wx/layout.h"
26 #include "wx/dialog.h"
27 #include "wx/msgdlg.h"
29 #if wxUSE_DRAG_AND_DROP
34 #include "wx/tooltip.h"
42 #include "wx/statusbr.h"
44 #include "wx/settings.h"
48 #include "wx/thread.h"
55 #include <gdk/gdkprivate.h>
56 #include <gdk/gdkkeysyms.h>
60 #include <gtk/gtkprivate.h>
62 #include "wx/gtk/win_gtk.h"
64 //-----------------------------------------------------------------------------
65 // documentation on internals
66 //-----------------------------------------------------------------------------
69 I have been asked several times about writing some documentation about
70 the GTK port of wxWindows, especially its internal structures. Obviously,
71 you cannot understand wxGTK without knowing a little about the GTK, but
72 some more information about what the wxWindow, which is the base class
73 for all other window classes, does seems required as well.
77 What does wxWindow do? It contains the common interface for the following
78 jobs of its descendants:
80 1) Define the rudimentary behaviour common to all window classes, such as
81 resizing, intercepting user input (so as to make it possible to use these
82 events for special purposes in a derived class), window names etc.
84 2) Provide the possibility to contain and manage children, if the derived
85 class is allowed to contain children, which holds true for those window
86 classes which do not display a native GTK widget. To name them, these
87 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
88 work classes are a special case and are handled a bit differently from
89 the rest. The same holds true for the wxNotebook class.
91 3) Provide the possibility to draw into a client area of a window. This,
92 too, only holds true for classes that do not display a native GTK widget
95 4) Provide the entire mechanism for scrolling widgets. This actual inter-
96 face for this is usually in wxScrolledWindow, but the GTK implementation
99 5) A multitude of helper or extra methods for special purposes, such as
100 Drag'n'Drop, managing validators etc.
102 6) Display a border (sunken, raised, simple or none).
104 Normally one might expect, that one wxWindows window would always correspond
105 to one GTK widget. Under GTK, there is no such allround widget that has all
106 the functionality. Moreover, the GTK defines a client area as a different
107 widget from the actual widget you are handling. Last but not least some
108 special classes (e.g. wxFrame) handle different categories of widgets and
109 still have the possibility to draw something in the client area.
110 It was therefore required to write a special purpose GTK widget, that would
111 represent a client area in the sense of wxWindows capable to do the jobs
112 2), 3) and 4). I have written this class and it resides in win_gtk.c of
115 All windows must have a widget, with which they interact with other under-
116 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
117 thw wxWindow class has a member variable called m_widget which holds a
118 pointer to this widget. When the window class represents a GTK native widget,
119 this is (in most cases) the only GTK widget the class manages. E.g. the
120 wxStatitText class handles only a GtkLabel widget a pointer to which you
121 can find in m_widget (defined in wxWindow)
123 When the class has a client area for drawing into and for containing children
124 it has to handle the client area widget (of the type GtkPizza, defined in
125 win_gtk.c), but there could be any number of widgets, handled by a class
126 The common rule for all windows is only, that the widget that interacts with
127 the rest of GTK must be referenced in m_widget and all other widgets must be
128 children of this widget on the GTK level. The top-most widget, which also
129 represents the client area, must be in the m_wxwindow field and must be of
132 As I said, the window classes that display a GTK native widget only have
133 one widget, so in the case of e.g. the wxButton class m_widget holds a
134 pointer to a GtkButton widget. But windows with client areas (for drawing
135 and children) have a m_widget field that is a pointer to a GtkScrolled-
136 Window and a m_wxwindow field that is pointer to a GtkPizza and this
137 one is (in the GTK sense) a child of the GtkScrolledWindow.
139 If the m_wxwindow field is set, then all input to this widget is inter-
140 cepted and sent to the wxWindows class. If not, all input to the widget
141 that gets pointed to by m_widget gets intercepted and sent to the class.
145 The design of scrolling in wxWindows is markedly different from that offered
146 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
147 clicking on a scrollbar belonging to scrolled window will inevitably move
148 the window. In wxWindows, the scrollbar will only emit an event, send this
149 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
150 which actually moves the window and its subchildren. Note that GtkPizza
151 memorizes how much it has been scrolled but that wxWindows forgets this
152 so that the two coordinates systems have to be kept in synch. This is done
153 in various places using the pizza->xoffset and pizza->yoffset values.
157 Singularily the most broken code in GTK is the code that is supposes to
158 inform subwindows (child windows) about new positions. Very often, duplicate
159 events are sent without changes in size or position, equally often no
160 events are sent at all (All this is due to a bug in the GtkContainer code
161 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
162 GTK's own system and it simply waits for size events for toplevel windows
163 and then iterates down the respective size events to all window. This has
164 the disadvantage, that windows might get size events before the GTK widget
165 actually has the reported size. This doesn't normally pose any problem, but
166 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
167 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
168 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
169 window that is used for OpenGl output really has that size (as reported by
174 If someone at some point of time feels the immense desire to have a look at,
175 change or attempt to optimse the Refresh() logic, this person will need an
176 intimate understanding of what a "draw" and what an "expose" events are and
177 what there are used for, in particular when used in connection with GTK's
178 own windowless widgets. Beware.
182 Cursors, too, have been a constant source of pleasure. The main difficulty
183 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
184 for the parent. To prevent this from doing too much harm, I use idle time
185 to set the cursor over and over again, starting from the toplevel windows
186 and ending with the youngest generation (speaking of parent and child windows).
187 Also don't forget that cursors (like much else) are connected to GdkWindows,
188 not GtkWidgets and that the "window" field of a GtkWidget might very well
189 point to the GdkWindow of the parent widget (-> "window less widget") and
190 that the two obviously have very different meanings.
194 //-----------------------------------------------------------------------------
196 //-----------------------------------------------------------------------------
198 extern wxList wxPendingDelete
;
199 extern bool g_blockEventsOnDrag
;
200 extern bool g_blockEventsOnScroll
;
201 extern wxCursor g_globalCursor
;
202 static wxWindow
*g_captureWindow
= (wxWindow
*) NULL
;
204 /* extern */ wxWindow
*g_focusWindow
= (wxWindow
*) NULL
;
206 // if we detect that the app has got/lost the focus, we set this variable to
207 // either TRUE or FALSE and an activate event will be sent during the next
208 // OnIdle() call and it is reset to -1: this value means that we shouldn't
209 // send any activate events at all
210 static int g_sendActivateEvent
= -1;
212 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
213 the last click here */
214 static guint32 gs_timeLastClick
= 0;
216 extern bool g_mainThreadLocked
;
218 //-----------------------------------------------------------------------------
220 //-----------------------------------------------------------------------------
222 #define DISABLE_STYLE_IF_BROKEN_THEME 1
227 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
229 # define DEBUG_MAIN_THREAD
232 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
233 GdkEvent
*WXUNUSED(event
),
234 const wxChar
*WXUNUSED(name
) )
237 static bool s_done = FALSE;
240 wxLog::AddTraceMask("focus");
243 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
249 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
251 // suppress warnings about gtk_debug_focus_in_callback being unused with
256 tmp
+= wxT(" FROM ");
259 wxChar
*s
= new wxChar
[tmp
.Length()+1];
263 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
264 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
269 #define DEBUG_MAIN_THREAD
272 //-----------------------------------------------------------------------------
273 // missing gdk functions
274 //-----------------------------------------------------------------------------
277 gdk_window_warp_pointer (GdkWindow
*window
,
282 GdkWindowPrivate
*priv
;
286 window
= GDK_ROOT_PARENT();
289 if (!GDK_WINDOW_DESTROYED(window
))
291 XWarpPointer (GDK_WINDOW_XDISPLAY(window
),
292 None
, /* not source window -> move from anywhere */
293 GDK_WINDOW_XID(window
), /* dest window */
294 0, 0, 0, 0, /* not source window -> move from anywhere */
298 priv
= (GdkWindowPrivate
*) window
;
300 if (!priv
->destroyed
)
302 XWarpPointer (priv
->xdisplay
,
303 None
, /* not source window -> move from anywhere */
304 priv
->xwindow
, /* dest window */
305 0, 0, 0, 0, /* not source window -> move from anywhere */
311 //-----------------------------------------------------------------------------
313 //-----------------------------------------------------------------------------
315 extern void wxapp_install_idle_handler();
316 extern bool g_isIdle
;
318 //-----------------------------------------------------------------------------
319 // local code (see below)
320 //-----------------------------------------------------------------------------
322 // returns the child of win which currently has focus or NULL if not found
323 static wxWindow
*FindFocusedChild(wxWindow
*win
)
325 wxWindow
*winFocus
= wxWindow::FindFocus();
327 return (wxWindow
*)NULL
;
329 if ( winFocus
== win
)
332 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
334 node
= node
->GetNext() )
336 wxWindow
*child
= FindFocusedChild(node
->GetData());
341 return (wxWindow
*)NULL
;
344 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
352 if (win
->m_hasScrolling
)
354 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
356 GtkRequisition vscroll_req
;
357 vscroll_req
.width
= 2;
358 vscroll_req
.height
= 2;
359 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
360 (scroll_window
->vscrollbar
, &vscroll_req
);
362 GtkRequisition hscroll_req
;
363 hscroll_req
.width
= 2;
364 hscroll_req
.height
= 2;
365 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
366 (scroll_window
->hscrollbar
, &hscroll_req
);
368 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) );
370 if (scroll_window
->vscrollbar_visible
)
372 dw
+= vscroll_req
.width
;
373 dw
+= scroll_class
->scrollbar_spacing
;
376 if (scroll_window
->hscrollbar_visible
)
378 dh
+= hscroll_req
.height
;
379 dh
+= scroll_class
->scrollbar_spacing
;
385 if (GTK_WIDGET_NO_WINDOW (widget
))
387 dx
+= widget
->allocation
.x
;
388 dy
+= widget
->allocation
.y
;
391 if (win
->HasFlag(wxRAISED_BORDER
))
393 gtk_draw_shadow( widget
->style
,
398 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
402 if (win
->HasFlag(wxSUNKEN_BORDER
))
404 gtk_draw_shadow( widget
->style
,
409 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
413 if (win
->HasFlag(wxSIMPLE_BORDER
))
416 gc
= gdk_gc_new( widget
->window
);
417 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
418 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
420 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
426 //-----------------------------------------------------------------------------
427 // "expose_event" of m_widget
428 //-----------------------------------------------------------------------------
430 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
432 if (gdk_event
->count
> 0) return FALSE
;
434 draw_frame( widget
, win
);
439 //-----------------------------------------------------------------------------
440 // "draw" of m_widget
441 //-----------------------------------------------------------------------------
443 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
445 draw_frame( widget
, win
);
448 //-----------------------------------------------------------------------------
449 // key code mapping routines
450 //-----------------------------------------------------------------------------
452 static long map_to_unmodified_wx_keysym( KeySym keysym
)
459 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
461 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
467 case GDK_Super_R
: key_code
= WXK_ALT
; break;
468 case GDK_Menu
: key_code
= WXK_MENU
; break;
469 case GDK_Help
: key_code
= WXK_HELP
; break;
470 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
471 case GDK_ISO_Left_Tab
:
472 case GDK_Tab
: key_code
= WXK_TAB
; break;
473 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
474 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
475 case GDK_Return
: key_code
= WXK_RETURN
; break;
476 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
477 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
478 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
479 case GDK_Delete
: key_code
= WXK_DELETE
; break;
480 case GDK_Home
: key_code
= WXK_HOME
; break;
481 case GDK_Left
: key_code
= WXK_LEFT
; break;
482 case GDK_Up
: key_code
= WXK_UP
; break;
483 case GDK_Right
: key_code
= WXK_RIGHT
; break;
484 case GDK_Down
: key_code
= WXK_DOWN
; break;
485 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
486 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
487 case GDK_Next
: key_code
= WXK_NEXT
; break;
488 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
489 case GDK_End
: key_code
= WXK_END
; break;
490 case GDK_Begin
: key_code
= WXK_HOME
; break;
491 case GDK_Select
: key_code
= WXK_SELECT
; break;
492 case GDK_Print
: key_code
= WXK_PRINT
; break;
493 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
494 case GDK_Insert
: key_code
= WXK_INSERT
; break;
495 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
497 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
498 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
499 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
500 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
501 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
502 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
503 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
504 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
505 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
506 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
507 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
508 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
509 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
510 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
511 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
512 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
513 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
514 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
515 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
516 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
517 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
518 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
519 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
520 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
521 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
522 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
523 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
524 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
525 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
526 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
527 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
528 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
529 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
530 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
531 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
532 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
533 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
535 case GDK_F1
: key_code
= WXK_F1
; break;
536 case GDK_F2
: key_code
= WXK_F2
; break;
537 case GDK_F3
: key_code
= WXK_F3
; break;
538 case GDK_F4
: key_code
= WXK_F4
; break;
539 case GDK_F5
: key_code
= WXK_F5
; break;
540 case GDK_F6
: key_code
= WXK_F6
; break;
541 case GDK_F7
: key_code
= WXK_F7
; break;
542 case GDK_F8
: key_code
= WXK_F8
; break;
543 case GDK_F9
: key_code
= WXK_F9
; break;
544 case GDK_F10
: key_code
= WXK_F10
; break;
545 case GDK_F11
: key_code
= WXK_F11
; break;
546 case GDK_F12
: key_code
= WXK_F12
; break;
549 if ((keysym
& 0xF000) == 0)
551 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
552 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
553 key_code
= (guint
)keysym
;
561 static long map_to_wx_keysym( KeySym keysym
)
567 case GDK_Menu
: key_code
= WXK_MENU
; break;
568 case GDK_Help
: key_code
= WXK_HELP
; break;
569 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
570 case GDK_ISO_Left_Tab
:
571 case GDK_Tab
: key_code
= WXK_TAB
; break;
572 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
573 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
574 case GDK_Return
: key_code
= WXK_RETURN
; break;
575 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
576 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
577 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
578 case GDK_Delete
: key_code
= WXK_DELETE
; break;
579 case GDK_Home
: key_code
= WXK_HOME
; break;
580 case GDK_Left
: key_code
= WXK_LEFT
; break;
581 case GDK_Up
: key_code
= WXK_UP
; break;
582 case GDK_Right
: key_code
= WXK_RIGHT
; break;
583 case GDK_Down
: key_code
= WXK_DOWN
; break;
584 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
585 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
586 case GDK_Next
: key_code
= WXK_NEXT
; break;
587 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
588 case GDK_End
: key_code
= WXK_END
; break;
589 case GDK_Begin
: key_code
= WXK_HOME
; break;
590 case GDK_Select
: key_code
= WXK_SELECT
; break;
591 case GDK_Print
: key_code
= WXK_PRINT
; break;
592 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
593 case GDK_Insert
: key_code
= WXK_INSERT
; break;
594 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
596 case GDK_KP_0
: key_code
= '0'; break;
597 case GDK_KP_1
: key_code
= '1'; break;
598 case GDK_KP_2
: key_code
= '2'; break;
599 case GDK_KP_3
: key_code
= '3'; break;
600 case GDK_KP_4
: key_code
= '4'; break;
601 case GDK_KP_5
: key_code
= '5'; break;
602 case GDK_KP_6
: key_code
= '6'; break;
603 case GDK_KP_7
: key_code
= '7'; break;
604 case GDK_KP_8
: key_code
= '8'; break;
605 case GDK_KP_9
: key_code
= '9'; break;
606 case GDK_KP_Space
: key_code
= ' '; break;
607 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
608 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
609 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
610 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
611 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
612 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
613 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
614 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
615 case GDK_KP_Up
: key_code
= WXK_UP
; break;
616 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
617 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
618 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
619 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
620 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
621 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
622 case GDK_KP_End
: key_code
= WXK_END
; break;
623 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
624 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
625 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
626 case GDK_KP_Equal
: key_code
= '='; break;
627 case GDK_KP_Multiply
: key_code
= '*'; break;
628 case GDK_KP_Add
: key_code
= '+'; break;
629 case GDK_KP_Separator
: key_code
= ','; break;
630 case GDK_KP_Subtract
: key_code
= '-'; break;
631 case GDK_KP_Decimal
: key_code
= '.'; break;
632 case GDK_KP_Divide
: key_code
= '/'; break;
634 case GDK_F1
: key_code
= WXK_F1
; break;
635 case GDK_F2
: key_code
= WXK_F2
; break;
636 case GDK_F3
: key_code
= WXK_F3
; break;
637 case GDK_F4
: key_code
= WXK_F4
; break;
638 case GDK_F5
: key_code
= WXK_F5
; break;
639 case GDK_F6
: key_code
= WXK_F6
; break;
640 case GDK_F7
: key_code
= WXK_F7
; break;
641 case GDK_F8
: key_code
= WXK_F8
; break;
642 case GDK_F9
: key_code
= WXK_F9
; break;
643 case GDK_F10
: key_code
= WXK_F10
; break;
644 case GDK_F11
: key_code
= WXK_F11
; break;
645 case GDK_F12
: key_code
= WXK_F12
; break;
648 if ((keysym
& 0xF000) == 0)
650 key_code
= (guint
)keysym
;
658 //-----------------------------------------------------------------------------
659 // "expose_event" of m_wxwindow
660 //-----------------------------------------------------------------------------
662 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
667 wxapp_install_idle_handler();
670 if (win->GetName() == wxT("panel"))
672 wxPrintf( wxT("OnExpose from ") );
673 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
674 wxPrintf( win->GetClassInfo()->GetClassName() );
675 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
676 (int)gdk_event->area.y,
677 (int)gdk_event->area.width,
678 (int)gdk_event->area.height );
682 GtkPizza
*pizza
= GTK_PIZZA (widget
);
684 if (win
->GetThemeEnabled())
686 wxWindow
*parent
= win
->GetParent();
687 while (parent
&& !parent
->IsTopLevel())
688 parent
= parent
->GetParent();
692 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
693 GTK_SHADOW_NONE
, &gdk_event
->area
, parent
->m_widget
, "base", 0, 0, -1, -1);
696 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
698 gdk_event
->area
.width
,
699 gdk_event
->area
.height
);
701 if (gdk_event
->count
== 0)
703 win
->m_clipPaintRegion
= TRUE
;
705 wxEraseEvent
eevent( win
->GetId() );
706 eevent
.SetEventObject( win
);
707 win
->GetEventHandler()->ProcessEvent(eevent
);
709 wxPaintEvent
event( win
->GetId() );
710 event
.SetEventObject( win
);
711 win
->GetEventHandler()->ProcessEvent( event
);
713 win
->GetUpdateRegion().Clear();
715 win
->m_clipPaintRegion
= FALSE
;
718 /* The following code will result in all window-less widgets
719 being redrawn if the wxWindows class is given a chance to
720 paint *anything* because it will then be allowed to paint
721 over the window-less widgets */
723 GList
*children
= pizza
->children
;
726 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
727 children
= children
->next
;
729 GdkEventExpose child_event
= *gdk_event
;
731 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
732 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
733 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
735 child_event
.area
.x
= child
->widget
->allocation
.x
;
736 child_event
.area
.y
= child
->widget
->allocation
.y
;
737 child_event
.area
.width
= child
->widget
->allocation
.width
;
738 child_event
.area
.height
= child
->widget
->allocation
.height
;
739 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
746 //-----------------------------------------------------------------------------
747 // "event" of m_wxwindow
748 //-----------------------------------------------------------------------------
750 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
751 expose events. We need them, of course, so we override the main event
752 procedure in GtkWidget by giving our own handler for all system events.
753 There, we look for expose events ourselves whereas all other events are
756 gint
gtk_window_event_event_callback( GtkWidget
*widget
, GdkEventExpose
*event
, wxWindow
*win
)
758 if (event
->type
== GDK_EXPOSE
)
760 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
767 //-----------------------------------------------------------------------------
768 // "draw" of m_wxwindow
769 //-----------------------------------------------------------------------------
771 /* This callback is a complete replacement of the gtk_pizza_draw() function,
774 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
779 wxapp_install_idle_handler();
781 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
782 (win
->GetChildren().GetCount() == 0))
788 if (win->GetName() == wxT("panel"))
790 wxPrintf( wxT("OnDraw from ") );
791 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
792 wxPrintf( win->GetClassInfo()->GetClassName() );
793 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
800 GtkPizza
*pizza
= GTK_PIZZA (widget
);
802 if (win
->GetThemeEnabled())
804 wxWindow
*parent
= win
->GetParent();
805 while (parent
&& !parent
->IsTopLevel())
806 parent
= parent
->GetParent();
810 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
811 GTK_SHADOW_NONE
, rect
, parent
->m_widget
, "base", 0, 0, -1, -1);
815 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
816 (pizza
->clear_on_draw
))
818 gdk_window_clear_area( pizza
->bin_window
,
819 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
822 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
824 win
->m_clipPaintRegion
= TRUE
;
826 wxEraseEvent
eevent( win
->GetId() );
827 eevent
.SetEventObject( win
);
828 win
->GetEventHandler()->ProcessEvent(eevent
);
830 wxPaintEvent
event( win
->GetId() );
831 event
.SetEventObject( win
);
832 win
->GetEventHandler()->ProcessEvent( event
);
834 win
->GetUpdateRegion().Clear();
836 win
->m_clipPaintRegion
= FALSE
;
839 GList
*children
= pizza
->children
;
842 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
843 children
= children
->next
;
845 GdkRectangle child_area
;
846 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
848 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
853 //-----------------------------------------------------------------------------
854 // "key_press_event" from any window
855 //-----------------------------------------------------------------------------
857 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
862 wxapp_install_idle_handler();
864 if (!win
->m_hasVMT
) return FALSE
;
865 if (g_blockEventsOnDrag
) return FALSE
;
870 tmp += (char)gdk_event->keyval;
871 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
872 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
877 GdkModifierType state
;
878 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
882 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
883 /* sending unknown key events doesn't really make sense */
884 if (key_code
== 0) return FALSE
;
886 wxKeyEvent
event( wxEVT_KEY_DOWN
);
887 event
.SetTimestamp( gdk_event
->time
);
888 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
889 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
890 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
891 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
892 event
.m_keyCode
= key_code
;
893 event
.m_scanCode
= gdk_event
->keyval
;
896 event
.SetEventObject( win
);
897 ret
= win
->GetEventHandler()->ProcessEvent( event
);
902 wxWindow
*ancestor
= win
;
905 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
908 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
909 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
912 if (ancestor
->IsTopLevel())
914 ancestor
= ancestor
->GetParent();
917 #endif // wxUSE_ACCEL
919 /* wxMSW doesn't send char events with Alt pressed */
920 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
921 will only be sent if it is not in an accelerator table. */
922 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
927 wxKeyEvent
event2( wxEVT_CHAR
);
928 event2
.SetTimestamp( gdk_event
->time
);
929 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
930 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
931 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
932 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
933 event2
.m_keyCode
= key_code
;
934 event2
.m_scanCode
= gdk_event
->keyval
;
937 event2
.SetEventObject( win
);
938 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
941 /* win is a control: tab can be propagated up */
943 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
944 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
945 // have this style, yet choose not to process this particular TAB in which
946 // case TAB must still work as a navigational character
948 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
950 (win
->GetParent()) &&
951 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
953 wxNavigationKeyEvent new_event
;
954 new_event
.SetEventObject( win
->GetParent() );
955 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
956 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
957 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
958 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
959 new_event
.SetCurrentFocus( win
);
960 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
963 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
965 (gdk_event
->keyval
== GDK_Escape
) )
967 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
968 new_event
.SetEventObject( win
);
969 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
972 #if (GTK_MINOR_VERSION > 0)
973 /* Pressing F10 will activate the menu bar of the top frame. */
977 (gdk_event->keyval == GDK_F10) )
979 wxWindow *ancestor = win;
982 if (wxIsKindOf(ancestor,wxFrame))
984 wxFrame *frame = (wxFrame*) ancestor;
985 wxMenuBar *menubar = frame->GetMenuBar();
988 wxNode *node = menubar->GetMenus().First();
991 wxMenu *firstMenu = (wxMenu*) node->Data();
992 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
998 ancestor = ancestor->GetParent();
1006 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1013 //-----------------------------------------------------------------------------
1014 // "key_release_event" from any window
1015 //-----------------------------------------------------------------------------
1017 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
1022 wxapp_install_idle_handler();
1024 if (!win
->m_hasVMT
) return FALSE
;
1025 if (g_blockEventsOnDrag
) return FALSE
;
1028 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
1029 if (gdk_event->state & GDK_SHIFT_MASK)
1030 printf( "ShiftDown.\n" );
1032 printf( "ShiftUp.\n" );
1033 if (gdk_event->state & GDK_CONTROL_MASK)
1034 printf( "ControlDown.\n" );
1036 printf( "ControlUp.\n" );
1040 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
1042 /* sending unknown key events doesn't really make sense */
1043 if (key_code
== 0) return FALSE
;
1047 GdkModifierType state
;
1048 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1050 wxKeyEvent
event( wxEVT_KEY_UP
);
1051 event
.SetTimestamp( gdk_event
->time
);
1052 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1053 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1054 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1055 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1056 event
.m_keyCode
= key_code
;
1057 event
.m_scanCode
= gdk_event
->keyval
;
1060 event
.SetEventObject( win
);
1062 if (win
->GetEventHandler()->ProcessEvent( event
))
1064 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1071 // ----------------------------------------------------------------------------
1072 // mouse event processing helper
1073 // ----------------------------------------------------------------------------
1075 static void AdjustEventButtonState(wxMouseEvent
& event
)
1077 // GDK reports the old state of the button for a button press event, but
1078 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1079 // for a LEFT_DOWN event, not FALSE, so we will invert
1080 // left/right/middleDown for the corresponding click events
1081 switch ( event
.GetEventType() )
1083 case wxEVT_LEFT_DOWN
:
1084 case wxEVT_LEFT_DCLICK
:
1086 event
.m_leftDown
= !event
.m_leftDown
;
1089 case wxEVT_MIDDLE_DOWN
:
1090 case wxEVT_MIDDLE_DCLICK
:
1091 case wxEVT_MIDDLE_UP
:
1092 event
.m_middleDown
= !event
.m_middleDown
;
1095 case wxEVT_RIGHT_DOWN
:
1096 case wxEVT_RIGHT_DCLICK
:
1097 case wxEVT_RIGHT_UP
:
1098 event
.m_rightDown
= !event
.m_rightDown
;
1103 //-----------------------------------------------------------------------------
1104 // "button_press_event"
1105 //-----------------------------------------------------------------------------
1107 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1112 wxapp_install_idle_handler();
1115 wxPrintf( wxT("1) OnButtonPress from ") );
1116 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1117 wxPrintf( win->GetClassInfo()->GetClassName() );
1118 wxPrintf( wxT(".\n") );
1120 if (!win
->m_hasVMT
) return FALSE
;
1121 if (g_blockEventsOnDrag
) return TRUE
;
1122 if (g_blockEventsOnScroll
) return TRUE
;
1124 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1126 if (win
->m_wxwindow
)
1128 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1130 gtk_widget_grab_focus (win
->m_wxwindow
);
1133 wxPrintf( wxT("GrabFocus from ") );
1134 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1135 wxPrintf( win->GetClassInfo()->GetClassName() );
1136 wxPrintf( wxT(".\n") );
1142 wxEventType event_type
= wxEVT_NULL
;
1144 if (gdk_event
->button
== 1)
1146 switch (gdk_event
->type
)
1148 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1149 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1153 else if (gdk_event
->button
== 2)
1155 switch (gdk_event
->type
)
1157 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1158 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1162 else if (gdk_event
->button
== 3)
1164 switch (gdk_event
->type
)
1166 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1167 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1172 if ( event_type
== wxEVT_NULL
)
1174 // unknown mouse button or click type
1178 wxMouseEvent
event( event_type
);
1179 event
.SetTimestamp( gdk_event
->time
);
1180 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1181 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1182 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1183 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1184 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1185 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1186 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1188 event
.m_x
= (wxCoord
)gdk_event
->x
;
1189 event
.m_y
= (wxCoord
)gdk_event
->y
;
1191 AdjustEventButtonState(event
);
1193 // Some control don't have their own X window and thus cannot get
1196 if (!g_captureWindow
)
1198 wxCoord x
= event
.m_x
;
1199 wxCoord y
= event
.m_y
;
1200 if (win
->m_wxwindow
)
1202 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1203 x
+= pizza
->xoffset
;
1204 y
+= pizza
->yoffset
;
1207 wxNode
*node
= win
->GetChildren().First();
1210 wxWindow
*child
= (wxWindow
*)node
->Data();
1212 node
= node
->Next();
1213 if (!child
->IsShown())
1216 if (child
->m_isStaticBox
)
1218 // wxStaticBox is transparent in the box itself
1219 int xx1
= child
->m_x
;
1220 int yy1
= child
->m_y
;
1221 int xx2
= child
->m_x
+ child
->m_width
;
1222 int yy2
= child
->m_x
+ child
->m_height
;
1225 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1227 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1229 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1231 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1234 event
.m_x
-= child
->m_x
;
1235 event
.m_y
-= child
->m_y
;
1242 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1243 (child
->m_x
<= x
) &&
1244 (child
->m_y
<= y
) &&
1245 (child
->m_x
+child
->m_width
>= x
) &&
1246 (child
->m_y
+child
->m_height
>= y
))
1249 event
.m_x
-= child
->m_x
;
1250 event
.m_y
-= child
->m_y
;
1257 event
.SetEventObject( win
);
1259 gs_timeLastClick
= gdk_event
->time
;
1262 wxPrintf( wxT("2) OnButtonPress from ") );
1263 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1264 wxPrintf( win->GetClassInfo()->GetClassName() );
1265 wxPrintf( wxT(".\n") );
1268 if (win
->GetEventHandler()->ProcessEvent( event
))
1270 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1277 //-----------------------------------------------------------------------------
1278 // "button_release_event"
1279 //-----------------------------------------------------------------------------
1281 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1286 wxapp_install_idle_handler();
1288 if (!win
->m_hasVMT
) return FALSE
;
1289 if (g_blockEventsOnDrag
) return FALSE
;
1290 if (g_blockEventsOnScroll
) return FALSE
;
1292 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1295 printf( "OnButtonRelease from " );
1296 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1297 printf( win->GetClassInfo()->GetClassName() );
1301 wxEventType event_type
= wxEVT_NULL
;
1303 switch (gdk_event
->button
)
1305 case 1: event_type
= wxEVT_LEFT_UP
; break;
1306 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1307 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1308 default: return FALSE
;
1311 wxMouseEvent
event( event_type
);
1312 event
.SetTimestamp( gdk_event
->time
);
1313 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1314 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1315 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1316 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1317 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1318 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1319 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1320 event
.m_x
= (wxCoord
)gdk_event
->x
;
1321 event
.m_y
= (wxCoord
)gdk_event
->y
;
1323 AdjustEventButtonState(event
);
1325 // Some control don't have their own X window and thus cannot get
1328 if (!g_captureWindow
)
1330 wxCoord x
= event
.m_x
;
1331 wxCoord y
= event
.m_y
;
1332 if (win
->m_wxwindow
)
1334 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1335 x
+= pizza
->xoffset
;
1336 y
+= pizza
->yoffset
;
1339 wxNode
*node
= win
->GetChildren().First();
1342 wxWindow
*child
= (wxWindow
*)node
->Data();
1344 node
= node
->Next();
1345 if (!child
->IsShown())
1348 if (child
->m_isStaticBox
)
1350 // wxStaticBox is transparent in the box itself
1351 int xx1
= child
->m_x
;
1352 int yy1
= child
->m_y
;
1353 int xx2
= child
->m_x
+ child
->m_width
;
1354 int yy2
= child
->m_x
+ child
->m_height
;
1357 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1359 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1361 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1363 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1366 event
.m_x
-= child
->m_x
;
1367 event
.m_y
-= child
->m_y
;
1374 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1375 (child
->m_x
<= x
) &&
1376 (child
->m_y
<= y
) &&
1377 (child
->m_x
+child
->m_width
>= x
) &&
1378 (child
->m_y
+child
->m_height
>= y
))
1381 event
.m_x
-= child
->m_x
;
1382 event
.m_y
-= child
->m_y
;
1389 event
.SetEventObject( win
);
1391 if (win
->GetEventHandler()->ProcessEvent( event
))
1393 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1400 //-----------------------------------------------------------------------------
1401 // "motion_notify_event"
1402 //-----------------------------------------------------------------------------
1404 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1409 wxapp_install_idle_handler();
1411 if (!win
->m_hasVMT
) return FALSE
;
1412 if (g_blockEventsOnDrag
) return FALSE
;
1413 if (g_blockEventsOnScroll
) return FALSE
;
1415 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1417 if (gdk_event
->is_hint
)
1421 GdkModifierType state
;
1422 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1428 printf( "OnMotion from " );
1429 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1430 printf( win->GetClassInfo()->GetClassName() );
1434 wxMouseEvent
event( wxEVT_MOTION
);
1435 event
.SetTimestamp( gdk_event
->time
);
1436 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1437 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1438 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1439 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1440 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1441 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1442 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1444 event
.m_x
= (wxCoord
)gdk_event
->x
;
1445 event
.m_y
= (wxCoord
)gdk_event
->y
;
1447 // Some control don't have their own X window and thus cannot get
1450 if (!g_captureWindow
)
1452 wxCoord x
= event
.m_x
;
1453 wxCoord y
= event
.m_y
;
1454 if (win
->m_wxwindow
)
1456 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1457 x
+= pizza
->xoffset
;
1458 y
+= pizza
->yoffset
;
1461 wxNode
*node
= win
->GetChildren().First();
1464 wxWindow
*child
= (wxWindow
*)node
->Data();
1466 node
= node
->Next();
1467 if (!child
->IsShown())
1470 if (child
->m_isStaticBox
)
1472 // wxStaticBox is transparent in the box itself
1473 int xx1
= child
->m_x
;
1474 int yy1
= child
->m_y
;
1475 int xx2
= child
->m_x
+ child
->m_width
;
1476 int yy2
= child
->m_x
+ child
->m_height
;
1479 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1481 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1483 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1485 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1488 event
.m_x
-= child
->m_x
;
1489 event
.m_y
-= child
->m_y
;
1496 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1497 (child
->m_x
<= x
) &&
1498 (child
->m_y
<= y
) &&
1499 (child
->m_x
+child
->m_width
>= x
) &&
1500 (child
->m_y
+child
->m_height
>= y
))
1503 event
.m_x
-= child
->m_x
;
1504 event
.m_y
-= child
->m_y
;
1511 event
.SetEventObject( win
);
1513 if (win
->GetEventHandler()->ProcessEvent( event
))
1515 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1522 //-----------------------------------------------------------------------------
1524 //-----------------------------------------------------------------------------
1526 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1531 wxapp_install_idle_handler();
1533 if (!win
->m_hasVMT
) return FALSE
;
1534 if (g_blockEventsOnDrag
) return FALSE
;
1536 switch ( g_sendActivateEvent
)
1539 // we've got focus from outside, synthtize wxActivateEvent
1540 g_sendActivateEvent
= 1;
1544 // another our window just lost focus, it was already ours before
1545 // - don't send any wxActivateEvent
1546 g_sendActivateEvent
= -1;
1550 g_focusWindow
= win
;
1553 printf( "OnSetFocus from " );
1554 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1555 printf( win->GetClassInfo()->GetClassName() );
1557 printf( WXSTRINGCAST win->GetLabel() );
1561 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1564 panel
->SetLastFocus(win
);
1569 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1573 // caret needs to be informed about focus change
1574 wxCaret
*caret
= win
->GetCaret();
1577 caret
->OnSetFocus();
1579 #endif // wxUSE_CARET
1581 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1582 event
.SetEventObject( win
);
1584 if (win
->GetEventHandler()->ProcessEvent( event
))
1586 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1593 //-----------------------------------------------------------------------------
1594 // "focus_out_event"
1595 //-----------------------------------------------------------------------------
1597 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1602 wxapp_install_idle_handler();
1604 if (!win
->m_hasVMT
) return FALSE
;
1605 if (g_blockEventsOnDrag
) return FALSE
;
1607 // if the focus goes out of our app alltogether, OnIdle() will send
1608 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1609 // g_sendActivateEvent to -1
1610 g_sendActivateEvent
= 0;
1612 wxWindow
*winFocus
= FindFocusedChild(win
);
1616 g_focusWindow
= (wxWindow
*)NULL
;
1619 printf( "OnKillFocus from " );
1620 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1621 printf( win->GetClassInfo()->GetClassName() );
1631 // caret needs to be informed about focus change
1632 wxCaret
*caret
= win
->GetCaret();
1635 caret
->OnKillFocus();
1637 #endif // wxUSE_CARET
1639 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1640 event
.SetEventObject( win
);
1642 if (win
->GetEventHandler()->ProcessEvent( event
))
1644 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1651 //-----------------------------------------------------------------------------
1652 // "enter_notify_event"
1653 //-----------------------------------------------------------------------------
1655 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1660 wxapp_install_idle_handler();
1662 if (!win
->m_hasVMT
) return FALSE
;
1663 if (g_blockEventsOnDrag
) return FALSE
;
1665 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1667 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1668 #if (GTK_MINOR_VERSION > 0)
1669 event
.SetTimestamp( gdk_event
->time
);
1671 event
.SetEventObject( win
);
1675 GdkModifierType state
= (GdkModifierType
)0;
1677 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1679 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1680 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1681 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1682 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1683 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1684 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1685 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1690 if (win
->GetEventHandler()->ProcessEvent( event
))
1692 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1699 //-----------------------------------------------------------------------------
1700 // "leave_notify_event"
1701 //-----------------------------------------------------------------------------
1703 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1708 wxapp_install_idle_handler();
1710 if (!win
->m_hasVMT
) return FALSE
;
1711 if (g_blockEventsOnDrag
) return FALSE
;
1713 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1715 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1716 #if (GTK_MINOR_VERSION > 0)
1717 event
.SetTimestamp( gdk_event
->time
);
1719 event
.SetEventObject( win
);
1723 GdkModifierType state
= (GdkModifierType
)0;
1725 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1727 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1728 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1729 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1730 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1731 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1732 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1733 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1738 if (win
->GetEventHandler()->ProcessEvent( event
))
1740 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1747 //-----------------------------------------------------------------------------
1748 // "value_changed" from m_vAdjust
1749 //-----------------------------------------------------------------------------
1751 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1756 wxapp_install_idle_handler();
1758 if (g_blockEventsOnDrag
) return;
1760 if (!win
->m_hasVMT
) return;
1762 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1763 if (fabs(diff
) < 0.2) return;
1765 win
->m_oldVerticalPos
= adjust
->value
;
1767 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1768 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1770 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1771 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1772 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1773 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1774 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1776 int value
= (int)(adjust
->value
+0.5);
1778 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1779 event
.SetEventObject( win
);
1780 win
->GetEventHandler()->ProcessEvent( event
);
1783 //-----------------------------------------------------------------------------
1784 // "value_changed" from m_hAdjust
1785 //-----------------------------------------------------------------------------
1787 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1792 wxapp_install_idle_handler();
1794 if (g_blockEventsOnDrag
) return;
1795 if (!win
->m_hasVMT
) return;
1797 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1798 if (fabs(diff
) < 0.2) return;
1800 win
->m_oldHorizontalPos
= adjust
->value
;
1802 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1803 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1805 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1806 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1807 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1808 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1809 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1811 int value
= (int)(adjust
->value
+0.5);
1813 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1814 event
.SetEventObject( win
);
1815 win
->GetEventHandler()->ProcessEvent( event
);
1818 //-----------------------------------------------------------------------------
1819 // "button_press_event" from scrollbar
1820 //-----------------------------------------------------------------------------
1822 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1823 GdkEventButton
*gdk_event
,
1829 wxapp_install_idle_handler();
1832 g_blockEventsOnScroll
= TRUE
;
1833 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1838 //-----------------------------------------------------------------------------
1839 // "button_release_event" from scrollbar
1840 //-----------------------------------------------------------------------------
1842 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1843 GdkEventButton
*WXUNUSED(gdk_event
),
1848 // don't test here as we can release the mouse while being over
1849 // a different window than the slider
1851 // if (gdk_event->window != widget->slider) return FALSE;
1853 g_blockEventsOnScroll
= FALSE
;
1855 if (win
->m_isScrolling
)
1857 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
1861 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1862 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1864 value
= (int)(win
->m_hAdjust
->value
+0.5);
1867 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1869 value
= (int)(win
->m_vAdjust
->value
+0.5);
1873 wxScrollWinEvent
event( command
, value
, dir
);
1874 event
.SetEventObject( win
);
1875 win
->GetEventHandler()->ProcessEvent( event
);
1878 win
->m_isScrolling
= FALSE
;
1883 // ----------------------------------------------------------------------------
1884 // this wxWindowBase function is implemented here (in platform-specific file)
1885 // because it is static and so couldn't be made virtual
1886 // ----------------------------------------------------------------------------
1888 wxWindow
*wxWindowBase::FindFocus()
1890 return g_focusWindow
;
1893 //-----------------------------------------------------------------------------
1894 // "realize" from m_widget
1895 //-----------------------------------------------------------------------------
1897 /* We cannot set colours and fonts before the widget has
1898 been realized, so we do this directly after realization. */
1901 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1906 wxapp_install_idle_handler();
1908 if (win
->m_delayedBackgroundColour
)
1909 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1911 if (win
->m_delayedForegroundColour
)
1912 win
->SetForegroundColour( win
->GetForegroundColour() );
1914 wxWindowCreateEvent
event( win
);
1915 event
.SetEventObject( win
);
1916 win
->GetEventHandler()->ProcessEvent( event
);
1921 //-----------------------------------------------------------------------------
1923 //-----------------------------------------------------------------------------
1926 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
1927 GtkAllocation
*WXUNUSED(alloc
),
1931 wxapp_install_idle_handler();
1933 if (!win
->m_hasScrolling
) return;
1935 int client_width
= 0;
1936 int client_height
= 0;
1937 win
->GetClientSize( &client_width
, &client_height
);
1938 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
1941 win
->m_oldClientWidth
= client_width
;
1942 win
->m_oldClientHeight
= client_height
;
1944 if (!win
->m_nativeSizeEvent
)
1946 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
1947 event
.SetEventObject( win
);
1948 win
->GetEventHandler()->ProcessEvent( event
);
1954 #define WXUNUSED_UNLESS_XIM(param) param
1956 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1959 /* Resize XIM window */
1962 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1963 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1964 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1967 wxapp_install_idle_handler();
1973 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1977 gdk_window_get_size (widget
->window
, &width
, &height
);
1978 win
->m_icattr
->preedit_area
.width
= width
;
1979 win
->m_icattr
->preedit_area
.height
= height
;
1980 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
1985 //-----------------------------------------------------------------------------
1986 // "realize" from m_wxwindow
1987 //-----------------------------------------------------------------------------
1989 /* Initialize XIM support */
1992 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1993 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1996 wxapp_install_idle_handler();
1999 if (win
->m_ic
) return FALSE
;
2000 if (!widget
) return FALSE
;
2001 if (!gdk_im_ready()) return FALSE
;
2003 win
->m_icattr
= gdk_ic_attr_new();
2004 if (!win
->m_icattr
) return FALSE
;
2008 GdkColormap
*colormap
;
2009 GdkICAttr
*attr
= win
->m_icattr
;
2010 unsigned attrmask
= GDK_IC_ALL_REQ
;
2012 GdkIMStyle supported_style
= (GdkIMStyle
)
2013 (GDK_IM_PREEDIT_NONE
|
2014 GDK_IM_PREEDIT_NOTHING
|
2015 GDK_IM_PREEDIT_POSITION
|
2016 GDK_IM_STATUS_NONE
|
2017 GDK_IM_STATUS_NOTHING
);
2019 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2020 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2022 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2023 attr
->client_window
= widget
->window
;
2025 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2026 gtk_widget_get_default_colormap ())
2028 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2029 attr
->preedit_colormap
= colormap
;
2032 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2033 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2034 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2035 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2037 switch (style
& GDK_IM_PREEDIT_MASK
)
2039 case GDK_IM_PREEDIT_POSITION
:
2040 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2042 g_warning ("over-the-spot style requires fontset");
2046 gdk_window_get_size (widget
->window
, &width
, &height
);
2048 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2049 attr
->spot_location
.x
= 0;
2050 attr
->spot_location
.y
= height
;
2051 attr
->preedit_area
.x
= 0;
2052 attr
->preedit_area
.y
= 0;
2053 attr
->preedit_area
.width
= width
;
2054 attr
->preedit_area
.height
= height
;
2055 attr
->preedit_fontset
= widget
->style
->font
;
2060 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2062 if (win
->m_ic
== NULL
)
2063 g_warning ("Can't create input context.");
2066 mask
= gdk_window_get_events (widget
->window
);
2067 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2068 gdk_window_set_events (widget
->window
, mask
);
2070 if (GTK_WIDGET_HAS_FOCUS(widget
))
2071 gdk_im_begin (win
->m_ic
, widget
->window
);
2078 //-----------------------------------------------------------------------------
2079 // InsertChild for wxWindow.
2080 //-----------------------------------------------------------------------------
2082 /* Callback for wxWindow. This very strange beast has to be used because
2083 * C++ has no virtual methods in a constructor. We have to emulate a
2084 * virtual function here as wxNotebook requires a different way to insert
2085 * a child in it. I had opted for creating a wxNotebookPage window class
2086 * which would have made this superfluous (such in the MDI window system),
2087 * but no-one was listening to me... */
2089 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
2091 /* the window might have been scrolled already, do we
2092 have to adapt the position */
2093 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2094 child
->m_x
+= pizza
->xoffset
;
2095 child
->m_y
+= pizza
->yoffset
;
2097 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2098 GTK_WIDGET(child
->m_widget
),
2105 //-----------------------------------------------------------------------------
2107 //-----------------------------------------------------------------------------
2109 wxWindow
* wxGetActiveWindow()
2111 return g_focusWindow
;
2114 //-----------------------------------------------------------------------------
2116 //-----------------------------------------------------------------------------
2118 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2120 void wxWindow::Init()
2126 m_widget
= (GtkWidget
*) NULL
;
2127 m_wxwindow
= (GtkWidget
*) NULL
;
2137 m_needParent
= TRUE
;
2138 m_isBeingDeleted
= FALSE
;
2141 m_nativeSizeEvent
= FALSE
;
2143 m_hasScrolling
= FALSE
;
2144 m_isScrolling
= FALSE
;
2146 m_hAdjust
= (GtkAdjustment
*) NULL
;
2147 m_vAdjust
= (GtkAdjustment
*) NULL
;
2148 m_oldHorizontalPos
= 0.0;
2149 m_oldVerticalPos
= 0.0;
2152 m_widgetStyle
= (GtkStyle
*) NULL
;
2154 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2156 m_isStaticBox
= FALSE
;
2157 m_isRadioButton
= FALSE
;
2159 m_acceptsFocus
= FALSE
;
2161 m_clipPaintRegion
= FALSE
;
2163 m_cursor
= *wxSTANDARD_CURSOR
;
2165 m_delayedForegroundColour
= FALSE
;
2166 m_delayedBackgroundColour
= FALSE
;
2169 m_ic
= (GdkIC
*) NULL
;
2170 m_icattr
= (GdkICAttr
*) NULL
;
2174 wxWindow::wxWindow()
2179 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
2180 const wxPoint
&pos
, const wxSize
&size
,
2181 long style
, const wxString
&name
)
2185 Create( parent
, id
, pos
, size
, style
, name
);
2188 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
2189 const wxPoint
&pos
, const wxSize
&size
,
2190 long style
, const wxString
&name
)
2192 if (!PreCreation( parent
, pos
, size
) ||
2193 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2195 wxFAIL_MSG( wxT("wxWindow creation failed") );
2199 m_insertCallback
= wxInsertChildInWindow
;
2201 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2202 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2204 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2206 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2207 scroll_class
->scrollbar_spacing
= 0;
2209 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2211 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2212 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2214 m_wxwindow
= gtk_pizza_new();
2216 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2218 #if (GTK_MINOR_VERSION > 0)
2219 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2221 if (HasFlag(wxRAISED_BORDER
))
2223 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2225 else if (HasFlag(wxSUNKEN_BORDER
))
2227 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2229 else if (HasFlag(wxSIMPLE_BORDER
))
2231 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2235 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2237 #else // GTK_MINOR_VERSION == 0
2238 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2240 if (HasFlag(wxRAISED_BORDER
))
2242 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2244 else if (HasFlag(wxSUNKEN_BORDER
))
2246 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2250 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2252 #endif // GTK_MINOR_VERSION
2254 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2255 m_acceptsFocus
= TRUE
;
2257 #if (GTK_MINOR_VERSION == 0)
2258 // shut the viewport up
2259 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2260 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2261 #endif // GTK_MINOR_VERSION == 0
2263 // I _really_ don't want scrollbars in the beginning
2264 m_vAdjust
->lower
= 0.0;
2265 m_vAdjust
->upper
= 1.0;
2266 m_vAdjust
->value
= 0.0;
2267 m_vAdjust
->step_increment
= 1.0;
2268 m_vAdjust
->page_increment
= 1.0;
2269 m_vAdjust
->page_size
= 5.0;
2270 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2271 m_hAdjust
->lower
= 0.0;
2272 m_hAdjust
->upper
= 1.0;
2273 m_hAdjust
->value
= 0.0;
2274 m_hAdjust
->step_increment
= 1.0;
2275 m_hAdjust
->page_increment
= 1.0;
2276 m_hAdjust
->page_size
= 5.0;
2277 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2279 // these handlers block mouse events to any window during scrolling such as
2280 // motion events and prevent GTK and wxWindows from fighting over where the
2283 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2284 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2286 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2287 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2289 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2290 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2292 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2293 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2295 // these handlers get notified when screen updates are required either when
2296 // scrolling or when the window size (and therefore scrollbar configuration)
2299 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2300 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2301 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2302 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2304 gtk_widget_show( m_wxwindow
);
2307 m_parent
->DoAddChild( this );
2316 wxWindow::~wxWindow()
2318 m_isBeingDeleted
= TRUE
;
2327 m_parent
->RemoveChild( this );
2331 gdk_ic_destroy (m_ic
);
2333 gdk_ic_attr_destroy (m_icattr
);
2338 #if DISABLE_STYLE_IF_BROKEN_THEME
2339 // don't delete if it's a pixmap theme style
2340 if (!m_widgetStyle
->engine_data
)
2341 gtk_style_unref( m_widgetStyle
);
2343 m_widgetStyle
= (GtkStyle
*) NULL
;
2348 gtk_widget_destroy( m_wxwindow
);
2349 m_wxwindow
= (GtkWidget
*) NULL
;
2354 gtk_widget_destroy( m_widget
);
2355 m_widget
= (GtkWidget
*) NULL
;
2359 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2361 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2363 /* this turns -1 into 20 so that a minimal window is
2364 visible even although -1,-1 has been given as the
2365 size of the window. the same trick is used in other
2366 ports and should make debugging easier */
2367 m_width
= WidthDefault(size
.x
);
2368 m_height
= HeightDefault(size
.y
);
2373 /* some reasonable defaults */
2378 m_x
= (gdk_screen_width () - m_width
) / 2;
2379 if (m_x
< 10) m_x
= 10;
2383 m_y
= (gdk_screen_height () - m_height
) / 2;
2384 if (m_y
< 10) m_y
= 10;
2391 void wxWindow::PostCreation()
2393 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2399 /* these get reported to wxWindows -> wxPaintEvent */
2401 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2403 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2404 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2406 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2407 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2409 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2411 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2412 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2416 #if (GTK_MINOR_VERSION > 0)
2417 /* these are called when the "sunken" or "raised" borders are drawn */
2418 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2419 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2421 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2422 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2426 if (m_wxwindow
&& m_needParent
)
2428 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2429 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2431 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2432 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2436 // For dialogs and frames, we are interested mainly in
2437 // m_widget's focus.
2439 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2440 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2442 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2443 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2446 GtkWidget
*connect_widget
= GetConnectWidget();
2448 ConnectWidget( connect_widget
);
2450 /* We cannot set colours, fonts and cursors before the widget has
2451 been realized, so we do this directly after realization */
2452 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2453 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2457 /* Catch native resize events. */
2458 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2459 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2461 /* Initialize XIM support. */
2462 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2463 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2465 /* And resize XIM window. */
2466 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2467 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2473 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2475 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2476 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2478 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2479 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2481 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2482 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2484 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2485 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2487 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2488 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2490 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2491 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2493 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2494 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2497 bool wxWindow::Destroy()
2499 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2503 return wxWindowBase::Destroy();
2506 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2508 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2511 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2513 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2514 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2516 if (m_resizing
) return; /* I don't like recursions */
2519 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2521 /* don't set the size for children of wxNotebook, just take the values. */
2529 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2531 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2533 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2534 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2535 if (width
!= -1) m_width
= width
;
2536 if (height
!= -1) m_height
= height
;
2540 m_x
= x
+ pizza
->xoffset
;
2541 m_y
= y
+ pizza
->yoffset
;
2546 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2548 if (width
== -1) m_width
= 80;
2551 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2553 if (height
== -1) m_height
= 26;
2556 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2557 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2558 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2559 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2562 int bottom_border
= 0;
2564 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2566 /* the default button has a border around it */
2571 DoMoveWindow( m_x
-border
,
2574 m_height
+border
+bottom_border
);
2579 /* Sometimes the client area changes size without the
2580 whole windows's size changing, but if the whole
2581 windows's size doesn't change, no wxSizeEvent will
2582 normally be sent. Here we add an extra test if
2583 the client test has been changed and this will
2585 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2589 wxPrintf( "OnSize sent from " );
2590 if (GetClassInfo() && GetClassInfo()->GetClassName())
2591 wxPrintf( GetClassInfo()->GetClassName() );
2592 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2595 if (!m_nativeSizeEvent
)
2597 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2598 event
.SetEventObject( this );
2599 GetEventHandler()->ProcessEvent( event
);
2605 void wxWindow::OnInternalIdle()
2607 if ( g_sendActivateEvent
!= -1 )
2609 bool activate
= g_sendActivateEvent
!= 0;
2612 g_sendActivateEvent
= -1;
2614 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2615 event
.SetEventObject(this);
2617 (void)GetEventHandler()->ProcessEvent(event
);
2620 wxCursor cursor
= m_cursor
;
2621 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2625 /* I now set the cursor anew in every OnInternalIdle call
2626 as setting the cursor in a parent window also effects the
2627 windows above so that checking for the current cursor is
2632 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2634 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2636 if (!g_globalCursor
.Ok())
2637 cursor
= *wxSTANDARD_CURSOR
;
2639 window
= m_widget
->window
;
2640 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2641 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2647 GdkWindow
*window
= m_widget
->window
;
2648 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2649 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2657 void wxWindow::DoGetSize( int *width
, int *height
) const
2659 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2661 if (width
) (*width
) = m_width
;
2662 if (height
) (*height
) = m_height
;
2665 void wxWindow::DoSetClientSize( int width
, int height
)
2667 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2671 SetSize( width
, height
);
2678 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2680 /* when using GTK 1.2 we set the shadow border size to 2 */
2684 if (HasFlag(wxSIMPLE_BORDER
))
2686 /* when using GTK 1.2 we set the simple border size to 1 */
2693 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2695 GtkRequisition vscroll_req
;
2696 vscroll_req
.width
= 2;
2697 vscroll_req
.height
= 2;
2698 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2699 (scroll_window
->vscrollbar
, &vscroll_req
);
2701 GtkRequisition hscroll_req
;
2702 hscroll_req
.width
= 2;
2703 hscroll_req
.height
= 2;
2704 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2705 (scroll_window
->hscrollbar
, &hscroll_req
);
2707 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2709 if (scroll_window
->vscrollbar_visible
)
2711 dw
+= vscroll_req
.width
;
2712 dw
+= scroll_class
->scrollbar_spacing
;
2715 if (scroll_window
->hscrollbar_visible
)
2717 dh
+= hscroll_req
.height
;
2718 dh
+= scroll_class
->scrollbar_spacing
;
2722 SetSize( width
+dw
, height
+dh
);
2726 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2728 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2732 if (width
) (*width
) = m_width
;
2733 if (height
) (*height
) = m_height
;
2740 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2742 /* when using GTK 1.2 we set the shadow border size to 2 */
2746 if (HasFlag(wxSIMPLE_BORDER
))
2748 /* when using GTK 1.2 we set the simple border size to 1 */
2755 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2757 GtkRequisition vscroll_req
;
2758 vscroll_req
.width
= 2;
2759 vscroll_req
.height
= 2;
2760 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2761 (scroll_window
->vscrollbar
, &vscroll_req
);
2763 GtkRequisition hscroll_req
;
2764 hscroll_req
.width
= 2;
2765 hscroll_req
.height
= 2;
2766 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2767 (scroll_window
->hscrollbar
, &hscroll_req
);
2769 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2771 if (scroll_window
->vscrollbar_visible
)
2773 dw
+= vscroll_req
.width
;
2774 dw
+= scroll_class
->scrollbar_spacing
;
2777 if (scroll_window
->hscrollbar_visible
)
2779 dh
+= hscroll_req
.height
;
2780 dh
+= scroll_class
->scrollbar_spacing
;
2784 if (width
) (*width
) = m_width
- dw
;
2785 if (height
) (*height
) = m_height
- dh
;
2789 void wxWindow::DoGetPosition( int *x
, int *y
) const
2791 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2795 if (m_parent
&& m_parent
->m_wxwindow
)
2797 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2798 dx
= pizza
->xoffset
;
2799 dy
= pizza
->yoffset
;
2802 if (x
) (*x
) = m_x
- dx
;
2803 if (y
) (*y
) = m_y
- dy
;
2806 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2808 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2810 if (!m_widget
->window
) return;
2812 GdkWindow
*source
= (GdkWindow
*) NULL
;
2814 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2816 source
= m_widget
->window
;
2820 gdk_window_get_origin( source
, &org_x
, &org_y
);
2824 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2826 org_x
+= m_widget
->allocation
.x
;
2827 org_y
+= m_widget
->allocation
.y
;
2835 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2837 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2839 if (!m_widget
->window
) return;
2841 GdkWindow
*source
= (GdkWindow
*) NULL
;
2843 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2845 source
= m_widget
->window
;
2849 gdk_window_get_origin( source
, &org_x
, &org_y
);
2853 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2855 org_x
+= m_widget
->allocation
.x
;
2856 org_y
+= m_widget
->allocation
.y
;
2864 bool wxWindow::Show( bool show
)
2866 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2868 if (!wxWindowBase::Show(show
))
2875 gtk_widget_show( m_widget
);
2877 gtk_widget_hide( m_widget
);
2882 bool wxWindow::Enable( bool enable
)
2884 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2886 if (!wxWindowBase::Enable(enable
))
2892 gtk_widget_set_sensitive( m_widget
, enable
);
2894 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2899 int wxWindow::GetCharHeight() const
2901 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2903 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2905 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2907 return font
->ascent
+ font
->descent
;
2910 int wxWindow::GetCharWidth() const
2912 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2914 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2916 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2918 return gdk_string_width( font
, "H" );
2921 void wxWindow::GetTextExtent( const wxString
& string
,
2925 int *externalLeading
,
2926 const wxFont
*theFont
) const
2928 wxFont fontToUse
= m_font
;
2929 if (theFont
) fontToUse
= *theFont
;
2931 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2933 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2934 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2935 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2936 if (descent
) (*descent
) = font
->descent
;
2937 if (externalLeading
) (*externalLeading
) = 0; // ??
2940 void wxWindow::SetFocus()
2942 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2946 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2947 gtk_widget_grab_focus (m_wxwindow
);
2953 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2955 gtk_widget_grab_focus (m_widget
);
2957 else if (GTK_IS_CONTAINER(m_widget
))
2959 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2968 bool wxWindow::AcceptsFocus() const
2970 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2973 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2975 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2977 wxWindow
*oldParent
= m_parent
,
2978 *newParent
= (wxWindow
*)newParentBase
;
2980 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2982 if ( !wxWindowBase::Reparent(newParent
) )
2985 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2987 /* prevent GTK from deleting the widget arbitrarily */
2988 gtk_widget_ref( m_widget
);
2992 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2995 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2999 /* insert GTK representation */
3000 (*(newParent
->m_insertCallback
))(newParent
, this);
3003 /* reverse: prevent GTK from deleting the widget arbitrarily */
3004 gtk_widget_unref( m_widget
);
3009 void wxWindow::DoAddChild(wxWindow
*child
)
3011 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3013 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3015 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3020 /* insert GTK representation */
3021 (*m_insertCallback
)(this, child
);
3024 void wxWindow::Raise()
3026 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3028 if (!m_widget
->window
) return;
3030 gdk_window_raise( m_widget
->window
);
3033 void wxWindow::Lower()
3035 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3037 if (!m_widget
->window
) return;
3039 gdk_window_lower( m_widget
->window
);
3042 bool wxWindow::SetCursor( const wxCursor
&cursor
)
3044 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3046 if (cursor
== m_cursor
)
3050 wxapp_install_idle_handler();
3052 if (cursor
== wxNullCursor
)
3053 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3055 return wxWindowBase::SetCursor( cursor
);
3058 void wxWindow::WarpPointer( int x
, int y
)
3060 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3062 /* we provide this function ourselves as it is
3063 missing in GDK (top of this file) */
3065 GdkWindow
*window
= (GdkWindow
*) NULL
;
3067 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3069 window
= GetConnectWidget()->window
;
3072 gdk_window_warp_pointer( window
, x
, y
);
3075 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
3077 if (!m_widget
) return;
3078 if (!m_widget
->window
) return;
3080 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3084 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3086 rect
->width
, rect
->height
);
3090 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3094 /* there is no GTK equivalent of "draw only, don't clear" so we
3095 invent our own in the GtkPizza widget */
3103 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3104 gboolean old_clear = pizza->clear_on_draw;
3105 gtk_pizza_set_clear( pizza, FALSE );
3106 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3107 gtk_pizza_set_clear( pizza, old_clear );
3109 GdkEventExpose gdk_event
;
3110 gdk_event
.type
= GDK_EXPOSE
;
3111 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3112 gdk_event
.count
= 0;
3113 gdk_event
.area
.x
= 0;
3114 gdk_event
.area
.y
= 0;
3115 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3116 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3117 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3122 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3131 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3132 gboolean old_clear = pizza->clear_on_draw;
3133 gtk_pizza_set_clear( pizza, FALSE );
3135 GdkRectangle gdk_rect;
3136 gdk_rect.x = rect->x;
3137 gdk_rect.y = rect->y;
3138 gdk_rect.width = rect->width;
3139 gdk_rect.height = rect->height;
3140 gtk_widget_draw( m_wxwindow, &gdk_rect );
3141 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3143 gtk_pizza_set_clear( pizza, old_clear );
3145 GdkEventExpose gdk_event
;
3146 gdk_event
.type
= GDK_EXPOSE
;
3147 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3148 gdk_event
.count
= 0;
3149 gdk_event
.area
.x
= rect
->x
;
3150 gdk_event
.area
.y
= rect
->y
;
3151 gdk_event
.area
.width
= rect
->width
;
3152 gdk_event
.area
.height
= rect
->height
;
3153 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3157 GdkRectangle gdk_rect
;
3158 gdk_rect
.x
= rect
->x
;
3159 gdk_rect
.y
= rect
->y
;
3160 gdk_rect
.width
= rect
->width
;
3161 gdk_rect
.height
= rect
->height
;
3162 gtk_widget_draw( m_widget
, &gdk_rect
);
3167 void wxWindow::Clear()
3169 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3171 if (!m_widget
->window
) return;
3173 if (m_wxwindow
&& m_wxwindow
->window
)
3175 // gdk_window_clear( m_wxwindow->window );
3180 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
3182 wxWindowBase::DoSetToolTip(tip
);
3185 m_tooltip
->Apply( this );
3188 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3190 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3192 #endif // wxUSE_TOOLTIPS
3194 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
3196 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3198 if (!wxWindowBase::SetBackgroundColour(colour
))
3200 // don't leave if the GTK widget has just
3202 if (!m_delayedBackgroundColour
) return FALSE
;
3205 GdkWindow
*window
= (GdkWindow
*) NULL
;
3207 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3209 window
= GetConnectWidget()->window
;
3213 // indicate that a new style has been set
3214 // but it couldn't get applied as the
3215 // widget hasn't been realized yet.
3216 m_delayedBackgroundColour
= TRUE
;
3220 (m_wxwindow
->window
) &&
3221 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3223 /* wxMSW doesn't clear the window here. I don't do that either to
3224 provide compatibility. call Clear() to do the job. */
3226 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3227 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3235 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
3237 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3239 if (!wxWindowBase::SetForegroundColour(colour
))
3241 // don't leave if the GTK widget has just
3243 if (!m_delayedForegroundColour
) return FALSE
;
3246 GdkWindow
*window
= (GdkWindow
*) NULL
;
3248 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3250 window
= GetConnectWidget()->window
;
3254 // indicate that a new style has been set
3255 // but it couldn't get applied as the
3256 // widget hasn't been realized yet.
3257 m_delayedForegroundColour
= TRUE
;
3265 GtkStyle
*wxWindow::GetWidgetStyle()
3269 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3271 /* FIXME: is this necessary? */
3272 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3274 remake
->klass
= m_widgetStyle
->klass
;
3277 gtk_style_unref( m_widgetStyle
);
3278 m_widgetStyle
= remake
;
3282 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3285 def
= gtk_widget_get_default_style();
3287 m_widgetStyle
= gtk_style_copy( def
);
3289 /* FIXME: is this necessary? */
3290 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3292 m_widgetStyle
->klass
= def
->klass
;
3296 return m_widgetStyle
;
3299 void wxWindow::SetWidgetStyle()
3301 #if DISABLE_STYLE_IF_BROKEN_THEM
3302 if (m_widget
->style
->engine_data
)
3304 static bool s_warningPrinted
= FALSE
;
3305 if (!s_warningPrinted
)
3307 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3308 s_warningPrinted
= TRUE
;
3310 m_widgetStyle
= m_widget
->style
;
3315 GtkStyle
*style
= GetWidgetStyle();
3317 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3319 gdk_font_unref( style
->font
);
3320 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3323 if (m_foregroundColour
.Ok())
3325 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3326 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3328 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3329 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3330 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3334 // Try to restore the gtk default style. This is still a little
3335 // oversimplified for what is probably really needed here for controls
3336 // other than buttons, but is better than not being able to (re)set a
3337 // control's foreground colour to *wxBLACK -- RL
3338 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3341 def
= gtk_widget_get_default_style();
3343 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3344 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3345 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3349 if (m_backgroundColour
.Ok())
3351 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3352 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3354 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3355 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3356 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3357 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3358 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3359 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3360 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3361 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3365 // Try to restore the gtk default style. This is still a little
3366 // oversimplified for what is probably really needed here for controls
3367 // other than buttons, but is better than not being able to (re)set a
3368 // control's background colour to default grey and means resetting a
3369 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3371 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3374 def
= gtk_widget_get_default_style();
3376 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3377 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3378 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3379 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3380 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3381 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3382 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3383 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3388 void wxWindow::ApplyWidgetStyle()
3392 //-----------------------------------------------------------------------------
3393 // Pop-up menu stuff
3394 //-----------------------------------------------------------------------------
3396 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3398 *is_waiting
= FALSE
;
3401 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3403 menu
->SetInvokingWindow( win
);
3404 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3407 wxMenuItem
*menuitem
= node
->GetData();
3408 if (menuitem
->IsSubMenu())
3410 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3413 node
= node
->GetNext();
3417 static gint gs_pop_x
= 0;
3418 static gint gs_pop_y
= 0;
3420 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3424 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3429 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3431 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3433 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3435 SetInvokingWindow( menu
, this );
3442 bool is_waiting
= TRUE
;
3444 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3445 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3448 GTK_MENU(menu
->m_menu
),
3449 (GtkWidget
*) NULL
, // parent menu shell
3450 (GtkWidget
*) NULL
, // parent menu item
3451 (GtkMenuPositionFunc
) pop_pos_callback
,
3452 (gpointer
) this, // client data
3453 0, // button used to activate it
3454 gs_timeLastClick
// the time of activation
3459 while (gtk_events_pending())
3460 gtk_main_iteration();
3466 #if wxUSE_DRAG_AND_DROP
3468 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3470 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3472 GtkWidget
*dnd_widget
= GetConnectWidget();
3474 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3476 if (m_dropTarget
) delete m_dropTarget
;
3477 m_dropTarget
= dropTarget
;
3479 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3482 #endif // wxUSE_DRAG_AND_DROP
3484 GtkWidget
* wxWindow::GetConnectWidget()
3486 GtkWidget
*connect_widget
= m_widget
;
3487 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3489 return connect_widget
;
3492 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3495 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3497 return (window
== m_widget
->window
);
3500 bool wxWindow::SetFont( const wxFont
&font
)
3502 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3504 if (!wxWindowBase::SetFont(font
))
3509 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3510 if ( sysbg
== m_backgroundColour
)
3512 m_backgroundColour
= wxNullColour
;
3514 m_backgroundColour
= sysbg
;
3524 void wxWindow::CaptureMouse()
3526 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3528 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3530 GdkWindow
*window
= (GdkWindow
*) NULL
;
3532 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3534 window
= GetConnectWidget()->window
;
3536 if (!window
) return;
3538 wxCursor
* cursor
= & m_cursor
;
3540 cursor
= wxSTANDARD_CURSOR
;
3542 gdk_pointer_grab( window
, FALSE
,
3544 (GDK_BUTTON_PRESS_MASK
|
3545 GDK_BUTTON_RELEASE_MASK
|
3546 GDK_POINTER_MOTION_HINT_MASK
|
3547 GDK_POINTER_MOTION_MASK
),
3549 cursor
->GetCursor(),
3550 (guint32
)GDK_CURRENT_TIME
);
3551 g_captureWindow
= this;
3554 void wxWindow::ReleaseMouse()
3556 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3558 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3560 GdkWindow
*window
= (GdkWindow
*) NULL
;
3562 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3564 window
= GetConnectWidget()->window
;
3569 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3570 g_captureWindow
= (wxWindow
*) NULL
;
3573 bool wxWindow::IsRetained() const
3578 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3579 int range
, bool refresh
)
3581 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3583 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3585 m_hasScrolling
= TRUE
;
3587 if (orient
== wxHORIZONTAL
)
3589 float fpos
= (float)pos
;
3590 float frange
= (float)range
;
3591 float fthumb
= (float)thumbVisible
;
3592 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3593 if (fpos
< 0.0) fpos
= 0.0;
3595 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3596 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3598 SetScrollPos( orient
, pos
, refresh
);
3602 m_oldHorizontalPos
= fpos
;
3604 m_hAdjust
->lower
= 0.0;
3605 m_hAdjust
->upper
= frange
;
3606 m_hAdjust
->value
= fpos
;
3607 m_hAdjust
->step_increment
= 1.0;
3608 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3609 m_hAdjust
->page_size
= fthumb
;
3613 float fpos
= (float)pos
;
3614 float frange
= (float)range
;
3615 float fthumb
= (float)thumbVisible
;
3616 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3617 if (fpos
< 0.0) fpos
= 0.0;
3619 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3620 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3622 SetScrollPos( orient
, pos
, refresh
);
3626 m_oldVerticalPos
= fpos
;
3628 m_vAdjust
->lower
= 0.0;
3629 m_vAdjust
->upper
= frange
;
3630 m_vAdjust
->value
= fpos
;
3631 m_vAdjust
->step_increment
= 1.0;
3632 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3633 m_vAdjust
->page_size
= fthumb
;
3636 if (orient
== wxHORIZONTAL
)
3637 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3639 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3642 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3644 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3646 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3648 if (orient
== wxHORIZONTAL
)
3650 float fpos
= (float)pos
;
3651 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3652 if (fpos
< 0.0) fpos
= 0.0;
3653 m_oldHorizontalPos
= fpos
;
3655 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3656 m_hAdjust
->value
= fpos
;
3660 float fpos
= (float)pos
;
3661 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3662 if (fpos
< 0.0) fpos
= 0.0;
3663 m_oldVerticalPos
= fpos
;
3665 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3666 m_vAdjust
->value
= fpos
;
3669 if (m_wxwindow
->window
)
3671 if (orient
== wxHORIZONTAL
)
3673 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3674 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3676 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3678 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3679 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3683 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3684 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3686 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3688 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3689 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3694 int wxWindow::GetScrollThumb( int orient
) const
3696 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3698 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3700 if (orient
== wxHORIZONTAL
)
3701 return (int)(m_hAdjust
->page_size
+0.5);
3703 return (int)(m_vAdjust
->page_size
+0.5);
3706 int wxWindow::GetScrollPos( int orient
) const
3708 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3710 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3712 if (orient
== wxHORIZONTAL
)
3713 return (int)(m_hAdjust
->value
+0.5);
3715 return (int)(m_vAdjust
->value
+0.5);
3718 int wxWindow::GetScrollRange( int orient
) const
3720 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3722 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3724 if (orient
== wxHORIZONTAL
)
3725 return (int)(m_hAdjust
->upper
+0.5);
3727 return (int)(m_vAdjust
->upper
+0.5);
3730 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3732 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3734 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3736 if ((dx
== 0) && (dy
== 0)) return;
3738 m_clipPaintRegion
= TRUE
;
3739 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3740 m_clipPaintRegion
= FALSE
;
3743 if (m_children.GetCount() > 0)
3745 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3749 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3751 pizza->xoffset -= dx;
3752 pizza->yoffset -= dy;
3754 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3755 gdk_gc_set_exposures( m_scrollGC, TRUE );
3759 GetClientSize( &cw, &ch );
3760 int w = cw - abs(dx);
3761 int h = ch - abs(dy);
3763 if ((h < 0) || (w < 0))
3771 if (dx < 0) s_x = -dx;
3772 if (dy < 0) s_y = -dy;
3775 if (dx > 0) d_x = dx;
3776 if (dy > 0) d_y = dy;
3778 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3779 pizza->bin_window, s_x, s_y, w, h );
3782 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3783 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3784 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3785 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3787 Refresh( TRUE, &rect );
3790 gdk_gc_unref( m_scrollGC );
3795 // Find the wxWindow at the current mouse position, also returning the mouse
3797 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
3799 pt
= wxGetMousePosition();
3800 wxWindow
* found
= wxFindWindowAtPoint(pt
);
3804 // Get the current mouse position.
3805 wxPoint
wxGetMousePosition()
3807 /* This crashes when used within wxHelpContext,
3808 so we have to use the X-specific implementation below.
3810 GdkModifierType *mask;
3811 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
3813 return wxPoint(x, y);
3817 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
3819 return wxPoint(-999, -999);
3821 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
3822 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
3823 Window rootReturn
, childReturn
;
3824 int rootX
, rootY
, winX
, winY
;
3825 unsigned int maskReturn
;
3827 XQueryPointer (display
,
3831 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
3832 return wxPoint(rootX
, rootY
);