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
);
685 if (win->IsTopLevel())
687 gtk_paint_flat_box (win->m_widget->style, pizza->bin_window, GTK_STATE_NORMAL,
688 GTK_SHADOW_NONE, &gdk_event->area, win->m_widget, "base", 0, 0, -1, -1);
691 wxWindow *parent = win->GetParent();
692 if (parent && GTK_IS_NOTEBOOK(parent->m_widget))
694 while (!parent->IsTopLevel())
695 parent = parent->GetParent();
696 gtk_paint_flat_box (parent->m_widget->style, pizza->bin_window, GTK_STATE_NORMAL,
697 GTK_SHADOW_NONE, &gdk_event->area, parent->m_widget, "base", 0, 0, -1, -1);
700 if (win
->GetThemeEnabled())
702 wxWindow
*parent
= win
->GetParent();
703 while (parent
&& !parent
->IsTopLevel())
704 parent
= parent
->GetParent();
708 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
709 GTK_SHADOW_NONE
, &gdk_event
->area
, parent
->m_widget
, "base", 0, 0, -1, -1);
712 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
714 gdk_event
->area
.width
,
715 gdk_event
->area
.height
);
717 if (gdk_event
->count
== 0)
719 wxEraseEvent
eevent( win
->GetId() );
720 eevent
.SetEventObject( win
);
721 win
->GetEventHandler()->ProcessEvent(eevent
);
723 wxPaintEvent
event( win
->GetId() );
724 event
.SetEventObject( win
);
725 win
->GetEventHandler()->ProcessEvent( event
);
727 win
->GetUpdateRegion().Clear();
730 /* The following code will result in all window-less widgets
731 being redrawn if the wxWindows class is given a chance to
732 paint *anything* because it will then be allowed to paint
733 over the window-less widgets */
735 GList
*children
= pizza
->children
;
738 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
739 children
= children
->next
;
741 GdkEventExpose child_event
= *gdk_event
;
743 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
744 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
745 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
747 child_event
.area
.x
= child
->widget
->allocation
.x
;
748 child_event
.area
.y
= child
->widget
->allocation
.y
;
749 child_event
.area
.width
= child
->widget
->allocation
.width
;
750 child_event
.area
.height
= child
->widget
->allocation
.height
;
751 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
758 //-----------------------------------------------------------------------------
759 // "event" of m_wxwindow
760 //-----------------------------------------------------------------------------
762 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
763 expose events. We need them, of course, so we override the main event
764 procedure in GtkWidget by giving our own handler for all system events.
765 There, we look for expose events ourselves whereas all other events are
768 gint
gtk_window_event_event_callback( GtkWidget
*widget
, GdkEventExpose
*event
, wxWindow
*win
)
770 if (event
->type
== GDK_EXPOSE
)
772 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
779 //-----------------------------------------------------------------------------
780 // "draw" of m_wxwindow
781 //-----------------------------------------------------------------------------
783 /* This callback is a complete replacement of the gtk_pizza_draw() function,
786 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
791 wxapp_install_idle_handler();
794 if (win->GetName() == wxT("panel"))
796 wxPrintf( wxT("OnDraw from ") );
797 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
798 wxPrintf( win->GetClassInfo()->GetClassName() );
799 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
806 GtkPizza
*pizza
= GTK_PIZZA (widget
);
808 if (win
->IsTopLevel())
810 gtk_paint_flat_box (win
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
811 GTK_SHADOW_NONE
, rect
, win
->m_widget
, "base", 0, 0, -1, -1);
814 wxWindow
*parent
= win
->GetParent();
815 if (parent
&& GTK_IS_NOTEBOOK(parent
->m_widget
))
817 while (!parent
->IsTopLevel())
818 parent
= parent
->GetParent();
819 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
820 GTK_SHADOW_NONE
, rect
, parent
->m_widget
, "base", 0, 0, -1, -1);
823 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
824 (pizza
->clear_on_draw
))
826 gdk_window_clear_area( pizza
->bin_window
,
827 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
830 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
832 win
->m_clipPaintRegion
= TRUE
;
834 wxEraseEvent
eevent( win
->GetId() );
835 eevent
.SetEventObject( win
);
836 win
->GetEventHandler()->ProcessEvent(eevent
);
838 wxPaintEvent
event( win
->GetId() );
839 event
.SetEventObject( win
);
840 win
->GetEventHandler()->ProcessEvent( event
);
842 win
->GetUpdateRegion().Clear();
844 win
->m_clipPaintRegion
= FALSE
;
847 GList
*children
= pizza
->children
;
850 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
851 children
= children
->next
;
853 GdkRectangle child_area
;
854 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
856 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
861 //-----------------------------------------------------------------------------
862 // "key_press_event" from any window
863 //-----------------------------------------------------------------------------
865 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
870 wxapp_install_idle_handler();
872 if (!win
->m_hasVMT
) return FALSE
;
873 if (g_blockEventsOnDrag
) return FALSE
;
878 tmp += (char)gdk_event->keyval;
879 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
880 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
885 GdkModifierType state
;
886 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
890 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
891 /* sending unknown key events doesn't really make sense */
892 if (key_code
== 0) return FALSE
;
894 wxKeyEvent
event( wxEVT_KEY_DOWN
);
895 event
.SetTimestamp( gdk_event
->time
);
896 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
897 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
898 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
899 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
900 event
.m_keyCode
= key_code
;
901 event
.m_scanCode
= gdk_event
->keyval
;
904 event
.SetEventObject( win
);
905 ret
= win
->GetEventHandler()->ProcessEvent( event
);
910 wxWindow
*ancestor
= win
;
913 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
916 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
917 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
920 if (ancestor
->IsTopLevel())
922 ancestor
= ancestor
->GetParent();
925 #endif // wxUSE_ACCEL
927 /* wxMSW doesn't send char events with Alt pressed */
928 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
929 will only be sent if it is not in an accelerator table. */
930 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
935 wxKeyEvent
event2( wxEVT_CHAR
);
936 event2
.SetTimestamp( gdk_event
->time
);
937 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
938 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
939 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
940 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
941 event2
.m_keyCode
= key_code
;
942 event2
.m_scanCode
= gdk_event
->keyval
;
945 event2
.SetEventObject( win
);
946 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
949 /* win is a control: tab can be propagated up */
951 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
952 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
953 // have this style, yet choose not to process this particular TAB in which
954 // case TAB must still work as a navigational character
956 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
958 (win
->GetParent()) &&
959 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
961 wxNavigationKeyEvent new_event
;
962 new_event
.SetEventObject( win
->GetParent() );
963 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
964 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
965 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
966 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
967 new_event
.SetCurrentFocus( win
);
968 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
971 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
973 (gdk_event
->keyval
== GDK_Escape
) )
975 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
976 new_event
.SetEventObject( win
);
977 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
980 #if (GTK_MINOR_VERSION > 0)
981 /* Pressing F10 will activate the menu bar of the top frame. */
985 (gdk_event->keyval == GDK_F10) )
987 wxWindow *ancestor = win;
990 if (wxIsKindOf(ancestor,wxFrame))
992 wxFrame *frame = (wxFrame*) ancestor;
993 wxMenuBar *menubar = frame->GetMenuBar();
996 wxNode *node = menubar->GetMenus().First();
999 wxMenu *firstMenu = (wxMenu*) node->Data();
1000 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
1006 ancestor = ancestor->GetParent();
1014 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1021 //-----------------------------------------------------------------------------
1022 // "key_release_event" from any window
1023 //-----------------------------------------------------------------------------
1025 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
1030 wxapp_install_idle_handler();
1032 if (!win
->m_hasVMT
) return FALSE
;
1033 if (g_blockEventsOnDrag
) return FALSE
;
1036 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
1037 if (gdk_event->state & GDK_SHIFT_MASK)
1038 printf( "ShiftDown.\n" );
1040 printf( "ShiftUp.\n" );
1041 if (gdk_event->state & GDK_CONTROL_MASK)
1042 printf( "ControlDown.\n" );
1044 printf( "ControlUp.\n" );
1048 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
1050 /* sending unknown key events doesn't really make sense */
1051 if (key_code
== 0) return FALSE
;
1055 GdkModifierType state
;
1056 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1058 wxKeyEvent
event( wxEVT_KEY_UP
);
1059 event
.SetTimestamp( gdk_event
->time
);
1060 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1061 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1062 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1063 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1064 event
.m_keyCode
= key_code
;
1065 event
.m_scanCode
= gdk_event
->keyval
;
1068 event
.SetEventObject( win
);
1070 if (win
->GetEventHandler()->ProcessEvent( event
))
1072 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1079 // ----------------------------------------------------------------------------
1080 // mouse event processing helper
1081 // ----------------------------------------------------------------------------
1083 static void AdjustEventButtonState(wxMouseEvent
& event
)
1085 // GDK reports the old state of the button for a button press event, but
1086 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1087 // for a LEFT_DOWN event, not FALSE, so we will invert
1088 // left/right/middleDown for the corresponding click events
1089 switch ( event
.GetEventType() )
1091 case wxEVT_LEFT_DOWN
:
1092 case wxEVT_LEFT_DCLICK
:
1094 event
.m_leftDown
= !event
.m_leftDown
;
1097 case wxEVT_MIDDLE_DOWN
:
1098 case wxEVT_MIDDLE_DCLICK
:
1099 case wxEVT_MIDDLE_UP
:
1100 event
.m_middleDown
= !event
.m_middleDown
;
1103 case wxEVT_RIGHT_DOWN
:
1104 case wxEVT_RIGHT_DCLICK
:
1105 case wxEVT_RIGHT_UP
:
1106 event
.m_rightDown
= !event
.m_rightDown
;
1111 //-----------------------------------------------------------------------------
1112 // "button_press_event"
1113 //-----------------------------------------------------------------------------
1115 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1120 wxapp_install_idle_handler();
1123 wxPrintf( wxT("1) OnButtonPress from ") );
1124 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1125 wxPrintf( win->GetClassInfo()->GetClassName() );
1126 wxPrintf( wxT(".\n") );
1128 if (!win
->m_hasVMT
) return FALSE
;
1129 if (g_blockEventsOnDrag
) return TRUE
;
1130 if (g_blockEventsOnScroll
) return TRUE
;
1132 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1134 if (win
->m_wxwindow
)
1136 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1138 gtk_widget_grab_focus (win
->m_wxwindow
);
1141 wxPrintf( wxT("GrabFocus from ") );
1142 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1143 wxPrintf( win->GetClassInfo()->GetClassName() );
1144 wxPrintf( wxT(".\n") );
1150 wxEventType event_type
= wxEVT_NULL
;
1152 if (gdk_event
->button
== 1)
1154 switch (gdk_event
->type
)
1156 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1157 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1161 else if (gdk_event
->button
== 2)
1163 switch (gdk_event
->type
)
1165 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1166 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1170 else if (gdk_event
->button
== 3)
1172 switch (gdk_event
->type
)
1174 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1175 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1180 if ( event_type
== wxEVT_NULL
)
1182 // unknown mouse button or click type
1186 wxMouseEvent
event( event_type
);
1187 event
.SetTimestamp( gdk_event
->time
);
1188 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1189 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1190 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1191 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1192 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1193 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1194 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1196 event
.m_x
= (wxCoord
)gdk_event
->x
;
1197 event
.m_y
= (wxCoord
)gdk_event
->y
;
1199 AdjustEventButtonState(event
);
1201 // Some control don't have their own X window and thus cannot get
1204 if (!g_captureWindow
)
1206 wxCoord x
= event
.m_x
;
1207 wxCoord y
= event
.m_y
;
1208 if (win
->m_wxwindow
)
1210 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1211 x
+= pizza
->xoffset
;
1212 y
+= pizza
->yoffset
;
1215 wxNode
*node
= win
->GetChildren().First();
1218 wxWindow
*child
= (wxWindow
*)node
->Data();
1220 node
= node
->Next();
1221 if (!child
->IsShown())
1224 if (child
->m_isStaticBox
)
1226 // wxStaticBox is transparent in the box itself
1227 int xx1
= child
->m_x
;
1228 int yy1
= child
->m_y
;
1229 int xx2
= child
->m_x
+ child
->m_width
;
1230 int yy2
= child
->m_x
+ child
->m_height
;
1233 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1235 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1237 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1239 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1242 event
.m_x
-= child
->m_x
;
1243 event
.m_y
-= child
->m_y
;
1250 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1251 (child
->m_x
<= x
) &&
1252 (child
->m_y
<= y
) &&
1253 (child
->m_x
+child
->m_width
>= x
) &&
1254 (child
->m_y
+child
->m_height
>= y
))
1257 event
.m_x
-= child
->m_x
;
1258 event
.m_y
-= child
->m_y
;
1265 event
.SetEventObject( win
);
1267 gs_timeLastClick
= gdk_event
->time
;
1270 wxPrintf( wxT("2) OnButtonPress from ") );
1271 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1272 wxPrintf( win->GetClassInfo()->GetClassName() );
1273 wxPrintf( wxT(".\n") );
1276 if (win
->GetEventHandler()->ProcessEvent( event
))
1278 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1285 //-----------------------------------------------------------------------------
1286 // "button_release_event"
1287 //-----------------------------------------------------------------------------
1289 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1294 wxapp_install_idle_handler();
1296 if (!win
->m_hasVMT
) return FALSE
;
1297 if (g_blockEventsOnDrag
) return FALSE
;
1298 if (g_blockEventsOnScroll
) return FALSE
;
1300 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1303 printf( "OnButtonRelease from " );
1304 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1305 printf( win->GetClassInfo()->GetClassName() );
1309 wxEventType event_type
= wxEVT_NULL
;
1311 switch (gdk_event
->button
)
1313 case 1: event_type
= wxEVT_LEFT_UP
; break;
1314 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1315 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1316 default: return FALSE
;
1319 wxMouseEvent
event( event_type
);
1320 event
.SetTimestamp( gdk_event
->time
);
1321 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1322 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1323 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1324 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1325 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1326 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1327 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1328 event
.m_x
= (wxCoord
)gdk_event
->x
;
1329 event
.m_y
= (wxCoord
)gdk_event
->y
;
1331 AdjustEventButtonState(event
);
1333 // Some control don't have their own X window and thus cannot get
1336 if (!g_captureWindow
)
1338 wxCoord x
= event
.m_x
;
1339 wxCoord y
= event
.m_y
;
1340 if (win
->m_wxwindow
)
1342 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1343 x
+= pizza
->xoffset
;
1344 y
+= pizza
->yoffset
;
1347 wxNode
*node
= win
->GetChildren().First();
1350 wxWindow
*child
= (wxWindow
*)node
->Data();
1352 node
= node
->Next();
1353 if (!child
->IsShown())
1356 if (child
->m_isStaticBox
)
1358 // wxStaticBox is transparent in the box itself
1359 int xx1
= child
->m_x
;
1360 int yy1
= child
->m_y
;
1361 int xx2
= child
->m_x
+ child
->m_width
;
1362 int yy2
= child
->m_x
+ child
->m_height
;
1365 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1367 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1369 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1371 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1374 event
.m_x
-= child
->m_x
;
1375 event
.m_y
-= child
->m_y
;
1382 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1383 (child
->m_x
<= x
) &&
1384 (child
->m_y
<= y
) &&
1385 (child
->m_x
+child
->m_width
>= x
) &&
1386 (child
->m_y
+child
->m_height
>= y
))
1389 event
.m_x
-= child
->m_x
;
1390 event
.m_y
-= child
->m_y
;
1397 event
.SetEventObject( win
);
1399 if (win
->GetEventHandler()->ProcessEvent( event
))
1401 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1408 //-----------------------------------------------------------------------------
1409 // "motion_notify_event"
1410 //-----------------------------------------------------------------------------
1412 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1417 wxapp_install_idle_handler();
1419 if (!win
->m_hasVMT
) return FALSE
;
1420 if (g_blockEventsOnDrag
) return FALSE
;
1421 if (g_blockEventsOnScroll
) return FALSE
;
1423 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1425 if (gdk_event
->is_hint
)
1429 GdkModifierType state
;
1430 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1436 printf( "OnMotion from " );
1437 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1438 printf( win->GetClassInfo()->GetClassName() );
1442 wxMouseEvent
event( wxEVT_MOTION
);
1443 event
.SetTimestamp( gdk_event
->time
);
1444 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1445 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1446 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1447 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1448 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1449 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1450 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1452 event
.m_x
= (wxCoord
)gdk_event
->x
;
1453 event
.m_y
= (wxCoord
)gdk_event
->y
;
1455 // Some control don't have their own X window and thus cannot get
1458 if (!g_captureWindow
)
1460 wxCoord x
= event
.m_x
;
1461 wxCoord y
= event
.m_y
;
1462 if (win
->m_wxwindow
)
1464 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1465 x
+= pizza
->xoffset
;
1466 y
+= pizza
->yoffset
;
1469 wxNode
*node
= win
->GetChildren().First();
1472 wxWindow
*child
= (wxWindow
*)node
->Data();
1474 node
= node
->Next();
1475 if (!child
->IsShown())
1478 if (child
->m_isStaticBox
)
1480 // wxStaticBox is transparent in the box itself
1481 int xx1
= child
->m_x
;
1482 int yy1
= child
->m_y
;
1483 int xx2
= child
->m_x
+ child
->m_width
;
1484 int yy2
= child
->m_x
+ child
->m_height
;
1487 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1489 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1491 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1493 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1496 event
.m_x
-= child
->m_x
;
1497 event
.m_y
-= child
->m_y
;
1504 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1505 (child
->m_x
<= x
) &&
1506 (child
->m_y
<= y
) &&
1507 (child
->m_x
+child
->m_width
>= x
) &&
1508 (child
->m_y
+child
->m_height
>= y
))
1511 event
.m_x
-= child
->m_x
;
1512 event
.m_y
-= child
->m_y
;
1519 event
.SetEventObject( win
);
1521 if (win
->GetEventHandler()->ProcessEvent( event
))
1523 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1530 //-----------------------------------------------------------------------------
1532 //-----------------------------------------------------------------------------
1534 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1539 wxapp_install_idle_handler();
1541 if (!win
->m_hasVMT
) return FALSE
;
1542 if (g_blockEventsOnDrag
) return FALSE
;
1544 switch ( g_sendActivateEvent
)
1547 // we've got focus from outside, synthtize wxActivateEvent
1548 g_sendActivateEvent
= 1;
1552 // another our window just lost focus, it was already ours before
1553 // - don't send any wxActivateEvent
1554 g_sendActivateEvent
= -1;
1558 g_focusWindow
= win
;
1561 printf( "OnSetFocus from " );
1562 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1563 printf( win->GetClassInfo()->GetClassName() );
1565 printf( WXSTRINGCAST win->GetLabel() );
1569 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1572 panel
->SetLastFocus(win
);
1577 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1581 // caret needs to be informed about focus change
1582 wxCaret
*caret
= win
->GetCaret();
1585 caret
->OnSetFocus();
1587 #endif // wxUSE_CARET
1589 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1590 event
.SetEventObject( win
);
1592 if (win
->GetEventHandler()->ProcessEvent( event
))
1594 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1601 //-----------------------------------------------------------------------------
1602 // "focus_out_event"
1603 //-----------------------------------------------------------------------------
1605 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1610 wxapp_install_idle_handler();
1612 if (!win
->m_hasVMT
) return FALSE
;
1613 if (g_blockEventsOnDrag
) return FALSE
;
1615 // if the focus goes out of our app alltogether, OnIdle() will send
1616 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1617 // g_sendActivateEvent to -1
1618 g_sendActivateEvent
= 0;
1620 wxWindow
*winFocus
= FindFocusedChild(win
);
1624 g_focusWindow
= (wxWindow
*)NULL
;
1627 printf( "OnKillFocus from " );
1628 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1629 printf( win->GetClassInfo()->GetClassName() );
1639 // caret needs to be informed about focus change
1640 wxCaret
*caret
= win
->GetCaret();
1643 caret
->OnKillFocus();
1645 #endif // wxUSE_CARET
1647 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1648 event
.SetEventObject( win
);
1650 if (win
->GetEventHandler()->ProcessEvent( event
))
1652 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1659 //-----------------------------------------------------------------------------
1660 // "enter_notify_event"
1661 //-----------------------------------------------------------------------------
1663 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1668 wxapp_install_idle_handler();
1670 if (!win
->m_hasVMT
) return FALSE
;
1671 if (g_blockEventsOnDrag
) return FALSE
;
1673 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1675 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1676 #if (GTK_MINOR_VERSION > 0)
1677 event
.SetTimestamp( gdk_event
->time
);
1679 event
.SetEventObject( win
);
1683 GdkModifierType state
= (GdkModifierType
)0;
1685 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1687 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1688 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1689 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1690 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1691 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1692 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1693 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1698 if (win
->GetEventHandler()->ProcessEvent( event
))
1700 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1707 //-----------------------------------------------------------------------------
1708 // "leave_notify_event"
1709 //-----------------------------------------------------------------------------
1711 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1716 wxapp_install_idle_handler();
1718 if (!win
->m_hasVMT
) return FALSE
;
1719 if (g_blockEventsOnDrag
) return FALSE
;
1721 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1723 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1724 #if (GTK_MINOR_VERSION > 0)
1725 event
.SetTimestamp( gdk_event
->time
);
1727 event
.SetEventObject( win
);
1731 GdkModifierType state
= (GdkModifierType
)0;
1733 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1735 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1736 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1737 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1738 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1739 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1740 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1741 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1746 if (win
->GetEventHandler()->ProcessEvent( event
))
1748 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1755 //-----------------------------------------------------------------------------
1756 // "value_changed" from m_vAdjust
1757 //-----------------------------------------------------------------------------
1759 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1764 wxapp_install_idle_handler();
1766 if (g_blockEventsOnDrag
) return;
1768 if (!win
->m_hasVMT
) return;
1770 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1771 if (fabs(diff
) < 0.2) return;
1773 win
->m_oldVerticalPos
= adjust
->value
;
1775 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1776 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1778 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1779 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1780 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1781 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1782 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1784 int value
= (int)(adjust
->value
+0.5);
1786 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1787 event
.SetEventObject( win
);
1788 win
->GetEventHandler()->ProcessEvent( event
);
1791 //-----------------------------------------------------------------------------
1792 // "value_changed" from m_hAdjust
1793 //-----------------------------------------------------------------------------
1795 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1800 wxapp_install_idle_handler();
1802 if (g_blockEventsOnDrag
) return;
1803 if (!win
->m_hasVMT
) return;
1805 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1806 if (fabs(diff
) < 0.2) return;
1808 win
->m_oldHorizontalPos
= adjust
->value
;
1810 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1811 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1813 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1814 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1815 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1816 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1817 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1819 int value
= (int)(adjust
->value
+0.5);
1821 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1822 event
.SetEventObject( win
);
1823 win
->GetEventHandler()->ProcessEvent( event
);
1826 //-----------------------------------------------------------------------------
1827 // "button_press_event" from scrollbar
1828 //-----------------------------------------------------------------------------
1830 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1831 GdkEventButton
*gdk_event
,
1837 wxapp_install_idle_handler();
1840 g_blockEventsOnScroll
= TRUE
;
1841 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1846 //-----------------------------------------------------------------------------
1847 // "button_release_event" from scrollbar
1848 //-----------------------------------------------------------------------------
1850 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1851 GdkEventButton
*WXUNUSED(gdk_event
),
1856 // don't test here as we can release the mouse while being over
1857 // a different window than the slider
1859 // if (gdk_event->window != widget->slider) return FALSE;
1861 g_blockEventsOnScroll
= FALSE
;
1863 if (win
->m_isScrolling
)
1865 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
1869 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1870 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1872 value
= (int)(win
->m_hAdjust
->value
+0.5);
1875 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1877 value
= (int)(win
->m_vAdjust
->value
+0.5);
1881 wxScrollWinEvent
event( command
, value
, dir
);
1882 event
.SetEventObject( win
);
1883 win
->GetEventHandler()->ProcessEvent( event
);
1886 win
->m_isScrolling
= FALSE
;
1891 // ----------------------------------------------------------------------------
1892 // this wxWindowBase function is implemented here (in platform-specific file)
1893 // because it is static and so couldn't be made virtual
1894 // ----------------------------------------------------------------------------
1896 wxWindow
*wxWindowBase::FindFocus()
1898 return g_focusWindow
;
1901 //-----------------------------------------------------------------------------
1902 // "realize" from m_widget
1903 //-----------------------------------------------------------------------------
1905 /* We cannot set colours and fonts before the widget has
1906 been realized, so we do this directly after realization. */
1909 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1914 wxapp_install_idle_handler();
1916 if (win
->m_delayedBackgroundColour
)
1917 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1919 if (win
->m_delayedForegroundColour
)
1920 win
->SetForegroundColour( win
->GetForegroundColour() );
1922 wxWindowCreateEvent
event( win
);
1923 event
.SetEventObject( win
);
1924 win
->GetEventHandler()->ProcessEvent( event
);
1929 //-----------------------------------------------------------------------------
1931 //-----------------------------------------------------------------------------
1934 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
1935 GtkAllocation
*WXUNUSED(alloc
),
1939 wxapp_install_idle_handler();
1941 if (!win
->m_hasScrolling
) return;
1943 int client_width
= 0;
1944 int client_height
= 0;
1945 win
->GetClientSize( &client_width
, &client_height
);
1946 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
1949 win
->m_oldClientWidth
= client_width
;
1950 win
->m_oldClientHeight
= client_height
;
1952 if (!win
->m_nativeSizeEvent
)
1954 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
1955 event
.SetEventObject( win
);
1956 win
->GetEventHandler()->ProcessEvent( event
);
1962 #define WXUNUSED_UNLESS_XIM(param) param
1964 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1967 /* Resize XIM window */
1970 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1971 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1972 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1975 wxapp_install_idle_handler();
1981 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1985 gdk_window_get_size (widget
->window
, &width
, &height
);
1986 win
->m_icattr
->preedit_area
.width
= width
;
1987 win
->m_icattr
->preedit_area
.height
= height
;
1988 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
1993 //-----------------------------------------------------------------------------
1994 // "realize" from m_wxwindow
1995 //-----------------------------------------------------------------------------
1997 /* Initialize XIM support */
2000 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2001 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
2004 wxapp_install_idle_handler();
2007 if (win
->m_ic
) return FALSE
;
2008 if (!widget
) return FALSE
;
2009 if (!gdk_im_ready()) return FALSE
;
2011 win
->m_icattr
= gdk_ic_attr_new();
2012 if (!win
->m_icattr
) return FALSE
;
2016 GdkColormap
*colormap
;
2017 GdkICAttr
*attr
= win
->m_icattr
;
2018 unsigned attrmask
= GDK_IC_ALL_REQ
;
2020 GdkIMStyle supported_style
= (GdkIMStyle
)
2021 (GDK_IM_PREEDIT_NONE
|
2022 GDK_IM_PREEDIT_NOTHING
|
2023 GDK_IM_PREEDIT_POSITION
|
2024 GDK_IM_STATUS_NONE
|
2025 GDK_IM_STATUS_NOTHING
);
2027 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2028 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2030 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2031 attr
->client_window
= widget
->window
;
2033 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2034 gtk_widget_get_default_colormap ())
2036 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2037 attr
->preedit_colormap
= colormap
;
2040 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2041 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2042 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2043 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2045 switch (style
& GDK_IM_PREEDIT_MASK
)
2047 case GDK_IM_PREEDIT_POSITION
:
2048 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2050 g_warning ("over-the-spot style requires fontset");
2054 gdk_window_get_size (widget
->window
, &width
, &height
);
2056 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2057 attr
->spot_location
.x
= 0;
2058 attr
->spot_location
.y
= height
;
2059 attr
->preedit_area
.x
= 0;
2060 attr
->preedit_area
.y
= 0;
2061 attr
->preedit_area
.width
= width
;
2062 attr
->preedit_area
.height
= height
;
2063 attr
->preedit_fontset
= widget
->style
->font
;
2068 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2070 if (win
->m_ic
== NULL
)
2071 g_warning ("Can't create input context.");
2074 mask
= gdk_window_get_events (widget
->window
);
2075 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2076 gdk_window_set_events (widget
->window
, mask
);
2078 if (GTK_WIDGET_HAS_FOCUS(widget
))
2079 gdk_im_begin (win
->m_ic
, widget
->window
);
2086 //-----------------------------------------------------------------------------
2087 // InsertChild for wxWindow.
2088 //-----------------------------------------------------------------------------
2090 /* Callback for wxWindow. This very strange beast has to be used because
2091 * C++ has no virtual methods in a constructor. We have to emulate a
2092 * virtual function here as wxNotebook requires a different way to insert
2093 * a child in it. I had opted for creating a wxNotebookPage window class
2094 * which would have made this superfluous (such in the MDI window system),
2095 * but no-one was listening to me... */
2097 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
2099 /* the window might have been scrolled already, do we
2100 have to adapt the position */
2101 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2102 child
->m_x
+= pizza
->xoffset
;
2103 child
->m_y
+= pizza
->yoffset
;
2105 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2106 GTK_WIDGET(child
->m_widget
),
2113 //-----------------------------------------------------------------------------
2115 //-----------------------------------------------------------------------------
2117 wxWindow
* wxGetActiveWindow()
2119 return g_focusWindow
;
2122 //-----------------------------------------------------------------------------
2124 //-----------------------------------------------------------------------------
2126 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2128 void wxWindow::Init()
2134 m_widget
= (GtkWidget
*) NULL
;
2135 m_wxwindow
= (GtkWidget
*) NULL
;
2145 m_needParent
= TRUE
;
2146 m_isBeingDeleted
= FALSE
;
2149 m_nativeSizeEvent
= FALSE
;
2151 m_hasScrolling
= FALSE
;
2152 m_isScrolling
= FALSE
;
2154 m_hAdjust
= (GtkAdjustment
*) NULL
;
2155 m_vAdjust
= (GtkAdjustment
*) NULL
;
2156 m_oldHorizontalPos
= 0.0;
2157 m_oldVerticalPos
= 0.0;
2160 m_widgetStyle
= (GtkStyle
*) NULL
;
2162 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2164 m_isStaticBox
= FALSE
;
2165 m_isRadioButton
= FALSE
;
2167 m_acceptsFocus
= FALSE
;
2169 m_clipPaintRegion
= FALSE
;
2171 m_cursor
= *wxSTANDARD_CURSOR
;
2173 m_delayedForegroundColour
= FALSE
;
2174 m_delayedBackgroundColour
= FALSE
;
2177 m_ic
= (GdkIC
*) NULL
;
2178 m_icattr
= (GdkICAttr
*) NULL
;
2182 wxWindow::wxWindow()
2187 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
2188 const wxPoint
&pos
, const wxSize
&size
,
2189 long style
, const wxString
&name
)
2193 Create( parent
, id
, pos
, size
, style
, name
);
2196 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
2197 const wxPoint
&pos
, const wxSize
&size
,
2198 long style
, const wxString
&name
)
2200 if (!PreCreation( parent
, pos
, size
) ||
2201 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2203 wxFAIL_MSG( wxT("wxWindow creation failed") );
2207 m_insertCallback
= wxInsertChildInWindow
;
2209 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2210 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2212 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2214 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2215 scroll_class
->scrollbar_spacing
= 0;
2217 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2219 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2220 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2222 m_wxwindow
= gtk_pizza_new();
2224 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2226 #if (GTK_MINOR_VERSION > 0)
2227 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2229 if (HasFlag(wxRAISED_BORDER
))
2231 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2233 else if (HasFlag(wxSUNKEN_BORDER
))
2235 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2237 else if (HasFlag(wxSIMPLE_BORDER
))
2239 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2243 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2245 #else // GTK_MINOR_VERSION == 0
2246 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2248 if (HasFlag(wxRAISED_BORDER
))
2250 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2252 else if (HasFlag(wxSUNKEN_BORDER
))
2254 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2258 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2260 #endif // GTK_MINOR_VERSION
2262 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2263 m_acceptsFocus
= TRUE
;
2265 #if (GTK_MINOR_VERSION == 0)
2266 // shut the viewport up
2267 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2268 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2269 #endif // GTK_MINOR_VERSION == 0
2271 // I _really_ don't want scrollbars in the beginning
2272 m_vAdjust
->lower
= 0.0;
2273 m_vAdjust
->upper
= 1.0;
2274 m_vAdjust
->value
= 0.0;
2275 m_vAdjust
->step_increment
= 1.0;
2276 m_vAdjust
->page_increment
= 1.0;
2277 m_vAdjust
->page_size
= 5.0;
2278 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2279 m_hAdjust
->lower
= 0.0;
2280 m_hAdjust
->upper
= 1.0;
2281 m_hAdjust
->value
= 0.0;
2282 m_hAdjust
->step_increment
= 1.0;
2283 m_hAdjust
->page_increment
= 1.0;
2284 m_hAdjust
->page_size
= 5.0;
2285 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2287 // these handlers block mouse events to any window during scrolling such as
2288 // motion events and prevent GTK and wxWindows from fighting over where the
2291 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2292 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2294 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2295 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2297 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2298 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2300 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2301 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2303 // these handlers get notified when screen updates are required either when
2304 // scrolling or when the window size (and therefore scrollbar configuration)
2307 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2308 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2309 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2310 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2312 gtk_widget_show( m_wxwindow
);
2315 m_parent
->DoAddChild( this );
2324 wxWindow::~wxWindow()
2326 m_isBeingDeleted
= TRUE
;
2335 m_parent
->RemoveChild( this );
2339 gdk_ic_destroy (m_ic
);
2341 gdk_ic_attr_destroy (m_icattr
);
2346 #if DISABLE_STYLE_IF_BROKEN_THEME
2347 // don't delete if it's a pixmap theme style
2348 if (!m_widgetStyle
->engine_data
)
2349 gtk_style_unref( m_widgetStyle
);
2351 m_widgetStyle
= (GtkStyle
*) NULL
;
2356 gtk_widget_destroy( m_wxwindow
);
2357 m_wxwindow
= (GtkWidget
*) NULL
;
2362 gtk_widget_destroy( m_widget
);
2363 m_widget
= (GtkWidget
*) NULL
;
2367 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2369 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2371 /* this turns -1 into 20 so that a minimal window is
2372 visible even although -1,-1 has been given as the
2373 size of the window. the same trick is used in other
2374 ports and should make debugging easier */
2375 m_width
= WidthDefault(size
.x
);
2376 m_height
= HeightDefault(size
.y
);
2381 /* some reasonable defaults */
2386 m_x
= (gdk_screen_width () - m_width
) / 2;
2387 if (m_x
< 10) m_x
= 10;
2391 m_y
= (gdk_screen_height () - m_height
) / 2;
2392 if (m_y
< 10) m_y
= 10;
2399 void wxWindow::PostCreation()
2401 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2407 /* these get reported to wxWindows -> wxPaintEvent */
2409 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2411 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2412 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2414 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2415 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2417 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2418 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2421 #if (GTK_MINOR_VERSION > 0)
2422 /* these are called when the "sunken" or "raised" borders are drawn */
2423 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2424 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2426 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2427 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2431 if (m_wxwindow
&& m_needParent
)
2433 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2434 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2436 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2437 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2441 // For dialogs and frames, we are interested mainly in
2442 // m_widget's focus.
2444 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2445 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2447 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2448 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2451 GtkWidget
*connect_widget
= GetConnectWidget();
2453 ConnectWidget( connect_widget
);
2455 /* We cannot set colours, fonts and cursors before the widget has
2456 been realized, so we do this directly after realization */
2457 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2458 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2462 /* Catch native resize events. */
2463 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2464 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2466 /* Initialize XIM support. */
2467 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2468 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2470 /* And resize XIM window. */
2471 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2472 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2478 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2480 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2481 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2483 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2484 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2486 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2487 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2489 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2490 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2492 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2493 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2495 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2496 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2498 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2499 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2502 bool wxWindow::Destroy()
2504 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2508 return wxWindowBase::Destroy();
2511 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2513 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2516 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2518 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2519 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2521 if (m_resizing
) return; /* I don't like recursions */
2524 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2526 /* don't set the size for children of wxNotebook, just take the values. */
2534 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2536 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2538 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2539 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2540 if (width
!= -1) m_width
= width
;
2541 if (height
!= -1) m_height
= height
;
2545 m_x
= x
+ pizza
->xoffset
;
2546 m_y
= y
+ pizza
->yoffset
;
2551 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2553 if (width
== -1) m_width
= 80;
2556 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2558 if (height
== -1) m_height
= 26;
2561 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2562 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2563 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2564 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2567 int bottom_border
= 0;
2569 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2571 /* the default button has a border around it */
2576 DoMoveWindow( m_x
-border
,
2579 m_height
+border
+bottom_border
);
2584 /* Sometimes the client area changes size without the
2585 whole windows's size changing, but if the whole
2586 windows's size doesn't change, no wxSizeEvent will
2587 normally be sent. Here we add an extra test if
2588 the client test has been changed and this will
2590 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2594 wxPrintf( "OnSize sent from " );
2595 if (GetClassInfo() && GetClassInfo()->GetClassName())
2596 wxPrintf( GetClassInfo()->GetClassName() );
2597 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2600 if (!m_nativeSizeEvent
)
2602 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2603 event
.SetEventObject( this );
2604 GetEventHandler()->ProcessEvent( event
);
2610 void wxWindow::OnInternalIdle()
2612 if ( g_sendActivateEvent
!= -1 )
2614 bool activate
= g_sendActivateEvent
!= 0;
2617 g_sendActivateEvent
= -1;
2619 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2620 event
.SetEventObject(this);
2622 (void)GetEventHandler()->ProcessEvent(event
);
2625 wxCursor cursor
= m_cursor
;
2626 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2630 /* I now set the cursor anew in every OnInternalIdle call
2631 as setting the cursor in a parent window also effects the
2632 windows above so that checking for the current cursor is
2637 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2639 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2641 if (!g_globalCursor
.Ok())
2642 cursor
= *wxSTANDARD_CURSOR
;
2644 window
= m_widget
->window
;
2645 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2646 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2652 GdkWindow
*window
= m_widget
->window
;
2653 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2654 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2662 void wxWindow::DoGetSize( int *width
, int *height
) const
2664 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2666 if (width
) (*width
) = m_width
;
2667 if (height
) (*height
) = m_height
;
2670 void wxWindow::DoSetClientSize( int width
, int height
)
2672 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2676 SetSize( width
, height
);
2683 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2685 /* when using GTK 1.2 we set the shadow border size to 2 */
2689 if (HasFlag(wxSIMPLE_BORDER
))
2691 /* when using GTK 1.2 we set the simple border size to 1 */
2698 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2700 GtkRequisition vscroll_req
;
2701 vscroll_req
.width
= 2;
2702 vscroll_req
.height
= 2;
2703 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2704 (scroll_window
->vscrollbar
, &vscroll_req
);
2706 GtkRequisition hscroll_req
;
2707 hscroll_req
.width
= 2;
2708 hscroll_req
.height
= 2;
2709 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2710 (scroll_window
->hscrollbar
, &hscroll_req
);
2712 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2714 if (scroll_window
->vscrollbar_visible
)
2716 dw
+= vscroll_req
.width
;
2717 dw
+= scroll_class
->scrollbar_spacing
;
2720 if (scroll_window
->hscrollbar_visible
)
2722 dh
+= hscroll_req
.height
;
2723 dh
+= scroll_class
->scrollbar_spacing
;
2727 SetSize( width
+dw
, height
+dh
);
2731 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2733 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2737 if (width
) (*width
) = m_width
;
2738 if (height
) (*height
) = m_height
;
2745 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2747 /* when using GTK 1.2 we set the shadow border size to 2 */
2751 if (HasFlag(wxSIMPLE_BORDER
))
2753 /* when using GTK 1.2 we set the simple border size to 1 */
2760 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2762 GtkRequisition vscroll_req
;
2763 vscroll_req
.width
= 2;
2764 vscroll_req
.height
= 2;
2765 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2766 (scroll_window
->vscrollbar
, &vscroll_req
);
2768 GtkRequisition hscroll_req
;
2769 hscroll_req
.width
= 2;
2770 hscroll_req
.height
= 2;
2771 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2772 (scroll_window
->hscrollbar
, &hscroll_req
);
2774 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2776 if (scroll_window
->vscrollbar_visible
)
2778 dw
+= vscroll_req
.width
;
2779 dw
+= scroll_class
->scrollbar_spacing
;
2782 if (scroll_window
->hscrollbar_visible
)
2784 dh
+= hscroll_req
.height
;
2785 dh
+= scroll_class
->scrollbar_spacing
;
2789 if (width
) (*width
) = m_width
- dw
;
2790 if (height
) (*height
) = m_height
- dh
;
2794 void wxWindow::DoGetPosition( int *x
, int *y
) const
2796 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2800 if (m_parent
&& m_parent
->m_wxwindow
)
2802 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2803 dx
= pizza
->xoffset
;
2804 dy
= pizza
->yoffset
;
2807 if (x
) (*x
) = m_x
- dx
;
2808 if (y
) (*y
) = m_y
- dy
;
2811 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2813 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2815 if (!m_widget
->window
) return;
2817 GdkWindow
*source
= (GdkWindow
*) NULL
;
2819 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2821 source
= m_widget
->window
;
2825 gdk_window_get_origin( source
, &org_x
, &org_y
);
2829 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2831 org_x
+= m_widget
->allocation
.x
;
2832 org_y
+= m_widget
->allocation
.y
;
2840 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2842 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2844 if (!m_widget
->window
) return;
2846 GdkWindow
*source
= (GdkWindow
*) NULL
;
2848 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2850 source
= m_widget
->window
;
2854 gdk_window_get_origin( source
, &org_x
, &org_y
);
2858 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2860 org_x
+= m_widget
->allocation
.x
;
2861 org_y
+= m_widget
->allocation
.y
;
2869 bool wxWindow::Show( bool show
)
2871 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2873 if (!wxWindowBase::Show(show
))
2880 gtk_widget_show( m_widget
);
2882 gtk_widget_hide( m_widget
);
2887 bool wxWindow::Enable( bool enable
)
2889 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2891 if (!wxWindowBase::Enable(enable
))
2897 gtk_widget_set_sensitive( m_widget
, enable
);
2899 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2904 int wxWindow::GetCharHeight() const
2906 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2908 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2910 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2912 return font
->ascent
+ font
->descent
;
2915 int wxWindow::GetCharWidth() const
2917 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2919 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2921 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2923 return gdk_string_width( font
, "H" );
2926 void wxWindow::GetTextExtent( const wxString
& string
,
2930 int *externalLeading
,
2931 const wxFont
*theFont
) const
2933 wxFont fontToUse
= m_font
;
2934 if (theFont
) fontToUse
= *theFont
;
2936 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2938 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2939 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2940 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2941 if (descent
) (*descent
) = font
->descent
;
2942 if (externalLeading
) (*externalLeading
) = 0; // ??
2945 void wxWindow::SetFocus()
2947 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2951 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2952 gtk_widget_grab_focus (m_wxwindow
);
2958 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2960 gtk_widget_grab_focus (m_widget
);
2962 else if (GTK_IS_CONTAINER(m_widget
))
2964 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2973 bool wxWindow::AcceptsFocus() const
2975 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2978 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2980 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2982 wxWindow
*oldParent
= m_parent
,
2983 *newParent
= (wxWindow
*)newParentBase
;
2985 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2987 if ( !wxWindowBase::Reparent(newParent
) )
2990 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2992 /* prevent GTK from deleting the widget arbitrarily */
2993 gtk_widget_ref( m_widget
);
2997 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3000 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3004 /* insert GTK representation */
3005 (*(newParent
->m_insertCallback
))(newParent
, this);
3008 /* reverse: prevent GTK from deleting the widget arbitrarily */
3009 gtk_widget_unref( m_widget
);
3014 void wxWindow::DoAddChild(wxWindow
*child
)
3016 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3018 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3020 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3025 /* insert GTK representation */
3026 (*m_insertCallback
)(this, child
);
3029 void wxWindow::Raise()
3031 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3033 if (!m_widget
->window
) return;
3035 gdk_window_raise( m_widget
->window
);
3038 void wxWindow::Lower()
3040 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3042 if (!m_widget
->window
) return;
3044 gdk_window_lower( m_widget
->window
);
3047 bool wxWindow::SetCursor( const wxCursor
&cursor
)
3049 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3051 if (cursor
== m_cursor
)
3055 wxapp_install_idle_handler();
3057 if (cursor
== wxNullCursor
)
3058 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3060 return wxWindowBase::SetCursor( cursor
);
3063 void wxWindow::WarpPointer( int x
, int y
)
3065 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3067 /* we provide this function ourselves as it is
3068 missing in GDK (top of this file) */
3070 GdkWindow
*window
= (GdkWindow
*) NULL
;
3072 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3074 window
= GetConnectWidget()->window
;
3077 gdk_window_warp_pointer( window
, x
, y
);
3080 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
3082 if (!m_widget
) return;
3083 if (!m_widget
->window
) return;
3085 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3089 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3091 rect
->width
, rect
->height
);
3095 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3099 /* there is no GTK equivalent of "draw only, don't clear" so we
3100 invent our own in the GtkPizza widget */
3108 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3109 gboolean old_clear = pizza->clear_on_draw;
3110 gtk_pizza_set_clear( pizza, FALSE );
3111 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3112 gtk_pizza_set_clear( pizza, old_clear );
3114 GdkEventExpose gdk_event
;
3115 gdk_event
.type
= GDK_EXPOSE
;
3116 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3117 gdk_event
.count
= 0;
3118 gdk_event
.area
.x
= 0;
3119 gdk_event
.area
.y
= 0;
3120 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3121 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3122 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3127 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3136 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3137 gboolean old_clear = pizza->clear_on_draw;
3138 gtk_pizza_set_clear( pizza, FALSE );
3140 GdkRectangle gdk_rect;
3141 gdk_rect.x = rect->x;
3142 gdk_rect.y = rect->y;
3143 gdk_rect.width = rect->width;
3144 gdk_rect.height = rect->height;
3145 gtk_widget_draw( m_wxwindow, &gdk_rect );
3146 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3148 gtk_pizza_set_clear( pizza, old_clear );
3150 GdkEventExpose gdk_event
;
3151 gdk_event
.type
= GDK_EXPOSE
;
3152 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3153 gdk_event
.count
= 0;
3154 gdk_event
.area
.x
= rect
->x
;
3155 gdk_event
.area
.y
= rect
->y
;
3156 gdk_event
.area
.width
= rect
->width
;
3157 gdk_event
.area
.height
= rect
->height
;
3158 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3162 GdkRectangle gdk_rect
;
3163 gdk_rect
.x
= rect
->x
;
3164 gdk_rect
.y
= rect
->y
;
3165 gdk_rect
.width
= rect
->width
;
3166 gdk_rect
.height
= rect
->height
;
3167 gtk_widget_draw( m_widget
, &gdk_rect
);
3172 void wxWindow::Clear()
3174 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3176 if (!m_widget
->window
) return;
3178 if (m_wxwindow
&& m_wxwindow
->window
)
3180 // gdk_window_clear( m_wxwindow->window );
3185 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
3187 wxWindowBase::DoSetToolTip(tip
);
3190 m_tooltip
->Apply( this );
3193 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3195 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3197 #endif // wxUSE_TOOLTIPS
3199 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
3201 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3203 if (!wxWindowBase::SetBackgroundColour(colour
))
3205 // don't leave if the GTK widget has just
3207 if (!m_delayedBackgroundColour
) return FALSE
;
3210 GdkWindow
*window
= (GdkWindow
*) NULL
;
3212 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3214 window
= GetConnectWidget()->window
;
3218 // indicate that a new style has been set
3219 // but it couldn't get applied as the
3220 // widget hasn't been realized yet.
3221 m_delayedBackgroundColour
= TRUE
;
3225 (m_wxwindow
->window
) &&
3226 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3228 /* wxMSW doesn't clear the window here. I don't do that either to
3229 provide compatibility. call Clear() to do the job. */
3231 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3232 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3240 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
3242 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3244 if (!wxWindowBase::SetForegroundColour(colour
))
3246 // don't leave if the GTK widget has just
3248 if (!m_delayedForegroundColour
) return FALSE
;
3251 GdkWindow
*window
= (GdkWindow
*) NULL
;
3253 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3255 window
= GetConnectWidget()->window
;
3259 // indicate that a new style has been set
3260 // but it couldn't get applied as the
3261 // widget hasn't been realized yet.
3262 m_delayedForegroundColour
= TRUE
;
3270 GtkStyle
*wxWindow::GetWidgetStyle()
3274 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3276 /* FIXME: is this necessary? */
3277 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3279 remake
->klass
= m_widgetStyle
->klass
;
3282 gtk_style_unref( m_widgetStyle
);
3283 m_widgetStyle
= remake
;
3287 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3290 def
= gtk_widget_get_default_style();
3292 m_widgetStyle
= gtk_style_copy( def
);
3294 /* FIXME: is this necessary? */
3295 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3297 m_widgetStyle
->klass
= def
->klass
;
3301 return m_widgetStyle
;
3304 void wxWindow::SetWidgetStyle()
3306 #if DISABLE_STYLE_IF_BROKEN_THEM
3307 if (m_widget
->style
->engine_data
)
3309 static bool s_warningPrinted
= FALSE
;
3310 if (!s_warningPrinted
)
3312 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3313 s_warningPrinted
= TRUE
;
3315 m_widgetStyle
= m_widget
->style
;
3320 GtkStyle
*style
= GetWidgetStyle();
3322 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3324 gdk_font_unref( style
->font
);
3325 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3328 if (m_foregroundColour
.Ok())
3330 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3331 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3333 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3334 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3335 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3339 // Try to restore the gtk default style. This is still a little
3340 // oversimplified for what is probably really needed here for controls
3341 // other than buttons, but is better than not being able to (re)set a
3342 // control's foreground colour to *wxBLACK -- RL
3343 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3346 def
= gtk_widget_get_default_style();
3348 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3349 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3350 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3354 if (m_backgroundColour
.Ok())
3356 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3357 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3359 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3360 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3361 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3362 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3363 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3364 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3365 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3366 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3370 // Try to restore the gtk default style. This is still a little
3371 // oversimplified for what is probably really needed here for controls
3372 // other than buttons, but is better than not being able to (re)set a
3373 // control's background colour to default grey and means resetting a
3374 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3376 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3379 def
= gtk_widget_get_default_style();
3381 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3382 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3383 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3384 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3385 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3386 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3387 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3388 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3393 void wxWindow::ApplyWidgetStyle()
3397 //-----------------------------------------------------------------------------
3398 // Pop-up menu stuff
3399 //-----------------------------------------------------------------------------
3401 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3403 *is_waiting
= FALSE
;
3406 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3408 menu
->SetInvokingWindow( win
);
3409 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3412 wxMenuItem
*menuitem
= node
->GetData();
3413 if (menuitem
->IsSubMenu())
3415 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3418 node
= node
->GetNext();
3422 static gint gs_pop_x
= 0;
3423 static gint gs_pop_y
= 0;
3425 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3429 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3434 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3436 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3438 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3440 SetInvokingWindow( menu
, this );
3447 bool is_waiting
= TRUE
;
3449 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3450 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3453 GTK_MENU(menu
->m_menu
),
3454 (GtkWidget
*) NULL
, // parent menu shell
3455 (GtkWidget
*) NULL
, // parent menu item
3456 (GtkMenuPositionFunc
) pop_pos_callback
,
3457 (gpointer
) this, // client data
3458 0, // button used to activate it
3459 gs_timeLastClick
// the time of activation
3464 while (gtk_events_pending())
3465 gtk_main_iteration();
3471 #if wxUSE_DRAG_AND_DROP
3473 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3475 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3477 GtkWidget
*dnd_widget
= GetConnectWidget();
3479 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3481 if (m_dropTarget
) delete m_dropTarget
;
3482 m_dropTarget
= dropTarget
;
3484 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3487 #endif // wxUSE_DRAG_AND_DROP
3489 GtkWidget
* wxWindow::GetConnectWidget()
3491 GtkWidget
*connect_widget
= m_widget
;
3492 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3494 return connect_widget
;
3497 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3500 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3502 return (window
== m_widget
->window
);
3505 bool wxWindow::SetFont( const wxFont
&font
)
3507 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3509 if (!wxWindowBase::SetFont(font
))
3514 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3515 if ( sysbg
== m_backgroundColour
)
3517 m_backgroundColour
= wxNullColour
;
3519 m_backgroundColour
= sysbg
;
3529 void wxWindow::CaptureMouse()
3531 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3533 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3535 GdkWindow
*window
= (GdkWindow
*) NULL
;
3537 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3539 window
= GetConnectWidget()->window
;
3541 if (!window
) return;
3543 wxCursor
* cursor
= & m_cursor
;
3545 cursor
= wxSTANDARD_CURSOR
;
3547 gdk_pointer_grab( window
, FALSE
,
3549 (GDK_BUTTON_PRESS_MASK
|
3550 GDK_BUTTON_RELEASE_MASK
|
3551 GDK_POINTER_MOTION_HINT_MASK
|
3552 GDK_POINTER_MOTION_MASK
),
3554 cursor
->GetCursor(),
3555 (guint32
)GDK_CURRENT_TIME
);
3556 g_captureWindow
= this;
3559 void wxWindow::ReleaseMouse()
3561 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3563 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3565 GdkWindow
*window
= (GdkWindow
*) NULL
;
3567 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3569 window
= GetConnectWidget()->window
;
3574 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3575 g_captureWindow
= (wxWindow
*) NULL
;
3578 bool wxWindow::IsRetained() const
3583 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3584 int range
, bool refresh
)
3586 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3588 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3590 m_hasScrolling
= TRUE
;
3592 if (orient
== wxHORIZONTAL
)
3594 float fpos
= (float)pos
;
3595 float frange
= (float)range
;
3596 float fthumb
= (float)thumbVisible
;
3597 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3598 if (fpos
< 0.0) fpos
= 0.0;
3600 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3601 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3603 SetScrollPos( orient
, pos
, refresh
);
3607 m_oldHorizontalPos
= fpos
;
3609 m_hAdjust
->lower
= 0.0;
3610 m_hAdjust
->upper
= frange
;
3611 m_hAdjust
->value
= fpos
;
3612 m_hAdjust
->step_increment
= 1.0;
3613 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3614 m_hAdjust
->page_size
= fthumb
;
3618 float fpos
= (float)pos
;
3619 float frange
= (float)range
;
3620 float fthumb
= (float)thumbVisible
;
3621 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3622 if (fpos
< 0.0) fpos
= 0.0;
3624 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3625 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3627 SetScrollPos( orient
, pos
, refresh
);
3631 m_oldVerticalPos
= fpos
;
3633 m_vAdjust
->lower
= 0.0;
3634 m_vAdjust
->upper
= frange
;
3635 m_vAdjust
->value
= fpos
;
3636 m_vAdjust
->step_increment
= 1.0;
3637 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3638 m_vAdjust
->page_size
= fthumb
;
3641 if (orient
== wxHORIZONTAL
)
3642 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3644 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3647 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3649 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3651 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3653 if (orient
== wxHORIZONTAL
)
3655 float fpos
= (float)pos
;
3656 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3657 if (fpos
< 0.0) fpos
= 0.0;
3658 m_oldHorizontalPos
= fpos
;
3660 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3661 m_hAdjust
->value
= fpos
;
3665 float fpos
= (float)pos
;
3666 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3667 if (fpos
< 0.0) fpos
= 0.0;
3668 m_oldVerticalPos
= fpos
;
3670 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3671 m_vAdjust
->value
= fpos
;
3674 if (m_wxwindow
->window
)
3676 if (orient
== wxHORIZONTAL
)
3678 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3679 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3681 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3683 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3684 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3688 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3689 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3691 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3693 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3694 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3699 int wxWindow::GetScrollThumb( int orient
) const
3701 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3703 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3705 if (orient
== wxHORIZONTAL
)
3706 return (int)(m_hAdjust
->page_size
+0.5);
3708 return (int)(m_vAdjust
->page_size
+0.5);
3711 int wxWindow::GetScrollPos( int orient
) const
3713 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3715 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3717 if (orient
== wxHORIZONTAL
)
3718 return (int)(m_hAdjust
->value
+0.5);
3720 return (int)(m_vAdjust
->value
+0.5);
3723 int wxWindow::GetScrollRange( int orient
) const
3725 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3727 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3729 if (orient
== wxHORIZONTAL
)
3730 return (int)(m_hAdjust
->upper
+0.5);
3732 return (int)(m_vAdjust
->upper
+0.5);
3735 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3737 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3739 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3741 if ((dx
== 0) && (dy
== 0)) return;
3743 m_clipPaintRegion
= TRUE
;
3744 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3745 m_clipPaintRegion
= FALSE
;
3748 if (m_children.GetCount() > 0)
3750 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3754 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3756 pizza->xoffset -= dx;
3757 pizza->yoffset -= dy;
3759 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3760 gdk_gc_set_exposures( m_scrollGC, TRUE );
3764 GetClientSize( &cw, &ch );
3765 int w = cw - abs(dx);
3766 int h = ch - abs(dy);
3768 if ((h < 0) || (w < 0))
3776 if (dx < 0) s_x = -dx;
3777 if (dy < 0) s_y = -dy;
3780 if (dx > 0) d_x = dx;
3781 if (dy > 0) d_y = dy;
3783 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3784 pizza->bin_window, s_x, s_y, w, h );
3787 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3788 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3789 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3790 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3792 Refresh( TRUE, &rect );
3795 gdk_gc_unref( m_scrollGC );
3800 // Find the wxWindow at the current mouse position, also returning the mouse
3802 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
3804 pt
= wxGetMousePosition();
3805 wxWindow
* found
= wxFindWindowAtPoint(pt
);
3809 // Get the current mouse position.
3810 wxPoint
wxGetMousePosition()
3812 /* This crashes when used within wxHelpContext,
3813 so we have to use the X-specific implementation below.
3815 GdkModifierType *mask;
3816 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
3818 return wxPoint(x, y);
3822 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
3824 return wxPoint(-999, -999);
3826 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
3827 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
3828 Window rootReturn
, childReturn
;
3829 int rootX
, rootY
, winX
, winY
;
3830 unsigned int maskReturn
;
3832 XQueryPointer (display
,
3836 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
3837 return wxPoint(rootX
, rootY
);