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 // "size_request" of m_widget
660 //-----------------------------------------------------------------------------
662 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
665 win
->GetSize( &w
, &h
);
669 requisition
->height
= h
;
670 requisition
->width
= w
;
673 //-----------------------------------------------------------------------------
674 // "expose_event" of m_wxwindow
675 //-----------------------------------------------------------------------------
677 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
682 wxapp_install_idle_handler();
685 if (win->GetName() == wxT("panel"))
687 wxPrintf( wxT("OnExpose from ") );
688 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
689 wxPrintf( win->GetClassInfo()->GetClassName() );
690 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
691 (int)gdk_event->area.y,
692 (int)gdk_event->area.width,
693 (int)gdk_event->area.height );
697 GtkPizza
*pizza
= GTK_PIZZA (widget
);
699 if (win
->GetThemeEnabled())
701 wxWindow
*parent
= win
->GetParent();
702 while (parent
&& !parent
->IsTopLevel())
703 parent
= parent
->GetParent();
707 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
708 GTK_SHADOW_NONE
, &gdk_event
->area
, parent
->m_widget
, "base", 0, 0, -1, -1);
711 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
713 gdk_event
->area
.width
,
714 gdk_event
->area
.height
);
716 if (gdk_event
->count
== 0)
718 win
->m_clipPaintRegion
= TRUE
;
720 wxEraseEvent
eevent( win
->GetId() );
721 eevent
.SetEventObject( win
);
722 win
->GetEventHandler()->ProcessEvent(eevent
);
724 wxPaintEvent
event( win
->GetId() );
725 event
.SetEventObject( win
);
726 win
->GetEventHandler()->ProcessEvent( event
);
728 win
->GetUpdateRegion().Clear();
730 win
->m_clipPaintRegion
= FALSE
;
733 /* The following code will result in all window-less widgets
734 being redrawn if the wxWindows class is given a chance to
735 paint *anything* because it will then be allowed to paint
736 over the window-less widgets */
738 GList
*children
= pizza
->children
;
741 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
742 children
= children
->next
;
744 GdkEventExpose child_event
= *gdk_event
;
746 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
747 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
748 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
750 child_event
.area
.x
= child
->widget
->allocation
.x
;
751 child_event
.area
.y
= child
->widget
->allocation
.y
;
752 child_event
.area
.width
= child
->widget
->allocation
.width
;
753 child_event
.area
.height
= child
->widget
->allocation
.height
;
754 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
761 //-----------------------------------------------------------------------------
762 // "event" of m_wxwindow
763 //-----------------------------------------------------------------------------
765 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
766 expose events. We need them, of course, so we override the main event
767 procedure in GtkWidget by giving our own handler for all system events.
768 There, we look for expose events ourselves whereas all other events are
771 gint
gtk_window_event_event_callback( GtkWidget
*widget
, GdkEventExpose
*event
, wxWindow
*win
)
773 if (event
->type
== GDK_EXPOSE
)
775 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
782 //-----------------------------------------------------------------------------
783 // "draw" of m_wxwindow
784 //-----------------------------------------------------------------------------
786 /* This callback is a complete replacement of the gtk_pizza_draw() function,
789 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
794 wxapp_install_idle_handler();
796 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
797 (win
->GetChildren().GetCount() == 0))
803 if (win->GetName() == wxT("panel"))
805 wxPrintf( wxT("OnDraw from ") );
806 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
807 wxPrintf( win->GetClassInfo()->GetClassName() );
808 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
815 GtkPizza
*pizza
= GTK_PIZZA (widget
);
817 if (win
->GetThemeEnabled())
819 wxWindow
*parent
= win
->GetParent();
820 while (parent
&& !parent
->IsTopLevel())
821 parent
= parent
->GetParent();
825 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
826 GTK_SHADOW_NONE
, rect
, parent
->m_widget
, "base", 0, 0, -1, -1);
830 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
831 (pizza
->clear_on_draw
))
833 gdk_window_clear_area( pizza
->bin_window
,
834 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
837 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
839 win
->m_clipPaintRegion
= TRUE
;
841 wxEraseEvent
eevent( win
->GetId() );
842 eevent
.SetEventObject( win
);
843 win
->GetEventHandler()->ProcessEvent(eevent
);
845 wxPaintEvent
event( win
->GetId() );
846 event
.SetEventObject( win
);
847 win
->GetEventHandler()->ProcessEvent( event
);
849 win
->GetUpdateRegion().Clear();
851 win
->m_clipPaintRegion
= FALSE
;
854 GList
*children
= pizza
->children
;
857 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
858 children
= children
->next
;
860 GdkRectangle child_area
;
861 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
863 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
868 //-----------------------------------------------------------------------------
869 // "key_press_event" from any window
870 //-----------------------------------------------------------------------------
872 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
877 wxapp_install_idle_handler();
879 if (!win
->m_hasVMT
) return FALSE
;
880 if (g_blockEventsOnDrag
) return FALSE
;
885 tmp += (char)gdk_event->keyval;
886 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
887 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
892 GdkModifierType state
;
893 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
897 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
898 /* sending unknown key events doesn't really make sense */
899 if (key_code
== 0) return FALSE
;
901 wxKeyEvent
event( wxEVT_KEY_DOWN
);
902 event
.SetTimestamp( gdk_event
->time
);
903 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
904 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
905 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
906 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
907 event
.m_keyCode
= key_code
;
908 event
.m_scanCode
= gdk_event
->keyval
;
911 event
.SetEventObject( win
);
912 ret
= win
->GetEventHandler()->ProcessEvent( event
);
917 wxWindow
*ancestor
= win
;
920 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
923 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
924 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
927 if (ancestor
->IsTopLevel())
929 ancestor
= ancestor
->GetParent();
932 #endif // wxUSE_ACCEL
934 /* wxMSW doesn't send char events with Alt pressed */
935 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
936 will only be sent if it is not in an accelerator table. */
937 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
942 wxKeyEvent
event2( wxEVT_CHAR
);
943 event2
.SetTimestamp( gdk_event
->time
);
944 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
945 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
946 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
947 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
948 event2
.m_keyCode
= key_code
;
949 event2
.m_scanCode
= gdk_event
->keyval
;
952 event2
.SetEventObject( win
);
953 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
956 /* win is a control: tab can be propagated up */
958 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
959 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
960 // have this style, yet choose not to process this particular TAB in which
961 // case TAB must still work as a navigational character
963 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
965 (win
->GetParent()) &&
966 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
968 wxNavigationKeyEvent new_event
;
969 new_event
.SetEventObject( win
->GetParent() );
970 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
971 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
972 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
973 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
974 new_event
.SetCurrentFocus( win
);
975 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
978 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
980 (gdk_event
->keyval
== GDK_Escape
) )
982 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
983 new_event
.SetEventObject( win
);
984 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
987 #if (GTK_MINOR_VERSION > 0)
988 /* Pressing F10 will activate the menu bar of the top frame. */
992 (gdk_event->keyval == GDK_F10) )
994 wxWindow *ancestor = win;
997 if (wxIsKindOf(ancestor,wxFrame))
999 wxFrame *frame = (wxFrame*) ancestor;
1000 wxMenuBar *menubar = frame->GetMenuBar();
1003 wxNode *node = menubar->GetMenus().First();
1006 wxMenu *firstMenu = (wxMenu*) node->Data();
1007 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
1013 ancestor = ancestor->GetParent();
1021 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1028 //-----------------------------------------------------------------------------
1029 // "key_release_event" from any window
1030 //-----------------------------------------------------------------------------
1032 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
1037 wxapp_install_idle_handler();
1039 if (!win
->m_hasVMT
) return FALSE
;
1040 if (g_blockEventsOnDrag
) return FALSE
;
1043 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
1044 if (gdk_event->state & GDK_SHIFT_MASK)
1045 printf( "ShiftDown.\n" );
1047 printf( "ShiftUp.\n" );
1048 if (gdk_event->state & GDK_CONTROL_MASK)
1049 printf( "ControlDown.\n" );
1051 printf( "ControlUp.\n" );
1055 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
1057 /* sending unknown key events doesn't really make sense */
1058 if (key_code
== 0) return FALSE
;
1062 GdkModifierType state
;
1063 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1065 wxKeyEvent
event( wxEVT_KEY_UP
);
1066 event
.SetTimestamp( gdk_event
->time
);
1067 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1068 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1069 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1070 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1071 event
.m_keyCode
= key_code
;
1072 event
.m_scanCode
= gdk_event
->keyval
;
1075 event
.SetEventObject( win
);
1077 if (win
->GetEventHandler()->ProcessEvent( event
))
1079 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1086 // ----------------------------------------------------------------------------
1087 // mouse event processing helper
1088 // ----------------------------------------------------------------------------
1090 static void AdjustEventButtonState(wxMouseEvent
& event
)
1092 // GDK reports the old state of the button for a button press event, but
1093 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1094 // for a LEFT_DOWN event, not FALSE, so we will invert
1095 // left/right/middleDown for the corresponding click events
1097 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1098 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1099 (event
.GetEventType() == wxEVT_LEFT_UP
))
1101 event
.m_leftDown
= !event
.m_leftDown
;
1105 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1106 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1107 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1109 event
.m_middleDown
= !event
.m_middleDown
;
1113 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1114 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1115 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1117 event
.m_rightDown
= !event
.m_rightDown
;
1122 //-----------------------------------------------------------------------------
1123 // "button_press_event"
1124 //-----------------------------------------------------------------------------
1126 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1131 wxapp_install_idle_handler();
1134 wxPrintf( wxT("1) OnButtonPress from ") );
1135 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1136 wxPrintf( win->GetClassInfo()->GetClassName() );
1137 wxPrintf( wxT(".\n") );
1139 if (!win
->m_hasVMT
) return FALSE
;
1140 if (g_blockEventsOnDrag
) return TRUE
;
1141 if (g_blockEventsOnScroll
) return TRUE
;
1143 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1145 if (win
->m_wxwindow
)
1147 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1149 gtk_widget_grab_focus (win
->m_wxwindow
);
1152 wxPrintf( wxT("GrabFocus from ") );
1153 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1154 wxPrintf( win->GetClassInfo()->GetClassName() );
1155 wxPrintf( wxT(".\n") );
1161 wxEventType event_type
= wxEVT_NULL
;
1163 if (gdk_event
->button
== 1)
1165 switch (gdk_event
->type
)
1167 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1168 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1172 else if (gdk_event
->button
== 2)
1174 switch (gdk_event
->type
)
1176 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1177 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1181 else if (gdk_event
->button
== 3)
1183 switch (gdk_event
->type
)
1185 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1186 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1191 if ( event_type
== wxEVT_NULL
)
1193 // unknown mouse button or click type
1197 wxMouseEvent
event( event_type
);
1198 event
.SetTimestamp( gdk_event
->time
);
1199 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1200 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1201 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1202 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1203 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1204 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1205 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1207 event
.m_x
= (wxCoord
)gdk_event
->x
;
1208 event
.m_y
= (wxCoord
)gdk_event
->y
;
1210 AdjustEventButtonState(event
);
1212 // Some control don't have their own X window and thus cannot get
1215 if (!g_captureWindow
)
1217 wxCoord x
= event
.m_x
;
1218 wxCoord y
= event
.m_y
;
1219 if (win
->m_wxwindow
)
1221 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1222 x
+= pizza
->xoffset
;
1223 y
+= pizza
->yoffset
;
1226 wxNode
*node
= win
->GetChildren().First();
1229 wxWindow
*child
= (wxWindow
*)node
->Data();
1231 node
= node
->Next();
1232 if (!child
->IsShown())
1235 if (child
->m_isStaticBox
)
1237 // wxStaticBox is transparent in the box itself
1238 int xx1
= child
->m_x
;
1239 int yy1
= child
->m_y
;
1240 int xx2
= child
->m_x
+ child
->m_width
;
1241 int yy2
= child
->m_x
+ child
->m_height
;
1244 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1246 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1248 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1250 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1253 event
.m_x
-= child
->m_x
;
1254 event
.m_y
-= child
->m_y
;
1261 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1262 (child
->m_x
<= x
) &&
1263 (child
->m_y
<= y
) &&
1264 (child
->m_x
+child
->m_width
>= x
) &&
1265 (child
->m_y
+child
->m_height
>= y
))
1268 event
.m_x
-= child
->m_x
;
1269 event
.m_y
-= child
->m_y
;
1276 event
.SetEventObject( win
);
1278 gs_timeLastClick
= gdk_event
->time
;
1281 wxPrintf( wxT("2) OnButtonPress from ") );
1282 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1283 wxPrintf( win->GetClassInfo()->GetClassName() );
1284 wxPrintf( wxT(".\n") );
1287 if (win
->GetEventHandler()->ProcessEvent( event
))
1289 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1296 //-----------------------------------------------------------------------------
1297 // "button_release_event"
1298 //-----------------------------------------------------------------------------
1300 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1305 wxapp_install_idle_handler();
1307 if (!win
->m_hasVMT
) return FALSE
;
1308 if (g_blockEventsOnDrag
) return FALSE
;
1309 if (g_blockEventsOnScroll
) return FALSE
;
1311 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1314 printf( "OnButtonRelease from " );
1315 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1316 printf( win->GetClassInfo()->GetClassName() );
1320 wxEventType event_type
= wxEVT_NULL
;
1322 switch (gdk_event
->button
)
1324 case 1: event_type
= wxEVT_LEFT_UP
; break;
1325 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1326 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1327 default: return FALSE
;
1330 wxMouseEvent
event( event_type
);
1331 event
.SetTimestamp( gdk_event
->time
);
1332 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1333 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1334 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1335 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1336 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1337 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1338 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1339 event
.m_x
= (wxCoord
)gdk_event
->x
;
1340 event
.m_y
= (wxCoord
)gdk_event
->y
;
1342 AdjustEventButtonState(event
);
1344 // Some control don't have their own X window and thus cannot get
1347 if (!g_captureWindow
)
1349 wxCoord x
= event
.m_x
;
1350 wxCoord y
= event
.m_y
;
1351 if (win
->m_wxwindow
)
1353 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1354 x
+= pizza
->xoffset
;
1355 y
+= pizza
->yoffset
;
1358 wxNode
*node
= win
->GetChildren().First();
1361 wxWindow
*child
= (wxWindow
*)node
->Data();
1363 node
= node
->Next();
1364 if (!child
->IsShown())
1367 if (child
->m_isStaticBox
)
1369 // wxStaticBox is transparent in the box itself
1370 int xx1
= child
->m_x
;
1371 int yy1
= child
->m_y
;
1372 int xx2
= child
->m_x
+ child
->m_width
;
1373 int yy2
= child
->m_x
+ child
->m_height
;
1376 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1378 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1380 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1382 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1385 event
.m_x
-= child
->m_x
;
1386 event
.m_y
-= child
->m_y
;
1393 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1394 (child
->m_x
<= x
) &&
1395 (child
->m_y
<= y
) &&
1396 (child
->m_x
+child
->m_width
>= x
) &&
1397 (child
->m_y
+child
->m_height
>= y
))
1400 event
.m_x
-= child
->m_x
;
1401 event
.m_y
-= child
->m_y
;
1408 event
.SetEventObject( win
);
1410 if (win
->GetEventHandler()->ProcessEvent( event
))
1412 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1419 //-----------------------------------------------------------------------------
1420 // "motion_notify_event"
1421 //-----------------------------------------------------------------------------
1423 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1428 wxapp_install_idle_handler();
1430 if (!win
->m_hasVMT
) return FALSE
;
1431 if (g_blockEventsOnDrag
) return FALSE
;
1432 if (g_blockEventsOnScroll
) return FALSE
;
1434 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1436 if (gdk_event
->is_hint
)
1440 GdkModifierType state
;
1441 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1447 printf( "OnMotion from " );
1448 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1449 printf( win->GetClassInfo()->GetClassName() );
1453 wxMouseEvent
event( wxEVT_MOTION
);
1454 event
.SetTimestamp( gdk_event
->time
);
1455 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1456 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1457 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1458 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1459 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1460 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1461 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1463 event
.m_x
= (wxCoord
)gdk_event
->x
;
1464 event
.m_y
= (wxCoord
)gdk_event
->y
;
1466 // Some control don't have their own X window and thus cannot get
1469 if (!g_captureWindow
)
1471 wxCoord x
= event
.m_x
;
1472 wxCoord y
= event
.m_y
;
1473 if (win
->m_wxwindow
)
1475 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1476 x
+= pizza
->xoffset
;
1477 y
+= pizza
->yoffset
;
1480 wxNode
*node
= win
->GetChildren().First();
1483 wxWindow
*child
= (wxWindow
*)node
->Data();
1485 node
= node
->Next();
1486 if (!child
->IsShown())
1489 if (child
->m_isStaticBox
)
1491 // wxStaticBox is transparent in the box itself
1492 int xx1
= child
->m_x
;
1493 int yy1
= child
->m_y
;
1494 int xx2
= child
->m_x
+ child
->m_width
;
1495 int yy2
= child
->m_x
+ child
->m_height
;
1498 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1500 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1502 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1504 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1507 event
.m_x
-= child
->m_x
;
1508 event
.m_y
-= child
->m_y
;
1515 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1516 (child
->m_x
<= x
) &&
1517 (child
->m_y
<= y
) &&
1518 (child
->m_x
+child
->m_width
>= x
) &&
1519 (child
->m_y
+child
->m_height
>= y
))
1522 event
.m_x
-= child
->m_x
;
1523 event
.m_y
-= child
->m_y
;
1530 event
.SetEventObject( win
);
1532 if (win
->GetEventHandler()->ProcessEvent( event
))
1534 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1541 //-----------------------------------------------------------------------------
1543 //-----------------------------------------------------------------------------
1545 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1550 wxapp_install_idle_handler();
1552 if (!win
->m_hasVMT
) return FALSE
;
1553 if (g_blockEventsOnDrag
) return FALSE
;
1555 switch ( g_sendActivateEvent
)
1558 // we've got focus from outside, synthtize wxActivateEvent
1559 g_sendActivateEvent
= 1;
1563 // another our window just lost focus, it was already ours before
1564 // - don't send any wxActivateEvent
1565 g_sendActivateEvent
= -1;
1569 g_focusWindow
= win
;
1572 printf( "OnSetFocus from " );
1573 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1574 printf( win->GetClassInfo()->GetClassName() );
1576 printf( WXSTRINGCAST win->GetLabel() );
1580 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1583 panel
->SetLastFocus(win
);
1588 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1592 // caret needs to be informed about focus change
1593 wxCaret
*caret
= win
->GetCaret();
1596 caret
->OnSetFocus();
1598 #endif // wxUSE_CARET
1600 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1601 event
.SetEventObject( win
);
1603 if (win
->GetEventHandler()->ProcessEvent( event
))
1605 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1612 //-----------------------------------------------------------------------------
1613 // "focus_out_event"
1614 //-----------------------------------------------------------------------------
1616 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1621 wxapp_install_idle_handler();
1623 if (!win
->m_hasVMT
) return FALSE
;
1624 if (g_blockEventsOnDrag
) return FALSE
;
1626 // if the focus goes out of our app alltogether, OnIdle() will send
1627 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1628 // g_sendActivateEvent to -1
1629 g_sendActivateEvent
= 0;
1631 wxWindow
*winFocus
= FindFocusedChild(win
);
1635 g_focusWindow
= (wxWindow
*)NULL
;
1638 printf( "OnKillFocus from " );
1639 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1640 printf( win->GetClassInfo()->GetClassName() );
1650 // caret needs to be informed about focus change
1651 wxCaret
*caret
= win
->GetCaret();
1654 caret
->OnKillFocus();
1656 #endif // wxUSE_CARET
1658 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1659 event
.SetEventObject( win
);
1661 if (win
->GetEventHandler()->ProcessEvent( event
))
1663 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1670 //-----------------------------------------------------------------------------
1671 // "enter_notify_event"
1672 //-----------------------------------------------------------------------------
1674 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1679 wxapp_install_idle_handler();
1681 if (!win
->m_hasVMT
) return FALSE
;
1682 if (g_blockEventsOnDrag
) return FALSE
;
1684 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1686 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1687 #if (GTK_MINOR_VERSION > 0)
1688 event
.SetTimestamp( gdk_event
->time
);
1690 event
.SetEventObject( win
);
1694 GdkModifierType state
= (GdkModifierType
)0;
1696 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1698 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1699 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1700 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1701 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1702 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1703 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1704 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1709 if (win
->GetEventHandler()->ProcessEvent( event
))
1711 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1718 //-----------------------------------------------------------------------------
1719 // "leave_notify_event"
1720 //-----------------------------------------------------------------------------
1722 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1727 wxapp_install_idle_handler();
1729 if (!win
->m_hasVMT
) return FALSE
;
1730 if (g_blockEventsOnDrag
) return FALSE
;
1732 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1734 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1735 #if (GTK_MINOR_VERSION > 0)
1736 event
.SetTimestamp( gdk_event
->time
);
1738 event
.SetEventObject( win
);
1742 GdkModifierType state
= (GdkModifierType
)0;
1744 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1746 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1747 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1748 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1749 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1750 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1751 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1752 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1757 if (win
->GetEventHandler()->ProcessEvent( event
))
1759 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1766 //-----------------------------------------------------------------------------
1767 // "value_changed" from m_vAdjust
1768 //-----------------------------------------------------------------------------
1770 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1775 wxapp_install_idle_handler();
1777 if (g_blockEventsOnDrag
) return;
1779 if (!win
->m_hasVMT
) return;
1781 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1782 if (fabs(diff
) < 0.2) return;
1784 win
->m_oldVerticalPos
= adjust
->value
;
1786 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1787 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1789 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1790 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1791 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1792 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1793 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1795 int value
= (int)(adjust
->value
+0.5);
1797 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1798 event
.SetEventObject( win
);
1799 win
->GetEventHandler()->ProcessEvent( event
);
1802 //-----------------------------------------------------------------------------
1803 // "value_changed" from m_hAdjust
1804 //-----------------------------------------------------------------------------
1806 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1811 wxapp_install_idle_handler();
1813 if (g_blockEventsOnDrag
) return;
1814 if (!win
->m_hasVMT
) return;
1816 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1817 if (fabs(diff
) < 0.2) return;
1819 win
->m_oldHorizontalPos
= adjust
->value
;
1821 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1822 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1824 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1825 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1826 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1827 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1828 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1830 int value
= (int)(adjust
->value
+0.5);
1832 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1833 event
.SetEventObject( win
);
1834 win
->GetEventHandler()->ProcessEvent( event
);
1837 //-----------------------------------------------------------------------------
1838 // "button_press_event" from scrollbar
1839 //-----------------------------------------------------------------------------
1841 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1842 GdkEventButton
*gdk_event
,
1848 wxapp_install_idle_handler();
1851 g_blockEventsOnScroll
= TRUE
;
1852 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1857 //-----------------------------------------------------------------------------
1858 // "button_release_event" from scrollbar
1859 //-----------------------------------------------------------------------------
1861 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1862 GdkEventButton
*WXUNUSED(gdk_event
),
1867 // don't test here as we can release the mouse while being over
1868 // a different window than the slider
1870 // if (gdk_event->window != widget->slider) return FALSE;
1872 g_blockEventsOnScroll
= FALSE
;
1874 if (win
->m_isScrolling
)
1876 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
1880 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1881 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1883 value
= (int)(win
->m_hAdjust
->value
+0.5);
1886 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1888 value
= (int)(win
->m_vAdjust
->value
+0.5);
1892 wxScrollWinEvent
event( command
, value
, dir
);
1893 event
.SetEventObject( win
);
1894 win
->GetEventHandler()->ProcessEvent( event
);
1897 win
->m_isScrolling
= FALSE
;
1902 // ----------------------------------------------------------------------------
1903 // this wxWindowBase function is implemented here (in platform-specific file)
1904 // because it is static and so couldn't be made virtual
1905 // ----------------------------------------------------------------------------
1907 wxWindow
*wxWindowBase::FindFocus()
1909 return g_focusWindow
;
1912 //-----------------------------------------------------------------------------
1913 // "realize" from m_widget
1914 //-----------------------------------------------------------------------------
1916 /* We cannot set colours and fonts before the widget has
1917 been realized, so we do this directly after realization. */
1920 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1925 wxapp_install_idle_handler();
1927 if (win
->m_delayedBackgroundColour
)
1928 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1930 if (win
->m_delayedForegroundColour
)
1931 win
->SetForegroundColour( win
->GetForegroundColour() );
1933 wxWindowCreateEvent
event( win
);
1934 event
.SetEventObject( win
);
1935 win
->GetEventHandler()->ProcessEvent( event
);
1940 //-----------------------------------------------------------------------------
1942 //-----------------------------------------------------------------------------
1945 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
1946 GtkAllocation
*WXUNUSED(alloc
),
1950 wxapp_install_idle_handler();
1952 if (!win
->m_hasScrolling
) return;
1954 int client_width
= 0;
1955 int client_height
= 0;
1956 win
->GetClientSize( &client_width
, &client_height
);
1957 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
1960 win
->m_oldClientWidth
= client_width
;
1961 win
->m_oldClientHeight
= client_height
;
1963 if (!win
->m_nativeSizeEvent
)
1965 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
1966 event
.SetEventObject( win
);
1967 win
->GetEventHandler()->ProcessEvent( event
);
1973 #define WXUNUSED_UNLESS_XIM(param) param
1975 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1978 /* Resize XIM window */
1981 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1982 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1983 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1986 wxapp_install_idle_handler();
1992 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1996 gdk_window_get_size (widget
->window
, &width
, &height
);
1997 win
->m_icattr
->preedit_area
.width
= width
;
1998 win
->m_icattr
->preedit_area
.height
= height
;
1999 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2004 //-----------------------------------------------------------------------------
2005 // "realize" from m_wxwindow
2006 //-----------------------------------------------------------------------------
2008 /* Initialize XIM support */
2011 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2012 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
2015 wxapp_install_idle_handler();
2018 if (win
->m_ic
) return FALSE
;
2019 if (!widget
) return FALSE
;
2020 if (!gdk_im_ready()) return FALSE
;
2022 win
->m_icattr
= gdk_ic_attr_new();
2023 if (!win
->m_icattr
) return FALSE
;
2027 GdkColormap
*colormap
;
2028 GdkICAttr
*attr
= win
->m_icattr
;
2029 unsigned attrmask
= GDK_IC_ALL_REQ
;
2031 GdkIMStyle supported_style
= (GdkIMStyle
)
2032 (GDK_IM_PREEDIT_NONE
|
2033 GDK_IM_PREEDIT_NOTHING
|
2034 GDK_IM_PREEDIT_POSITION
|
2035 GDK_IM_STATUS_NONE
|
2036 GDK_IM_STATUS_NOTHING
);
2038 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2039 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2041 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2042 attr
->client_window
= widget
->window
;
2044 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2045 gtk_widget_get_default_colormap ())
2047 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2048 attr
->preedit_colormap
= colormap
;
2051 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2052 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2053 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2054 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2056 switch (style
& GDK_IM_PREEDIT_MASK
)
2058 case GDK_IM_PREEDIT_POSITION
:
2059 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2061 g_warning ("over-the-spot style requires fontset");
2065 gdk_window_get_size (widget
->window
, &width
, &height
);
2067 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2068 attr
->spot_location
.x
= 0;
2069 attr
->spot_location
.y
= height
;
2070 attr
->preedit_area
.x
= 0;
2071 attr
->preedit_area
.y
= 0;
2072 attr
->preedit_area
.width
= width
;
2073 attr
->preedit_area
.height
= height
;
2074 attr
->preedit_fontset
= widget
->style
->font
;
2079 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2081 if (win
->m_ic
== NULL
)
2082 g_warning ("Can't create input context.");
2085 mask
= gdk_window_get_events (widget
->window
);
2086 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2087 gdk_window_set_events (widget
->window
, mask
);
2089 if (GTK_WIDGET_HAS_FOCUS(widget
))
2090 gdk_im_begin (win
->m_ic
, widget
->window
);
2097 //-----------------------------------------------------------------------------
2098 // InsertChild for wxWindow.
2099 //-----------------------------------------------------------------------------
2101 /* Callback for wxWindow. This very strange beast has to be used because
2102 * C++ has no virtual methods in a constructor. We have to emulate a
2103 * virtual function here as wxNotebook requires a different way to insert
2104 * a child in it. I had opted for creating a wxNotebookPage window class
2105 * which would have made this superfluous (such in the MDI window system),
2106 * but no-one was listening to me... */
2108 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
2110 /* the window might have been scrolled already, do we
2111 have to adapt the position */
2112 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2113 child
->m_x
+= pizza
->xoffset
;
2114 child
->m_y
+= pizza
->yoffset
;
2116 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2117 GTK_WIDGET(child
->m_widget
),
2124 //-----------------------------------------------------------------------------
2126 //-----------------------------------------------------------------------------
2128 wxWindow
* wxGetActiveWindow()
2130 return g_focusWindow
;
2133 //-----------------------------------------------------------------------------
2135 //-----------------------------------------------------------------------------
2137 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2139 void wxWindow::Init()
2145 m_widget
= (GtkWidget
*) NULL
;
2146 m_wxwindow
= (GtkWidget
*) NULL
;
2156 m_needParent
= TRUE
;
2157 m_isBeingDeleted
= FALSE
;
2160 m_nativeSizeEvent
= FALSE
;
2162 m_hasScrolling
= FALSE
;
2163 m_isScrolling
= FALSE
;
2165 m_hAdjust
= (GtkAdjustment
*) NULL
;
2166 m_vAdjust
= (GtkAdjustment
*) NULL
;
2167 m_oldHorizontalPos
= 0.0;
2168 m_oldVerticalPos
= 0.0;
2171 m_widgetStyle
= (GtkStyle
*) NULL
;
2173 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2175 m_isStaticBox
= FALSE
;
2176 m_isRadioButton
= FALSE
;
2178 m_acceptsFocus
= FALSE
;
2180 m_clipPaintRegion
= FALSE
;
2182 m_cursor
= *wxSTANDARD_CURSOR
;
2184 m_delayedForegroundColour
= FALSE
;
2185 m_delayedBackgroundColour
= FALSE
;
2188 m_ic
= (GdkIC
*) NULL
;
2189 m_icattr
= (GdkICAttr
*) NULL
;
2193 wxWindow::wxWindow()
2198 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
2199 const wxPoint
&pos
, const wxSize
&size
,
2200 long style
, const wxString
&name
)
2204 Create( parent
, id
, pos
, size
, style
, name
);
2207 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
2208 const wxPoint
&pos
, const wxSize
&size
,
2209 long style
, const wxString
&name
)
2211 if (!PreCreation( parent
, pos
, size
) ||
2212 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2214 wxFAIL_MSG( wxT("wxWindow creation failed") );
2218 m_insertCallback
= wxInsertChildInWindow
;
2220 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2221 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2223 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2225 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2226 scroll_class
->scrollbar_spacing
= 0;
2228 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2230 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2231 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2233 m_wxwindow
= gtk_pizza_new();
2235 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2237 #if (GTK_MINOR_VERSION > 0)
2238 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2240 if (HasFlag(wxRAISED_BORDER
))
2242 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2244 else if (HasFlag(wxSUNKEN_BORDER
))
2246 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2248 else if (HasFlag(wxSIMPLE_BORDER
))
2250 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2254 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2256 #else // GTK_MINOR_VERSION == 0
2257 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2259 if (HasFlag(wxRAISED_BORDER
))
2261 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2263 else if (HasFlag(wxSUNKEN_BORDER
))
2265 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2269 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2271 #endif // GTK_MINOR_VERSION
2273 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2274 m_acceptsFocus
= TRUE
;
2276 #if (GTK_MINOR_VERSION == 0)
2277 // shut the viewport up
2278 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2279 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2280 #endif // GTK_MINOR_VERSION == 0
2282 // I _really_ don't want scrollbars in the beginning
2283 m_vAdjust
->lower
= 0.0;
2284 m_vAdjust
->upper
= 1.0;
2285 m_vAdjust
->value
= 0.0;
2286 m_vAdjust
->step_increment
= 1.0;
2287 m_vAdjust
->page_increment
= 1.0;
2288 m_vAdjust
->page_size
= 5.0;
2289 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2290 m_hAdjust
->lower
= 0.0;
2291 m_hAdjust
->upper
= 1.0;
2292 m_hAdjust
->value
= 0.0;
2293 m_hAdjust
->step_increment
= 1.0;
2294 m_hAdjust
->page_increment
= 1.0;
2295 m_hAdjust
->page_size
= 5.0;
2296 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2298 // these handlers block mouse events to any window during scrolling such as
2299 // motion events and prevent GTK and wxWindows from fighting over where the
2302 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2303 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2305 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2306 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2308 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2309 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2311 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2312 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2314 // these handlers get notified when screen updates are required either when
2315 // scrolling or when the window size (and therefore scrollbar configuration)
2318 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2319 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2320 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2321 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2323 gtk_widget_show( m_wxwindow
);
2326 m_parent
->DoAddChild( this );
2335 wxWindow::~wxWindow()
2337 if (g_focusWindow
== this)
2338 g_focusWindow
= NULL
;
2340 m_isBeingDeleted
= TRUE
;
2349 m_parent
->RemoveChild( this );
2353 gdk_ic_destroy (m_ic
);
2355 gdk_ic_attr_destroy (m_icattr
);
2360 #if DISABLE_STYLE_IF_BROKEN_THEME
2361 // don't delete if it's a pixmap theme style
2362 if (!m_widgetStyle
->engine_data
)
2363 gtk_style_unref( m_widgetStyle
);
2365 m_widgetStyle
= (GtkStyle
*) NULL
;
2370 gtk_widget_destroy( m_wxwindow
);
2371 m_wxwindow
= (GtkWidget
*) NULL
;
2376 gtk_widget_destroy( m_widget
);
2377 m_widget
= (GtkWidget
*) NULL
;
2381 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2383 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2385 /* this turns -1 into 20 so that a minimal window is
2386 visible even although -1,-1 has been given as the
2387 size of the window. the same trick is used in other
2388 ports and should make debugging easier */
2389 m_width
= WidthDefault(size
.x
);
2390 m_height
= HeightDefault(size
.y
);
2395 /* some reasonable defaults */
2400 m_x
= (gdk_screen_width () - m_width
) / 2;
2401 if (m_x
< 10) m_x
= 10;
2405 m_y
= (gdk_screen_height () - m_height
) / 2;
2406 if (m_y
< 10) m_y
= 10;
2413 void wxWindow::PostCreation()
2415 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2421 /* these get reported to wxWindows -> wxPaintEvent */
2423 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2425 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2426 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2428 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2429 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2431 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2433 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2434 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2438 #if (GTK_MINOR_VERSION > 0)
2439 /* these are called when the "sunken" or "raised" borders are drawn */
2440 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2441 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2443 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2444 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2448 if (m_wxwindow
&& m_needParent
)
2450 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2451 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2453 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2454 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2458 // For dialogs and frames, we are interested mainly in
2459 // m_widget's focus.
2461 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2462 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2464 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2465 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2468 GtkWidget
*connect_widget
= GetConnectWidget();
2470 ConnectWidget( connect_widget
);
2472 /* We cannot set colours, fonts and cursors before the widget has
2473 been realized, so we do this directly after realization */
2474 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2475 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2479 // Catch native resize events
2480 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2481 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2483 // Initialize XIM support
2484 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2485 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2487 // And resize XIM window
2488 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2489 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2492 if (!GTK_IS_COMBO(m_widget
))
2494 // This is needed if we want to add our windows into native
2495 // GTK control, such as the toolbar. With this callback, the
2496 // toolbar gets to know the correct size (the one set by the
2497 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2498 // when moving to GTK 2.0.
2499 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2500 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2506 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2508 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2509 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2511 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2512 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2514 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2515 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2517 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2518 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2520 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2521 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2523 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2524 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2526 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2527 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2530 bool wxWindow::Destroy()
2532 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2536 return wxWindowBase::Destroy();
2539 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2541 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2544 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2546 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2547 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2549 if (m_resizing
) return; /* I don't like recursions */
2552 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2554 /* don't set the size for children of wxNotebook, just take the values. */
2562 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2564 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2566 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2567 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2568 if (width
!= -1) m_width
= width
;
2569 if (height
!= -1) m_height
= height
;
2573 m_x
= x
+ pizza
->xoffset
;
2574 m_y
= y
+ pizza
->yoffset
;
2579 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2581 if (width
== -1) m_width
= 80;
2584 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2586 if (height
== -1) m_height
= 26;
2589 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2590 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2591 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2592 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2595 int bottom_border
= 0;
2597 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2599 /* the default button has a border around it */
2604 DoMoveWindow( m_x
-border
,
2607 m_height
+border
+bottom_border
);
2612 /* Sometimes the client area changes size without the
2613 whole windows's size changing, but if the whole
2614 windows's size doesn't change, no wxSizeEvent will
2615 normally be sent. Here we add an extra test if
2616 the client test has been changed and this will
2618 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2622 wxPrintf( "OnSize sent from " );
2623 if (GetClassInfo() && GetClassInfo()->GetClassName())
2624 wxPrintf( GetClassInfo()->GetClassName() );
2625 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2628 if (!m_nativeSizeEvent
)
2630 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2631 event
.SetEventObject( this );
2632 GetEventHandler()->ProcessEvent( event
);
2638 void wxWindow::OnInternalIdle()
2640 if ( g_sendActivateEvent
!= -1 )
2642 bool activate
= g_sendActivateEvent
!= 0;
2645 g_sendActivateEvent
= -1;
2647 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2648 event
.SetEventObject(this);
2650 (void)GetEventHandler()->ProcessEvent(event
);
2653 wxCursor cursor
= m_cursor
;
2654 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2658 /* I now set the cursor anew in every OnInternalIdle call
2659 as setting the cursor in a parent window also effects the
2660 windows above so that checking for the current cursor is
2665 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2667 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2669 if (!g_globalCursor
.Ok())
2670 cursor
= *wxSTANDARD_CURSOR
;
2672 window
= m_widget
->window
;
2673 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2674 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2680 GdkWindow
*window
= m_widget
->window
;
2681 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2682 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2690 void wxWindow::DoGetSize( int *width
, int *height
) const
2692 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2694 if (width
) (*width
) = m_width
;
2695 if (height
) (*height
) = m_height
;
2698 void wxWindow::DoSetClientSize( int width
, int height
)
2700 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2704 SetSize( width
, height
);
2711 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2713 /* when using GTK 1.2 we set the shadow border size to 2 */
2717 if (HasFlag(wxSIMPLE_BORDER
))
2719 /* when using GTK 1.2 we set the simple border size to 1 */
2726 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2728 GtkRequisition vscroll_req
;
2729 vscroll_req
.width
= 2;
2730 vscroll_req
.height
= 2;
2731 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2732 (scroll_window
->vscrollbar
, &vscroll_req
);
2734 GtkRequisition hscroll_req
;
2735 hscroll_req
.width
= 2;
2736 hscroll_req
.height
= 2;
2737 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2738 (scroll_window
->hscrollbar
, &hscroll_req
);
2740 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2742 if (scroll_window
->vscrollbar_visible
)
2744 dw
+= vscroll_req
.width
;
2745 dw
+= scroll_class
->scrollbar_spacing
;
2748 if (scroll_window
->hscrollbar_visible
)
2750 dh
+= hscroll_req
.height
;
2751 dh
+= scroll_class
->scrollbar_spacing
;
2755 SetSize( width
+dw
, height
+dh
);
2759 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2761 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2765 if (width
) (*width
) = m_width
;
2766 if (height
) (*height
) = m_height
;
2773 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2775 /* when using GTK 1.2 we set the shadow border size to 2 */
2779 if (HasFlag(wxSIMPLE_BORDER
))
2781 /* when using GTK 1.2 we set the simple border size to 1 */
2788 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2790 GtkRequisition vscroll_req
;
2791 vscroll_req
.width
= 2;
2792 vscroll_req
.height
= 2;
2793 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2794 (scroll_window
->vscrollbar
, &vscroll_req
);
2796 GtkRequisition hscroll_req
;
2797 hscroll_req
.width
= 2;
2798 hscroll_req
.height
= 2;
2799 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2800 (scroll_window
->hscrollbar
, &hscroll_req
);
2802 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2804 if (scroll_window
->vscrollbar_visible
)
2806 dw
+= vscroll_req
.width
;
2807 dw
+= scroll_class
->scrollbar_spacing
;
2810 if (scroll_window
->hscrollbar_visible
)
2812 dh
+= hscroll_req
.height
;
2813 dh
+= scroll_class
->scrollbar_spacing
;
2817 if (width
) (*width
) = m_width
- dw
;
2818 if (height
) (*height
) = m_height
- dh
;
2822 void wxWindow::DoGetPosition( int *x
, int *y
) const
2824 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2828 if (m_parent
&& m_parent
->m_wxwindow
)
2830 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2831 dx
= pizza
->xoffset
;
2832 dy
= pizza
->yoffset
;
2835 if (x
) (*x
) = m_x
- dx
;
2836 if (y
) (*y
) = m_y
- dy
;
2839 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2841 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2843 if (!m_widget
->window
) return;
2845 GdkWindow
*source
= (GdkWindow
*) NULL
;
2847 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2849 source
= m_widget
->window
;
2853 gdk_window_get_origin( source
, &org_x
, &org_y
);
2857 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2859 org_x
+= m_widget
->allocation
.x
;
2860 org_y
+= m_widget
->allocation
.y
;
2868 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2870 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2872 if (!m_widget
->window
) return;
2874 GdkWindow
*source
= (GdkWindow
*) NULL
;
2876 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2878 source
= m_widget
->window
;
2882 gdk_window_get_origin( source
, &org_x
, &org_y
);
2886 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2888 org_x
+= m_widget
->allocation
.x
;
2889 org_y
+= m_widget
->allocation
.y
;
2897 bool wxWindow::Show( bool show
)
2899 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2901 if (!wxWindowBase::Show(show
))
2908 gtk_widget_show( m_widget
);
2910 gtk_widget_hide( m_widget
);
2915 bool wxWindow::Enable( bool enable
)
2917 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2919 if (!wxWindowBase::Enable(enable
))
2925 gtk_widget_set_sensitive( m_widget
, enable
);
2927 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2932 int wxWindow::GetCharHeight() const
2934 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2936 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2938 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2940 return font
->ascent
+ font
->descent
;
2943 int wxWindow::GetCharWidth() const
2945 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2947 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2949 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2951 return gdk_string_width( font
, "H" );
2954 void wxWindow::GetTextExtent( const wxString
& string
,
2958 int *externalLeading
,
2959 const wxFont
*theFont
) const
2961 wxFont fontToUse
= m_font
;
2962 if (theFont
) fontToUse
= *theFont
;
2964 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2966 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2967 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2968 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2969 if (descent
) (*descent
) = font
->descent
;
2970 if (externalLeading
) (*externalLeading
) = 0; // ??
2973 void wxWindow::SetFocus()
2975 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2979 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2980 gtk_widget_grab_focus (m_wxwindow
);
2986 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2988 gtk_widget_grab_focus (m_widget
);
2990 else if (GTK_IS_CONTAINER(m_widget
))
2992 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
3001 bool wxWindow::AcceptsFocus() const
3003 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3006 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
3008 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3010 wxWindow
*oldParent
= m_parent
,
3011 *newParent
= (wxWindow
*)newParentBase
;
3013 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3015 if ( !wxWindowBase::Reparent(newParent
) )
3018 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3020 /* prevent GTK from deleting the widget arbitrarily */
3021 gtk_widget_ref( m_widget
);
3025 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3028 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3032 /* insert GTK representation */
3033 (*(newParent
->m_insertCallback
))(newParent
, this);
3036 /* reverse: prevent GTK from deleting the widget arbitrarily */
3037 gtk_widget_unref( m_widget
);
3042 void wxWindow::DoAddChild(wxWindow
*child
)
3044 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3046 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3048 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3053 /* insert GTK representation */
3054 (*m_insertCallback
)(this, child
);
3057 void wxWindow::Raise()
3059 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3061 if (!m_widget
->window
) return;
3063 gdk_window_raise( m_widget
->window
);
3066 void wxWindow::Lower()
3068 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3070 if (!m_widget
->window
) return;
3072 gdk_window_lower( m_widget
->window
);
3075 bool wxWindow::SetCursor( const wxCursor
&cursor
)
3077 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3079 if (cursor
== m_cursor
)
3083 wxapp_install_idle_handler();
3085 if (cursor
== wxNullCursor
)
3086 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3088 return wxWindowBase::SetCursor( cursor
);
3091 void wxWindow::WarpPointer( int x
, int y
)
3093 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3095 /* we provide this function ourselves as it is
3096 missing in GDK (top of this file) */
3098 GdkWindow
*window
= (GdkWindow
*) NULL
;
3100 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3102 window
= GetConnectWidget()->window
;
3105 gdk_window_warp_pointer( window
, x
, y
);
3108 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
3110 if (!m_widget
) return;
3111 if (!m_widget
->window
) return;
3113 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3117 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3119 rect
->width
, rect
->height
);
3123 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3127 /* there is no GTK equivalent of "draw only, don't clear" so we
3128 invent our own in the GtkPizza widget */
3136 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3137 gboolean old_clear = pizza->clear_on_draw;
3138 gtk_pizza_set_clear( pizza, FALSE );
3139 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3140 gtk_pizza_set_clear( pizza, old_clear );
3142 GdkEventExpose gdk_event
;
3143 gdk_event
.type
= GDK_EXPOSE
;
3144 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3145 gdk_event
.count
= 0;
3146 gdk_event
.area
.x
= 0;
3147 gdk_event
.area
.y
= 0;
3148 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3149 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3150 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3155 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3164 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3165 gboolean old_clear = pizza->clear_on_draw;
3166 gtk_pizza_set_clear( pizza, FALSE );
3168 GdkRectangle gdk_rect;
3169 gdk_rect.x = rect->x;
3170 gdk_rect.y = rect->y;
3171 gdk_rect.width = rect->width;
3172 gdk_rect.height = rect->height;
3173 gtk_widget_draw( m_wxwindow, &gdk_rect );
3174 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3176 gtk_pizza_set_clear( pizza, old_clear );
3178 GdkEventExpose gdk_event
;
3179 gdk_event
.type
= GDK_EXPOSE
;
3180 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3181 gdk_event
.count
= 0;
3182 gdk_event
.area
.x
= rect
->x
;
3183 gdk_event
.area
.y
= rect
->y
;
3184 gdk_event
.area
.width
= rect
->width
;
3185 gdk_event
.area
.height
= rect
->height
;
3186 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3190 GdkRectangle gdk_rect
;
3191 gdk_rect
.x
= rect
->x
;
3192 gdk_rect
.y
= rect
->y
;
3193 gdk_rect
.width
= rect
->width
;
3194 gdk_rect
.height
= rect
->height
;
3195 gtk_widget_draw( m_widget
, &gdk_rect
);
3200 void wxWindow::Clear()
3202 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3204 if (!m_widget
->window
) return;
3206 if (m_wxwindow
&& m_wxwindow
->window
)
3208 // gdk_window_clear( m_wxwindow->window );
3213 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
3215 wxWindowBase::DoSetToolTip(tip
);
3218 m_tooltip
->Apply( this );
3221 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3223 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3225 #endif // wxUSE_TOOLTIPS
3227 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
3229 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3231 if (!wxWindowBase::SetBackgroundColour(colour
))
3233 // don't leave if the GTK widget has just
3235 if (!m_delayedBackgroundColour
) return FALSE
;
3238 GdkWindow
*window
= (GdkWindow
*) NULL
;
3240 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3242 window
= GetConnectWidget()->window
;
3246 // indicate that a new style has been set
3247 // but it couldn't get applied as the
3248 // widget hasn't been realized yet.
3249 m_delayedBackgroundColour
= TRUE
;
3253 (m_wxwindow
->window
) &&
3254 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3256 /* wxMSW doesn't clear the window here. I don't do that either to
3257 provide compatibility. call Clear() to do the job. */
3259 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3260 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3268 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
3270 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3272 if (!wxWindowBase::SetForegroundColour(colour
))
3274 // don't leave if the GTK widget has just
3276 if (!m_delayedForegroundColour
) return FALSE
;
3279 GdkWindow
*window
= (GdkWindow
*) NULL
;
3281 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3283 window
= GetConnectWidget()->window
;
3287 // indicate that a new style has been set
3288 // but it couldn't get applied as the
3289 // widget hasn't been realized yet.
3290 m_delayedForegroundColour
= TRUE
;
3298 GtkStyle
*wxWindow::GetWidgetStyle()
3302 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3304 /* FIXME: is this necessary? */
3305 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3307 remake
->klass
= m_widgetStyle
->klass
;
3310 gtk_style_unref( m_widgetStyle
);
3311 m_widgetStyle
= remake
;
3315 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3318 def
= gtk_widget_get_default_style();
3320 m_widgetStyle
= gtk_style_copy( def
);
3322 /* FIXME: is this necessary? */
3323 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3325 m_widgetStyle
->klass
= def
->klass
;
3329 return m_widgetStyle
;
3332 void wxWindow::SetWidgetStyle()
3334 #if DISABLE_STYLE_IF_BROKEN_THEM
3335 if (m_widget
->style
->engine_data
)
3337 static bool s_warningPrinted
= FALSE
;
3338 if (!s_warningPrinted
)
3340 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3341 s_warningPrinted
= TRUE
;
3343 m_widgetStyle
= m_widget
->style
;
3348 GtkStyle
*style
= GetWidgetStyle();
3350 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3352 gdk_font_unref( style
->font
);
3353 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3356 if (m_foregroundColour
.Ok())
3358 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3359 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3361 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3362 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3363 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3367 // Try to restore the gtk default style. This is still a little
3368 // oversimplified for what is probably really needed here for controls
3369 // other than buttons, but is better than not being able to (re)set a
3370 // control's foreground colour to *wxBLACK -- RL
3371 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3374 def
= gtk_widget_get_default_style();
3376 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3377 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3378 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3382 if (m_backgroundColour
.Ok())
3384 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3385 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3387 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3388 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3389 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3390 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3391 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3392 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3393 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3394 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3398 // Try to restore the gtk default style. This is still a little
3399 // oversimplified for what is probably really needed here for controls
3400 // other than buttons, but is better than not being able to (re)set a
3401 // control's background colour to default grey and means resetting a
3402 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3404 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3407 def
= gtk_widget_get_default_style();
3409 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3410 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3411 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3412 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3413 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3414 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3415 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3416 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3421 void wxWindow::ApplyWidgetStyle()
3425 //-----------------------------------------------------------------------------
3426 // Pop-up menu stuff
3427 //-----------------------------------------------------------------------------
3429 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3431 *is_waiting
= FALSE
;
3434 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3436 menu
->SetInvokingWindow( win
);
3437 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3440 wxMenuItem
*menuitem
= node
->GetData();
3441 if (menuitem
->IsSubMenu())
3443 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3446 node
= node
->GetNext();
3450 static gint gs_pop_x
= 0;
3451 static gint gs_pop_y
= 0;
3453 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3457 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3462 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3464 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3466 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3468 SetInvokingWindow( menu
, this );
3475 bool is_waiting
= TRUE
;
3477 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3478 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3481 GTK_MENU(menu
->m_menu
),
3482 (GtkWidget
*) NULL
, // parent menu shell
3483 (GtkWidget
*) NULL
, // parent menu item
3484 (GtkMenuPositionFunc
) pop_pos_callback
,
3485 (gpointer
) this, // client data
3486 0, // button used to activate it
3487 gs_timeLastClick
// the time of activation
3492 while (gtk_events_pending())
3493 gtk_main_iteration();
3499 #if wxUSE_DRAG_AND_DROP
3501 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3503 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3505 GtkWidget
*dnd_widget
= GetConnectWidget();
3507 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3509 if (m_dropTarget
) delete m_dropTarget
;
3510 m_dropTarget
= dropTarget
;
3512 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3515 #endif // wxUSE_DRAG_AND_DROP
3517 GtkWidget
* wxWindow::GetConnectWidget()
3519 GtkWidget
*connect_widget
= m_widget
;
3520 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3522 return connect_widget
;
3525 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3528 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3530 return (window
== m_widget
->window
);
3533 bool wxWindow::SetFont( const wxFont
&font
)
3535 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3537 if (!wxWindowBase::SetFont(font
))
3542 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3543 if ( sysbg
== m_backgroundColour
)
3545 m_backgroundColour
= wxNullColour
;
3547 m_backgroundColour
= sysbg
;
3557 void wxWindow::CaptureMouse()
3559 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3561 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3563 GdkWindow
*window
= (GdkWindow
*) NULL
;
3565 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3567 window
= GetConnectWidget()->window
;
3569 if (!window
) return;
3571 wxCursor
* cursor
= & m_cursor
;
3573 cursor
= wxSTANDARD_CURSOR
;
3575 gdk_pointer_grab( window
, FALSE
,
3577 (GDK_BUTTON_PRESS_MASK
|
3578 GDK_BUTTON_RELEASE_MASK
|
3579 GDK_POINTER_MOTION_HINT_MASK
|
3580 GDK_POINTER_MOTION_MASK
),
3582 cursor
->GetCursor(),
3583 (guint32
)GDK_CURRENT_TIME
);
3584 g_captureWindow
= this;
3587 void wxWindow::ReleaseMouse()
3589 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3591 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3593 GdkWindow
*window
= (GdkWindow
*) NULL
;
3595 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3597 window
= GetConnectWidget()->window
;
3602 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3603 g_captureWindow
= (wxWindow
*) NULL
;
3606 bool wxWindow::IsRetained() const
3611 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3612 int range
, bool refresh
)
3614 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3616 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3618 m_hasScrolling
= TRUE
;
3620 if (orient
== wxHORIZONTAL
)
3622 float fpos
= (float)pos
;
3623 float frange
= (float)range
;
3624 float fthumb
= (float)thumbVisible
;
3625 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3626 if (fpos
< 0.0) fpos
= 0.0;
3628 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3629 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3631 SetScrollPos( orient
, pos
, refresh
);
3635 m_oldHorizontalPos
= fpos
;
3637 m_hAdjust
->lower
= 0.0;
3638 m_hAdjust
->upper
= frange
;
3639 m_hAdjust
->value
= fpos
;
3640 m_hAdjust
->step_increment
= 1.0;
3641 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3642 m_hAdjust
->page_size
= fthumb
;
3646 float fpos
= (float)pos
;
3647 float frange
= (float)range
;
3648 float fthumb
= (float)thumbVisible
;
3649 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3650 if (fpos
< 0.0) fpos
= 0.0;
3652 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3653 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3655 SetScrollPos( orient
, pos
, refresh
);
3659 m_oldVerticalPos
= fpos
;
3661 m_vAdjust
->lower
= 0.0;
3662 m_vAdjust
->upper
= frange
;
3663 m_vAdjust
->value
= fpos
;
3664 m_vAdjust
->step_increment
= 1.0;
3665 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3666 m_vAdjust
->page_size
= fthumb
;
3669 if (orient
== wxHORIZONTAL
)
3670 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3672 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3675 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3677 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3679 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3681 if (orient
== wxHORIZONTAL
)
3683 float fpos
= (float)pos
;
3684 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3685 if (fpos
< 0.0) fpos
= 0.0;
3686 m_oldHorizontalPos
= fpos
;
3688 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3689 m_hAdjust
->value
= fpos
;
3693 float fpos
= (float)pos
;
3694 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3695 if (fpos
< 0.0) fpos
= 0.0;
3696 m_oldVerticalPos
= fpos
;
3698 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3699 m_vAdjust
->value
= fpos
;
3702 if (m_wxwindow
->window
)
3704 if (orient
== wxHORIZONTAL
)
3706 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3707 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3709 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3711 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3712 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3716 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3717 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3719 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3721 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3722 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3727 int wxWindow::GetScrollThumb( int orient
) const
3729 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3731 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3733 if (orient
== wxHORIZONTAL
)
3734 return (int)(m_hAdjust
->page_size
+0.5);
3736 return (int)(m_vAdjust
->page_size
+0.5);
3739 int wxWindow::GetScrollPos( int orient
) const
3741 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3743 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3745 if (orient
== wxHORIZONTAL
)
3746 return (int)(m_hAdjust
->value
+0.5);
3748 return (int)(m_vAdjust
->value
+0.5);
3751 int wxWindow::GetScrollRange( int orient
) const
3753 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3755 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3757 if (orient
== wxHORIZONTAL
)
3758 return (int)(m_hAdjust
->upper
+0.5);
3760 return (int)(m_vAdjust
->upper
+0.5);
3763 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3765 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3767 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3769 if ((dx
== 0) && (dy
== 0)) return;
3771 m_clipPaintRegion
= TRUE
;
3772 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3773 m_clipPaintRegion
= FALSE
;
3776 if (m_children.GetCount() > 0)
3778 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3782 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3784 pizza->xoffset -= dx;
3785 pizza->yoffset -= dy;
3787 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3788 gdk_gc_set_exposures( m_scrollGC, TRUE );
3792 GetClientSize( &cw, &ch );
3793 int w = cw - abs(dx);
3794 int h = ch - abs(dy);
3796 if ((h < 0) || (w < 0))
3804 if (dx < 0) s_x = -dx;
3805 if (dy < 0) s_y = -dy;
3808 if (dx > 0) d_x = dx;
3809 if (dy > 0) d_y = dy;
3811 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3812 pizza->bin_window, s_x, s_y, w, h );
3815 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3816 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3817 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3818 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3820 Refresh( TRUE, &rect );
3823 gdk_gc_unref( m_scrollGC );
3828 // Find the wxWindow at the current mouse position, also returning the mouse
3830 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
3832 pt
= wxGetMousePosition();
3833 wxWindow
* found
= wxFindWindowAtPoint(pt
);
3837 // Get the current mouse position.
3838 wxPoint
wxGetMousePosition()
3840 /* This crashes when used within wxHelpContext,
3841 so we have to use the X-specific implementation below.
3843 GdkModifierType *mask;
3844 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
3846 return wxPoint(x, y);
3850 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
3852 return wxPoint(-999, -999);
3854 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
3855 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
3856 Window rootReturn
, childReturn
;
3857 int rootX
, rootY
, winX
, winY
;
3858 unsigned int maskReturn
;
3860 XQueryPointer (display
,
3864 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
3865 return wxPoint(rootX
, rootY
);