1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/window.cpp
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #define XWarpPointer XWARPPOINTER
20 #include "wx/window.h"
24 #include "wx/layout.h"
26 #include "wx/dialog.h"
27 #include "wx/msgdlg.h"
29 #if wxUSE_DRAG_AND_DROP
34 #include "wx/tooltip.h"
42 #include "wx/statusbr.h"
44 #include "wx/settings.h"
48 #include "wx/thread.h"
55 #include <gdk/gdkprivate.h>
56 #include <gdk/gdkkeysyms.h>
60 #include <gtk/gtkprivate.h>
62 #include "wx/gtk/win_gtk.h"
64 //-----------------------------------------------------------------------------
65 // documentation on internals
66 //-----------------------------------------------------------------------------
69 I have been asked several times about writing some documentation about
70 the GTK port of wxWindows, especially its internal structures. Obviously,
71 you cannot understand wxGTK without knowing a little about the GTK, but
72 some more information about what the wxWindow, which is the base class
73 for all other window classes, does seems required as well.
77 What does wxWindow do? It contains the common interface for the following
78 jobs of its descendants:
80 1) Define the rudimentary behaviour common to all window classes, such as
81 resizing, intercepting user input (so as to make it possible to use these
82 events for special purposes in a derived class), window names etc.
84 2) Provide the possibility to contain and manage children, if the derived
85 class is allowed to contain children, which holds true for those window
86 classes which do not display a native GTK widget. To name them, these
87 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
88 work classes are a special case and are handled a bit differently from
89 the rest. The same holds true for the wxNotebook class.
91 3) Provide the possibility to draw into a client area of a window. This,
92 too, only holds true for classes that do not display a native GTK widget
95 4) Provide the entire mechanism for scrolling widgets. This actual inter-
96 face for this is usually in wxScrolledWindow, but the GTK implementation
99 5) A multitude of helper or extra methods for special purposes, such as
100 Drag'n'Drop, managing validators etc.
102 6) Display a border (sunken, raised, simple or none).
104 Normally one might expect, that one wxWindows window would always correspond
105 to one GTK widget. Under GTK, there is no such allround widget that has all
106 the functionality. Moreover, the GTK defines a client area as a different
107 widget from the actual widget you are handling. Last but not least some
108 special classes (e.g. wxFrame) handle different categories of widgets and
109 still have the possibility to draw something in the client area.
110 It was therefore required to write a special purpose GTK widget, that would
111 represent a client area in the sense of wxWindows capable to do the jobs
112 2), 3) and 4). I have written this class and it resides in win_gtk.c of
115 All windows must have a widget, with which they interact with other under-
116 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
117 thw wxWindow class has a member variable called m_widget which holds a
118 pointer to this widget. When the window class represents a GTK native widget,
119 this is (in most cases) the only GTK widget the class manages. E.g. the
120 wxStatitText class handles only a GtkLabel widget a pointer to which you
121 can find in m_widget (defined in wxWindow)
123 When the class has a client area for drawing into and for containing children
124 it has to handle the client area widget (of the type GtkPizza, defined in
125 win_gtk.c), but there could be any number of widgets, handled by a class
126 The common rule for all windows is only, that the widget that interacts with
127 the rest of GTK must be referenced in m_widget and all other widgets must be
128 children of this widget on the GTK level. The top-most widget, which also
129 represents the client area, must be in the m_wxwindow field and must be of
132 As I said, the window classes that display a GTK native widget only have
133 one widget, so in the case of e.g. the wxButton class m_widget holds a
134 pointer to a GtkButton widget. But windows with client areas (for drawing
135 and children) have a m_widget field that is a pointer to a GtkScrolled-
136 Window and a m_wxwindow field that is pointer to a GtkPizza and this
137 one is (in the GTK sense) a child of the GtkScrolledWindow.
139 If the m_wxwindow field is set, then all input to this widget is inter-
140 cepted and sent to the wxWindows class. If not, all input to the widget
141 that gets pointed to by m_widget gets intercepted and sent to the class.
145 The design of scrolling in wxWindows is markedly different from that offered
146 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
147 clicking on a scrollbar belonging to scrolled window will inevitably move
148 the window. In wxWindows, the scrollbar will only emit an event, send this
149 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
150 which actually moves the window and its subchildren. Note that GtkPizza
151 memorizes how much it has been scrolled but that wxWindows forgets this
152 so that the two coordinates systems have to be kept in synch. This is done
153 in various places using the pizza->xoffset and pizza->yoffset values.
157 Singularily the most broken code in GTK is the code that is supposes to
158 inform subwindows (child windows) about new positions. Very often, duplicate
159 events are sent without changes in size or position, equally often no
160 events are sent at all (All this is due to a bug in the GtkContainer code
161 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
162 GTK's own system and it simply waits for size events for toplevel windows
163 and then iterates down the respective size events to all window. This has
164 the disadvantage, that windows might get size events before the GTK widget
165 actually has the reported size. This doesn't normally pose any problem, but
166 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
167 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
168 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
169 window that is used for OpenGl output really has that size (as reported by
174 If someone at some point of time feels the immense desire to have a look at,
175 change or attempt to optimse the Refresh() logic, this person will need an
176 intimate understanding of what a "draw" and what an "expose" events are and
177 what there are used for, in particular when used in connection with GTK's
178 own windowless widgets. Beware.
182 Cursors, too, have been a constant source of pleasure. The main difficulty
183 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
184 for the parent. To prevent this from doing too much harm, I use idle time
185 to set the cursor over and over again, starting from the toplevel windows
186 and ending with the youngest generation (speaking of parent and child windows).
187 Also don't forget that cursors (like much else) are connected to GdkWindows,
188 not GtkWidgets and that the "window" field of a GtkWidget might very well
189 point to the GdkWindow of the parent widget (-> "window less widget") and
190 that the two obviously have very different meanings.
194 //-----------------------------------------------------------------------------
196 //-----------------------------------------------------------------------------
198 extern wxList wxPendingDelete
;
199 extern bool g_blockEventsOnDrag
;
200 extern bool g_blockEventsOnScroll
;
201 extern wxCursor g_globalCursor
;
202 static wxWindow
*g_captureWindow
= (wxWindow
*) NULL
;
204 /* extern */ wxWindow
*g_focusWindow
= (wxWindow
*) NULL
;
206 // if we detect that the app has got/lost the focus, we set this variable to
207 // either TRUE or FALSE and an activate event will be sent during the next
208 // OnIdle() call and it is reset to -1: this value means that we shouldn't
209 // send any activate events at all
210 static int g_sendActivateEvent
= -1;
212 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
213 the last click here */
214 static guint32 gs_timeLastClick
= 0;
216 extern bool g_mainThreadLocked
;
218 //-----------------------------------------------------------------------------
220 //-----------------------------------------------------------------------------
222 #define DISABLE_STYLE_IF_BROKEN_THEME 1
227 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
229 # define DEBUG_MAIN_THREAD
232 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
233 GdkEvent
*WXUNUSED(event
),
234 const wxChar
*WXUNUSED(name
) )
237 static bool s_done = FALSE;
240 wxLog::AddTraceMask("focus");
243 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
249 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
251 // suppress warnings about gtk_debug_focus_in_callback being unused with
256 tmp
+= wxT(" FROM ");
259 wxChar
*s
= new wxChar
[tmp
.Length()+1];
263 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
264 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
269 #define DEBUG_MAIN_THREAD
272 //-----------------------------------------------------------------------------
273 // missing gdk functions
274 //-----------------------------------------------------------------------------
277 gdk_window_warp_pointer (GdkWindow
*window
,
282 GdkWindowPrivate
*priv
;
286 window
= GDK_ROOT_PARENT();
289 if (!GDK_WINDOW_DESTROYED(window
))
291 XWarpPointer (GDK_WINDOW_XDISPLAY(window
),
292 None
, /* not source window -> move from anywhere */
293 GDK_WINDOW_XID(window
), /* dest window */
294 0, 0, 0, 0, /* not source window -> move from anywhere */
298 priv
= (GdkWindowPrivate
*) window
;
300 if (!priv
->destroyed
)
302 XWarpPointer (priv
->xdisplay
,
303 None
, /* not source window -> move from anywhere */
304 priv
->xwindow
, /* dest window */
305 0, 0, 0, 0, /* not source window -> move from anywhere */
311 //-----------------------------------------------------------------------------
313 //-----------------------------------------------------------------------------
315 extern void wxapp_install_idle_handler();
316 extern bool g_isIdle
;
318 //-----------------------------------------------------------------------------
319 // local code (see below)
320 //-----------------------------------------------------------------------------
322 // returns the child of win which currently has focus or NULL if not found
323 static wxWindow
*FindFocusedChild(wxWindow
*win
)
325 wxWindow
*winFocus
= wxWindow::FindFocus();
327 return (wxWindow
*)NULL
;
329 if ( winFocus
== win
)
332 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
334 node
= node
->GetNext() )
336 wxWindow
*child
= FindFocusedChild(node
->GetData());
341 return (wxWindow
*)NULL
;
344 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
352 if (win
->m_hasScrolling
)
354 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
356 GtkRequisition vscroll_req
;
357 vscroll_req
.width
= 2;
358 vscroll_req
.height
= 2;
359 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
360 (scroll_window
->vscrollbar
, &vscroll_req
);
362 GtkRequisition hscroll_req
;
363 hscroll_req
.width
= 2;
364 hscroll_req
.height
= 2;
365 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
366 (scroll_window
->hscrollbar
, &hscroll_req
);
368 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) );
370 if (scroll_window
->vscrollbar_visible
)
372 dw
+= vscroll_req
.width
;
373 dw
+= scroll_class
->scrollbar_spacing
;
376 if (scroll_window
->hscrollbar_visible
)
378 dh
+= hscroll_req
.height
;
379 dh
+= scroll_class
->scrollbar_spacing
;
385 if (GTK_WIDGET_NO_WINDOW (widget
))
387 dx
+= widget
->allocation
.x
;
388 dy
+= widget
->allocation
.y
;
391 if (win
->HasFlag(wxRAISED_BORDER
))
393 gtk_draw_shadow( widget
->style
,
398 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
402 if (win
->HasFlag(wxSUNKEN_BORDER
))
404 gtk_draw_shadow( widget
->style
,
409 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
413 if (win
->HasFlag(wxSIMPLE_BORDER
))
416 gc
= gdk_gc_new( widget
->window
);
417 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
418 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
420 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
426 //-----------------------------------------------------------------------------
427 // "expose_event" of m_widget
428 //-----------------------------------------------------------------------------
430 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
432 if (gdk_event
->count
> 0) return FALSE
;
434 draw_frame( widget
, win
);
439 //-----------------------------------------------------------------------------
440 // "draw" of m_widget
441 //-----------------------------------------------------------------------------
443 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
445 draw_frame( widget
, win
);
448 //-----------------------------------------------------------------------------
449 // key code mapping routines
450 //-----------------------------------------------------------------------------
452 static long map_to_unmodified_wx_keysym( KeySym keysym
)
459 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
461 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
467 case GDK_Super_R
: key_code
= WXK_ALT
; break;
468 case GDK_Menu
: key_code
= WXK_MENU
; break;
469 case GDK_Help
: key_code
= WXK_HELP
; break;
470 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
471 case GDK_ISO_Left_Tab
:
472 case GDK_Tab
: key_code
= WXK_TAB
; break;
473 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
474 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
475 case GDK_Return
: key_code
= WXK_RETURN
; break;
476 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
477 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
478 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
479 case GDK_Delete
: key_code
= WXK_DELETE
; break;
480 case GDK_Home
: key_code
= WXK_HOME
; break;
481 case GDK_Left
: key_code
= WXK_LEFT
; break;
482 case GDK_Up
: key_code
= WXK_UP
; break;
483 case GDK_Right
: key_code
= WXK_RIGHT
; break;
484 case GDK_Down
: key_code
= WXK_DOWN
; break;
485 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
486 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
487 case GDK_Next
: key_code
= WXK_NEXT
; break;
488 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
489 case GDK_End
: key_code
= WXK_END
; break;
490 case GDK_Begin
: key_code
= WXK_HOME
; break;
491 case GDK_Select
: key_code
= WXK_SELECT
; break;
492 case GDK_Print
: key_code
= WXK_PRINT
; break;
493 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
494 case GDK_Insert
: key_code
= WXK_INSERT
; break;
495 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
497 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
498 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
499 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
500 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
501 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
502 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
503 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
504 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
505 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
506 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
507 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
508 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
509 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
510 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
511 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
512 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
513 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
514 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
515 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
516 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
517 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
518 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
519 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
520 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
521 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
522 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
523 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
524 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
525 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
526 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
527 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
528 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
529 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
530 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
531 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
532 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
533 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
535 case GDK_F1
: key_code
= WXK_F1
; break;
536 case GDK_F2
: key_code
= WXK_F2
; break;
537 case GDK_F3
: key_code
= WXK_F3
; break;
538 case GDK_F4
: key_code
= WXK_F4
; break;
539 case GDK_F5
: key_code
= WXK_F5
; break;
540 case GDK_F6
: key_code
= WXK_F6
; break;
541 case GDK_F7
: key_code
= WXK_F7
; break;
542 case GDK_F8
: key_code
= WXK_F8
; break;
543 case GDK_F9
: key_code
= WXK_F9
; break;
544 case GDK_F10
: key_code
= WXK_F10
; break;
545 case GDK_F11
: key_code
= WXK_F11
; break;
546 case GDK_F12
: key_code
= WXK_F12
; break;
549 if ((keysym
& 0xF000) == 0)
551 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
552 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
553 key_code
= (guint
)keysym
;
561 static long map_to_wx_keysym( KeySym keysym
)
567 case GDK_Menu
: key_code
= WXK_MENU
; break;
568 case GDK_Help
: key_code
= WXK_HELP
; break;
569 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
570 case GDK_ISO_Left_Tab
:
571 case GDK_Tab
: key_code
= WXK_TAB
; break;
572 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
573 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
574 case GDK_Return
: key_code
= WXK_RETURN
; break;
575 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
576 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
577 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
578 case GDK_Delete
: key_code
= WXK_DELETE
; break;
579 case GDK_Home
: key_code
= WXK_HOME
; break;
580 case GDK_Left
: key_code
= WXK_LEFT
; break;
581 case GDK_Up
: key_code
= WXK_UP
; break;
582 case GDK_Right
: key_code
= WXK_RIGHT
; break;
583 case GDK_Down
: key_code
= WXK_DOWN
; break;
584 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
585 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
586 case GDK_Next
: key_code
= WXK_NEXT
; break;
587 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
588 case GDK_End
: key_code
= WXK_END
; break;
589 case GDK_Begin
: key_code
= WXK_HOME
; break;
590 case GDK_Select
: key_code
= WXK_SELECT
; break;
591 case GDK_Print
: key_code
= WXK_PRINT
; break;
592 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
593 case GDK_Insert
: key_code
= WXK_INSERT
; break;
594 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
596 case GDK_KP_0
: key_code
= '0'; break;
597 case GDK_KP_1
: key_code
= '1'; break;
598 case GDK_KP_2
: key_code
= '2'; break;
599 case GDK_KP_3
: key_code
= '3'; break;
600 case GDK_KP_4
: key_code
= '4'; break;
601 case GDK_KP_5
: key_code
= '5'; break;
602 case GDK_KP_6
: key_code
= '6'; break;
603 case GDK_KP_7
: key_code
= '7'; break;
604 case GDK_KP_8
: key_code
= '8'; break;
605 case GDK_KP_9
: key_code
= '9'; break;
606 case GDK_KP_Space
: key_code
= ' '; break;
607 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
608 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
609 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
610 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
611 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
612 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
613 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
614 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
615 case GDK_KP_Up
: key_code
= WXK_UP
; break;
616 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
617 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
618 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
619 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
620 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
621 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
622 case GDK_KP_End
: key_code
= WXK_END
; break;
623 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
624 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
625 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
626 case GDK_KP_Equal
: key_code
= '='; break;
627 case GDK_KP_Multiply
: key_code
= '*'; break;
628 case GDK_KP_Add
: key_code
= '+'; break;
629 case GDK_KP_Separator
: key_code
= ','; break;
630 case GDK_KP_Subtract
: key_code
= '-'; break;
631 case GDK_KP_Decimal
: key_code
= '.'; break;
632 case GDK_KP_Divide
: key_code
= '/'; break;
634 case GDK_F1
: key_code
= WXK_F1
; break;
635 case GDK_F2
: key_code
= WXK_F2
; break;
636 case GDK_F3
: key_code
= WXK_F3
; break;
637 case GDK_F4
: key_code
= WXK_F4
; break;
638 case GDK_F5
: key_code
= WXK_F5
; break;
639 case GDK_F6
: key_code
= WXK_F6
; break;
640 case GDK_F7
: key_code
= WXK_F7
; break;
641 case GDK_F8
: key_code
= WXK_F8
; break;
642 case GDK_F9
: key_code
= WXK_F9
; break;
643 case GDK_F10
: key_code
= WXK_F10
; break;
644 case GDK_F11
: key_code
= WXK_F11
; break;
645 case GDK_F12
: key_code
= WXK_F12
; break;
648 if ((keysym
& 0xF000) == 0)
650 key_code
= (guint
)keysym
;
658 //-----------------------------------------------------------------------------
659 // "expose_event" of m_wxwindow
660 //-----------------------------------------------------------------------------
662 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
667 wxapp_install_idle_handler();
670 if (win->GetName() == wxT("panel"))
672 wxPrintf( wxT("OnExpose from ") );
673 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
674 wxPrintf( win->GetClassInfo()->GetClassName() );
675 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
676 (int)gdk_event->area.y,
677 (int)gdk_event->area.width,
678 (int)gdk_event->area.height );
682 GtkPizza
*pizza
= GTK_PIZZA (widget
);
684 if (win
->GetThemeEnabled())
686 wxWindow
*parent
= win
->GetParent();
687 while (parent
&& !parent
->IsTopLevel())
688 parent
= parent
->GetParent();
692 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
693 GTK_SHADOW_NONE
, &gdk_event
->area
, parent
->m_widget
, "base", 0, 0, -1, -1);
696 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
698 gdk_event
->area
.width
,
699 gdk_event
->area
.height
);
701 if (gdk_event
->count
== 0)
703 wxEraseEvent
eevent( win
->GetId() );
704 eevent
.SetEventObject( win
);
705 win
->GetEventHandler()->ProcessEvent(eevent
);
707 wxPaintEvent
event( win
->GetId() );
708 event
.SetEventObject( win
);
709 win
->GetEventHandler()->ProcessEvent( event
);
711 win
->GetUpdateRegion().Clear();
714 /* The following code will result in all window-less widgets
715 being redrawn if the wxWindows class is given a chance to
716 paint *anything* because it will then be allowed to paint
717 over the window-less widgets */
719 GList
*children
= pizza
->children
;
722 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
723 children
= children
->next
;
725 GdkEventExpose child_event
= *gdk_event
;
727 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
728 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
729 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
731 child_event
.area
.x
= child
->widget
->allocation
.x
;
732 child_event
.area
.y
= child
->widget
->allocation
.y
;
733 child_event
.area
.width
= child
->widget
->allocation
.width
;
734 child_event
.area
.height
= child
->widget
->allocation
.height
;
735 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
742 //-----------------------------------------------------------------------------
743 // "event" of m_wxwindow
744 //-----------------------------------------------------------------------------
746 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
747 expose events. We need them, of course, so we override the main event
748 procedure in GtkWidget by giving our own handler for all system events.
749 There, we look for expose events ourselves whereas all other events are
752 gint
gtk_window_event_event_callback( GtkWidget
*widget
, GdkEventExpose
*event
, wxWindow
*win
)
754 if (event
->type
== GDK_EXPOSE
)
756 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
763 //-----------------------------------------------------------------------------
764 // "draw" of m_wxwindow
765 //-----------------------------------------------------------------------------
767 /* This callback is a complete replacement of the gtk_pizza_draw() function,
770 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
775 wxapp_install_idle_handler();
777 // this is supposed to take care of extra (and unneeded) frame repaints
778 if (win
->GetChildren().GetCount() == 0)
782 if (win->GetName() == wxT("panel"))
784 wxPrintf( wxT("OnDraw from ") );
785 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
786 wxPrintf( win->GetClassInfo()->GetClassName() );
787 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
794 GtkPizza
*pizza
= GTK_PIZZA (widget
);
796 if (win
->GetThemeEnabled())
798 wxWindow
*parent
= win
->GetParent();
799 while (parent
&& !parent
->IsTopLevel())
800 parent
= parent
->GetParent();
804 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
805 GTK_SHADOW_NONE
, rect
, parent
->m_widget
, "base", 0, 0, -1, -1);
809 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
810 (pizza
->clear_on_draw
))
812 gdk_window_clear_area( pizza
->bin_window
,
813 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
816 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
818 win
->m_clipPaintRegion
= TRUE
;
820 wxEraseEvent
eevent( win
->GetId() );
821 eevent
.SetEventObject( win
);
822 win
->GetEventHandler()->ProcessEvent(eevent
);
824 wxPaintEvent
event( win
->GetId() );
825 event
.SetEventObject( win
);
826 win
->GetEventHandler()->ProcessEvent( event
);
828 win
->GetUpdateRegion().Clear();
830 win
->m_clipPaintRegion
= FALSE
;
833 GList
*children
= pizza
->children
;
836 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
837 children
= children
->next
;
839 GdkRectangle child_area
;
840 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
842 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
847 //-----------------------------------------------------------------------------
848 // "key_press_event" from any window
849 //-----------------------------------------------------------------------------
851 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
856 wxapp_install_idle_handler();
858 if (!win
->m_hasVMT
) return FALSE
;
859 if (g_blockEventsOnDrag
) return FALSE
;
864 tmp += (char)gdk_event->keyval;
865 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
866 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
871 GdkModifierType state
;
872 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
876 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
877 /* sending unknown key events doesn't really make sense */
878 if (key_code
== 0) return FALSE
;
880 wxKeyEvent
event( wxEVT_KEY_DOWN
);
881 event
.SetTimestamp( gdk_event
->time
);
882 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
883 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
884 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
885 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
886 event
.m_keyCode
= key_code
;
887 event
.m_scanCode
= gdk_event
->keyval
;
890 event
.SetEventObject( win
);
891 ret
= win
->GetEventHandler()->ProcessEvent( event
);
896 wxWindow
*ancestor
= win
;
899 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
902 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
903 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
906 if (ancestor
->IsTopLevel())
908 ancestor
= ancestor
->GetParent();
911 #endif // wxUSE_ACCEL
913 /* wxMSW doesn't send char events with Alt pressed */
914 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
915 will only be sent if it is not in an accelerator table. */
916 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
921 wxKeyEvent
event2( wxEVT_CHAR
);
922 event2
.SetTimestamp( gdk_event
->time
);
923 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
924 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
925 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
926 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
927 event2
.m_keyCode
= key_code
;
928 event2
.m_scanCode
= gdk_event
->keyval
;
931 event2
.SetEventObject( win
);
932 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
935 /* win is a control: tab can be propagated up */
937 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
938 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
939 // have this style, yet choose not to process this particular TAB in which
940 // case TAB must still work as a navigational character
942 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
944 (win
->GetParent()) &&
945 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
947 wxNavigationKeyEvent new_event
;
948 new_event
.SetEventObject( win
->GetParent() );
949 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
950 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
951 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
952 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
953 new_event
.SetCurrentFocus( win
);
954 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
957 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
959 (gdk_event
->keyval
== GDK_Escape
) )
961 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
962 new_event
.SetEventObject( win
);
963 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
966 #if (GTK_MINOR_VERSION > 0)
967 /* Pressing F10 will activate the menu bar of the top frame. */
971 (gdk_event->keyval == GDK_F10) )
973 wxWindow *ancestor = win;
976 if (wxIsKindOf(ancestor,wxFrame))
978 wxFrame *frame = (wxFrame*) ancestor;
979 wxMenuBar *menubar = frame->GetMenuBar();
982 wxNode *node = menubar->GetMenus().First();
985 wxMenu *firstMenu = (wxMenu*) node->Data();
986 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
992 ancestor = ancestor->GetParent();
1000 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1007 //-----------------------------------------------------------------------------
1008 // "key_release_event" from any window
1009 //-----------------------------------------------------------------------------
1011 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
1016 wxapp_install_idle_handler();
1018 if (!win
->m_hasVMT
) return FALSE
;
1019 if (g_blockEventsOnDrag
) return FALSE
;
1022 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
1023 if (gdk_event->state & GDK_SHIFT_MASK)
1024 printf( "ShiftDown.\n" );
1026 printf( "ShiftUp.\n" );
1027 if (gdk_event->state & GDK_CONTROL_MASK)
1028 printf( "ControlDown.\n" );
1030 printf( "ControlUp.\n" );
1034 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
1036 /* sending unknown key events doesn't really make sense */
1037 if (key_code
== 0) return FALSE
;
1041 GdkModifierType state
;
1042 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1044 wxKeyEvent
event( wxEVT_KEY_UP
);
1045 event
.SetTimestamp( gdk_event
->time
);
1046 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1047 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1048 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1049 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1050 event
.m_keyCode
= key_code
;
1051 event
.m_scanCode
= gdk_event
->keyval
;
1054 event
.SetEventObject( win
);
1056 if (win
->GetEventHandler()->ProcessEvent( event
))
1058 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1065 // ----------------------------------------------------------------------------
1066 // mouse event processing helper
1067 // ----------------------------------------------------------------------------
1069 static void AdjustEventButtonState(wxMouseEvent
& event
)
1071 // GDK reports the old state of the button for a button press event, but
1072 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1073 // for a LEFT_DOWN event, not FALSE, so we will invert
1074 // left/right/middleDown for the corresponding click events
1075 switch ( event
.GetEventType() )
1077 case wxEVT_LEFT_DOWN
:
1078 case wxEVT_LEFT_DCLICK
:
1080 event
.m_leftDown
= !event
.m_leftDown
;
1083 case wxEVT_MIDDLE_DOWN
:
1084 case wxEVT_MIDDLE_DCLICK
:
1085 case wxEVT_MIDDLE_UP
:
1086 event
.m_middleDown
= !event
.m_middleDown
;
1089 case wxEVT_RIGHT_DOWN
:
1090 case wxEVT_RIGHT_DCLICK
:
1091 case wxEVT_RIGHT_UP
:
1092 event
.m_rightDown
= !event
.m_rightDown
;
1097 //-----------------------------------------------------------------------------
1098 // "button_press_event"
1099 //-----------------------------------------------------------------------------
1101 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1106 wxapp_install_idle_handler();
1109 wxPrintf( wxT("1) OnButtonPress from ") );
1110 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1111 wxPrintf( win->GetClassInfo()->GetClassName() );
1112 wxPrintf( wxT(".\n") );
1114 if (!win
->m_hasVMT
) return FALSE
;
1115 if (g_blockEventsOnDrag
) return TRUE
;
1116 if (g_blockEventsOnScroll
) return TRUE
;
1118 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1120 if (win
->m_wxwindow
)
1122 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1124 gtk_widget_grab_focus (win
->m_wxwindow
);
1127 wxPrintf( wxT("GrabFocus from ") );
1128 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1129 wxPrintf( win->GetClassInfo()->GetClassName() );
1130 wxPrintf( wxT(".\n") );
1136 wxEventType event_type
= wxEVT_NULL
;
1138 if (gdk_event
->button
== 1)
1140 switch (gdk_event
->type
)
1142 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1143 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1147 else if (gdk_event
->button
== 2)
1149 switch (gdk_event
->type
)
1151 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1152 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1156 else if (gdk_event
->button
== 3)
1158 switch (gdk_event
->type
)
1160 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1161 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1166 if ( event_type
== wxEVT_NULL
)
1168 // unknown mouse button or click type
1172 wxMouseEvent
event( event_type
);
1173 event
.SetTimestamp( gdk_event
->time
);
1174 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1175 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1176 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1177 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1178 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1179 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1180 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1182 event
.m_x
= (wxCoord
)gdk_event
->x
;
1183 event
.m_y
= (wxCoord
)gdk_event
->y
;
1185 AdjustEventButtonState(event
);
1187 // Some control don't have their own X window and thus cannot get
1190 if (!g_captureWindow
)
1192 wxCoord x
= event
.m_x
;
1193 wxCoord y
= event
.m_y
;
1194 if (win
->m_wxwindow
)
1196 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1197 x
+= pizza
->xoffset
;
1198 y
+= pizza
->yoffset
;
1201 wxNode
*node
= win
->GetChildren().First();
1204 wxWindow
*child
= (wxWindow
*)node
->Data();
1206 node
= node
->Next();
1207 if (!child
->IsShown())
1210 if (child
->m_isStaticBox
)
1212 // wxStaticBox is transparent in the box itself
1213 int xx1
= child
->m_x
;
1214 int yy1
= child
->m_y
;
1215 int xx2
= child
->m_x
+ child
->m_width
;
1216 int yy2
= child
->m_x
+ child
->m_height
;
1219 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1221 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1223 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1225 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1228 event
.m_x
-= child
->m_x
;
1229 event
.m_y
-= child
->m_y
;
1236 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1237 (child
->m_x
<= x
) &&
1238 (child
->m_y
<= y
) &&
1239 (child
->m_x
+child
->m_width
>= x
) &&
1240 (child
->m_y
+child
->m_height
>= y
))
1243 event
.m_x
-= child
->m_x
;
1244 event
.m_y
-= child
->m_y
;
1251 event
.SetEventObject( win
);
1253 gs_timeLastClick
= gdk_event
->time
;
1256 wxPrintf( wxT("2) OnButtonPress from ") );
1257 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1258 wxPrintf( win->GetClassInfo()->GetClassName() );
1259 wxPrintf( wxT(".\n") );
1262 if (win
->GetEventHandler()->ProcessEvent( event
))
1264 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1271 //-----------------------------------------------------------------------------
1272 // "button_release_event"
1273 //-----------------------------------------------------------------------------
1275 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1280 wxapp_install_idle_handler();
1282 if (!win
->m_hasVMT
) return FALSE
;
1283 if (g_blockEventsOnDrag
) return FALSE
;
1284 if (g_blockEventsOnScroll
) return FALSE
;
1286 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1289 printf( "OnButtonRelease from " );
1290 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1291 printf( win->GetClassInfo()->GetClassName() );
1295 wxEventType event_type
= wxEVT_NULL
;
1297 switch (gdk_event
->button
)
1299 case 1: event_type
= wxEVT_LEFT_UP
; break;
1300 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1301 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1302 default: return FALSE
;
1305 wxMouseEvent
event( event_type
);
1306 event
.SetTimestamp( gdk_event
->time
);
1307 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1308 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1309 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1310 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1311 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1312 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1313 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1314 event
.m_x
= (wxCoord
)gdk_event
->x
;
1315 event
.m_y
= (wxCoord
)gdk_event
->y
;
1317 AdjustEventButtonState(event
);
1319 // Some control don't have their own X window and thus cannot get
1322 if (!g_captureWindow
)
1324 wxCoord x
= event
.m_x
;
1325 wxCoord y
= event
.m_y
;
1326 if (win
->m_wxwindow
)
1328 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1329 x
+= pizza
->xoffset
;
1330 y
+= pizza
->yoffset
;
1333 wxNode
*node
= win
->GetChildren().First();
1336 wxWindow
*child
= (wxWindow
*)node
->Data();
1338 node
= node
->Next();
1339 if (!child
->IsShown())
1342 if (child
->m_isStaticBox
)
1344 // wxStaticBox is transparent in the box itself
1345 int xx1
= child
->m_x
;
1346 int yy1
= child
->m_y
;
1347 int xx2
= child
->m_x
+ child
->m_width
;
1348 int yy2
= child
->m_x
+ child
->m_height
;
1351 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1353 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1355 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1357 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1360 event
.m_x
-= child
->m_x
;
1361 event
.m_y
-= child
->m_y
;
1368 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1369 (child
->m_x
<= x
) &&
1370 (child
->m_y
<= y
) &&
1371 (child
->m_x
+child
->m_width
>= x
) &&
1372 (child
->m_y
+child
->m_height
>= y
))
1375 event
.m_x
-= child
->m_x
;
1376 event
.m_y
-= child
->m_y
;
1383 event
.SetEventObject( win
);
1385 if (win
->GetEventHandler()->ProcessEvent( event
))
1387 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1394 //-----------------------------------------------------------------------------
1395 // "motion_notify_event"
1396 //-----------------------------------------------------------------------------
1398 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1403 wxapp_install_idle_handler();
1405 if (!win
->m_hasVMT
) return FALSE
;
1406 if (g_blockEventsOnDrag
) return FALSE
;
1407 if (g_blockEventsOnScroll
) return FALSE
;
1409 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1411 if (gdk_event
->is_hint
)
1415 GdkModifierType state
;
1416 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1422 printf( "OnMotion from " );
1423 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1424 printf( win->GetClassInfo()->GetClassName() );
1428 wxMouseEvent
event( wxEVT_MOTION
);
1429 event
.SetTimestamp( gdk_event
->time
);
1430 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1431 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1432 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1433 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1434 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1435 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1436 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1438 event
.m_x
= (wxCoord
)gdk_event
->x
;
1439 event
.m_y
= (wxCoord
)gdk_event
->y
;
1441 // Some control don't have their own X window and thus cannot get
1444 if (!g_captureWindow
)
1446 wxCoord x
= event
.m_x
;
1447 wxCoord y
= event
.m_y
;
1448 if (win
->m_wxwindow
)
1450 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1451 x
+= pizza
->xoffset
;
1452 y
+= pizza
->yoffset
;
1455 wxNode
*node
= win
->GetChildren().First();
1458 wxWindow
*child
= (wxWindow
*)node
->Data();
1460 node
= node
->Next();
1461 if (!child
->IsShown())
1464 if (child
->m_isStaticBox
)
1466 // wxStaticBox is transparent in the box itself
1467 int xx1
= child
->m_x
;
1468 int yy1
= child
->m_y
;
1469 int xx2
= child
->m_x
+ child
->m_width
;
1470 int yy2
= child
->m_x
+ child
->m_height
;
1473 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1475 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1477 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1479 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1482 event
.m_x
-= child
->m_x
;
1483 event
.m_y
-= child
->m_y
;
1490 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1491 (child
->m_x
<= x
) &&
1492 (child
->m_y
<= y
) &&
1493 (child
->m_x
+child
->m_width
>= x
) &&
1494 (child
->m_y
+child
->m_height
>= y
))
1497 event
.m_x
-= child
->m_x
;
1498 event
.m_y
-= child
->m_y
;
1505 event
.SetEventObject( win
);
1507 if (win
->GetEventHandler()->ProcessEvent( event
))
1509 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1516 //-----------------------------------------------------------------------------
1518 //-----------------------------------------------------------------------------
1520 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1525 wxapp_install_idle_handler();
1527 if (!win
->m_hasVMT
) return FALSE
;
1528 if (g_blockEventsOnDrag
) return FALSE
;
1530 switch ( g_sendActivateEvent
)
1533 // we've got focus from outside, synthtize wxActivateEvent
1534 g_sendActivateEvent
= 1;
1538 // another our window just lost focus, it was already ours before
1539 // - don't send any wxActivateEvent
1540 g_sendActivateEvent
= -1;
1544 g_focusWindow
= win
;
1547 printf( "OnSetFocus from " );
1548 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1549 printf( win->GetClassInfo()->GetClassName() );
1551 printf( WXSTRINGCAST win->GetLabel() );
1555 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1558 panel
->SetLastFocus(win
);
1563 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1567 // caret needs to be informed about focus change
1568 wxCaret
*caret
= win
->GetCaret();
1571 caret
->OnSetFocus();
1573 #endif // wxUSE_CARET
1575 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1576 event
.SetEventObject( win
);
1578 if (win
->GetEventHandler()->ProcessEvent( event
))
1580 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1587 //-----------------------------------------------------------------------------
1588 // "focus_out_event"
1589 //-----------------------------------------------------------------------------
1591 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1596 wxapp_install_idle_handler();
1598 if (!win
->m_hasVMT
) return FALSE
;
1599 if (g_blockEventsOnDrag
) return FALSE
;
1601 // if the focus goes out of our app alltogether, OnIdle() will send
1602 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1603 // g_sendActivateEvent to -1
1604 g_sendActivateEvent
= 0;
1606 wxWindow
*winFocus
= FindFocusedChild(win
);
1610 g_focusWindow
= (wxWindow
*)NULL
;
1613 printf( "OnKillFocus from " );
1614 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1615 printf( win->GetClassInfo()->GetClassName() );
1625 // caret needs to be informed about focus change
1626 wxCaret
*caret
= win
->GetCaret();
1629 caret
->OnKillFocus();
1631 #endif // wxUSE_CARET
1633 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1634 event
.SetEventObject( win
);
1636 if (win
->GetEventHandler()->ProcessEvent( event
))
1638 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1645 //-----------------------------------------------------------------------------
1646 // "enter_notify_event"
1647 //-----------------------------------------------------------------------------
1649 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1654 wxapp_install_idle_handler();
1656 if (!win
->m_hasVMT
) return FALSE
;
1657 if (g_blockEventsOnDrag
) return FALSE
;
1659 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1661 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1662 #if (GTK_MINOR_VERSION > 0)
1663 event
.SetTimestamp( gdk_event
->time
);
1665 event
.SetEventObject( win
);
1669 GdkModifierType state
= (GdkModifierType
)0;
1671 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1673 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1674 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1675 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1676 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1677 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1678 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1679 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1684 if (win
->GetEventHandler()->ProcessEvent( event
))
1686 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1693 //-----------------------------------------------------------------------------
1694 // "leave_notify_event"
1695 //-----------------------------------------------------------------------------
1697 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1702 wxapp_install_idle_handler();
1704 if (!win
->m_hasVMT
) return FALSE
;
1705 if (g_blockEventsOnDrag
) return FALSE
;
1707 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1709 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1710 #if (GTK_MINOR_VERSION > 0)
1711 event
.SetTimestamp( gdk_event
->time
);
1713 event
.SetEventObject( win
);
1717 GdkModifierType state
= (GdkModifierType
)0;
1719 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1721 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1722 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1723 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1724 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1725 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1726 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1727 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1732 if (win
->GetEventHandler()->ProcessEvent( event
))
1734 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1741 //-----------------------------------------------------------------------------
1742 // "value_changed" from m_vAdjust
1743 //-----------------------------------------------------------------------------
1745 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1750 wxapp_install_idle_handler();
1752 if (g_blockEventsOnDrag
) return;
1754 if (!win
->m_hasVMT
) return;
1756 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1757 if (fabs(diff
) < 0.2) return;
1759 win
->m_oldVerticalPos
= adjust
->value
;
1761 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1762 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1764 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1765 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1766 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1767 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1768 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1770 int value
= (int)(adjust
->value
+0.5);
1772 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1773 event
.SetEventObject( win
);
1774 win
->GetEventHandler()->ProcessEvent( event
);
1777 //-----------------------------------------------------------------------------
1778 // "value_changed" from m_hAdjust
1779 //-----------------------------------------------------------------------------
1781 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1786 wxapp_install_idle_handler();
1788 if (g_blockEventsOnDrag
) return;
1789 if (!win
->m_hasVMT
) return;
1791 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1792 if (fabs(diff
) < 0.2) return;
1794 win
->m_oldHorizontalPos
= adjust
->value
;
1796 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1797 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1799 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1800 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1801 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1802 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1803 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1805 int value
= (int)(adjust
->value
+0.5);
1807 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1808 event
.SetEventObject( win
);
1809 win
->GetEventHandler()->ProcessEvent( event
);
1812 //-----------------------------------------------------------------------------
1813 // "button_press_event" from scrollbar
1814 //-----------------------------------------------------------------------------
1816 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1817 GdkEventButton
*gdk_event
,
1823 wxapp_install_idle_handler();
1826 g_blockEventsOnScroll
= TRUE
;
1827 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1832 //-----------------------------------------------------------------------------
1833 // "button_release_event" from scrollbar
1834 //-----------------------------------------------------------------------------
1836 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1837 GdkEventButton
*WXUNUSED(gdk_event
),
1842 // don't test here as we can release the mouse while being over
1843 // a different window than the slider
1845 // if (gdk_event->window != widget->slider) return FALSE;
1847 g_blockEventsOnScroll
= FALSE
;
1849 if (win
->m_isScrolling
)
1851 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
1855 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1856 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1858 value
= (int)(win
->m_hAdjust
->value
+0.5);
1861 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1863 value
= (int)(win
->m_vAdjust
->value
+0.5);
1867 wxScrollWinEvent
event( command
, value
, dir
);
1868 event
.SetEventObject( win
);
1869 win
->GetEventHandler()->ProcessEvent( event
);
1872 win
->m_isScrolling
= FALSE
;
1877 // ----------------------------------------------------------------------------
1878 // this wxWindowBase function is implemented here (in platform-specific file)
1879 // because it is static and so couldn't be made virtual
1880 // ----------------------------------------------------------------------------
1882 wxWindow
*wxWindowBase::FindFocus()
1884 return g_focusWindow
;
1887 //-----------------------------------------------------------------------------
1888 // "realize" from m_widget
1889 //-----------------------------------------------------------------------------
1891 /* We cannot set colours and fonts before the widget has
1892 been realized, so we do this directly after realization. */
1895 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1900 wxapp_install_idle_handler();
1902 if (win
->m_delayedBackgroundColour
)
1903 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1905 if (win
->m_delayedForegroundColour
)
1906 win
->SetForegroundColour( win
->GetForegroundColour() );
1908 wxWindowCreateEvent
event( win
);
1909 event
.SetEventObject( win
);
1910 win
->GetEventHandler()->ProcessEvent( event
);
1915 //-----------------------------------------------------------------------------
1917 //-----------------------------------------------------------------------------
1920 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
1921 GtkAllocation
*WXUNUSED(alloc
),
1925 wxapp_install_idle_handler();
1927 if (!win
->m_hasScrolling
) return;
1929 int client_width
= 0;
1930 int client_height
= 0;
1931 win
->GetClientSize( &client_width
, &client_height
);
1932 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
1935 win
->m_oldClientWidth
= client_width
;
1936 win
->m_oldClientHeight
= client_height
;
1938 if (!win
->m_nativeSizeEvent
)
1940 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
1941 event
.SetEventObject( win
);
1942 win
->GetEventHandler()->ProcessEvent( event
);
1948 #define WXUNUSED_UNLESS_XIM(param) param
1950 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1953 /* Resize XIM window */
1956 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1957 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1958 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1961 wxapp_install_idle_handler();
1967 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1971 gdk_window_get_size (widget
->window
, &width
, &height
);
1972 win
->m_icattr
->preedit_area
.width
= width
;
1973 win
->m_icattr
->preedit_area
.height
= height
;
1974 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
1979 //-----------------------------------------------------------------------------
1980 // "realize" from m_wxwindow
1981 //-----------------------------------------------------------------------------
1983 /* Initialize XIM support */
1986 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1987 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1990 wxapp_install_idle_handler();
1993 if (win
->m_ic
) return FALSE
;
1994 if (!widget
) return FALSE
;
1995 if (!gdk_im_ready()) return FALSE
;
1997 win
->m_icattr
= gdk_ic_attr_new();
1998 if (!win
->m_icattr
) return FALSE
;
2002 GdkColormap
*colormap
;
2003 GdkICAttr
*attr
= win
->m_icattr
;
2004 unsigned attrmask
= GDK_IC_ALL_REQ
;
2006 GdkIMStyle supported_style
= (GdkIMStyle
)
2007 (GDK_IM_PREEDIT_NONE
|
2008 GDK_IM_PREEDIT_NOTHING
|
2009 GDK_IM_PREEDIT_POSITION
|
2010 GDK_IM_STATUS_NONE
|
2011 GDK_IM_STATUS_NOTHING
);
2013 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2014 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2016 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2017 attr
->client_window
= widget
->window
;
2019 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2020 gtk_widget_get_default_colormap ())
2022 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2023 attr
->preedit_colormap
= colormap
;
2026 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2027 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2028 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2029 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2031 switch (style
& GDK_IM_PREEDIT_MASK
)
2033 case GDK_IM_PREEDIT_POSITION
:
2034 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2036 g_warning ("over-the-spot style requires fontset");
2040 gdk_window_get_size (widget
->window
, &width
, &height
);
2042 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2043 attr
->spot_location
.x
= 0;
2044 attr
->spot_location
.y
= height
;
2045 attr
->preedit_area
.x
= 0;
2046 attr
->preedit_area
.y
= 0;
2047 attr
->preedit_area
.width
= width
;
2048 attr
->preedit_area
.height
= height
;
2049 attr
->preedit_fontset
= widget
->style
->font
;
2054 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2056 if (win
->m_ic
== NULL
)
2057 g_warning ("Can't create input context.");
2060 mask
= gdk_window_get_events (widget
->window
);
2061 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2062 gdk_window_set_events (widget
->window
, mask
);
2064 if (GTK_WIDGET_HAS_FOCUS(widget
))
2065 gdk_im_begin (win
->m_ic
, widget
->window
);
2072 //-----------------------------------------------------------------------------
2073 // InsertChild for wxWindow.
2074 //-----------------------------------------------------------------------------
2076 /* Callback for wxWindow. This very strange beast has to be used because
2077 * C++ has no virtual methods in a constructor. We have to emulate a
2078 * virtual function here as wxNotebook requires a different way to insert
2079 * a child in it. I had opted for creating a wxNotebookPage window class
2080 * which would have made this superfluous (such in the MDI window system),
2081 * but no-one was listening to me... */
2083 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
2085 /* the window might have been scrolled already, do we
2086 have to adapt the position */
2087 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2088 child
->m_x
+= pizza
->xoffset
;
2089 child
->m_y
+= pizza
->yoffset
;
2091 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2092 GTK_WIDGET(child
->m_widget
),
2099 //-----------------------------------------------------------------------------
2101 //-----------------------------------------------------------------------------
2103 wxWindow
* wxGetActiveWindow()
2105 return g_focusWindow
;
2108 //-----------------------------------------------------------------------------
2110 //-----------------------------------------------------------------------------
2112 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2114 void wxWindow::Init()
2120 m_widget
= (GtkWidget
*) NULL
;
2121 m_wxwindow
= (GtkWidget
*) NULL
;
2131 m_needParent
= TRUE
;
2132 m_isBeingDeleted
= FALSE
;
2135 m_nativeSizeEvent
= FALSE
;
2137 m_hasScrolling
= FALSE
;
2138 m_isScrolling
= FALSE
;
2140 m_hAdjust
= (GtkAdjustment
*) NULL
;
2141 m_vAdjust
= (GtkAdjustment
*) NULL
;
2142 m_oldHorizontalPos
= 0.0;
2143 m_oldVerticalPos
= 0.0;
2146 m_widgetStyle
= (GtkStyle
*) NULL
;
2148 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2150 m_isStaticBox
= FALSE
;
2151 m_isRadioButton
= FALSE
;
2153 m_acceptsFocus
= FALSE
;
2155 m_clipPaintRegion
= FALSE
;
2157 m_cursor
= *wxSTANDARD_CURSOR
;
2159 m_delayedForegroundColour
= FALSE
;
2160 m_delayedBackgroundColour
= FALSE
;
2163 m_ic
= (GdkIC
*) NULL
;
2164 m_icattr
= (GdkICAttr
*) NULL
;
2168 wxWindow::wxWindow()
2173 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
2174 const wxPoint
&pos
, const wxSize
&size
,
2175 long style
, const wxString
&name
)
2179 Create( parent
, id
, pos
, size
, style
, name
);
2182 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
2183 const wxPoint
&pos
, const wxSize
&size
,
2184 long style
, const wxString
&name
)
2186 if (!PreCreation( parent
, pos
, size
) ||
2187 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2189 wxFAIL_MSG( wxT("wxWindow creation failed") );
2193 m_insertCallback
= wxInsertChildInWindow
;
2195 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2196 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2198 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2200 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2201 scroll_class
->scrollbar_spacing
= 0;
2203 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2205 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2206 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2208 m_wxwindow
= gtk_pizza_new();
2210 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2212 #if (GTK_MINOR_VERSION > 0)
2213 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2215 if (HasFlag(wxRAISED_BORDER
))
2217 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2219 else if (HasFlag(wxSUNKEN_BORDER
))
2221 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2223 else if (HasFlag(wxSIMPLE_BORDER
))
2225 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2229 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2231 #else // GTK_MINOR_VERSION == 0
2232 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2234 if (HasFlag(wxRAISED_BORDER
))
2236 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2238 else if (HasFlag(wxSUNKEN_BORDER
))
2240 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2244 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2246 #endif // GTK_MINOR_VERSION
2248 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2249 m_acceptsFocus
= TRUE
;
2251 #if (GTK_MINOR_VERSION == 0)
2252 // shut the viewport up
2253 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2254 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2255 #endif // GTK_MINOR_VERSION == 0
2257 // I _really_ don't want scrollbars in the beginning
2258 m_vAdjust
->lower
= 0.0;
2259 m_vAdjust
->upper
= 1.0;
2260 m_vAdjust
->value
= 0.0;
2261 m_vAdjust
->step_increment
= 1.0;
2262 m_vAdjust
->page_increment
= 1.0;
2263 m_vAdjust
->page_size
= 5.0;
2264 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2265 m_hAdjust
->lower
= 0.0;
2266 m_hAdjust
->upper
= 1.0;
2267 m_hAdjust
->value
= 0.0;
2268 m_hAdjust
->step_increment
= 1.0;
2269 m_hAdjust
->page_increment
= 1.0;
2270 m_hAdjust
->page_size
= 5.0;
2271 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2273 // these handlers block mouse events to any window during scrolling such as
2274 // motion events and prevent GTK and wxWindows from fighting over where the
2277 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2278 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2280 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2281 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2283 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2284 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2286 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2287 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2289 // these handlers get notified when screen updates are required either when
2290 // scrolling or when the window size (and therefore scrollbar configuration)
2293 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2294 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2295 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2296 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2298 gtk_widget_show( m_wxwindow
);
2301 m_parent
->DoAddChild( this );
2310 wxWindow::~wxWindow()
2312 m_isBeingDeleted
= TRUE
;
2321 m_parent
->RemoveChild( this );
2325 gdk_ic_destroy (m_ic
);
2327 gdk_ic_attr_destroy (m_icattr
);
2332 #if DISABLE_STYLE_IF_BROKEN_THEME
2333 // don't delete if it's a pixmap theme style
2334 if (!m_widgetStyle
->engine_data
)
2335 gtk_style_unref( m_widgetStyle
);
2337 m_widgetStyle
= (GtkStyle
*) NULL
;
2342 gtk_widget_destroy( m_wxwindow
);
2343 m_wxwindow
= (GtkWidget
*) NULL
;
2348 gtk_widget_destroy( m_widget
);
2349 m_widget
= (GtkWidget
*) NULL
;
2353 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2355 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2357 /* this turns -1 into 20 so that a minimal window is
2358 visible even although -1,-1 has been given as the
2359 size of the window. the same trick is used in other
2360 ports and should make debugging easier */
2361 m_width
= WidthDefault(size
.x
);
2362 m_height
= HeightDefault(size
.y
);
2367 /* some reasonable defaults */
2372 m_x
= (gdk_screen_width () - m_width
) / 2;
2373 if (m_x
< 10) m_x
= 10;
2377 m_y
= (gdk_screen_height () - m_height
) / 2;
2378 if (m_y
< 10) m_y
= 10;
2385 void wxWindow::PostCreation()
2387 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2393 /* these get reported to wxWindows -> wxPaintEvent */
2395 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2397 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2398 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2400 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2401 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2403 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2404 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2407 #if (GTK_MINOR_VERSION > 0)
2408 /* these are called when the "sunken" or "raised" borders are drawn */
2409 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2410 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2412 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2413 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2417 if (m_wxwindow
&& m_needParent
)
2419 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2420 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2422 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2423 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2427 // For dialogs and frames, we are interested mainly in
2428 // m_widget's focus.
2430 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2431 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2433 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2434 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2437 GtkWidget
*connect_widget
= GetConnectWidget();
2439 ConnectWidget( connect_widget
);
2441 /* We cannot set colours, fonts and cursors before the widget has
2442 been realized, so we do this directly after realization */
2443 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2444 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2448 /* Catch native resize events. */
2449 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2450 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2452 /* Initialize XIM support. */
2453 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2454 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2456 /* And resize XIM window. */
2457 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2458 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2464 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2466 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2467 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2469 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2470 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2472 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2473 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2475 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2476 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2478 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2479 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2481 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2482 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2484 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2485 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2488 bool wxWindow::Destroy()
2490 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2494 return wxWindowBase::Destroy();
2497 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2499 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2502 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2504 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2505 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2507 if (m_resizing
) return; /* I don't like recursions */
2510 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2512 /* don't set the size for children of wxNotebook, just take the values. */
2520 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2522 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2524 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2525 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2526 if (width
!= -1) m_width
= width
;
2527 if (height
!= -1) m_height
= height
;
2531 m_x
= x
+ pizza
->xoffset
;
2532 m_y
= y
+ pizza
->yoffset
;
2537 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2539 if (width
== -1) m_width
= 80;
2542 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2544 if (height
== -1) m_height
= 26;
2547 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2548 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2549 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2550 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2553 int bottom_border
= 0;
2555 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2557 /* the default button has a border around it */
2562 DoMoveWindow( m_x
-border
,
2565 m_height
+border
+bottom_border
);
2570 /* Sometimes the client area changes size without the
2571 whole windows's size changing, but if the whole
2572 windows's size doesn't change, no wxSizeEvent will
2573 normally be sent. Here we add an extra test if
2574 the client test has been changed and this will
2576 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2580 wxPrintf( "OnSize sent from " );
2581 if (GetClassInfo() && GetClassInfo()->GetClassName())
2582 wxPrintf( GetClassInfo()->GetClassName() );
2583 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2586 if (!m_nativeSizeEvent
)
2588 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2589 event
.SetEventObject( this );
2590 GetEventHandler()->ProcessEvent( event
);
2596 void wxWindow::OnInternalIdle()
2598 if ( g_sendActivateEvent
!= -1 )
2600 bool activate
= g_sendActivateEvent
!= 0;
2603 g_sendActivateEvent
= -1;
2605 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2606 event
.SetEventObject(this);
2608 (void)GetEventHandler()->ProcessEvent(event
);
2611 wxCursor cursor
= m_cursor
;
2612 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2616 /* I now set the cursor anew in every OnInternalIdle call
2617 as setting the cursor in a parent window also effects the
2618 windows above so that checking for the current cursor is
2623 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2625 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2627 if (!g_globalCursor
.Ok())
2628 cursor
= *wxSTANDARD_CURSOR
;
2630 window
= m_widget
->window
;
2631 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2632 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2638 GdkWindow
*window
= m_widget
->window
;
2639 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2640 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2648 void wxWindow::DoGetSize( int *width
, int *height
) const
2650 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2652 if (width
) (*width
) = m_width
;
2653 if (height
) (*height
) = m_height
;
2656 void wxWindow::DoSetClientSize( int width
, int height
)
2658 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2662 SetSize( width
, height
);
2669 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2671 /* when using GTK 1.2 we set the shadow border size to 2 */
2675 if (HasFlag(wxSIMPLE_BORDER
))
2677 /* when using GTK 1.2 we set the simple border size to 1 */
2684 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2686 GtkRequisition vscroll_req
;
2687 vscroll_req
.width
= 2;
2688 vscroll_req
.height
= 2;
2689 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2690 (scroll_window
->vscrollbar
, &vscroll_req
);
2692 GtkRequisition hscroll_req
;
2693 hscroll_req
.width
= 2;
2694 hscroll_req
.height
= 2;
2695 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2696 (scroll_window
->hscrollbar
, &hscroll_req
);
2698 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2700 if (scroll_window
->vscrollbar_visible
)
2702 dw
+= vscroll_req
.width
;
2703 dw
+= scroll_class
->scrollbar_spacing
;
2706 if (scroll_window
->hscrollbar_visible
)
2708 dh
+= hscroll_req
.height
;
2709 dh
+= scroll_class
->scrollbar_spacing
;
2713 SetSize( width
+dw
, height
+dh
);
2717 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2719 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2723 if (width
) (*width
) = m_width
;
2724 if (height
) (*height
) = m_height
;
2731 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2733 /* when using GTK 1.2 we set the shadow border size to 2 */
2737 if (HasFlag(wxSIMPLE_BORDER
))
2739 /* when using GTK 1.2 we set the simple border size to 1 */
2746 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2748 GtkRequisition vscroll_req
;
2749 vscroll_req
.width
= 2;
2750 vscroll_req
.height
= 2;
2751 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2752 (scroll_window
->vscrollbar
, &vscroll_req
);
2754 GtkRequisition hscroll_req
;
2755 hscroll_req
.width
= 2;
2756 hscroll_req
.height
= 2;
2757 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2758 (scroll_window
->hscrollbar
, &hscroll_req
);
2760 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2762 if (scroll_window
->vscrollbar_visible
)
2764 dw
+= vscroll_req
.width
;
2765 dw
+= scroll_class
->scrollbar_spacing
;
2768 if (scroll_window
->hscrollbar_visible
)
2770 dh
+= hscroll_req
.height
;
2771 dh
+= scroll_class
->scrollbar_spacing
;
2775 if (width
) (*width
) = m_width
- dw
;
2776 if (height
) (*height
) = m_height
- dh
;
2780 void wxWindow::DoGetPosition( int *x
, int *y
) const
2782 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2786 if (m_parent
&& m_parent
->m_wxwindow
)
2788 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2789 dx
= pizza
->xoffset
;
2790 dy
= pizza
->yoffset
;
2793 if (x
) (*x
) = m_x
- dx
;
2794 if (y
) (*y
) = m_y
- dy
;
2797 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2799 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2801 if (!m_widget
->window
) return;
2803 GdkWindow
*source
= (GdkWindow
*) NULL
;
2805 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2807 source
= m_widget
->window
;
2811 gdk_window_get_origin( source
, &org_x
, &org_y
);
2815 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2817 org_x
+= m_widget
->allocation
.x
;
2818 org_y
+= m_widget
->allocation
.y
;
2826 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2828 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2830 if (!m_widget
->window
) return;
2832 GdkWindow
*source
= (GdkWindow
*) NULL
;
2834 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2836 source
= m_widget
->window
;
2840 gdk_window_get_origin( source
, &org_x
, &org_y
);
2844 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2846 org_x
+= m_widget
->allocation
.x
;
2847 org_y
+= m_widget
->allocation
.y
;
2855 bool wxWindow::Show( bool show
)
2857 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2859 if (!wxWindowBase::Show(show
))
2866 gtk_widget_show( m_widget
);
2868 gtk_widget_hide( m_widget
);
2873 bool wxWindow::Enable( bool enable
)
2875 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2877 if (!wxWindowBase::Enable(enable
))
2883 gtk_widget_set_sensitive( m_widget
, enable
);
2885 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2890 int wxWindow::GetCharHeight() const
2892 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2894 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2896 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2898 return font
->ascent
+ font
->descent
;
2901 int wxWindow::GetCharWidth() const
2903 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2905 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2907 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2909 return gdk_string_width( font
, "H" );
2912 void wxWindow::GetTextExtent( const wxString
& string
,
2916 int *externalLeading
,
2917 const wxFont
*theFont
) const
2919 wxFont fontToUse
= m_font
;
2920 if (theFont
) fontToUse
= *theFont
;
2922 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2924 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2925 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2926 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2927 if (descent
) (*descent
) = font
->descent
;
2928 if (externalLeading
) (*externalLeading
) = 0; // ??
2931 void wxWindow::SetFocus()
2933 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2937 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2938 gtk_widget_grab_focus (m_wxwindow
);
2944 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2946 gtk_widget_grab_focus (m_widget
);
2948 else if (GTK_IS_CONTAINER(m_widget
))
2950 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2959 bool wxWindow::AcceptsFocus() const
2961 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2964 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2966 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2968 wxWindow
*oldParent
= m_parent
,
2969 *newParent
= (wxWindow
*)newParentBase
;
2971 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2973 if ( !wxWindowBase::Reparent(newParent
) )
2976 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2978 /* prevent GTK from deleting the widget arbitrarily */
2979 gtk_widget_ref( m_widget
);
2983 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2986 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2990 /* insert GTK representation */
2991 (*(newParent
->m_insertCallback
))(newParent
, this);
2994 /* reverse: prevent GTK from deleting the widget arbitrarily */
2995 gtk_widget_unref( m_widget
);
3000 void wxWindow::DoAddChild(wxWindow
*child
)
3002 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3004 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3006 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3011 /* insert GTK representation */
3012 (*m_insertCallback
)(this, child
);
3015 void wxWindow::Raise()
3017 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3019 if (!m_widget
->window
) return;
3021 gdk_window_raise( m_widget
->window
);
3024 void wxWindow::Lower()
3026 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3028 if (!m_widget
->window
) return;
3030 gdk_window_lower( m_widget
->window
);
3033 bool wxWindow::SetCursor( const wxCursor
&cursor
)
3035 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3037 if (cursor
== m_cursor
)
3041 wxapp_install_idle_handler();
3043 if (cursor
== wxNullCursor
)
3044 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3046 return wxWindowBase::SetCursor( cursor
);
3049 void wxWindow::WarpPointer( int x
, int y
)
3051 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3053 /* we provide this function ourselves as it is
3054 missing in GDK (top of this file) */
3056 GdkWindow
*window
= (GdkWindow
*) NULL
;
3058 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3060 window
= GetConnectWidget()->window
;
3063 gdk_window_warp_pointer( window
, x
, y
);
3066 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
3068 if (!m_widget
) return;
3069 if (!m_widget
->window
) return;
3071 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3075 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3077 rect
->width
, rect
->height
);
3081 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3085 /* there is no GTK equivalent of "draw only, don't clear" so we
3086 invent our own in the GtkPizza widget */
3094 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3095 gboolean old_clear = pizza->clear_on_draw;
3096 gtk_pizza_set_clear( pizza, FALSE );
3097 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3098 gtk_pizza_set_clear( pizza, old_clear );
3100 GdkEventExpose gdk_event
;
3101 gdk_event
.type
= GDK_EXPOSE
;
3102 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3103 gdk_event
.count
= 0;
3104 gdk_event
.area
.x
= 0;
3105 gdk_event
.area
.y
= 0;
3106 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3107 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3108 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3113 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3122 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3123 gboolean old_clear = pizza->clear_on_draw;
3124 gtk_pizza_set_clear( pizza, FALSE );
3126 GdkRectangle gdk_rect;
3127 gdk_rect.x = rect->x;
3128 gdk_rect.y = rect->y;
3129 gdk_rect.width = rect->width;
3130 gdk_rect.height = rect->height;
3131 gtk_widget_draw( m_wxwindow, &gdk_rect );
3132 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3134 gtk_pizza_set_clear( pizza, old_clear );
3136 GdkEventExpose gdk_event
;
3137 gdk_event
.type
= GDK_EXPOSE
;
3138 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3139 gdk_event
.count
= 0;
3140 gdk_event
.area
.x
= rect
->x
;
3141 gdk_event
.area
.y
= rect
->y
;
3142 gdk_event
.area
.width
= rect
->width
;
3143 gdk_event
.area
.height
= rect
->height
;
3144 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3148 GdkRectangle gdk_rect
;
3149 gdk_rect
.x
= rect
->x
;
3150 gdk_rect
.y
= rect
->y
;
3151 gdk_rect
.width
= rect
->width
;
3152 gdk_rect
.height
= rect
->height
;
3153 gtk_widget_draw( m_widget
, &gdk_rect
);
3158 void wxWindow::Clear()
3160 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3162 if (!m_widget
->window
) return;
3164 if (m_wxwindow
&& m_wxwindow
->window
)
3166 // gdk_window_clear( m_wxwindow->window );
3171 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
3173 wxWindowBase::DoSetToolTip(tip
);
3176 m_tooltip
->Apply( this );
3179 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3181 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3183 #endif // wxUSE_TOOLTIPS
3185 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
3187 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3189 if (!wxWindowBase::SetBackgroundColour(colour
))
3191 // don't leave if the GTK widget has just
3193 if (!m_delayedBackgroundColour
) return FALSE
;
3196 GdkWindow
*window
= (GdkWindow
*) NULL
;
3198 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3200 window
= GetConnectWidget()->window
;
3204 // indicate that a new style has been set
3205 // but it couldn't get applied as the
3206 // widget hasn't been realized yet.
3207 m_delayedBackgroundColour
= TRUE
;
3211 (m_wxwindow
->window
) &&
3212 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3214 /* wxMSW doesn't clear the window here. I don't do that either to
3215 provide compatibility. call Clear() to do the job. */
3217 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3218 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3226 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
3228 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3230 if (!wxWindowBase::SetForegroundColour(colour
))
3232 // don't leave if the GTK widget has just
3234 if (!m_delayedForegroundColour
) return FALSE
;
3237 GdkWindow
*window
= (GdkWindow
*) NULL
;
3239 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3241 window
= GetConnectWidget()->window
;
3245 // indicate that a new style has been set
3246 // but it couldn't get applied as the
3247 // widget hasn't been realized yet.
3248 m_delayedForegroundColour
= TRUE
;
3256 GtkStyle
*wxWindow::GetWidgetStyle()
3260 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3262 /* FIXME: is this necessary? */
3263 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3265 remake
->klass
= m_widgetStyle
->klass
;
3268 gtk_style_unref( m_widgetStyle
);
3269 m_widgetStyle
= remake
;
3273 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3276 def
= gtk_widget_get_default_style();
3278 m_widgetStyle
= gtk_style_copy( def
);
3280 /* FIXME: is this necessary? */
3281 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3283 m_widgetStyle
->klass
= def
->klass
;
3287 return m_widgetStyle
;
3290 void wxWindow::SetWidgetStyle()
3292 #if DISABLE_STYLE_IF_BROKEN_THEM
3293 if (m_widget
->style
->engine_data
)
3295 static bool s_warningPrinted
= FALSE
;
3296 if (!s_warningPrinted
)
3298 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3299 s_warningPrinted
= TRUE
;
3301 m_widgetStyle
= m_widget
->style
;
3306 GtkStyle
*style
= GetWidgetStyle();
3308 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3310 gdk_font_unref( style
->font
);
3311 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3314 if (m_foregroundColour
.Ok())
3316 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3317 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3319 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3320 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3321 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3325 // Try to restore the gtk default style. This is still a little
3326 // oversimplified for what is probably really needed here for controls
3327 // other than buttons, but is better than not being able to (re)set a
3328 // control's foreground colour to *wxBLACK -- RL
3329 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3332 def
= gtk_widget_get_default_style();
3334 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3335 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3336 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3340 if (m_backgroundColour
.Ok())
3342 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3343 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3345 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3346 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3347 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3348 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3349 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3350 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3351 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3352 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3356 // Try to restore the gtk default style. This is still a little
3357 // oversimplified for what is probably really needed here for controls
3358 // other than buttons, but is better than not being able to (re)set a
3359 // control's background colour to default grey and means resetting a
3360 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3362 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3365 def
= gtk_widget_get_default_style();
3367 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3368 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3369 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3370 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3371 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3372 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3373 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3374 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3379 void wxWindow::ApplyWidgetStyle()
3383 //-----------------------------------------------------------------------------
3384 // Pop-up menu stuff
3385 //-----------------------------------------------------------------------------
3387 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3389 *is_waiting
= FALSE
;
3392 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3394 menu
->SetInvokingWindow( win
);
3395 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3398 wxMenuItem
*menuitem
= node
->GetData();
3399 if (menuitem
->IsSubMenu())
3401 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3404 node
= node
->GetNext();
3408 static gint gs_pop_x
= 0;
3409 static gint gs_pop_y
= 0;
3411 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3415 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3420 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3422 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3424 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3426 SetInvokingWindow( menu
, this );
3433 bool is_waiting
= TRUE
;
3435 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3436 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3439 GTK_MENU(menu
->m_menu
),
3440 (GtkWidget
*) NULL
, // parent menu shell
3441 (GtkWidget
*) NULL
, // parent menu item
3442 (GtkMenuPositionFunc
) pop_pos_callback
,
3443 (gpointer
) this, // client data
3444 0, // button used to activate it
3445 gs_timeLastClick
// the time of activation
3450 while (gtk_events_pending())
3451 gtk_main_iteration();
3457 #if wxUSE_DRAG_AND_DROP
3459 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3461 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3463 GtkWidget
*dnd_widget
= GetConnectWidget();
3465 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3467 if (m_dropTarget
) delete m_dropTarget
;
3468 m_dropTarget
= dropTarget
;
3470 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3473 #endif // wxUSE_DRAG_AND_DROP
3475 GtkWidget
* wxWindow::GetConnectWidget()
3477 GtkWidget
*connect_widget
= m_widget
;
3478 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3480 return connect_widget
;
3483 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3486 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3488 return (window
== m_widget
->window
);
3491 bool wxWindow::SetFont( const wxFont
&font
)
3493 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3495 if (!wxWindowBase::SetFont(font
))
3500 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3501 if ( sysbg
== m_backgroundColour
)
3503 m_backgroundColour
= wxNullColour
;
3505 m_backgroundColour
= sysbg
;
3515 void wxWindow::CaptureMouse()
3517 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3519 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3521 GdkWindow
*window
= (GdkWindow
*) NULL
;
3523 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3525 window
= GetConnectWidget()->window
;
3527 if (!window
) return;
3529 wxCursor
* cursor
= & m_cursor
;
3531 cursor
= wxSTANDARD_CURSOR
;
3533 gdk_pointer_grab( window
, FALSE
,
3535 (GDK_BUTTON_PRESS_MASK
|
3536 GDK_BUTTON_RELEASE_MASK
|
3537 GDK_POINTER_MOTION_HINT_MASK
|
3538 GDK_POINTER_MOTION_MASK
),
3540 cursor
->GetCursor(),
3541 (guint32
)GDK_CURRENT_TIME
);
3542 g_captureWindow
= this;
3545 void wxWindow::ReleaseMouse()
3547 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3549 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3551 GdkWindow
*window
= (GdkWindow
*) NULL
;
3553 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3555 window
= GetConnectWidget()->window
;
3560 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3561 g_captureWindow
= (wxWindow
*) NULL
;
3564 bool wxWindow::IsRetained() const
3569 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3570 int range
, bool refresh
)
3572 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3574 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3576 m_hasScrolling
= TRUE
;
3578 if (orient
== wxHORIZONTAL
)
3580 float fpos
= (float)pos
;
3581 float frange
= (float)range
;
3582 float fthumb
= (float)thumbVisible
;
3583 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3584 if (fpos
< 0.0) fpos
= 0.0;
3586 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3587 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3589 SetScrollPos( orient
, pos
, refresh
);
3593 m_oldHorizontalPos
= fpos
;
3595 m_hAdjust
->lower
= 0.0;
3596 m_hAdjust
->upper
= frange
;
3597 m_hAdjust
->value
= fpos
;
3598 m_hAdjust
->step_increment
= 1.0;
3599 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3600 m_hAdjust
->page_size
= fthumb
;
3604 float fpos
= (float)pos
;
3605 float frange
= (float)range
;
3606 float fthumb
= (float)thumbVisible
;
3607 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3608 if (fpos
< 0.0) fpos
= 0.0;
3610 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3611 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3613 SetScrollPos( orient
, pos
, refresh
);
3617 m_oldVerticalPos
= fpos
;
3619 m_vAdjust
->lower
= 0.0;
3620 m_vAdjust
->upper
= frange
;
3621 m_vAdjust
->value
= fpos
;
3622 m_vAdjust
->step_increment
= 1.0;
3623 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3624 m_vAdjust
->page_size
= fthumb
;
3627 if (orient
== wxHORIZONTAL
)
3628 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3630 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3633 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3635 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3637 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3639 if (orient
== wxHORIZONTAL
)
3641 float fpos
= (float)pos
;
3642 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3643 if (fpos
< 0.0) fpos
= 0.0;
3644 m_oldHorizontalPos
= fpos
;
3646 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3647 m_hAdjust
->value
= fpos
;
3651 float fpos
= (float)pos
;
3652 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3653 if (fpos
< 0.0) fpos
= 0.0;
3654 m_oldVerticalPos
= fpos
;
3656 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3657 m_vAdjust
->value
= fpos
;
3660 if (m_wxwindow
->window
)
3662 if (orient
== wxHORIZONTAL
)
3664 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3665 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3667 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3669 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3670 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3674 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3675 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3677 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3679 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3680 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3685 int wxWindow::GetScrollThumb( int orient
) const
3687 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3689 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3691 if (orient
== wxHORIZONTAL
)
3692 return (int)(m_hAdjust
->page_size
+0.5);
3694 return (int)(m_vAdjust
->page_size
+0.5);
3697 int wxWindow::GetScrollPos( int orient
) const
3699 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3701 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3703 if (orient
== wxHORIZONTAL
)
3704 return (int)(m_hAdjust
->value
+0.5);
3706 return (int)(m_vAdjust
->value
+0.5);
3709 int wxWindow::GetScrollRange( int orient
) const
3711 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3713 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3715 if (orient
== wxHORIZONTAL
)
3716 return (int)(m_hAdjust
->upper
+0.5);
3718 return (int)(m_vAdjust
->upper
+0.5);
3721 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3723 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3725 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3727 if ((dx
== 0) && (dy
== 0)) return;
3729 m_clipPaintRegion
= TRUE
;
3730 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3731 m_clipPaintRegion
= FALSE
;
3734 if (m_children.GetCount() > 0)
3736 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3740 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3742 pizza->xoffset -= dx;
3743 pizza->yoffset -= dy;
3745 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3746 gdk_gc_set_exposures( m_scrollGC, TRUE );
3750 GetClientSize( &cw, &ch );
3751 int w = cw - abs(dx);
3752 int h = ch - abs(dy);
3754 if ((h < 0) || (w < 0))
3762 if (dx < 0) s_x = -dx;
3763 if (dy < 0) s_y = -dy;
3766 if (dx > 0) d_x = dx;
3767 if (dy > 0) d_y = dy;
3769 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3770 pizza->bin_window, s_x, s_y, w, h );
3773 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3774 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3775 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3776 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3778 Refresh( TRUE, &rect );
3781 gdk_gc_unref( m_scrollGC );
3786 // Find the wxWindow at the current mouse position, also returning the mouse
3788 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
3790 pt
= wxGetMousePosition();
3791 wxWindow
* found
= wxFindWindowAtPoint(pt
);
3795 // Get the current mouse position.
3796 wxPoint
wxGetMousePosition()
3798 /* This crashes when used within wxHelpContext,
3799 so we have to use the X-specific implementation below.
3801 GdkModifierType *mask;
3802 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
3804 return wxPoint(x, y);
3808 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
3810 return wxPoint(-999, -999);
3812 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
3813 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
3814 Window rootReturn
, childReturn
;
3815 int rootX
, rootY
, winX
, winY
;
3816 unsigned int maskReturn
;
3818 XQueryPointer (display
,
3822 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
3823 return wxPoint(rootX
, rootY
);