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
->IsTopLevel())
686 gtk_paint_flat_box (win
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
687 GTK_SHADOW_NONE
, &gdk_event
->area
, win
->m_widget
, "base", 0, 0, -1, -1);
690 wxWindow
*parent
= win
->GetParent();
691 if (parent
&& GTK_IS_NOTEBOOK(parent
->m_widget
))
693 while (!parent
->IsTopLevel())
694 parent
= parent
->GetParent();
695 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
696 GTK_SHADOW_NONE
, &gdk_event
->area
, parent
->m_widget
, "base", 0, 0, -1, -1);
699 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
701 gdk_event
->area
.width
,
702 gdk_event
->area
.height
);
704 if (gdk_event
->count
== 0)
706 wxEraseEvent
eevent( win
->GetId() );
707 eevent
.SetEventObject( win
);
708 win
->GetEventHandler()->ProcessEvent(eevent
);
710 wxPaintEvent
event( win
->GetId() );
711 event
.SetEventObject( win
);
712 win
->GetEventHandler()->ProcessEvent( event
);
714 win
->GetUpdateRegion().Clear();
717 /* The following code will result in all window-less widgets
718 being redrawn if the wxWindows class is given a chance to
719 paint *anything* because it will then be allowed to paint
720 over the window-less widgets */
722 GList
*children
= pizza
->children
;
725 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
726 children
= children
->next
;
728 GdkEventExpose child_event
= *gdk_event
;
730 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
731 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
732 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
734 child_event
.area
.x
= child
->widget
->allocation
.x
;
735 child_event
.area
.y
= child
->widget
->allocation
.y
;
736 child_event
.area
.width
= child
->widget
->allocation
.width
;
737 child_event
.area
.height
= child
->widget
->allocation
.height
;
738 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
745 //-----------------------------------------------------------------------------
746 // "event" of m_wxwindow
747 //-----------------------------------------------------------------------------
749 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
750 expose events. We need them, of course, so we override the main event
751 procedure in GtkWidget by giving our own handler for all system events.
752 There, we look for expose events ourselves whereas all other events are
755 gint
gtk_window_event_event_callback( GtkWidget
*widget
, GdkEventExpose
*event
, wxWindow
*win
)
757 if (event
->type
== GDK_EXPOSE
)
759 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
766 //-----------------------------------------------------------------------------
767 // "draw" of m_wxwindow
768 //-----------------------------------------------------------------------------
770 /* This callback is a complete replacement of the gtk_pizza_draw() function,
773 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
778 wxapp_install_idle_handler();
781 if (win->GetName() == wxT("panel"))
783 wxPrintf( wxT("OnDraw from ") );
784 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
785 wxPrintf( win->GetClassInfo()->GetClassName() );
786 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
793 GtkPizza
*pizza
= GTK_PIZZA (widget
);
795 if (win
->IsTopLevel())
797 gtk_paint_flat_box (win
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
798 GTK_SHADOW_NONE
, rect
, win
->m_widget
, "base", 0, 0, -1, -1);
801 wxWindow
*parent
= win
->GetParent();
802 if (parent
&& GTK_IS_NOTEBOOK(parent
->m_widget
))
804 while (!parent
->IsTopLevel())
805 parent
= parent
->GetParent();
806 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
807 GTK_SHADOW_NONE
, rect
, parent
->m_widget
, "base", 0, 0, -1, -1);
810 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
811 (pizza
->clear_on_draw
))
813 gdk_window_clear_area( pizza
->bin_window
,
814 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
817 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
819 win
->m_clipPaintRegion
= TRUE
;
821 wxEraseEvent
eevent( win
->GetId() );
822 eevent
.SetEventObject( win
);
823 win
->GetEventHandler()->ProcessEvent(eevent
);
825 wxPaintEvent
event( win
->GetId() );
826 event
.SetEventObject( win
);
827 win
->GetEventHandler()->ProcessEvent( event
);
829 win
->GetUpdateRegion().Clear();
831 win
->m_clipPaintRegion
= FALSE
;
834 GList
*children
= pizza
->children
;
837 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
838 children
= children
->next
;
840 GdkRectangle child_area
;
841 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
843 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
848 //-----------------------------------------------------------------------------
849 // "key_press_event" from any window
850 //-----------------------------------------------------------------------------
852 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
857 wxapp_install_idle_handler();
859 if (!win
->m_hasVMT
) return FALSE
;
860 if (g_blockEventsOnDrag
) return FALSE
;
865 tmp += (char)gdk_event->keyval;
866 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
867 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
872 GdkModifierType state
;
873 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
877 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
878 /* sending unknown key events doesn't really make sense */
879 if (key_code
== 0) return FALSE
;
881 wxKeyEvent
event( wxEVT_KEY_DOWN
);
882 event
.SetTimestamp( gdk_event
->time
);
883 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
884 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
885 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
886 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
887 event
.m_keyCode
= key_code
;
888 event
.m_scanCode
= gdk_event
->keyval
;
891 event
.SetEventObject( win
);
892 ret
= win
->GetEventHandler()->ProcessEvent( event
);
897 wxWindow
*ancestor
= win
;
900 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
903 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
904 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
907 if (ancestor
->IsTopLevel())
909 ancestor
= ancestor
->GetParent();
912 #endif // wxUSE_ACCEL
914 /* wxMSW doesn't send char events with Alt pressed */
915 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
916 will only be sent if it is not in an accelerator table. */
917 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
922 wxKeyEvent
event2( wxEVT_CHAR
);
923 event2
.SetTimestamp( gdk_event
->time
);
924 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
925 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
926 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
927 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
928 event2
.m_keyCode
= key_code
;
929 event2
.m_scanCode
= gdk_event
->keyval
;
932 event2
.SetEventObject( win
);
933 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
936 /* win is a control: tab can be propagated up */
938 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
939 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
940 // have this style, yet choose not to process this particular TAB in which
941 // case TAB must still work as a navigational character
943 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
945 (win
->GetParent()) &&
946 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
948 wxNavigationKeyEvent new_event
;
949 new_event
.SetEventObject( win
->GetParent() );
950 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
951 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
952 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
953 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
954 new_event
.SetCurrentFocus( win
);
955 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
958 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
960 (gdk_event
->keyval
== GDK_Escape
) )
962 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
963 new_event
.SetEventObject( win
);
964 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
967 #if (GTK_MINOR_VERSION > 0)
968 /* Pressing F10 will activate the menu bar of the top frame. */
972 (gdk_event->keyval == GDK_F10) )
974 wxWindow *ancestor = win;
977 if (wxIsKindOf(ancestor,wxFrame))
979 wxFrame *frame = (wxFrame*) ancestor;
980 wxMenuBar *menubar = frame->GetMenuBar();
983 wxNode *node = menubar->GetMenus().First();
986 wxMenu *firstMenu = (wxMenu*) node->Data();
987 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
993 ancestor = ancestor->GetParent();
1001 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1008 //-----------------------------------------------------------------------------
1009 // "key_release_event" from any window
1010 //-----------------------------------------------------------------------------
1012 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
1017 wxapp_install_idle_handler();
1019 if (!win
->m_hasVMT
) return FALSE
;
1020 if (g_blockEventsOnDrag
) return FALSE
;
1023 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
1024 if (gdk_event->state & GDK_SHIFT_MASK)
1025 printf( "ShiftDown.\n" );
1027 printf( "ShiftUp.\n" );
1028 if (gdk_event->state & GDK_CONTROL_MASK)
1029 printf( "ControlDown.\n" );
1031 printf( "ControlUp.\n" );
1035 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
1037 /* sending unknown key events doesn't really make sense */
1038 if (key_code
== 0) return FALSE
;
1042 GdkModifierType state
;
1043 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1045 wxKeyEvent
event( wxEVT_KEY_UP
);
1046 event
.SetTimestamp( gdk_event
->time
);
1047 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1048 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1049 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1050 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1051 event
.m_keyCode
= key_code
;
1052 event
.m_scanCode
= gdk_event
->keyval
;
1055 event
.SetEventObject( win
);
1057 if (win
->GetEventHandler()->ProcessEvent( event
))
1059 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1066 // ----------------------------------------------------------------------------
1067 // mouse event processing helper
1068 // ----------------------------------------------------------------------------
1070 static void AdjustEventButtonState(wxMouseEvent
& event
)
1072 // GDK reports the old state of the button for a button press event, but
1073 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1074 // for a LEFT_DOWN event, not FALSE, so we will invert
1075 // left/right/middleDown for the corresponding click events
1076 switch ( event
.GetEventType() )
1078 case wxEVT_LEFT_DOWN
:
1079 case wxEVT_LEFT_DCLICK
:
1081 event
.m_leftDown
= !event
.m_leftDown
;
1084 case wxEVT_MIDDLE_DOWN
:
1085 case wxEVT_MIDDLE_DCLICK
:
1086 case wxEVT_MIDDLE_UP
:
1087 event
.m_middleDown
= !event
.m_middleDown
;
1090 case wxEVT_RIGHT_DOWN
:
1091 case wxEVT_RIGHT_DCLICK
:
1092 case wxEVT_RIGHT_UP
:
1093 event
.m_rightDown
= !event
.m_rightDown
;
1098 //-----------------------------------------------------------------------------
1099 // "button_press_event"
1100 //-----------------------------------------------------------------------------
1102 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1107 wxapp_install_idle_handler();
1110 wxPrintf( wxT("1) OnButtonPress from ") );
1111 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1112 wxPrintf( win->GetClassInfo()->GetClassName() );
1113 wxPrintf( wxT(".\n") );
1115 if (!win
->m_hasVMT
) return FALSE
;
1116 if (g_blockEventsOnDrag
) return TRUE
;
1117 if (g_blockEventsOnScroll
) return TRUE
;
1119 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1121 if (win
->m_wxwindow
)
1123 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1125 gtk_widget_grab_focus (win
->m_wxwindow
);
1128 wxPrintf( wxT("GrabFocus from ") );
1129 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1130 wxPrintf( win->GetClassInfo()->GetClassName() );
1131 wxPrintf( wxT(".\n") );
1137 wxEventType event_type
= wxEVT_NULL
;
1139 if (gdk_event
->button
== 1)
1141 switch (gdk_event
->type
)
1143 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1144 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1148 else if (gdk_event
->button
== 2)
1150 switch (gdk_event
->type
)
1152 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1153 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1157 else if (gdk_event
->button
== 3)
1159 switch (gdk_event
->type
)
1161 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1162 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1167 if ( event_type
== wxEVT_NULL
)
1169 // unknown mouse button or click type
1173 wxMouseEvent
event( event_type
);
1174 event
.SetTimestamp( gdk_event
->time
);
1175 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1176 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1177 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1178 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1179 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1180 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1181 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1183 event
.m_x
= (wxCoord
)gdk_event
->x
;
1184 event
.m_y
= (wxCoord
)gdk_event
->y
;
1186 AdjustEventButtonState(event
);
1188 // Some control don't have their own X window and thus cannot get
1191 if (!g_captureWindow
)
1193 wxCoord x
= event
.m_x
;
1194 wxCoord y
= event
.m_y
;
1195 if (win
->m_wxwindow
)
1197 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1198 x
+= pizza
->xoffset
;
1199 y
+= pizza
->yoffset
;
1202 wxNode
*node
= win
->GetChildren().First();
1205 wxWindow
*child
= (wxWindow
*)node
->Data();
1207 node
= node
->Next();
1208 if (!child
->IsShown())
1211 if (child
->m_isStaticBox
)
1213 // wxStaticBox is transparent in the box itself
1214 int xx1
= child
->m_x
;
1215 int yy1
= child
->m_y
;
1216 int xx2
= child
->m_x
+ child
->m_width
;
1217 int yy2
= child
->m_x
+ child
->m_height
;
1220 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1222 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1224 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1226 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1229 event
.m_x
-= child
->m_x
;
1230 event
.m_y
-= child
->m_y
;
1237 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1238 (child
->m_x
<= x
) &&
1239 (child
->m_y
<= y
) &&
1240 (child
->m_x
+child
->m_width
>= x
) &&
1241 (child
->m_y
+child
->m_height
>= y
))
1244 event
.m_x
-= child
->m_x
;
1245 event
.m_y
-= child
->m_y
;
1252 event
.SetEventObject( win
);
1254 gs_timeLastClick
= gdk_event
->time
;
1257 wxPrintf( wxT("2) OnButtonPress from ") );
1258 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1259 wxPrintf( win->GetClassInfo()->GetClassName() );
1260 wxPrintf( wxT(".\n") );
1263 if (win
->GetEventHandler()->ProcessEvent( event
))
1265 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1272 //-----------------------------------------------------------------------------
1273 // "button_release_event"
1274 //-----------------------------------------------------------------------------
1276 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1281 wxapp_install_idle_handler();
1283 if (!win
->m_hasVMT
) return FALSE
;
1284 if (g_blockEventsOnDrag
) return FALSE
;
1285 if (g_blockEventsOnScroll
) return FALSE
;
1287 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1290 printf( "OnButtonRelease from " );
1291 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1292 printf( win->GetClassInfo()->GetClassName() );
1296 wxEventType event_type
= wxEVT_NULL
;
1298 switch (gdk_event
->button
)
1300 case 1: event_type
= wxEVT_LEFT_UP
; break;
1301 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1302 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1303 default: return FALSE
;
1306 wxMouseEvent
event( event_type
);
1307 event
.SetTimestamp( gdk_event
->time
);
1308 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1309 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1310 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1311 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1312 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1313 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1314 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1315 event
.m_x
= (wxCoord
)gdk_event
->x
;
1316 event
.m_y
= (wxCoord
)gdk_event
->y
;
1318 AdjustEventButtonState(event
);
1320 // Some control don't have their own X window and thus cannot get
1323 if (!g_captureWindow
)
1325 wxCoord x
= event
.m_x
;
1326 wxCoord y
= event
.m_y
;
1327 if (win
->m_wxwindow
)
1329 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1330 x
+= pizza
->xoffset
;
1331 y
+= pizza
->yoffset
;
1334 wxNode
*node
= win
->GetChildren().First();
1337 wxWindow
*child
= (wxWindow
*)node
->Data();
1339 node
= node
->Next();
1340 if (!child
->IsShown())
1343 if (child
->m_isStaticBox
)
1345 // wxStaticBox is transparent in the box itself
1346 int xx1
= child
->m_x
;
1347 int yy1
= child
->m_y
;
1348 int xx2
= child
->m_x
+ child
->m_width
;
1349 int yy2
= child
->m_x
+ child
->m_height
;
1352 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1354 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1356 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1358 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1361 event
.m_x
-= child
->m_x
;
1362 event
.m_y
-= child
->m_y
;
1369 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1370 (child
->m_x
<= x
) &&
1371 (child
->m_y
<= y
) &&
1372 (child
->m_x
+child
->m_width
>= x
) &&
1373 (child
->m_y
+child
->m_height
>= y
))
1376 event
.m_x
-= child
->m_x
;
1377 event
.m_y
-= child
->m_y
;
1384 event
.SetEventObject( win
);
1386 if (win
->GetEventHandler()->ProcessEvent( event
))
1388 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1395 //-----------------------------------------------------------------------------
1396 // "motion_notify_event"
1397 //-----------------------------------------------------------------------------
1399 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1404 wxapp_install_idle_handler();
1406 if (!win
->m_hasVMT
) return FALSE
;
1407 if (g_blockEventsOnDrag
) return FALSE
;
1408 if (g_blockEventsOnScroll
) return FALSE
;
1410 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1412 if (gdk_event
->is_hint
)
1416 GdkModifierType state
;
1417 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1423 printf( "OnMotion from " );
1424 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1425 printf( win->GetClassInfo()->GetClassName() );
1429 wxMouseEvent
event( wxEVT_MOTION
);
1430 event
.SetTimestamp( gdk_event
->time
);
1431 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1432 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1433 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1434 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1435 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1436 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1437 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1439 event
.m_x
= (wxCoord
)gdk_event
->x
;
1440 event
.m_y
= (wxCoord
)gdk_event
->y
;
1442 // Some control don't have their own X window and thus cannot get
1445 if (!g_captureWindow
)
1447 wxCoord x
= event
.m_x
;
1448 wxCoord y
= event
.m_y
;
1449 if (win
->m_wxwindow
)
1451 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1452 x
+= pizza
->xoffset
;
1453 y
+= pizza
->yoffset
;
1456 wxNode
*node
= win
->GetChildren().First();
1459 wxWindow
*child
= (wxWindow
*)node
->Data();
1461 node
= node
->Next();
1462 if (!child
->IsShown())
1465 if (child
->m_isStaticBox
)
1467 // wxStaticBox is transparent in the box itself
1468 int xx1
= child
->m_x
;
1469 int yy1
= child
->m_y
;
1470 int xx2
= child
->m_x
+ child
->m_width
;
1471 int yy2
= child
->m_x
+ child
->m_height
;
1474 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1476 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1478 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1480 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1483 event
.m_x
-= child
->m_x
;
1484 event
.m_y
-= child
->m_y
;
1491 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1492 (child
->m_x
<= x
) &&
1493 (child
->m_y
<= y
) &&
1494 (child
->m_x
+child
->m_width
>= x
) &&
1495 (child
->m_y
+child
->m_height
>= y
))
1498 event
.m_x
-= child
->m_x
;
1499 event
.m_y
-= child
->m_y
;
1506 event
.SetEventObject( win
);
1508 if (win
->GetEventHandler()->ProcessEvent( event
))
1510 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1517 //-----------------------------------------------------------------------------
1519 //-----------------------------------------------------------------------------
1521 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1526 wxapp_install_idle_handler();
1528 if (!win
->m_hasVMT
) return FALSE
;
1529 if (g_blockEventsOnDrag
) return FALSE
;
1531 switch ( g_sendActivateEvent
)
1534 // we've got focus from outside, synthtize wxActivateEvent
1535 g_sendActivateEvent
= 1;
1539 // another our window just lost focus, it was already ours before
1540 // - don't send any wxActivateEvent
1541 g_sendActivateEvent
= -1;
1545 g_focusWindow
= win
;
1548 printf( "OnSetFocus from " );
1549 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1550 printf( win->GetClassInfo()->GetClassName() );
1552 printf( WXSTRINGCAST win->GetLabel() );
1556 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1559 panel
->SetLastFocus(win
);
1564 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1568 // caret needs to be informed about focus change
1569 wxCaret
*caret
= win
->GetCaret();
1572 caret
->OnSetFocus();
1574 #endif // wxUSE_CARET
1576 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1577 event
.SetEventObject( win
);
1579 if (win
->GetEventHandler()->ProcessEvent( event
))
1581 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1588 //-----------------------------------------------------------------------------
1589 // "focus_out_event"
1590 //-----------------------------------------------------------------------------
1592 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1597 wxapp_install_idle_handler();
1599 if (!win
->m_hasVMT
) return FALSE
;
1600 if (g_blockEventsOnDrag
) return FALSE
;
1602 // if the focus goes out of our app alltogether, OnIdle() will send
1603 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1604 // g_sendActivateEvent to -1
1605 g_sendActivateEvent
= 0;
1607 wxWindow
*winFocus
= FindFocusedChild(win
);
1611 g_focusWindow
= (wxWindow
*)NULL
;
1614 printf( "OnKillFocus from " );
1615 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1616 printf( win->GetClassInfo()->GetClassName() );
1626 // caret needs to be informed about focus change
1627 wxCaret
*caret
= win
->GetCaret();
1630 caret
->OnKillFocus();
1632 #endif // wxUSE_CARET
1634 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1635 event
.SetEventObject( win
);
1637 if (win
->GetEventHandler()->ProcessEvent( event
))
1639 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1646 //-----------------------------------------------------------------------------
1647 // "enter_notify_event"
1648 //-----------------------------------------------------------------------------
1650 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1655 wxapp_install_idle_handler();
1657 if (!win
->m_hasVMT
) return FALSE
;
1658 if (g_blockEventsOnDrag
) return FALSE
;
1660 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1662 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1663 #if (GTK_MINOR_VERSION > 0)
1664 event
.SetTimestamp( gdk_event
->time
);
1666 event
.SetEventObject( win
);
1670 GdkModifierType state
= (GdkModifierType
)0;
1672 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1674 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1675 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1676 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1677 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1678 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1679 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1680 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1685 if (win
->GetEventHandler()->ProcessEvent( event
))
1687 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1694 //-----------------------------------------------------------------------------
1695 // "leave_notify_event"
1696 //-----------------------------------------------------------------------------
1698 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1703 wxapp_install_idle_handler();
1705 if (!win
->m_hasVMT
) return FALSE
;
1706 if (g_blockEventsOnDrag
) return FALSE
;
1708 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1710 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1711 #if (GTK_MINOR_VERSION > 0)
1712 event
.SetTimestamp( gdk_event
->time
);
1714 event
.SetEventObject( win
);
1718 GdkModifierType state
= (GdkModifierType
)0;
1720 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1722 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1723 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1724 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1725 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1726 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1727 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1728 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1733 if (win
->GetEventHandler()->ProcessEvent( event
))
1735 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1742 //-----------------------------------------------------------------------------
1743 // "value_changed" from m_vAdjust
1744 //-----------------------------------------------------------------------------
1746 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1751 wxapp_install_idle_handler();
1753 if (g_blockEventsOnDrag
) return;
1755 if (!win
->m_hasVMT
) return;
1757 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1758 if (fabs(diff
) < 0.2) return;
1760 win
->m_oldVerticalPos
= adjust
->value
;
1762 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1763 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1765 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1766 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1767 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1768 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1769 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1771 int value
= (int)(adjust
->value
+0.5);
1773 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1774 event
.SetEventObject( win
);
1775 win
->GetEventHandler()->ProcessEvent( event
);
1778 //-----------------------------------------------------------------------------
1779 // "value_changed" from m_hAdjust
1780 //-----------------------------------------------------------------------------
1782 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1787 wxapp_install_idle_handler();
1789 if (g_blockEventsOnDrag
) return;
1790 if (!win
->m_hasVMT
) return;
1792 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1793 if (fabs(diff
) < 0.2) return;
1795 win
->m_oldHorizontalPos
= adjust
->value
;
1797 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1798 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1800 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1801 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1802 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1803 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1804 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1806 int value
= (int)(adjust
->value
+0.5);
1808 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1809 event
.SetEventObject( win
);
1810 win
->GetEventHandler()->ProcessEvent( event
);
1813 //-----------------------------------------------------------------------------
1814 // "button_press_event" from scrollbar
1815 //-----------------------------------------------------------------------------
1817 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1818 GdkEventButton
*gdk_event
,
1824 wxapp_install_idle_handler();
1827 g_blockEventsOnScroll
= TRUE
;
1828 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1833 //-----------------------------------------------------------------------------
1834 // "button_release_event" from scrollbar
1835 //-----------------------------------------------------------------------------
1837 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1838 GdkEventButton
*WXUNUSED(gdk_event
),
1843 // don't test here as we can release the mouse while being over
1844 // a different window than the slider
1846 // if (gdk_event->window != widget->slider) return FALSE;
1848 g_blockEventsOnScroll
= FALSE
;
1850 if (win
->m_isScrolling
)
1852 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
1856 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1857 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1859 value
= (int)(win
->m_hAdjust
->value
+0.5);
1862 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1864 value
= (int)(win
->m_vAdjust
->value
+0.5);
1868 wxScrollWinEvent
event( command
, value
, dir
);
1869 event
.SetEventObject( win
);
1870 win
->GetEventHandler()->ProcessEvent( event
);
1873 win
->m_isScrolling
= FALSE
;
1878 // ----------------------------------------------------------------------------
1879 // this wxWindowBase function is implemented here (in platform-specific file)
1880 // because it is static and so couldn't be made virtual
1881 // ----------------------------------------------------------------------------
1883 wxWindow
*wxWindowBase::FindFocus()
1885 return g_focusWindow
;
1888 //-----------------------------------------------------------------------------
1889 // "realize" from m_widget
1890 //-----------------------------------------------------------------------------
1892 /* We cannot set colours and fonts before the widget has
1893 been realized, so we do this directly after realization. */
1896 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1901 wxapp_install_idle_handler();
1903 if (win
->m_delayedBackgroundColour
)
1904 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1906 if (win
->m_delayedForegroundColour
)
1907 win
->SetForegroundColour( win
->GetForegroundColour() );
1909 wxWindowCreateEvent
event( win
);
1910 event
.SetEventObject( win
);
1911 win
->GetEventHandler()->ProcessEvent( event
);
1916 //-----------------------------------------------------------------------------
1918 //-----------------------------------------------------------------------------
1921 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
1922 GtkAllocation
*WXUNUSED(alloc
),
1926 wxapp_install_idle_handler();
1928 if (!win
->m_hasScrolling
) return;
1930 int client_width
= 0;
1931 int client_height
= 0;
1932 win
->GetClientSize( &client_width
, &client_height
);
1933 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
1936 win
->m_oldClientWidth
= client_width
;
1937 win
->m_oldClientHeight
= client_height
;
1939 if (!win
->m_nativeSizeEvent
)
1941 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
1942 event
.SetEventObject( win
);
1943 win
->GetEventHandler()->ProcessEvent( event
);
1949 #define WXUNUSED_UNLESS_XIM(param) param
1951 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1954 /* Resize XIM window */
1957 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1958 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1959 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1962 wxapp_install_idle_handler();
1968 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1972 gdk_window_get_size (widget
->window
, &width
, &height
);
1973 win
->m_icattr
->preedit_area
.width
= width
;
1974 win
->m_icattr
->preedit_area
.height
= height
;
1975 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
1980 //-----------------------------------------------------------------------------
1981 // "realize" from m_wxwindow
1982 //-----------------------------------------------------------------------------
1984 /* Initialize XIM support */
1987 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1988 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1991 wxapp_install_idle_handler();
1994 if (win
->m_ic
) return FALSE
;
1995 if (!widget
) return FALSE
;
1996 if (!gdk_im_ready()) return FALSE
;
1998 win
->m_icattr
= gdk_ic_attr_new();
1999 if (!win
->m_icattr
) return FALSE
;
2003 GdkColormap
*colormap
;
2004 GdkICAttr
*attr
= win
->m_icattr
;
2005 unsigned attrmask
= GDK_IC_ALL_REQ
;
2007 GdkIMStyle supported_style
= (GdkIMStyle
)
2008 (GDK_IM_PREEDIT_NONE
|
2009 GDK_IM_PREEDIT_NOTHING
|
2010 GDK_IM_PREEDIT_POSITION
|
2011 GDK_IM_STATUS_NONE
|
2012 GDK_IM_STATUS_NOTHING
);
2014 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2015 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2017 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2018 attr
->client_window
= widget
->window
;
2020 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2021 gtk_widget_get_default_colormap ())
2023 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2024 attr
->preedit_colormap
= colormap
;
2027 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2028 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2029 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2030 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2032 switch (style
& GDK_IM_PREEDIT_MASK
)
2034 case GDK_IM_PREEDIT_POSITION
:
2035 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2037 g_warning ("over-the-spot style requires fontset");
2041 gdk_window_get_size (widget
->window
, &width
, &height
);
2043 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2044 attr
->spot_location
.x
= 0;
2045 attr
->spot_location
.y
= height
;
2046 attr
->preedit_area
.x
= 0;
2047 attr
->preedit_area
.y
= 0;
2048 attr
->preedit_area
.width
= width
;
2049 attr
->preedit_area
.height
= height
;
2050 attr
->preedit_fontset
= widget
->style
->font
;
2055 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2057 if (win
->m_ic
== NULL
)
2058 g_warning ("Can't create input context.");
2061 mask
= gdk_window_get_events (widget
->window
);
2062 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2063 gdk_window_set_events (widget
->window
, mask
);
2065 if (GTK_WIDGET_HAS_FOCUS(widget
))
2066 gdk_im_begin (win
->m_ic
, widget
->window
);
2073 //-----------------------------------------------------------------------------
2074 // InsertChild for wxWindow.
2075 //-----------------------------------------------------------------------------
2077 /* Callback for wxWindow. This very strange beast has to be used because
2078 * C++ has no virtual methods in a constructor. We have to emulate a
2079 * virtual function here as wxNotebook requires a different way to insert
2080 * a child in it. I had opted for creating a wxNotebookPage window class
2081 * which would have made this superfluous (such in the MDI window system),
2082 * but no-one was listening to me... */
2084 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
2086 /* the window might have been scrolled already, do we
2087 have to adapt the position */
2088 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2089 child
->m_x
+= pizza
->xoffset
;
2090 child
->m_y
+= pizza
->yoffset
;
2092 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2093 GTK_WIDGET(child
->m_widget
),
2100 //-----------------------------------------------------------------------------
2102 //-----------------------------------------------------------------------------
2104 wxWindow
* wxGetActiveWindow()
2106 return g_focusWindow
;
2109 //-----------------------------------------------------------------------------
2111 //-----------------------------------------------------------------------------
2113 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2115 void wxWindow::Init()
2121 m_widget
= (GtkWidget
*) NULL
;
2122 m_wxwindow
= (GtkWidget
*) NULL
;
2132 m_needParent
= TRUE
;
2133 m_isBeingDeleted
= FALSE
;
2136 m_nativeSizeEvent
= FALSE
;
2138 m_hasScrolling
= FALSE
;
2139 m_isScrolling
= FALSE
;
2141 m_hAdjust
= (GtkAdjustment
*) NULL
;
2142 m_vAdjust
= (GtkAdjustment
*) NULL
;
2143 m_oldHorizontalPos
= 0.0;
2144 m_oldVerticalPos
= 0.0;
2147 m_widgetStyle
= (GtkStyle
*) NULL
;
2149 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2151 m_isStaticBox
= FALSE
;
2152 m_isRadioButton
= FALSE
;
2154 m_acceptsFocus
= FALSE
;
2156 m_clipPaintRegion
= FALSE
;
2158 m_cursor
= *wxSTANDARD_CURSOR
;
2160 m_delayedForegroundColour
= FALSE
;
2161 m_delayedBackgroundColour
= FALSE
;
2164 m_ic
= (GdkIC
*) NULL
;
2165 m_icattr
= (GdkICAttr
*) NULL
;
2169 wxWindow::wxWindow()
2174 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
2175 const wxPoint
&pos
, const wxSize
&size
,
2176 long style
, const wxString
&name
)
2180 Create( parent
, id
, pos
, size
, style
, name
);
2183 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
2184 const wxPoint
&pos
, const wxSize
&size
,
2185 long style
, const wxString
&name
)
2187 if (!PreCreation( parent
, pos
, size
) ||
2188 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2190 wxFAIL_MSG( wxT("wxWindow creation failed") );
2194 m_insertCallback
= wxInsertChildInWindow
;
2196 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2197 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2199 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2201 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2202 scroll_class
->scrollbar_spacing
= 0;
2204 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2206 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2207 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2209 m_wxwindow
= gtk_pizza_new();
2211 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2213 #if (GTK_MINOR_VERSION > 0)
2214 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2216 if (HasFlag(wxRAISED_BORDER
))
2218 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2220 else if (HasFlag(wxSUNKEN_BORDER
))
2222 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2224 else if (HasFlag(wxSIMPLE_BORDER
))
2226 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2230 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2232 #else // GTK_MINOR_VERSION == 0
2233 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2235 if (HasFlag(wxRAISED_BORDER
))
2237 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2239 else if (HasFlag(wxSUNKEN_BORDER
))
2241 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2245 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2247 #endif // GTK_MINOR_VERSION
2249 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2250 m_acceptsFocus
= TRUE
;
2252 #if (GTK_MINOR_VERSION == 0)
2253 // shut the viewport up
2254 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2255 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2256 #endif // GTK_MINOR_VERSION == 0
2258 // I _really_ don't want scrollbars in the beginning
2259 m_vAdjust
->lower
= 0.0;
2260 m_vAdjust
->upper
= 1.0;
2261 m_vAdjust
->value
= 0.0;
2262 m_vAdjust
->step_increment
= 1.0;
2263 m_vAdjust
->page_increment
= 1.0;
2264 m_vAdjust
->page_size
= 5.0;
2265 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2266 m_hAdjust
->lower
= 0.0;
2267 m_hAdjust
->upper
= 1.0;
2268 m_hAdjust
->value
= 0.0;
2269 m_hAdjust
->step_increment
= 1.0;
2270 m_hAdjust
->page_increment
= 1.0;
2271 m_hAdjust
->page_size
= 5.0;
2272 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2274 // these handlers block mouse events to any window during scrolling such as
2275 // motion events and prevent GTK and wxWindows from fighting over where the
2278 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2279 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2281 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2282 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2284 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2285 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2287 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2288 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2290 // these handlers get notified when screen updates are required either when
2291 // scrolling or when the window size (and therefore scrollbar configuration)
2294 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2295 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2296 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2297 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2299 gtk_widget_show( m_wxwindow
);
2302 m_parent
->DoAddChild( this );
2311 wxWindow::~wxWindow()
2313 m_isBeingDeleted
= TRUE
;
2322 m_parent
->RemoveChild( this );
2326 gdk_ic_destroy (m_ic
);
2328 gdk_ic_attr_destroy (m_icattr
);
2333 #if DISABLE_STYLE_IF_BROKEN_THEME
2334 // don't delete if it's a pixmap theme style
2335 if (!m_widgetStyle
->engine_data
)
2336 gtk_style_unref( m_widgetStyle
);
2338 m_widgetStyle
= (GtkStyle
*) NULL
;
2343 gtk_widget_destroy( m_wxwindow
);
2344 m_wxwindow
= (GtkWidget
*) NULL
;
2349 gtk_widget_destroy( m_widget
);
2350 m_widget
= (GtkWidget
*) NULL
;
2354 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2356 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2358 /* this turns -1 into 20 so that a minimal window is
2359 visible even although -1,-1 has been given as the
2360 size of the window. the same trick is used in other
2361 ports and should make debugging easier */
2362 m_width
= WidthDefault(size
.x
);
2363 m_height
= HeightDefault(size
.y
);
2368 /* some reasonable defaults */
2373 m_x
= (gdk_screen_width () - m_width
) / 2;
2374 if (m_x
< 10) m_x
= 10;
2378 m_y
= (gdk_screen_height () - m_height
) / 2;
2379 if (m_y
< 10) m_y
= 10;
2386 void wxWindow::PostCreation()
2388 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2394 /* these get reported to wxWindows -> wxPaintEvent */
2396 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2398 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2399 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2401 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2402 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2404 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2405 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2408 #if (GTK_MINOR_VERSION > 0)
2409 /* these are called when the "sunken" or "raised" borders are drawn */
2410 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2411 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2413 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2414 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2418 if (m_wxwindow
&& m_needParent
)
2420 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2421 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2423 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2424 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2428 // For dialogs and frames, we are interested mainly in
2429 // m_widget's focus.
2431 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2432 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2434 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2435 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2438 GtkWidget
*connect_widget
= GetConnectWidget();
2440 ConnectWidget( connect_widget
);
2442 /* We cannot set colours, fonts and cursors before the widget has
2443 been realized, so we do this directly after realization */
2444 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2445 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2449 /* Catch native resize events. */
2450 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2451 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2453 /* Initialize XIM support. */
2454 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2455 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2457 /* And resize XIM window. */
2458 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2459 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2465 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2467 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2468 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2470 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2471 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2473 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2474 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2476 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2477 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2479 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2480 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2482 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2483 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2485 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2486 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2489 bool wxWindow::Destroy()
2491 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2495 return wxWindowBase::Destroy();
2498 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2500 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2503 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2505 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2506 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2508 if (m_resizing
) return; /* I don't like recursions */
2511 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2513 /* don't set the size for children of wxNotebook, just take the values. */
2521 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2523 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2525 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2526 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2527 if (width
!= -1) m_width
= width
;
2528 if (height
!= -1) m_height
= height
;
2532 m_x
= x
+ pizza
->xoffset
;
2533 m_y
= y
+ pizza
->yoffset
;
2538 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2540 if (width
== -1) m_width
= 80;
2543 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2545 if (height
== -1) m_height
= 26;
2548 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2549 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2550 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2551 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2554 int bottom_border
= 0;
2556 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2558 /* the default button has a border around it */
2563 DoMoveWindow( m_x
-border
,
2566 m_height
+border
+bottom_border
);
2571 /* Sometimes the client area changes size without the
2572 whole windows's size changing, but if the whole
2573 windows's size doesn't change, no wxSizeEvent will
2574 normally be sent. Here we add an extra test if
2575 the client test has been changed and this will
2577 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2581 wxPrintf( "OnSize sent from " );
2582 if (GetClassInfo() && GetClassInfo()->GetClassName())
2583 wxPrintf( GetClassInfo()->GetClassName() );
2584 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2587 if (!m_nativeSizeEvent
)
2589 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2590 event
.SetEventObject( this );
2591 GetEventHandler()->ProcessEvent( event
);
2597 void wxWindow::OnInternalIdle()
2599 if ( g_sendActivateEvent
!= -1 )
2601 bool activate
= g_sendActivateEvent
!= 0;
2604 g_sendActivateEvent
= -1;
2606 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2607 event
.SetEventObject(this);
2609 (void)GetEventHandler()->ProcessEvent(event
);
2612 wxCursor cursor
= m_cursor
;
2613 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2617 /* I now set the cursor anew in every OnInternalIdle call
2618 as setting the cursor in a parent window also effects the
2619 windows above so that checking for the current cursor is
2624 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2626 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2628 if (!g_globalCursor
.Ok())
2629 cursor
= *wxSTANDARD_CURSOR
;
2631 window
= m_widget
->window
;
2632 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2633 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2639 GdkWindow
*window
= m_widget
->window
;
2640 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2641 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2649 void wxWindow::DoGetSize( int *width
, int *height
) const
2651 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2653 if (width
) (*width
) = m_width
;
2654 if (height
) (*height
) = m_height
;
2657 void wxWindow::DoSetClientSize( int width
, int height
)
2659 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2663 SetSize( width
, height
);
2670 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2672 /* when using GTK 1.2 we set the shadow border size to 2 */
2676 if (HasFlag(wxSIMPLE_BORDER
))
2678 /* when using GTK 1.2 we set the simple border size to 1 */
2685 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2687 GtkRequisition vscroll_req
;
2688 vscroll_req
.width
= 2;
2689 vscroll_req
.height
= 2;
2690 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2691 (scroll_window
->vscrollbar
, &vscroll_req
);
2693 GtkRequisition hscroll_req
;
2694 hscroll_req
.width
= 2;
2695 hscroll_req
.height
= 2;
2696 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2697 (scroll_window
->hscrollbar
, &hscroll_req
);
2699 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2701 if (scroll_window
->vscrollbar_visible
)
2703 dw
+= vscroll_req
.width
;
2704 dw
+= scroll_class
->scrollbar_spacing
;
2707 if (scroll_window
->hscrollbar_visible
)
2709 dh
+= hscroll_req
.height
;
2710 dh
+= scroll_class
->scrollbar_spacing
;
2714 SetSize( width
+dw
, height
+dh
);
2718 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2720 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2724 if (width
) (*width
) = m_width
;
2725 if (height
) (*height
) = m_height
;
2732 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2734 /* when using GTK 1.2 we set the shadow border size to 2 */
2738 if (HasFlag(wxSIMPLE_BORDER
))
2740 /* when using GTK 1.2 we set the simple border size to 1 */
2747 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2749 GtkRequisition vscroll_req
;
2750 vscroll_req
.width
= 2;
2751 vscroll_req
.height
= 2;
2752 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2753 (scroll_window
->vscrollbar
, &vscroll_req
);
2755 GtkRequisition hscroll_req
;
2756 hscroll_req
.width
= 2;
2757 hscroll_req
.height
= 2;
2758 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2759 (scroll_window
->hscrollbar
, &hscroll_req
);
2761 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2763 if (scroll_window
->vscrollbar_visible
)
2765 dw
+= vscroll_req
.width
;
2766 dw
+= scroll_class
->scrollbar_spacing
;
2769 if (scroll_window
->hscrollbar_visible
)
2771 dh
+= hscroll_req
.height
;
2772 dh
+= scroll_class
->scrollbar_spacing
;
2776 if (width
) (*width
) = m_width
- dw
;
2777 if (height
) (*height
) = m_height
- dh
;
2781 void wxWindow::DoGetPosition( int *x
, int *y
) const
2783 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2787 if (m_parent
&& m_parent
->m_wxwindow
)
2789 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2790 dx
= pizza
->xoffset
;
2791 dy
= pizza
->yoffset
;
2794 if (x
) (*x
) = m_x
- dx
;
2795 if (y
) (*y
) = m_y
- dy
;
2798 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2800 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2802 if (!m_widget
->window
) return;
2804 GdkWindow
*source
= (GdkWindow
*) NULL
;
2806 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2808 source
= m_widget
->window
;
2812 gdk_window_get_origin( source
, &org_x
, &org_y
);
2816 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2818 org_x
+= m_widget
->allocation
.x
;
2819 org_y
+= m_widget
->allocation
.y
;
2827 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2829 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2831 if (!m_widget
->window
) return;
2833 GdkWindow
*source
= (GdkWindow
*) NULL
;
2835 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2837 source
= m_widget
->window
;
2841 gdk_window_get_origin( source
, &org_x
, &org_y
);
2845 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2847 org_x
+= m_widget
->allocation
.x
;
2848 org_y
+= m_widget
->allocation
.y
;
2856 bool wxWindow::Show( bool show
)
2858 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2860 if (!wxWindowBase::Show(show
))
2867 gtk_widget_show( m_widget
);
2869 gtk_widget_hide( m_widget
);
2874 bool wxWindow::Enable( bool enable
)
2876 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2878 if (!wxWindowBase::Enable(enable
))
2884 gtk_widget_set_sensitive( m_widget
, enable
);
2886 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2891 int wxWindow::GetCharHeight() const
2893 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2895 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2897 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2899 return font
->ascent
+ font
->descent
;
2902 int wxWindow::GetCharWidth() const
2904 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2906 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2908 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2910 return gdk_string_width( font
, "H" );
2913 void wxWindow::GetTextExtent( const wxString
& string
,
2917 int *externalLeading
,
2918 const wxFont
*theFont
) const
2920 wxFont fontToUse
= m_font
;
2921 if (theFont
) fontToUse
= *theFont
;
2923 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2925 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2926 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2927 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2928 if (descent
) (*descent
) = font
->descent
;
2929 if (externalLeading
) (*externalLeading
) = 0; // ??
2932 void wxWindow::SetFocus()
2934 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2938 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2939 gtk_widget_grab_focus (m_wxwindow
);
2945 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2947 gtk_widget_grab_focus (m_widget
);
2949 else if (GTK_IS_CONTAINER(m_widget
))
2951 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2960 bool wxWindow::AcceptsFocus() const
2962 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2965 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2967 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2969 wxWindow
*oldParent
= m_parent
,
2970 *newParent
= (wxWindow
*)newParentBase
;
2972 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2974 if ( !wxWindowBase::Reparent(newParent
) )
2977 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2979 /* prevent GTK from deleting the widget arbitrarily */
2980 gtk_widget_ref( m_widget
);
2984 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2987 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2991 /* insert GTK representation */
2992 (*(newParent
->m_insertCallback
))(newParent
, this);
2995 /* reverse: prevent GTK from deleting the widget arbitrarily */
2996 gtk_widget_unref( m_widget
);
3001 void wxWindow::DoAddChild(wxWindow
*child
)
3003 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3005 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3007 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3012 /* insert GTK representation */
3013 (*m_insertCallback
)(this, child
);
3016 void wxWindow::Raise()
3018 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3020 if (!m_widget
->window
) return;
3022 gdk_window_raise( m_widget
->window
);
3025 void wxWindow::Lower()
3027 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3029 if (!m_widget
->window
) return;
3031 gdk_window_lower( m_widget
->window
);
3034 bool wxWindow::SetCursor( const wxCursor
&cursor
)
3036 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3038 if (cursor
== m_cursor
)
3042 wxapp_install_idle_handler();
3044 if (cursor
== wxNullCursor
)
3045 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3047 return wxWindowBase::SetCursor( cursor
);
3050 void wxWindow::WarpPointer( int x
, int y
)
3052 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3054 /* we provide this function ourselves as it is
3055 missing in GDK (top of this file) */
3057 GdkWindow
*window
= (GdkWindow
*) NULL
;
3059 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3061 window
= GetConnectWidget()->window
;
3064 gdk_window_warp_pointer( window
, x
, y
);
3067 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
3069 if (!m_widget
) return;
3070 if (!m_widget
->window
) return;
3072 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3076 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3078 rect
->width
, rect
->height
);
3082 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3086 /* there is no GTK equivalent of "draw only, don't clear" so we
3087 invent our own in the GtkPizza widget */
3095 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3096 gboolean old_clear = pizza->clear_on_draw;
3097 gtk_pizza_set_clear( pizza, FALSE );
3098 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3099 gtk_pizza_set_clear( pizza, old_clear );
3101 GdkEventExpose gdk_event
;
3102 gdk_event
.type
= GDK_EXPOSE
;
3103 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3104 gdk_event
.count
= 0;
3105 gdk_event
.area
.x
= 0;
3106 gdk_event
.area
.y
= 0;
3107 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3108 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3109 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3114 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3123 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3124 gboolean old_clear = pizza->clear_on_draw;
3125 gtk_pizza_set_clear( pizza, FALSE );
3127 GdkRectangle gdk_rect;
3128 gdk_rect.x = rect->x;
3129 gdk_rect.y = rect->y;
3130 gdk_rect.width = rect->width;
3131 gdk_rect.height = rect->height;
3132 gtk_widget_draw( m_wxwindow, &gdk_rect );
3133 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3135 gtk_pizza_set_clear( pizza, old_clear );
3137 GdkEventExpose gdk_event
;
3138 gdk_event
.type
= GDK_EXPOSE
;
3139 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3140 gdk_event
.count
= 0;
3141 gdk_event
.area
.x
= rect
->x
;
3142 gdk_event
.area
.y
= rect
->y
;
3143 gdk_event
.area
.width
= rect
->width
;
3144 gdk_event
.area
.height
= rect
->height
;
3145 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3149 GdkRectangle gdk_rect
;
3150 gdk_rect
.x
= rect
->x
;
3151 gdk_rect
.y
= rect
->y
;
3152 gdk_rect
.width
= rect
->width
;
3153 gdk_rect
.height
= rect
->height
;
3154 gtk_widget_draw( m_widget
, &gdk_rect
);
3159 void wxWindow::Clear()
3161 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3163 if (!m_widget
->window
) return;
3165 if (m_wxwindow
&& m_wxwindow
->window
)
3167 // gdk_window_clear( m_wxwindow->window );
3172 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
3174 wxWindowBase::DoSetToolTip(tip
);
3177 m_tooltip
->Apply( this );
3180 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3182 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3184 #endif // wxUSE_TOOLTIPS
3186 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
3188 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3190 if (!wxWindowBase::SetBackgroundColour(colour
))
3192 // don't leave if the GTK widget has just
3194 if (!m_delayedBackgroundColour
) return FALSE
;
3197 GdkWindow
*window
= (GdkWindow
*) NULL
;
3199 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3201 window
= GetConnectWidget()->window
;
3205 // indicate that a new style has been set
3206 // but it couldn't get applied as the
3207 // widget hasn't been realized yet.
3208 m_delayedBackgroundColour
= TRUE
;
3212 (m_wxwindow
->window
) &&
3213 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3215 /* wxMSW doesn't clear the window here. I don't do that either to
3216 provide compatibility. call Clear() to do the job. */
3218 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3219 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3227 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
3229 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3231 if (!wxWindowBase::SetForegroundColour(colour
))
3233 // don't leave if the GTK widget has just
3235 if (!m_delayedForegroundColour
) return FALSE
;
3238 GdkWindow
*window
= (GdkWindow
*) NULL
;
3240 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3242 window
= GetConnectWidget()->window
;
3246 // indicate that a new style has been set
3247 // but it couldn't get applied as the
3248 // widget hasn't been realized yet.
3249 m_delayedForegroundColour
= TRUE
;
3257 GtkStyle
*wxWindow::GetWidgetStyle()
3261 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3263 /* FIXME: is this necessary? */
3264 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3266 remake
->klass
= m_widgetStyle
->klass
;
3269 gtk_style_unref( m_widgetStyle
);
3270 m_widgetStyle
= remake
;
3274 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3277 def
= gtk_widget_get_default_style();
3279 m_widgetStyle
= gtk_style_copy( def
);
3281 /* FIXME: is this necessary? */
3282 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3284 m_widgetStyle
->klass
= def
->klass
;
3288 return m_widgetStyle
;
3291 void wxWindow::SetWidgetStyle()
3293 #if DISABLE_STYLE_IF_BROKEN_THEM
3294 if (m_widget
->style
->engine_data
)
3296 static bool s_warningPrinted
= FALSE
;
3297 if (!s_warningPrinted
)
3299 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3300 s_warningPrinted
= TRUE
;
3302 m_widgetStyle
= m_widget
->style
;
3307 GtkStyle
*style
= GetWidgetStyle();
3309 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3311 gdk_font_unref( style
->font
);
3312 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3315 if (m_foregroundColour
.Ok())
3317 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3318 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3320 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3321 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3322 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3326 // Try to restore the gtk default style. This is still a little
3327 // oversimplified for what is probably really needed here for controls
3328 // other than buttons, but is better than not being able to (re)set a
3329 // control's foreground colour to *wxBLACK -- RL
3330 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3333 def
= gtk_widget_get_default_style();
3335 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3336 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3337 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3341 if (m_backgroundColour
.Ok())
3343 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3344 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3346 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3347 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3348 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3349 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3350 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3351 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3352 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3353 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3357 // Try to restore the gtk default style. This is still a little
3358 // oversimplified for what is probably really needed here for controls
3359 // other than buttons, but is better than not being able to (re)set a
3360 // control's background colour to default grey and means resetting a
3361 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3363 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3366 def
= gtk_widget_get_default_style();
3368 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3369 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3370 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3371 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3372 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3373 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3374 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3375 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3380 void wxWindow::ApplyWidgetStyle()
3384 //-----------------------------------------------------------------------------
3385 // Pop-up menu stuff
3386 //-----------------------------------------------------------------------------
3388 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3390 *is_waiting
= FALSE
;
3393 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3395 menu
->SetInvokingWindow( win
);
3396 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3399 wxMenuItem
*menuitem
= node
->GetData();
3400 if (menuitem
->IsSubMenu())
3402 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3405 node
= node
->GetNext();
3409 static gint gs_pop_x
= 0;
3410 static gint gs_pop_y
= 0;
3412 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3416 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3421 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3423 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3425 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3427 SetInvokingWindow( menu
, this );
3434 bool is_waiting
= TRUE
;
3436 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3437 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3440 GTK_MENU(menu
->m_menu
),
3441 (GtkWidget
*) NULL
, // parent menu shell
3442 (GtkWidget
*) NULL
, // parent menu item
3443 (GtkMenuPositionFunc
) pop_pos_callback
,
3444 (gpointer
) this, // client data
3445 0, // button used to activate it
3446 gs_timeLastClick
// the time of activation
3451 while (gtk_events_pending())
3452 gtk_main_iteration();
3458 #if wxUSE_DRAG_AND_DROP
3460 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3462 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3464 GtkWidget
*dnd_widget
= GetConnectWidget();
3466 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3468 if (m_dropTarget
) delete m_dropTarget
;
3469 m_dropTarget
= dropTarget
;
3471 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3474 #endif // wxUSE_DRAG_AND_DROP
3476 GtkWidget
* wxWindow::GetConnectWidget()
3478 GtkWidget
*connect_widget
= m_widget
;
3479 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3481 return connect_widget
;
3484 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3487 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3489 return (window
== m_widget
->window
);
3492 bool wxWindow::SetFont( const wxFont
&font
)
3494 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3496 if (!wxWindowBase::SetFont(font
))
3501 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3502 if ( sysbg
== m_backgroundColour
)
3504 m_backgroundColour
= wxNullColour
;
3506 m_backgroundColour
= sysbg
;
3516 void wxWindow::CaptureMouse()
3518 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3520 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3522 GdkWindow
*window
= (GdkWindow
*) NULL
;
3524 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3526 window
= GetConnectWidget()->window
;
3528 if (!window
) return;
3530 wxCursor
* cursor
= & m_cursor
;
3532 cursor
= wxSTANDARD_CURSOR
;
3534 gdk_pointer_grab( window
, FALSE
,
3536 (GDK_BUTTON_PRESS_MASK
|
3537 GDK_BUTTON_RELEASE_MASK
|
3538 GDK_POINTER_MOTION_HINT_MASK
|
3539 GDK_POINTER_MOTION_MASK
),
3541 cursor
->GetCursor(),
3542 (guint32
)GDK_CURRENT_TIME
);
3543 g_captureWindow
= this;
3546 void wxWindow::ReleaseMouse()
3548 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3550 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3552 GdkWindow
*window
= (GdkWindow
*) NULL
;
3554 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3556 window
= GetConnectWidget()->window
;
3561 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3562 g_captureWindow
= (wxWindow
*) NULL
;
3565 bool wxWindow::IsRetained() const
3570 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3571 int range
, bool refresh
)
3573 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3575 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3577 m_hasScrolling
= TRUE
;
3579 if (orient
== wxHORIZONTAL
)
3581 float fpos
= (float)pos
;
3582 float frange
= (float)range
;
3583 float fthumb
= (float)thumbVisible
;
3584 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3585 if (fpos
< 0.0) fpos
= 0.0;
3587 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3588 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3590 SetScrollPos( orient
, pos
, refresh
);
3594 m_oldHorizontalPos
= fpos
;
3596 m_hAdjust
->lower
= 0.0;
3597 m_hAdjust
->upper
= frange
;
3598 m_hAdjust
->value
= fpos
;
3599 m_hAdjust
->step_increment
= 1.0;
3600 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3601 m_hAdjust
->page_size
= fthumb
;
3605 float fpos
= (float)pos
;
3606 float frange
= (float)range
;
3607 float fthumb
= (float)thumbVisible
;
3608 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3609 if (fpos
< 0.0) fpos
= 0.0;
3611 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3612 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3614 SetScrollPos( orient
, pos
, refresh
);
3618 m_oldVerticalPos
= fpos
;
3620 m_vAdjust
->lower
= 0.0;
3621 m_vAdjust
->upper
= frange
;
3622 m_vAdjust
->value
= fpos
;
3623 m_vAdjust
->step_increment
= 1.0;
3624 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3625 m_vAdjust
->page_size
= fthumb
;
3628 if (orient
== wxHORIZONTAL
)
3629 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3631 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3634 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3636 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3638 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3640 if (orient
== wxHORIZONTAL
)
3642 float fpos
= (float)pos
;
3643 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3644 if (fpos
< 0.0) fpos
= 0.0;
3645 m_oldHorizontalPos
= fpos
;
3647 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3648 m_hAdjust
->value
= fpos
;
3652 float fpos
= (float)pos
;
3653 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3654 if (fpos
< 0.0) fpos
= 0.0;
3655 m_oldVerticalPos
= fpos
;
3657 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3658 m_vAdjust
->value
= fpos
;
3661 if (m_wxwindow
->window
)
3663 if (orient
== wxHORIZONTAL
)
3665 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3666 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3668 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3670 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3671 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3675 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3676 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3678 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3680 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3681 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3686 int wxWindow::GetScrollThumb( int orient
) const
3688 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3690 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3692 if (orient
== wxHORIZONTAL
)
3693 return (int)(m_hAdjust
->page_size
+0.5);
3695 return (int)(m_vAdjust
->page_size
+0.5);
3698 int wxWindow::GetScrollPos( int orient
) const
3700 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3702 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3704 if (orient
== wxHORIZONTAL
)
3705 return (int)(m_hAdjust
->value
+0.5);
3707 return (int)(m_vAdjust
->value
+0.5);
3710 int wxWindow::GetScrollRange( int orient
) const
3712 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3714 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3716 if (orient
== wxHORIZONTAL
)
3717 return (int)(m_hAdjust
->upper
+0.5);
3719 return (int)(m_vAdjust
->upper
+0.5);
3722 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3724 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3726 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3728 if ((dx
== 0) && (dy
== 0)) return;
3730 m_clipPaintRegion
= TRUE
;
3731 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3732 m_clipPaintRegion
= FALSE
;
3735 if (m_children.GetCount() > 0)
3737 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3741 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3743 pizza->xoffset -= dx;
3744 pizza->yoffset -= dy;
3746 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3747 gdk_gc_set_exposures( m_scrollGC, TRUE );
3751 GetClientSize( &cw, &ch );
3752 int w = cw - abs(dx);
3753 int h = ch - abs(dy);
3755 if ((h < 0) || (w < 0))
3763 if (dx < 0) s_x = -dx;
3764 if (dy < 0) s_y = -dy;
3767 if (dx > 0) d_x = dx;
3768 if (dy > 0) d_y = dy;
3770 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3771 pizza->bin_window, s_x, s_y, w, h );
3774 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3775 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3776 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3777 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3779 Refresh( TRUE, &rect );
3782 gdk_gc_unref( m_scrollGC );
3787 // Find the wxWindow at the current mouse position, also returning the mouse
3789 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
3791 pt
= wxGetMousePosition();
3792 wxWindow
* found
= wxFindWindowAtPoint(pt
);
3796 // Get the current mouse position.
3797 wxPoint
wxGetMousePosition()
3799 /* This crashes when used within wxHelpContext,
3800 so we have to use the X-specific implementation below.
3802 GdkModifierType *mask;
3803 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
3805 return wxPoint(x, y);
3809 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
3811 return wxPoint(-999, -999);
3813 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
3814 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
3815 Window rootReturn
, childReturn
;
3816 int rootX
, rootY
, winX
, winY
;
3817 unsigned int maskReturn
;
3819 XQueryPointer (display
,
3823 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
3824 return wxPoint(rootX
, rootY
);