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 //-----------------------------------------------------------------------------
223 #define DISABLE_STYLE_IF_BROKEN_THEME 1
229 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
231 # define DEBUG_MAIN_THREAD
234 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
235 GdkEvent
*WXUNUSED(event
),
236 const wxChar
*WXUNUSED(name
) )
239 static bool s_done = FALSE;
242 wxLog::AddTraceMask("focus");
245 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
251 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
253 // suppress warnings about gtk_debug_focus_in_callback being unused with
258 tmp
+= wxT(" FROM ");
261 wxChar
*s
= new wxChar
[tmp
.Length()+1];
265 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
266 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
271 #define DEBUG_MAIN_THREAD
274 //-----------------------------------------------------------------------------
275 // missing gdk functions
276 //-----------------------------------------------------------------------------
279 gdk_window_warp_pointer (GdkWindow
*window
,
284 GdkWindowPrivate
*priv
;
288 window
= GDK_ROOT_PARENT();
291 if (!GDK_WINDOW_DESTROYED(window
))
293 XWarpPointer (GDK_WINDOW_XDISPLAY(window
),
294 None
, /* not source window -> move from anywhere */
295 GDK_WINDOW_XID(window
), /* dest window */
296 0, 0, 0, 0, /* not source window -> move from anywhere */
300 priv
= (GdkWindowPrivate
*) window
;
302 if (!priv
->destroyed
)
304 XWarpPointer (priv
->xdisplay
,
305 None
, /* not source window -> move from anywhere */
306 priv
->xwindow
, /* dest window */
307 0, 0, 0, 0, /* not source window -> move from anywhere */
313 //-----------------------------------------------------------------------------
315 //-----------------------------------------------------------------------------
317 extern void wxapp_install_idle_handler();
318 extern bool g_isIdle
;
320 //-----------------------------------------------------------------------------
321 // local code (see below)
322 //-----------------------------------------------------------------------------
324 // returns the child of win which currently has focus or NULL if not found
325 // Note: can't be static, needed by textctrl.cpp.
326 /* static */ wxWindow
*FindFocusedChild(wxWindow
*win
)
328 wxWindow
*winFocus
= wxWindow::FindFocus();
330 return (wxWindow
*)NULL
;
332 if ( winFocus
== win
)
335 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
337 node
= node
->GetNext() )
339 wxWindow
*child
= FindFocusedChild(node
->GetData());
344 return (wxWindow
*)NULL
;
347 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
355 if (win
->m_hasScrolling
)
357 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
359 GtkRequisition vscroll_req
;
360 vscroll_req
.width
= 2;
361 vscroll_req
.height
= 2;
362 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
363 (scroll_window
->vscrollbar
, &vscroll_req
);
365 GtkRequisition hscroll_req
;
366 hscroll_req
.width
= 2;
367 hscroll_req
.height
= 2;
368 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
369 (scroll_window
->hscrollbar
, &hscroll_req
);
371 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) );
373 if (scroll_window
->vscrollbar_visible
)
375 dw
+= vscroll_req
.width
;
376 dw
+= scroll_class
->scrollbar_spacing
;
379 if (scroll_window
->hscrollbar_visible
)
381 dh
+= hscroll_req
.height
;
382 dh
+= scroll_class
->scrollbar_spacing
;
388 if (GTK_WIDGET_NO_WINDOW (widget
))
390 dx
+= widget
->allocation
.x
;
391 dy
+= widget
->allocation
.y
;
394 if (win
->HasFlag(wxRAISED_BORDER
))
396 gtk_draw_shadow( widget
->style
,
401 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
405 if (win
->HasFlag(wxSUNKEN_BORDER
))
407 gtk_draw_shadow( widget
->style
,
412 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
416 if (win
->HasFlag(wxSIMPLE_BORDER
))
419 gc
= gdk_gc_new( widget
->window
);
420 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
421 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
423 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
429 //-----------------------------------------------------------------------------
430 // "expose_event" of m_widget
431 //-----------------------------------------------------------------------------
433 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
435 if (gdk_event
->count
> 0) return FALSE
;
437 draw_frame( widget
, win
);
442 //-----------------------------------------------------------------------------
443 // "draw" of m_widget
444 //-----------------------------------------------------------------------------
446 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
448 draw_frame( widget
, win
);
451 //-----------------------------------------------------------------------------
452 // key code mapping routines
453 //-----------------------------------------------------------------------------
455 static long map_to_unmodified_wx_keysym( KeySym keysym
)
462 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
464 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
470 case GDK_Super_R
: key_code
= WXK_ALT
; break;
471 case GDK_Menu
: key_code
= WXK_MENU
; break;
472 case GDK_Help
: key_code
= WXK_HELP
; break;
473 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
474 case GDK_ISO_Left_Tab
:
475 case GDK_Tab
: key_code
= WXK_TAB
; break;
476 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
477 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
478 case GDK_Return
: key_code
= WXK_RETURN
; break;
479 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
480 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
481 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
482 case GDK_Delete
: key_code
= WXK_DELETE
; break;
483 case GDK_Home
: key_code
= WXK_HOME
; break;
484 case GDK_Left
: key_code
= WXK_LEFT
; break;
485 case GDK_Up
: key_code
= WXK_UP
; break;
486 case GDK_Right
: key_code
= WXK_RIGHT
; break;
487 case GDK_Down
: key_code
= WXK_DOWN
; break;
488 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
489 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
490 case GDK_Next
: key_code
= WXK_NEXT
; break;
491 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
492 case GDK_End
: key_code
= WXK_END
; break;
493 case GDK_Begin
: key_code
= WXK_HOME
; break;
494 case GDK_Select
: key_code
= WXK_SELECT
; break;
495 case GDK_Print
: key_code
= WXK_PRINT
; break;
496 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
497 case GDK_Insert
: key_code
= WXK_INSERT
; break;
498 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
500 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
501 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
502 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
503 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
504 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
505 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
506 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
507 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
508 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
509 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
510 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
511 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
512 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
513 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
514 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
515 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
516 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
517 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
518 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
519 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
520 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
521 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
522 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
523 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
524 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
525 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
526 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
527 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
528 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
529 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
530 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
531 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
532 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
533 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
534 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
535 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
536 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
538 case GDK_F1
: key_code
= WXK_F1
; break;
539 case GDK_F2
: key_code
= WXK_F2
; break;
540 case GDK_F3
: key_code
= WXK_F3
; break;
541 case GDK_F4
: key_code
= WXK_F4
; break;
542 case GDK_F5
: key_code
= WXK_F5
; break;
543 case GDK_F6
: key_code
= WXK_F6
; break;
544 case GDK_F7
: key_code
= WXK_F7
; break;
545 case GDK_F8
: key_code
= WXK_F8
; break;
546 case GDK_F9
: key_code
= WXK_F9
; break;
547 case GDK_F10
: key_code
= WXK_F10
; break;
548 case GDK_F11
: key_code
= WXK_F11
; break;
549 case GDK_F12
: key_code
= WXK_F12
; break;
552 if ((keysym
& 0xF000) == 0)
554 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
555 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
556 key_code
= (guint
)keysym
;
564 static long map_to_wx_keysym( KeySym keysym
)
570 case GDK_Menu
: key_code
= WXK_MENU
; break;
571 case GDK_Help
: key_code
= WXK_HELP
; break;
572 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
573 case GDK_ISO_Left_Tab
:
574 case GDK_Tab
: key_code
= WXK_TAB
; break;
575 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
576 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
577 case GDK_Return
: key_code
= WXK_RETURN
; break;
578 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
579 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
580 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
581 case GDK_Delete
: key_code
= WXK_DELETE
; break;
582 case GDK_Home
: key_code
= WXK_HOME
; break;
583 case GDK_Left
: key_code
= WXK_LEFT
; break;
584 case GDK_Up
: key_code
= WXK_UP
; break;
585 case GDK_Right
: key_code
= WXK_RIGHT
; break;
586 case GDK_Down
: key_code
= WXK_DOWN
; break;
587 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
588 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
589 case GDK_Next
: key_code
= WXK_NEXT
; break;
590 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
591 case GDK_End
: key_code
= WXK_END
; break;
592 case GDK_Begin
: key_code
= WXK_HOME
; break;
593 case GDK_Select
: key_code
= WXK_SELECT
; break;
594 case GDK_Print
: key_code
= WXK_PRINT
; break;
595 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
596 case GDK_Insert
: key_code
= WXK_INSERT
; break;
597 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
599 case GDK_KP_0
: key_code
= '0'; break;
600 case GDK_KP_1
: key_code
= '1'; break;
601 case GDK_KP_2
: key_code
= '2'; break;
602 case GDK_KP_3
: key_code
= '3'; break;
603 case GDK_KP_4
: key_code
= '4'; break;
604 case GDK_KP_5
: key_code
= '5'; break;
605 case GDK_KP_6
: key_code
= '6'; break;
606 case GDK_KP_7
: key_code
= '7'; break;
607 case GDK_KP_8
: key_code
= '8'; break;
608 case GDK_KP_9
: key_code
= '9'; break;
609 case GDK_KP_Space
: key_code
= ' '; break;
610 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
611 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
612 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
613 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
614 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
615 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
616 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
617 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
618 case GDK_KP_Up
: key_code
= WXK_UP
; break;
619 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
620 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
621 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
622 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
623 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
624 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
625 case GDK_KP_End
: key_code
= WXK_END
; break;
626 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
627 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
628 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
629 case GDK_KP_Equal
: key_code
= '='; break;
630 case GDK_KP_Multiply
: key_code
= '*'; break;
631 case GDK_KP_Add
: key_code
= '+'; break;
632 case GDK_KP_Separator
: key_code
= ','; break;
633 case GDK_KP_Subtract
: key_code
= '-'; break;
634 case GDK_KP_Decimal
: key_code
= '.'; break;
635 case GDK_KP_Divide
: key_code
= '/'; break;
637 case GDK_F1
: key_code
= WXK_F1
; break;
638 case GDK_F2
: key_code
= WXK_F2
; break;
639 case GDK_F3
: key_code
= WXK_F3
; break;
640 case GDK_F4
: key_code
= WXK_F4
; break;
641 case GDK_F5
: key_code
= WXK_F5
; break;
642 case GDK_F6
: key_code
= WXK_F6
; break;
643 case GDK_F7
: key_code
= WXK_F7
; break;
644 case GDK_F8
: key_code
= WXK_F8
; break;
645 case GDK_F9
: key_code
= WXK_F9
; break;
646 case GDK_F10
: key_code
= WXK_F10
; break;
647 case GDK_F11
: key_code
= WXK_F11
; break;
648 case GDK_F12
: key_code
= WXK_F12
; break;
651 if ((keysym
& 0xF000) == 0)
653 key_code
= (guint
)keysym
;
661 //-----------------------------------------------------------------------------
662 // "size_request" of m_widget
663 //-----------------------------------------------------------------------------
665 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
668 win
->GetSize( &w
, &h
);
672 requisition
->height
= h
;
673 requisition
->width
= w
;
676 //-----------------------------------------------------------------------------
677 // "expose_event" of m_wxwindow
678 //-----------------------------------------------------------------------------
680 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
685 wxapp_install_idle_handler();
688 if (win->GetName() == wxT("panel"))
690 wxPrintf( wxT("OnExpose from ") );
691 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
692 wxPrintf( win->GetClassInfo()->GetClassName() );
693 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
694 (int)gdk_event->area.y,
695 (int)gdk_event->area.width,
696 (int)gdk_event->area.height );
700 GtkPizza
*pizza
= GTK_PIZZA (widget
);
702 if (win
->GetThemeEnabled())
704 wxWindow
*parent
= win
->GetParent();
705 while (parent
&& !parent
->IsTopLevel())
706 parent
= parent
->GetParent();
710 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
711 GTK_SHADOW_NONE
, &gdk_event
->area
, parent
->m_widget
, "base", 0, 0, -1, -1);
714 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
716 gdk_event
->area
.width
,
717 gdk_event
->area
.height
);
719 if (gdk_event
->count
== 0)
721 win
->m_clipPaintRegion
= TRUE
;
723 wxEraseEvent
eevent( win
->GetId() );
724 eevent
.SetEventObject( win
);
725 win
->GetEventHandler()->ProcessEvent(eevent
);
727 wxPaintEvent
event( win
->GetId() );
728 event
.SetEventObject( win
);
729 win
->GetEventHandler()->ProcessEvent( event
);
731 win
->GetUpdateRegion().Clear();
733 win
->m_clipPaintRegion
= FALSE
;
736 /* The following code will result in all window-less widgets
737 being redrawn if the wxWindows class is given a chance to
738 paint *anything* because it will then be allowed to paint
739 over the window-less widgets */
741 GList
*children
= pizza
->children
;
744 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
745 children
= children
->next
;
747 GdkEventExpose child_event
= *gdk_event
;
749 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
750 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
751 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
753 child_event
.area
.x
= child
->widget
->allocation
.x
;
754 child_event
.area
.y
= child
->widget
->allocation
.y
;
755 child_event
.area
.width
= child
->widget
->allocation
.width
;
756 child_event
.area
.height
= child
->widget
->allocation
.height
;
757 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
764 //-----------------------------------------------------------------------------
765 // "event" of m_wxwindow
766 //-----------------------------------------------------------------------------
768 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
769 expose events. We need them, of course, so we override the main event
770 procedure in GtkWidget by giving our own handler for all system events.
771 There, we look for expose events ourselves whereas all other events are
774 gint
gtk_window_event_event_callback( GtkWidget
*widget
, GdkEventExpose
*event
, wxWindow
*win
)
776 if (event
->type
== GDK_EXPOSE
)
778 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
785 //-----------------------------------------------------------------------------
786 // "draw" of m_wxwindow
787 //-----------------------------------------------------------------------------
789 /* This callback is a complete replacement of the gtk_pizza_draw() function,
792 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
797 wxapp_install_idle_handler();
799 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
800 (win
->GetChildren().GetCount() == 0))
806 if (win->GetName() == wxT("panel"))
808 wxPrintf( wxT("OnDraw from ") );
809 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
810 wxPrintf( win->GetClassInfo()->GetClassName() );
811 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
818 GtkPizza
*pizza
= GTK_PIZZA (widget
);
820 if (win
->GetThemeEnabled())
822 wxWindow
*parent
= win
->GetParent();
823 while (parent
&& !parent
->IsTopLevel())
824 parent
= parent
->GetParent();
828 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
829 GTK_SHADOW_NONE
, rect
, parent
->m_widget
, "base", 0, 0, -1, -1);
833 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
834 (pizza
->clear_on_draw
))
836 gdk_window_clear_area( pizza
->bin_window
,
837 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
840 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
842 win
->m_clipPaintRegion
= TRUE
;
844 wxEraseEvent
eevent( win
->GetId() );
845 eevent
.SetEventObject( win
);
846 win
->GetEventHandler()->ProcessEvent(eevent
);
848 wxPaintEvent
event( win
->GetId() );
849 event
.SetEventObject( win
);
850 win
->GetEventHandler()->ProcessEvent( event
);
852 win
->GetUpdateRegion().Clear();
854 win
->m_clipPaintRegion
= FALSE
;
857 GList
*children
= pizza
->children
;
860 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
861 children
= children
->next
;
863 GdkRectangle child_area
;
864 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
866 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
871 //-----------------------------------------------------------------------------
872 // "key_press_event" from any window
873 //-----------------------------------------------------------------------------
875 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
880 wxapp_install_idle_handler();
882 if (!win
->m_hasVMT
) return FALSE
;
883 if (g_blockEventsOnDrag
) return FALSE
;
888 tmp += (char)gdk_event->keyval;
889 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
890 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
895 GdkModifierType state
;
896 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
900 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
901 /* sending unknown key events doesn't really make sense */
902 if (key_code
== 0) return FALSE
;
904 wxKeyEvent
event( wxEVT_KEY_DOWN
);
905 event
.SetTimestamp( gdk_event
->time
);
906 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
907 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
908 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
909 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
910 event
.m_keyCode
= key_code
;
911 event
.m_scanCode
= gdk_event
->keyval
;
914 event
.SetEventObject( win
);
915 ret
= win
->GetEventHandler()->ProcessEvent( event
);
920 wxWindow
*ancestor
= win
;
923 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
926 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
927 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
930 if (ancestor
->IsTopLevel())
932 ancestor
= ancestor
->GetParent();
935 #endif // wxUSE_ACCEL
937 /* wxMSW doesn't send char events with Alt pressed */
938 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
939 will only be sent if it is not in an accelerator table. */
940 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
945 wxKeyEvent
event2( wxEVT_CHAR
);
946 event2
.SetTimestamp( gdk_event
->time
);
947 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
948 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
949 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
950 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
951 event2
.m_keyCode
= key_code
;
952 event2
.m_scanCode
= gdk_event
->keyval
;
955 event2
.SetEventObject( win
);
956 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
959 /* win is a control: tab can be propagated up */
961 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
962 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
963 // have this style, yet choose not to process this particular TAB in which
964 // case TAB must still work as a navigational character
966 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
968 (win
->GetParent()) &&
969 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
971 wxNavigationKeyEvent new_event
;
972 new_event
.SetEventObject( win
->GetParent() );
973 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
974 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
975 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
976 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
977 new_event
.SetCurrentFocus( win
);
978 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
981 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
983 (gdk_event
->keyval
== GDK_Escape
) )
985 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
986 new_event
.SetEventObject( win
);
987 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
990 #if (GTK_MINOR_VERSION > 0)
991 /* Pressing F10 will activate the menu bar of the top frame. */
995 (gdk_event->keyval == GDK_F10) )
997 wxWindow *ancestor = win;
1000 if (wxIsKindOf(ancestor,wxFrame))
1002 wxFrame *frame = (wxFrame*) ancestor;
1003 wxMenuBar *menubar = frame->GetMenuBar();
1006 wxNode *node = menubar->GetMenus().First();
1009 wxMenu *firstMenu = (wxMenu*) node->Data();
1010 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
1016 ancestor = ancestor->GetParent();
1024 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1031 //-----------------------------------------------------------------------------
1032 // "key_release_event" from any window
1033 //-----------------------------------------------------------------------------
1035 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
1040 wxapp_install_idle_handler();
1042 if (!win
->m_hasVMT
) return FALSE
;
1043 if (g_blockEventsOnDrag
) return FALSE
;
1046 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
1047 if (gdk_event->state & GDK_SHIFT_MASK)
1048 printf( "ShiftDown.\n" );
1050 printf( "ShiftUp.\n" );
1051 if (gdk_event->state & GDK_CONTROL_MASK)
1052 printf( "ControlDown.\n" );
1054 printf( "ControlUp.\n" );
1058 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
1060 /* sending unknown key events doesn't really make sense */
1061 if (key_code
== 0) return FALSE
;
1065 GdkModifierType state
;
1066 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1068 wxKeyEvent
event( wxEVT_KEY_UP
);
1069 event
.SetTimestamp( gdk_event
->time
);
1070 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1071 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1072 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1073 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1074 event
.m_keyCode
= key_code
;
1075 event
.m_scanCode
= gdk_event
->keyval
;
1078 event
.SetEventObject( win
);
1080 if (win
->GetEventHandler()->ProcessEvent( event
))
1082 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1089 // ----------------------------------------------------------------------------
1090 // mouse event processing helper
1091 // ----------------------------------------------------------------------------
1093 static void AdjustEventButtonState(wxMouseEvent
& event
)
1095 // GDK reports the old state of the button for a button press event, but
1096 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1097 // for a LEFT_DOWN event, not FALSE, so we will invert
1098 // left/right/middleDown for the corresponding click events
1100 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1101 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1102 (event
.GetEventType() == wxEVT_LEFT_UP
))
1104 event
.m_leftDown
= !event
.m_leftDown
;
1108 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1109 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1110 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1112 event
.m_middleDown
= !event
.m_middleDown
;
1116 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1117 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1118 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1120 event
.m_rightDown
= !event
.m_rightDown
;
1125 //-----------------------------------------------------------------------------
1126 // "button_press_event"
1127 //-----------------------------------------------------------------------------
1129 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1134 wxapp_install_idle_handler();
1137 wxPrintf( wxT("1) OnButtonPress from ") );
1138 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1139 wxPrintf( win->GetClassInfo()->GetClassName() );
1140 wxPrintf( wxT(".\n") );
1142 if (!win
->m_hasVMT
) return FALSE
;
1143 if (g_blockEventsOnDrag
) return TRUE
;
1144 if (g_blockEventsOnScroll
) return TRUE
;
1146 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1148 if (win
->m_wxwindow
)
1150 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1152 gtk_widget_grab_focus (win
->m_wxwindow
);
1155 wxPrintf( wxT("GrabFocus from ") );
1156 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1157 wxPrintf( win->GetClassInfo()->GetClassName() );
1158 wxPrintf( wxT(".\n") );
1164 wxEventType event_type
= wxEVT_NULL
;
1166 if (gdk_event
->button
== 1)
1168 switch (gdk_event
->type
)
1170 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1171 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1175 else if (gdk_event
->button
== 2)
1177 switch (gdk_event
->type
)
1179 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1180 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1184 else if (gdk_event
->button
== 3)
1186 switch (gdk_event
->type
)
1188 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1189 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1194 if ( event_type
== wxEVT_NULL
)
1196 // unknown mouse button or click type
1200 wxMouseEvent
event( event_type
);
1201 event
.SetTimestamp( gdk_event
->time
);
1202 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1203 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1204 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1205 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1206 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1207 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1208 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1210 event
.m_x
= (wxCoord
)gdk_event
->x
;
1211 event
.m_y
= (wxCoord
)gdk_event
->y
;
1213 AdjustEventButtonState(event
);
1215 // Some control don't have their own X window and thus cannot get
1218 if (!g_captureWindow
)
1220 wxCoord x
= event
.m_x
;
1221 wxCoord y
= event
.m_y
;
1222 if (win
->m_wxwindow
)
1224 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1225 x
+= pizza
->xoffset
;
1226 y
+= pizza
->yoffset
;
1229 wxNode
*node
= win
->GetChildren().First();
1232 wxWindow
*child
= (wxWindow
*)node
->Data();
1234 node
= node
->Next();
1235 if (!child
->IsShown())
1238 if (child
->m_isStaticBox
)
1240 // wxStaticBox is transparent in the box itself
1241 int xx1
= child
->m_x
;
1242 int yy1
= child
->m_y
;
1243 int xx2
= child
->m_x
+ child
->m_width
;
1244 int yy2
= child
->m_x
+ child
->m_height
;
1247 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1249 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1251 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1253 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1256 event
.m_x
-= child
->m_x
;
1257 event
.m_y
-= child
->m_y
;
1264 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1265 (child
->m_x
<= x
) &&
1266 (child
->m_y
<= y
) &&
1267 (child
->m_x
+child
->m_width
>= x
) &&
1268 (child
->m_y
+child
->m_height
>= y
))
1271 event
.m_x
-= child
->m_x
;
1272 event
.m_y
-= child
->m_y
;
1279 event
.SetEventObject( win
);
1281 gs_timeLastClick
= gdk_event
->time
;
1284 wxPrintf( wxT("2) OnButtonPress from ") );
1285 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1286 wxPrintf( win->GetClassInfo()->GetClassName() );
1287 wxPrintf( wxT(".\n") );
1290 if (win
->GetEventHandler()->ProcessEvent( event
))
1292 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1299 //-----------------------------------------------------------------------------
1300 // "button_release_event"
1301 //-----------------------------------------------------------------------------
1303 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1308 wxapp_install_idle_handler();
1310 if (!win
->m_hasVMT
) return FALSE
;
1311 if (g_blockEventsOnDrag
) return FALSE
;
1312 if (g_blockEventsOnScroll
) return FALSE
;
1314 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1317 printf( "OnButtonRelease from " );
1318 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1319 printf( win->GetClassInfo()->GetClassName() );
1323 wxEventType event_type
= wxEVT_NULL
;
1325 switch (gdk_event
->button
)
1327 case 1: event_type
= wxEVT_LEFT_UP
; break;
1328 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1329 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1330 default: return FALSE
;
1333 wxMouseEvent
event( event_type
);
1334 event
.SetTimestamp( gdk_event
->time
);
1335 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1336 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1337 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1338 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1339 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1340 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1341 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1342 event
.m_x
= (wxCoord
)gdk_event
->x
;
1343 event
.m_y
= (wxCoord
)gdk_event
->y
;
1345 AdjustEventButtonState(event
);
1347 // Some control don't have their own X window and thus cannot get
1350 if (!g_captureWindow
)
1352 wxCoord x
= event
.m_x
;
1353 wxCoord y
= event
.m_y
;
1354 if (win
->m_wxwindow
)
1356 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1357 x
+= pizza
->xoffset
;
1358 y
+= pizza
->yoffset
;
1361 wxNode
*node
= win
->GetChildren().First();
1364 wxWindow
*child
= (wxWindow
*)node
->Data();
1366 node
= node
->Next();
1367 if (!child
->IsShown())
1370 if (child
->m_isStaticBox
)
1372 // wxStaticBox is transparent in the box itself
1373 int xx1
= child
->m_x
;
1374 int yy1
= child
->m_y
;
1375 int xx2
= child
->m_x
+ child
->m_width
;
1376 int yy2
= child
->m_x
+ child
->m_height
;
1379 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1381 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1383 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1385 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1388 event
.m_x
-= child
->m_x
;
1389 event
.m_y
-= child
->m_y
;
1396 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1397 (child
->m_x
<= x
) &&
1398 (child
->m_y
<= y
) &&
1399 (child
->m_x
+child
->m_width
>= x
) &&
1400 (child
->m_y
+child
->m_height
>= y
))
1403 event
.m_x
-= child
->m_x
;
1404 event
.m_y
-= child
->m_y
;
1411 event
.SetEventObject( win
);
1413 if (win
->GetEventHandler()->ProcessEvent( event
))
1415 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1422 //-----------------------------------------------------------------------------
1423 // "motion_notify_event"
1424 //-----------------------------------------------------------------------------
1426 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1431 wxapp_install_idle_handler();
1433 if (!win
->m_hasVMT
) return FALSE
;
1434 if (g_blockEventsOnDrag
) return FALSE
;
1435 if (g_blockEventsOnScroll
) return FALSE
;
1437 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1439 if (gdk_event
->is_hint
)
1443 GdkModifierType state
;
1444 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1450 printf( "OnMotion from " );
1451 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1452 printf( win->GetClassInfo()->GetClassName() );
1456 wxMouseEvent
event( wxEVT_MOTION
);
1457 event
.SetTimestamp( gdk_event
->time
);
1458 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1459 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1460 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1461 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1462 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1463 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1464 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1466 event
.m_x
= (wxCoord
)gdk_event
->x
;
1467 event
.m_y
= (wxCoord
)gdk_event
->y
;
1469 // Some control don't have their own X window and thus cannot get
1472 if (!g_captureWindow
)
1474 wxCoord x
= event
.m_x
;
1475 wxCoord y
= event
.m_y
;
1476 if (win
->m_wxwindow
)
1478 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1479 x
+= pizza
->xoffset
;
1480 y
+= pizza
->yoffset
;
1483 wxNode
*node
= win
->GetChildren().First();
1486 wxWindow
*child
= (wxWindow
*)node
->Data();
1488 node
= node
->Next();
1489 if (!child
->IsShown())
1492 if (child
->m_isStaticBox
)
1494 // wxStaticBox is transparent in the box itself
1495 int xx1
= child
->m_x
;
1496 int yy1
= child
->m_y
;
1497 int xx2
= child
->m_x
+ child
->m_width
;
1498 int yy2
= child
->m_x
+ child
->m_height
;
1501 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1503 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1505 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1507 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1510 event
.m_x
-= child
->m_x
;
1511 event
.m_y
-= child
->m_y
;
1518 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1519 (child
->m_x
<= x
) &&
1520 (child
->m_y
<= y
) &&
1521 (child
->m_x
+child
->m_width
>= x
) &&
1522 (child
->m_y
+child
->m_height
>= y
))
1525 event
.m_x
-= child
->m_x
;
1526 event
.m_y
-= child
->m_y
;
1533 event
.SetEventObject( win
);
1535 if (win
->GetEventHandler()->ProcessEvent( event
))
1537 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1544 //-----------------------------------------------------------------------------
1546 //-----------------------------------------------------------------------------
1548 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1553 wxapp_install_idle_handler();
1555 if (!win
->m_hasVMT
) return FALSE
;
1556 if (g_blockEventsOnDrag
) return FALSE
;
1558 switch ( g_sendActivateEvent
)
1561 // we've got focus from outside, synthtize wxActivateEvent
1562 g_sendActivateEvent
= 1;
1566 // another our window just lost focus, it was already ours before
1567 // - don't send any wxActivateEvent
1568 g_sendActivateEvent
= -1;
1572 g_focusWindow
= win
;
1575 printf( "OnSetFocus from " );
1576 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1577 printf( win->GetClassInfo()->GetClassName() );
1579 printf( WXSTRINGCAST win->GetLabel() );
1583 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1586 panel
->SetLastFocus(win
);
1591 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1595 // caret needs to be informed about focus change
1596 wxCaret
*caret
= win
->GetCaret();
1599 caret
->OnSetFocus();
1601 #endif // wxUSE_CARET
1603 if (win
->IsTopLevel())
1605 wxActivateEvent
event( wxEVT_ACTIVATE
, TRUE
, win
->GetId() );
1606 event
.SetEventObject( win
);
1608 // ignore return value
1609 win
->GetEventHandler()->ProcessEvent( event
);
1612 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1613 event
.SetEventObject( win
);
1615 if (win
->GetEventHandler()->ProcessEvent( event
))
1617 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1625 //-----------------------------------------------------------------------------
1626 // "focus_out_event"
1627 //-----------------------------------------------------------------------------
1629 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1634 wxapp_install_idle_handler();
1636 if (!win
->m_hasVMT
) return FALSE
;
1637 if (g_blockEventsOnDrag
) return FALSE
;
1639 // if the focus goes out of our app alltogether, OnIdle() will send
1640 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1641 // g_sendActivateEvent to -1
1642 g_sendActivateEvent
= 0;
1644 wxWindow
*winFocus
= FindFocusedChild(win
);
1648 g_focusWindow
= (wxWindow
*)NULL
;
1651 printf( "OnKillFocus from " );
1652 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1653 printf( win->GetClassInfo()->GetClassName() );
1663 // caret needs to be informed about focus change
1664 wxCaret
*caret
= win
->GetCaret();
1667 caret
->OnKillFocus();
1669 #endif // wxUSE_CARET
1671 if (win
->IsTopLevel())
1673 wxActivateEvent
event( wxEVT_ACTIVATE
, FALSE
, win
->GetId() );
1674 event
.SetEventObject( win
);
1676 // ignore return value
1677 win
->GetEventHandler()->ProcessEvent( event
);
1680 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1681 event
.SetEventObject( win
);
1683 if (win
->GetEventHandler()->ProcessEvent( event
))
1685 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1692 //-----------------------------------------------------------------------------
1693 // "enter_notify_event"
1694 //-----------------------------------------------------------------------------
1696 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1701 wxapp_install_idle_handler();
1703 if (!win
->m_hasVMT
) return FALSE
;
1704 if (g_blockEventsOnDrag
) return FALSE
;
1706 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1708 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1709 #if (GTK_MINOR_VERSION > 0)
1710 event
.SetTimestamp( gdk_event
->time
);
1712 event
.SetEventObject( win
);
1716 GdkModifierType state
= (GdkModifierType
)0;
1718 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1720 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1721 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1722 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1723 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1724 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1725 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1726 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1731 if (win
->GetEventHandler()->ProcessEvent( event
))
1733 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1740 //-----------------------------------------------------------------------------
1741 // "leave_notify_event"
1742 //-----------------------------------------------------------------------------
1744 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1749 wxapp_install_idle_handler();
1751 if (!win
->m_hasVMT
) return FALSE
;
1752 if (g_blockEventsOnDrag
) return FALSE
;
1754 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1756 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1757 #if (GTK_MINOR_VERSION > 0)
1758 event
.SetTimestamp( gdk_event
->time
);
1760 event
.SetEventObject( win
);
1764 GdkModifierType state
= (GdkModifierType
)0;
1766 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1768 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1769 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1770 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1771 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1772 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1773 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1774 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1779 if (win
->GetEventHandler()->ProcessEvent( event
))
1781 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1788 //-----------------------------------------------------------------------------
1789 // "value_changed" from m_vAdjust
1790 //-----------------------------------------------------------------------------
1792 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1797 wxapp_install_idle_handler();
1799 if (g_blockEventsOnDrag
) return;
1801 if (!win
->m_hasVMT
) return;
1803 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1804 if (fabs(diff
) < 0.2) return;
1806 win
->m_oldVerticalPos
= adjust
->value
;
1808 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1809 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1811 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1812 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1813 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1814 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1815 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1817 int value
= (int)(adjust
->value
+0.5);
1819 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1820 event
.SetEventObject( win
);
1821 win
->GetEventHandler()->ProcessEvent( event
);
1824 //-----------------------------------------------------------------------------
1825 // "value_changed" from m_hAdjust
1826 //-----------------------------------------------------------------------------
1828 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1833 wxapp_install_idle_handler();
1835 if (g_blockEventsOnDrag
) return;
1836 if (!win
->m_hasVMT
) return;
1838 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1839 if (fabs(diff
) < 0.2) return;
1841 win
->m_oldHorizontalPos
= adjust
->value
;
1843 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1844 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1846 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1847 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1848 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1849 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1850 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1852 int value
= (int)(adjust
->value
+0.5);
1854 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1855 event
.SetEventObject( win
);
1856 win
->GetEventHandler()->ProcessEvent( event
);
1859 //-----------------------------------------------------------------------------
1860 // "button_press_event" from scrollbar
1861 //-----------------------------------------------------------------------------
1863 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1864 GdkEventButton
*gdk_event
,
1870 wxapp_install_idle_handler();
1873 g_blockEventsOnScroll
= TRUE
;
1874 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1879 //-----------------------------------------------------------------------------
1880 // "button_release_event" from scrollbar
1881 //-----------------------------------------------------------------------------
1883 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1884 GdkEventButton
*WXUNUSED(gdk_event
),
1889 // don't test here as we can release the mouse while being over
1890 // a different window than the slider
1892 // if (gdk_event->window != widget->slider) return FALSE;
1894 g_blockEventsOnScroll
= FALSE
;
1896 if (win
->m_isScrolling
)
1898 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
1902 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1903 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1905 value
= (int)(win
->m_hAdjust
->value
+0.5);
1908 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1910 value
= (int)(win
->m_vAdjust
->value
+0.5);
1914 wxScrollWinEvent
event( command
, value
, dir
);
1915 event
.SetEventObject( win
);
1916 win
->GetEventHandler()->ProcessEvent( event
);
1919 win
->m_isScrolling
= FALSE
;
1924 // ----------------------------------------------------------------------------
1925 // this wxWindowBase function is implemented here (in platform-specific file)
1926 // because it is static and so couldn't be made virtual
1927 // ----------------------------------------------------------------------------
1929 wxWindow
*wxWindowBase::FindFocus()
1931 return g_focusWindow
;
1934 //-----------------------------------------------------------------------------
1935 // "realize" from m_widget
1936 //-----------------------------------------------------------------------------
1938 /* We cannot set colours and fonts before the widget has
1939 been realized, so we do this directly after realization. */
1942 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1947 wxapp_install_idle_handler();
1949 if (win
->m_delayedBackgroundColour
)
1950 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1952 if (win
->m_delayedForegroundColour
)
1953 win
->SetForegroundColour( win
->GetForegroundColour() );
1955 wxWindowCreateEvent
event( win
);
1956 event
.SetEventObject( win
);
1957 win
->GetEventHandler()->ProcessEvent( event
);
1962 //-----------------------------------------------------------------------------
1964 //-----------------------------------------------------------------------------
1967 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
1968 GtkAllocation
*WXUNUSED(alloc
),
1972 wxapp_install_idle_handler();
1974 if (!win
->m_hasScrolling
) return;
1976 int client_width
= 0;
1977 int client_height
= 0;
1978 win
->GetClientSize( &client_width
, &client_height
);
1979 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
1982 win
->m_oldClientWidth
= client_width
;
1983 win
->m_oldClientHeight
= client_height
;
1985 if (!win
->m_nativeSizeEvent
)
1987 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
1988 event
.SetEventObject( win
);
1989 win
->GetEventHandler()->ProcessEvent( event
);
1995 #define WXUNUSED_UNLESS_XIM(param) param
1997 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2000 /* Resize XIM window */
2003 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2004 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
2005 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
2008 wxapp_install_idle_handler();
2014 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
2018 gdk_window_get_size (widget
->window
, &width
, &height
);
2019 win
->m_icattr
->preedit_area
.width
= width
;
2020 win
->m_icattr
->preedit_area
.height
= height
;
2021 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2026 //-----------------------------------------------------------------------------
2027 // "realize" from m_wxwindow
2028 //-----------------------------------------------------------------------------
2030 /* Initialize XIM support */
2033 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2034 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
2037 wxapp_install_idle_handler();
2040 if (win
->m_ic
) return FALSE
;
2041 if (!widget
) return FALSE
;
2042 if (!gdk_im_ready()) return FALSE
;
2044 win
->m_icattr
= gdk_ic_attr_new();
2045 if (!win
->m_icattr
) return FALSE
;
2049 GdkColormap
*colormap
;
2050 GdkICAttr
*attr
= win
->m_icattr
;
2051 unsigned attrmask
= GDK_IC_ALL_REQ
;
2053 GdkIMStyle supported_style
= (GdkIMStyle
)
2054 (GDK_IM_PREEDIT_NONE
|
2055 GDK_IM_PREEDIT_NOTHING
|
2056 GDK_IM_PREEDIT_POSITION
|
2057 GDK_IM_STATUS_NONE
|
2058 GDK_IM_STATUS_NOTHING
);
2060 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2061 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2063 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2064 attr
->client_window
= widget
->window
;
2066 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2067 gtk_widget_get_default_colormap ())
2069 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2070 attr
->preedit_colormap
= colormap
;
2073 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2074 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2075 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2076 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2078 switch (style
& GDK_IM_PREEDIT_MASK
)
2080 case GDK_IM_PREEDIT_POSITION
:
2081 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2083 g_warning ("over-the-spot style requires fontset");
2087 gdk_window_get_size (widget
->window
, &width
, &height
);
2089 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2090 attr
->spot_location
.x
= 0;
2091 attr
->spot_location
.y
= height
;
2092 attr
->preedit_area
.x
= 0;
2093 attr
->preedit_area
.y
= 0;
2094 attr
->preedit_area
.width
= width
;
2095 attr
->preedit_area
.height
= height
;
2096 attr
->preedit_fontset
= widget
->style
->font
;
2101 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2103 if (win
->m_ic
== NULL
)
2104 g_warning ("Can't create input context.");
2107 mask
= gdk_window_get_events (widget
->window
);
2108 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2109 gdk_window_set_events (widget
->window
, mask
);
2111 if (GTK_WIDGET_HAS_FOCUS(widget
))
2112 gdk_im_begin (win
->m_ic
, widget
->window
);
2119 //-----------------------------------------------------------------------------
2120 // InsertChild for wxWindow.
2121 //-----------------------------------------------------------------------------
2123 /* Callback for wxWindow. This very strange beast has to be used because
2124 * C++ has no virtual methods in a constructor. We have to emulate a
2125 * virtual function here as wxNotebook requires a different way to insert
2126 * a child in it. I had opted for creating a wxNotebookPage window class
2127 * which would have made this superfluous (such in the MDI window system),
2128 * but no-one was listening to me... */
2130 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
2132 /* the window might have been scrolled already, do we
2133 have to adapt the position */
2134 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2135 child
->m_x
+= pizza
->xoffset
;
2136 child
->m_y
+= pizza
->yoffset
;
2138 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2139 GTK_WIDGET(child
->m_widget
),
2146 //-----------------------------------------------------------------------------
2148 //-----------------------------------------------------------------------------
2150 wxWindow
* wxGetActiveWindow()
2152 return g_focusWindow
;
2155 //-----------------------------------------------------------------------------
2157 //-----------------------------------------------------------------------------
2159 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2161 void wxWindow::Init()
2167 m_widget
= (GtkWidget
*) NULL
;
2168 m_wxwindow
= (GtkWidget
*) NULL
;
2178 m_needParent
= TRUE
;
2179 m_isBeingDeleted
= FALSE
;
2182 m_nativeSizeEvent
= FALSE
;
2184 m_hasScrolling
= FALSE
;
2185 m_isScrolling
= FALSE
;
2187 m_hAdjust
= (GtkAdjustment
*) NULL
;
2188 m_vAdjust
= (GtkAdjustment
*) NULL
;
2189 m_oldHorizontalPos
= 0.0;
2190 m_oldVerticalPos
= 0.0;
2193 m_widgetStyle
= (GtkStyle
*) NULL
;
2195 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2197 m_isStaticBox
= FALSE
;
2198 m_isRadioButton
= FALSE
;
2200 m_acceptsFocus
= FALSE
;
2202 m_clipPaintRegion
= FALSE
;
2204 m_cursor
= *wxSTANDARD_CURSOR
;
2206 m_delayedForegroundColour
= FALSE
;
2207 m_delayedBackgroundColour
= FALSE
;
2210 m_ic
= (GdkIC
*) NULL
;
2211 m_icattr
= (GdkICAttr
*) NULL
;
2215 wxWindow::wxWindow()
2220 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
2221 const wxPoint
&pos
, const wxSize
&size
,
2222 long style
, const wxString
&name
)
2226 Create( parent
, id
, pos
, size
, style
, name
);
2229 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
2230 const wxPoint
&pos
, const wxSize
&size
,
2231 long style
, const wxString
&name
)
2233 if (!PreCreation( parent
, pos
, size
) ||
2234 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2236 wxFAIL_MSG( wxT("wxWindow creation failed") );
2240 m_insertCallback
= wxInsertChildInWindow
;
2242 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2243 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2245 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2247 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2248 scroll_class
->scrollbar_spacing
= 0;
2250 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2252 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2253 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2255 m_wxwindow
= gtk_pizza_new();
2257 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2259 #if (GTK_MINOR_VERSION > 0)
2260 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2262 if (HasFlag(wxRAISED_BORDER
))
2264 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2266 else if (HasFlag(wxSUNKEN_BORDER
))
2268 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2270 else if (HasFlag(wxSIMPLE_BORDER
))
2272 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2276 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2278 #else // GTK_MINOR_VERSION == 0
2279 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2281 if (HasFlag(wxRAISED_BORDER
))
2283 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2285 else if (HasFlag(wxSUNKEN_BORDER
))
2287 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2291 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2293 #endif // GTK_MINOR_VERSION
2295 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2296 m_acceptsFocus
= TRUE
;
2298 #if (GTK_MINOR_VERSION == 0)
2299 // shut the viewport up
2300 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2301 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2302 #endif // GTK_MINOR_VERSION == 0
2304 // I _really_ don't want scrollbars in the beginning
2305 m_vAdjust
->lower
= 0.0;
2306 m_vAdjust
->upper
= 1.0;
2307 m_vAdjust
->value
= 0.0;
2308 m_vAdjust
->step_increment
= 1.0;
2309 m_vAdjust
->page_increment
= 1.0;
2310 m_vAdjust
->page_size
= 5.0;
2311 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2312 m_hAdjust
->lower
= 0.0;
2313 m_hAdjust
->upper
= 1.0;
2314 m_hAdjust
->value
= 0.0;
2315 m_hAdjust
->step_increment
= 1.0;
2316 m_hAdjust
->page_increment
= 1.0;
2317 m_hAdjust
->page_size
= 5.0;
2318 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2320 // these handlers block mouse events to any window during scrolling such as
2321 // motion events and prevent GTK and wxWindows from fighting over where the
2324 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2325 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2327 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2328 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2330 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2331 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2333 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2334 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2336 // these handlers get notified when screen updates are required either when
2337 // scrolling or when the window size (and therefore scrollbar configuration)
2340 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2341 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2342 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2343 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2345 gtk_widget_show( m_wxwindow
);
2348 m_parent
->DoAddChild( this );
2357 wxWindow::~wxWindow()
2359 if (g_focusWindow
== this)
2360 g_focusWindow
= NULL
;
2362 m_isBeingDeleted
= TRUE
;
2371 m_parent
->RemoveChild( this );
2375 gdk_ic_destroy (m_ic
);
2377 gdk_ic_attr_destroy (m_icattr
);
2382 #if DISABLE_STYLE_IF_BROKEN_THEME
2383 // don't delete if it's a pixmap theme style
2384 if (!m_widgetStyle
->engine_data
)
2385 gtk_style_unref( m_widgetStyle
);
2387 m_widgetStyle
= (GtkStyle
*) NULL
;
2392 gtk_widget_destroy( m_wxwindow
);
2393 m_wxwindow
= (GtkWidget
*) NULL
;
2398 gtk_widget_destroy( m_widget
);
2399 m_widget
= (GtkWidget
*) NULL
;
2403 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2405 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2407 /* this turns -1 into 20 so that a minimal window is
2408 visible even although -1,-1 has been given as the
2409 size of the window. the same trick is used in other
2410 ports and should make debugging easier */
2411 m_width
= WidthDefault(size
.x
);
2412 m_height
= HeightDefault(size
.y
);
2417 /* some reasonable defaults */
2422 m_x
= (gdk_screen_width () - m_width
) / 2;
2423 if (m_x
< 10) m_x
= 10;
2427 m_y
= (gdk_screen_height () - m_height
) / 2;
2428 if (m_y
< 10) m_y
= 10;
2435 void wxWindow::PostCreation()
2437 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2443 /* these get reported to wxWindows -> wxPaintEvent */
2445 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2447 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2448 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2450 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2451 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2453 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2455 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2456 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2460 #if (GTK_MINOR_VERSION > 0)
2461 /* these are called when the "sunken" or "raised" borders are drawn */
2462 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2463 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2465 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2466 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2470 if (m_wxwindow
&& m_needParent
)
2472 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2473 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2475 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2476 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2480 // For dialogs and frames, we are interested mainly in
2481 // m_widget's focus.
2483 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2484 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2486 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2487 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2490 GtkWidget
*connect_widget
= GetConnectWidget();
2492 ConnectWidget( connect_widget
);
2494 /* We cannot set colours, fonts and cursors before the widget has
2495 been realized, so we do this directly after realization */
2496 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2497 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2501 // Catch native resize events
2502 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2503 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2505 // Initialize XIM support
2506 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2507 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2509 // And resize XIM window
2510 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2511 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2514 if (!GTK_IS_COMBO(m_widget
))
2516 // This is needed if we want to add our windows into native
2517 // GTK control, such as the toolbar. With this callback, the
2518 // toolbar gets to know the correct size (the one set by the
2519 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2520 // when moving to GTK 2.0.
2521 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2522 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2528 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2530 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2531 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2533 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2534 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2536 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2537 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2539 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2540 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2542 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2543 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2545 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2546 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2548 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2549 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2552 bool wxWindow::Destroy()
2554 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2558 return wxWindowBase::Destroy();
2561 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2563 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2566 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2568 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2569 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2571 if (m_resizing
) return; /* I don't like recursions */
2574 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2576 /* don't set the size for children of wxNotebook, just take the values. */
2584 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2586 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2588 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2589 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2590 if (width
!= -1) m_width
= width
;
2591 if (height
!= -1) m_height
= height
;
2595 m_x
= x
+ pizza
->xoffset
;
2596 m_y
= y
+ pizza
->yoffset
;
2601 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2603 if (width
== -1) m_width
= 80;
2606 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2608 if (height
== -1) m_height
= 26;
2611 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2612 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2613 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2614 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2617 int bottom_border
= 0;
2619 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2621 /* the default button has a border around it */
2626 DoMoveWindow( m_x
-border
,
2629 m_height
+border
+bottom_border
);
2634 /* Sometimes the client area changes size without the
2635 whole windows's size changing, but if the whole
2636 windows's size doesn't change, no wxSizeEvent will
2637 normally be sent. Here we add an extra test if
2638 the client test has been changed and this will
2640 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2644 wxPrintf( "OnSize sent from " );
2645 if (GetClassInfo() && GetClassInfo()->GetClassName())
2646 wxPrintf( GetClassInfo()->GetClassName() );
2647 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2650 if (!m_nativeSizeEvent
)
2652 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2653 event
.SetEventObject( this );
2654 GetEventHandler()->ProcessEvent( event
);
2660 void wxWindow::OnInternalIdle()
2662 if ( g_sendActivateEvent
!= -1 )
2664 bool activate
= g_sendActivateEvent
!= 0;
2667 g_sendActivateEvent
= -1;
2669 wxActivateEvent
event(wxEVT_ACTIVATE_APP
, activate
, GetId());
2670 event
.SetEventObject(this);
2672 (void)GetEventHandler()->ProcessEvent(event
);
2675 wxCursor cursor
= m_cursor
;
2676 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2680 /* I now set the cursor anew in every OnInternalIdle call
2681 as setting the cursor in a parent window also effects the
2682 windows above so that checking for the current cursor is
2687 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2689 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2691 if (!g_globalCursor
.Ok())
2692 cursor
= *wxSTANDARD_CURSOR
;
2694 window
= m_widget
->window
;
2695 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2696 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2702 GdkWindow
*window
= m_widget
->window
;
2703 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2704 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2712 void wxWindow::DoGetSize( int *width
, int *height
) const
2714 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2716 if (width
) (*width
) = m_width
;
2717 if (height
) (*height
) = m_height
;
2720 void wxWindow::DoSetClientSize( int width
, int height
)
2722 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2726 SetSize( width
, height
);
2733 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2735 /* when using GTK 1.2 we set the shadow border size to 2 */
2739 if (HasFlag(wxSIMPLE_BORDER
))
2741 /* when using GTK 1.2 we set the simple border size to 1 */
2748 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2750 GtkRequisition vscroll_req
;
2751 vscroll_req
.width
= 2;
2752 vscroll_req
.height
= 2;
2753 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2754 (scroll_window
->vscrollbar
, &vscroll_req
);
2756 GtkRequisition hscroll_req
;
2757 hscroll_req
.width
= 2;
2758 hscroll_req
.height
= 2;
2759 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2760 (scroll_window
->hscrollbar
, &hscroll_req
);
2762 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2764 if (scroll_window
->vscrollbar_visible
)
2766 dw
+= vscroll_req
.width
;
2767 dw
+= scroll_class
->scrollbar_spacing
;
2770 if (scroll_window
->hscrollbar_visible
)
2772 dh
+= hscroll_req
.height
;
2773 dh
+= scroll_class
->scrollbar_spacing
;
2777 SetSize( width
+dw
, height
+dh
);
2781 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2783 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2787 if (width
) (*width
) = m_width
;
2788 if (height
) (*height
) = m_height
;
2795 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2797 /* when using GTK 1.2 we set the shadow border size to 2 */
2801 if (HasFlag(wxSIMPLE_BORDER
))
2803 /* when using GTK 1.2 we set the simple border size to 1 */
2810 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2812 GtkRequisition vscroll_req
;
2813 vscroll_req
.width
= 2;
2814 vscroll_req
.height
= 2;
2815 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2816 (scroll_window
->vscrollbar
, &vscroll_req
);
2818 GtkRequisition hscroll_req
;
2819 hscroll_req
.width
= 2;
2820 hscroll_req
.height
= 2;
2821 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2822 (scroll_window
->hscrollbar
, &hscroll_req
);
2824 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2826 if (scroll_window
->vscrollbar_visible
)
2828 dw
+= vscroll_req
.width
;
2829 dw
+= scroll_class
->scrollbar_spacing
;
2832 if (scroll_window
->hscrollbar_visible
)
2834 dh
+= hscroll_req
.height
;
2835 dh
+= scroll_class
->scrollbar_spacing
;
2839 if (width
) (*width
) = m_width
- dw
;
2840 if (height
) (*height
) = m_height
- dh
;
2844 void wxWindow::DoGetPosition( int *x
, int *y
) const
2846 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2850 if (m_parent
&& m_parent
->m_wxwindow
)
2852 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2853 dx
= pizza
->xoffset
;
2854 dy
= pizza
->yoffset
;
2857 if (x
) (*x
) = m_x
- dx
;
2858 if (y
) (*y
) = m_y
- dy
;
2861 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2863 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2865 if (!m_widget
->window
) return;
2867 GdkWindow
*source
= (GdkWindow
*) NULL
;
2869 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2871 source
= m_widget
->window
;
2875 gdk_window_get_origin( source
, &org_x
, &org_y
);
2879 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2881 org_x
+= m_widget
->allocation
.x
;
2882 org_y
+= m_widget
->allocation
.y
;
2890 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2892 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2894 if (!m_widget
->window
) return;
2896 GdkWindow
*source
= (GdkWindow
*) NULL
;
2898 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2900 source
= m_widget
->window
;
2904 gdk_window_get_origin( source
, &org_x
, &org_y
);
2908 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2910 org_x
+= m_widget
->allocation
.x
;
2911 org_y
+= m_widget
->allocation
.y
;
2919 bool wxWindow::Show( bool show
)
2921 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2923 if (!wxWindowBase::Show(show
))
2930 gtk_widget_show( m_widget
);
2932 gtk_widget_hide( m_widget
);
2937 bool wxWindow::Enable( bool enable
)
2939 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2941 if (!wxWindowBase::Enable(enable
))
2947 gtk_widget_set_sensitive( m_widget
, enable
);
2949 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2954 int wxWindow::GetCharHeight() const
2956 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2958 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2960 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2962 return font
->ascent
+ font
->descent
;
2965 int wxWindow::GetCharWidth() const
2967 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2969 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2971 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2973 return gdk_string_width( font
, "H" );
2976 void wxWindow::GetTextExtent( const wxString
& string
,
2980 int *externalLeading
,
2981 const wxFont
*theFont
) const
2983 wxFont fontToUse
= m_font
;
2984 if (theFont
) fontToUse
= *theFont
;
2986 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2988 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2989 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2990 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2991 if (descent
) (*descent
) = font
->descent
;
2992 if (externalLeading
) (*externalLeading
) = 0; // ??
2995 void wxWindow::SetFocus()
2997 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3001 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3002 gtk_widget_grab_focus (m_wxwindow
);
3008 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
3010 gtk_widget_grab_focus (m_widget
);
3012 else if (GTK_IS_CONTAINER(m_widget
))
3014 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
3023 bool wxWindow::AcceptsFocus() const
3025 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3028 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
3030 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3032 wxWindow
*oldParent
= m_parent
,
3033 *newParent
= (wxWindow
*)newParentBase
;
3035 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3037 if ( !wxWindowBase::Reparent(newParent
) )
3040 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3042 /* prevent GTK from deleting the widget arbitrarily */
3043 gtk_widget_ref( m_widget
);
3047 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3050 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3054 /* insert GTK representation */
3055 (*(newParent
->m_insertCallback
))(newParent
, this);
3058 /* reverse: prevent GTK from deleting the widget arbitrarily */
3059 gtk_widget_unref( m_widget
);
3064 void wxWindow::DoAddChild(wxWindow
*child
)
3066 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3068 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3070 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3075 /* insert GTK representation */
3076 (*m_insertCallback
)(this, child
);
3079 void wxWindow::Raise()
3081 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3083 if (!m_widget
->window
) return;
3085 gdk_window_raise( m_widget
->window
);
3088 void wxWindow::Lower()
3090 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3092 if (!m_widget
->window
) return;
3094 gdk_window_lower( m_widget
->window
);
3097 bool wxWindow::SetCursor( const wxCursor
&cursor
)
3099 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3101 if (cursor
== m_cursor
)
3105 wxapp_install_idle_handler();
3107 if (cursor
== wxNullCursor
)
3108 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3110 return wxWindowBase::SetCursor( cursor
);
3113 void wxWindow::WarpPointer( int x
, int y
)
3115 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3117 /* we provide this function ourselves as it is
3118 missing in GDK (top of this file) */
3120 GdkWindow
*window
= (GdkWindow
*) NULL
;
3122 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3124 window
= GetConnectWidget()->window
;
3127 gdk_window_warp_pointer( window
, x
, y
);
3130 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
3132 if (!m_widget
) return;
3133 if (!m_widget
->window
) return;
3135 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3139 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3141 rect
->width
, rect
->height
);
3145 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3149 /* there is no GTK equivalent of "draw only, don't clear" so we
3150 invent our own in the GtkPizza widget */
3158 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3159 gboolean old_clear = pizza->clear_on_draw;
3160 gtk_pizza_set_clear( pizza, FALSE );
3161 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3162 gtk_pizza_set_clear( pizza, old_clear );
3164 GdkEventExpose gdk_event
;
3165 gdk_event
.type
= GDK_EXPOSE
;
3166 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3167 gdk_event
.count
= 0;
3168 gdk_event
.area
.x
= 0;
3169 gdk_event
.area
.y
= 0;
3170 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3171 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3172 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3177 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3186 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3187 gboolean old_clear = pizza->clear_on_draw;
3188 gtk_pizza_set_clear( pizza, FALSE );
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_wxwindow, &gdk_rect );
3196 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3198 gtk_pizza_set_clear( pizza, old_clear );
3200 GdkEventExpose gdk_event
;
3201 gdk_event
.type
= GDK_EXPOSE
;
3202 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3203 gdk_event
.count
= 0;
3204 gdk_event
.area
.x
= rect
->x
;
3205 gdk_event
.area
.y
= rect
->y
;
3206 gdk_event
.area
.width
= rect
->width
;
3207 gdk_event
.area
.height
= rect
->height
;
3208 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3212 GdkRectangle gdk_rect
;
3213 gdk_rect
.x
= rect
->x
;
3214 gdk_rect
.y
= rect
->y
;
3215 gdk_rect
.width
= rect
->width
;
3216 gdk_rect
.height
= rect
->height
;
3217 gtk_widget_draw( m_widget
, &gdk_rect
);
3222 void wxWindow::Clear()
3224 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3226 if (!m_widget
->window
) return;
3228 if (m_wxwindow
&& m_wxwindow
->window
)
3230 // gdk_window_clear( m_wxwindow->window );
3235 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
3237 wxWindowBase::DoSetToolTip(tip
);
3240 m_tooltip
->Apply( this );
3243 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3245 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3247 #endif // wxUSE_TOOLTIPS
3249 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
3251 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3253 if (!wxWindowBase::SetBackgroundColour(colour
))
3255 // don't leave if the GTK widget has just
3257 if (!m_delayedBackgroundColour
) return FALSE
;
3260 GdkWindow
*window
= (GdkWindow
*) NULL
;
3262 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3264 window
= GetConnectWidget()->window
;
3268 // indicate that a new style has been set
3269 // but it couldn't get applied as the
3270 // widget hasn't been realized yet.
3271 m_delayedBackgroundColour
= TRUE
;
3275 (m_wxwindow
->window
) &&
3276 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3278 /* wxMSW doesn't clear the window here. I don't do that either to
3279 provide compatibility. call Clear() to do the job. */
3281 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3282 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3290 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
3292 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3294 if (!wxWindowBase::SetForegroundColour(colour
))
3296 // don't leave if the GTK widget has just
3298 if (!m_delayedForegroundColour
) return FALSE
;
3301 GdkWindow
*window
= (GdkWindow
*) NULL
;
3303 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3305 window
= GetConnectWidget()->window
;
3309 // indicate that a new style has been set
3310 // but it couldn't get applied as the
3311 // widget hasn't been realized yet.
3312 m_delayedForegroundColour
= TRUE
;
3320 GtkStyle
*wxWindow::GetWidgetStyle()
3324 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3326 /* FIXME: is this necessary? */
3327 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3329 remake
->klass
= m_widgetStyle
->klass
;
3332 gtk_style_unref( m_widgetStyle
);
3333 m_widgetStyle
= remake
;
3337 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3340 def
= gtk_widget_get_default_style();
3342 m_widgetStyle
= gtk_style_copy( def
);
3344 /* FIXME: is this necessary? */
3345 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3347 m_widgetStyle
->klass
= def
->klass
;
3351 return m_widgetStyle
;
3354 void wxWindow::SetWidgetStyle()
3356 #if DISABLE_STYLE_IF_BROKEN_THEM
3357 if (m_widget
->style
->engine_data
)
3359 static bool s_warningPrinted
= FALSE
;
3360 if (!s_warningPrinted
)
3362 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3363 s_warningPrinted
= TRUE
;
3365 m_widgetStyle
= m_widget
->style
;
3370 GtkStyle
*style
= GetWidgetStyle();
3372 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3374 gdk_font_unref( style
->font
);
3375 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3378 if (m_foregroundColour
.Ok())
3380 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3381 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3383 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3384 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3385 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3389 // Try to restore the gtk default style. This is still a little
3390 // oversimplified for what is probably really needed here for controls
3391 // other than buttons, but is better than not being able to (re)set a
3392 // control's foreground colour to *wxBLACK -- RL
3393 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3396 def
= gtk_widget_get_default_style();
3398 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3399 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3400 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3404 if (m_backgroundColour
.Ok())
3406 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3407 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3409 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3410 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3411 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3412 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3413 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3414 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3415 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3416 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3420 // Try to restore the gtk default style. This is still a little
3421 // oversimplified for what is probably really needed here for controls
3422 // other than buttons, but is better than not being able to (re)set a
3423 // control's background colour to default grey and means resetting a
3424 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3426 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3429 def
= gtk_widget_get_default_style();
3431 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3432 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3433 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3434 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3435 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3436 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3437 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3438 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3443 void wxWindow::ApplyWidgetStyle()
3447 //-----------------------------------------------------------------------------
3448 // Pop-up menu stuff
3449 //-----------------------------------------------------------------------------
3451 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3453 *is_waiting
= FALSE
;
3456 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3458 menu
->SetInvokingWindow( win
);
3459 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3462 wxMenuItem
*menuitem
= node
->GetData();
3463 if (menuitem
->IsSubMenu())
3465 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3468 node
= node
->GetNext();
3472 static gint gs_pop_x
= 0;
3473 static gint gs_pop_y
= 0;
3475 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3479 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3484 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3486 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3488 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3490 SetInvokingWindow( menu
, this );
3497 bool is_waiting
= TRUE
;
3499 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3500 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3503 GTK_MENU(menu
->m_menu
),
3504 (GtkWidget
*) NULL
, // parent menu shell
3505 (GtkWidget
*) NULL
, // parent menu item
3506 (GtkMenuPositionFunc
) pop_pos_callback
,
3507 (gpointer
) this, // client data
3508 0, // button used to activate it
3509 gs_timeLastClick
// the time of activation
3514 while (gtk_events_pending())
3515 gtk_main_iteration();
3521 #if wxUSE_DRAG_AND_DROP
3523 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3525 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3527 GtkWidget
*dnd_widget
= GetConnectWidget();
3529 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3531 if (m_dropTarget
) delete m_dropTarget
;
3532 m_dropTarget
= dropTarget
;
3534 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3537 #endif // wxUSE_DRAG_AND_DROP
3539 GtkWidget
* wxWindow::GetConnectWidget()
3541 GtkWidget
*connect_widget
= m_widget
;
3542 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3544 return connect_widget
;
3547 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3550 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3552 return (window
== m_widget
->window
);
3555 bool wxWindow::SetFont( const wxFont
&font
)
3557 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3559 if (!wxWindowBase::SetFont(font
))
3564 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3565 if ( sysbg
== m_backgroundColour
)
3567 m_backgroundColour
= wxNullColour
;
3569 m_backgroundColour
= sysbg
;
3579 void wxWindow::CaptureMouse()
3581 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3583 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3585 GdkWindow
*window
= (GdkWindow
*) NULL
;
3587 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3589 window
= GetConnectWidget()->window
;
3591 if (!window
) return;
3593 wxCursor
* cursor
= & m_cursor
;
3595 cursor
= wxSTANDARD_CURSOR
;
3597 gdk_pointer_grab( window
, FALSE
,
3599 (GDK_BUTTON_PRESS_MASK
|
3600 GDK_BUTTON_RELEASE_MASK
|
3601 GDK_POINTER_MOTION_HINT_MASK
|
3602 GDK_POINTER_MOTION_MASK
),
3604 cursor
->GetCursor(),
3605 (guint32
)GDK_CURRENT_TIME
);
3606 g_captureWindow
= this;
3609 void wxWindow::ReleaseMouse()
3611 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3613 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3615 GdkWindow
*window
= (GdkWindow
*) NULL
;
3617 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3619 window
= GetConnectWidget()->window
;
3624 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3625 g_captureWindow
= (wxWindow
*) NULL
;
3628 bool wxWindow::IsRetained() const
3633 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3634 int range
, bool refresh
)
3636 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3638 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3640 m_hasScrolling
= TRUE
;
3642 if (orient
== wxHORIZONTAL
)
3644 float fpos
= (float)pos
;
3645 float frange
= (float)range
;
3646 float fthumb
= (float)thumbVisible
;
3647 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3648 if (fpos
< 0.0) fpos
= 0.0;
3650 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3651 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3653 SetScrollPos( orient
, pos
, refresh
);
3657 m_oldHorizontalPos
= fpos
;
3659 m_hAdjust
->lower
= 0.0;
3660 m_hAdjust
->upper
= frange
;
3661 m_hAdjust
->value
= fpos
;
3662 m_hAdjust
->step_increment
= 1.0;
3663 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3664 m_hAdjust
->page_size
= fthumb
;
3668 float fpos
= (float)pos
;
3669 float frange
= (float)range
;
3670 float fthumb
= (float)thumbVisible
;
3671 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3672 if (fpos
< 0.0) fpos
= 0.0;
3674 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3675 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3677 SetScrollPos( orient
, pos
, refresh
);
3681 m_oldVerticalPos
= fpos
;
3683 m_vAdjust
->lower
= 0.0;
3684 m_vAdjust
->upper
= frange
;
3685 m_vAdjust
->value
= fpos
;
3686 m_vAdjust
->step_increment
= 1.0;
3687 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3688 m_vAdjust
->page_size
= fthumb
;
3691 if (orient
== wxHORIZONTAL
)
3692 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3694 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3697 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3699 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3701 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3703 if (orient
== wxHORIZONTAL
)
3705 float fpos
= (float)pos
;
3706 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3707 if (fpos
< 0.0) fpos
= 0.0;
3708 m_oldHorizontalPos
= fpos
;
3710 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3711 m_hAdjust
->value
= fpos
;
3715 float fpos
= (float)pos
;
3716 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3717 if (fpos
< 0.0) fpos
= 0.0;
3718 m_oldVerticalPos
= fpos
;
3720 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3721 m_vAdjust
->value
= fpos
;
3724 if (m_wxwindow
->window
)
3726 if (orient
== wxHORIZONTAL
)
3728 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3729 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3731 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3733 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3734 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3738 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3739 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3741 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3743 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3744 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3749 int wxWindow::GetScrollThumb( int orient
) const
3751 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3753 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3755 if (orient
== wxHORIZONTAL
)
3756 return (int)(m_hAdjust
->page_size
+0.5);
3758 return (int)(m_vAdjust
->page_size
+0.5);
3761 int wxWindow::GetScrollPos( int orient
) const
3763 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3765 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3767 if (orient
== wxHORIZONTAL
)
3768 return (int)(m_hAdjust
->value
+0.5);
3770 return (int)(m_vAdjust
->value
+0.5);
3773 int wxWindow::GetScrollRange( int orient
) const
3775 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3777 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3779 if (orient
== wxHORIZONTAL
)
3780 return (int)(m_hAdjust
->upper
+0.5);
3782 return (int)(m_vAdjust
->upper
+0.5);
3785 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3787 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3789 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3791 if ((dx
== 0) && (dy
== 0)) return;
3793 m_clipPaintRegion
= TRUE
;
3794 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3795 m_clipPaintRegion
= FALSE
;
3798 if (m_children.GetCount() > 0)
3800 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3804 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3806 pizza->xoffset -= dx;
3807 pizza->yoffset -= dy;
3809 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3810 gdk_gc_set_exposures( m_scrollGC, TRUE );
3814 GetClientSize( &cw, &ch );
3815 int w = cw - abs(dx);
3816 int h = ch - abs(dy);
3818 if ((h < 0) || (w < 0))
3826 if (dx < 0) s_x = -dx;
3827 if (dy < 0) s_y = -dy;
3830 if (dx > 0) d_x = dx;
3831 if (dy > 0) d_y = dy;
3833 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3834 pizza->bin_window, s_x, s_y, w, h );
3837 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3838 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3839 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3840 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3842 Refresh( TRUE, &rect );
3845 gdk_gc_unref( m_scrollGC );
3850 // Find the wxWindow at the current mouse position, also returning the mouse
3852 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
3854 pt
= wxGetMousePosition();
3855 wxWindow
* found
= wxFindWindowAtPoint(pt
);
3859 // Get the current mouse position.
3860 wxPoint
wxGetMousePosition()
3862 /* This crashes when used within wxHelpContext,
3863 so we have to use the X-specific implementation below.
3865 GdkModifierType *mask;
3866 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
3868 return wxPoint(x, y);
3872 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
3874 return wxPoint(-999, -999);
3876 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
3877 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
3878 Window rootReturn
, childReturn
;
3879 int rootX
, rootY
, winX
, winY
;
3880 unsigned int maskReturn
;
3882 XQueryPointer (display
,
3886 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
3887 return wxPoint(rootX
, rootY
);