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 static wxWindow
*FindFocusedChild(wxWindow
*win
)
327 wxWindow
*winFocus
= wxWindow::FindFocus();
329 return (wxWindow
*)NULL
;
331 if ( winFocus
== win
)
334 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
336 node
= node
->GetNext() )
338 wxWindow
*child
= FindFocusedChild(node
->GetData());
343 return (wxWindow
*)NULL
;
346 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
354 if (win
->m_hasScrolling
)
356 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
358 GtkRequisition vscroll_req
;
359 vscroll_req
.width
= 2;
360 vscroll_req
.height
= 2;
361 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
362 (scroll_window
->vscrollbar
, &vscroll_req
);
364 GtkRequisition hscroll_req
;
365 hscroll_req
.width
= 2;
366 hscroll_req
.height
= 2;
367 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
368 (scroll_window
->hscrollbar
, &hscroll_req
);
370 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) );
372 if (scroll_window
->vscrollbar_visible
)
374 dw
+= vscroll_req
.width
;
375 dw
+= scroll_class
->scrollbar_spacing
;
378 if (scroll_window
->hscrollbar_visible
)
380 dh
+= hscroll_req
.height
;
381 dh
+= scroll_class
->scrollbar_spacing
;
387 if (GTK_WIDGET_NO_WINDOW (widget
))
389 dx
+= widget
->allocation
.x
;
390 dy
+= widget
->allocation
.y
;
393 if (win
->HasFlag(wxRAISED_BORDER
))
395 gtk_draw_shadow( widget
->style
,
400 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
404 if (win
->HasFlag(wxSUNKEN_BORDER
))
406 gtk_draw_shadow( widget
->style
,
411 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
415 if (win
->HasFlag(wxSIMPLE_BORDER
))
418 gc
= gdk_gc_new( widget
->window
);
419 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
420 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
422 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
428 //-----------------------------------------------------------------------------
429 // "expose_event" of m_widget
430 //-----------------------------------------------------------------------------
432 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
434 if (gdk_event
->count
> 0) return FALSE
;
436 draw_frame( widget
, win
);
441 //-----------------------------------------------------------------------------
442 // "draw" of m_widget
443 //-----------------------------------------------------------------------------
445 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
447 draw_frame( widget
, win
);
450 //-----------------------------------------------------------------------------
451 // key code mapping routines
452 //-----------------------------------------------------------------------------
454 static long map_to_unmodified_wx_keysym( KeySym keysym
)
461 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
463 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
469 case GDK_Super_R
: key_code
= WXK_ALT
; break;
470 case GDK_Menu
: key_code
= WXK_MENU
; break;
471 case GDK_Help
: key_code
= WXK_HELP
; break;
472 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
473 case GDK_ISO_Left_Tab
:
474 case GDK_Tab
: key_code
= WXK_TAB
; break;
475 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
476 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
477 case GDK_Return
: key_code
= WXK_RETURN
; break;
478 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
479 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
480 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
481 case GDK_Delete
: key_code
= WXK_DELETE
; break;
482 case GDK_Home
: key_code
= WXK_HOME
; break;
483 case GDK_Left
: key_code
= WXK_LEFT
; break;
484 case GDK_Up
: key_code
= WXK_UP
; break;
485 case GDK_Right
: key_code
= WXK_RIGHT
; break;
486 case GDK_Down
: key_code
= WXK_DOWN
; break;
487 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
488 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
489 case GDK_Next
: key_code
= WXK_NEXT
; break;
490 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
491 case GDK_End
: key_code
= WXK_END
; break;
492 case GDK_Begin
: key_code
= WXK_HOME
; break;
493 case GDK_Select
: key_code
= WXK_SELECT
; break;
494 case GDK_Print
: key_code
= WXK_PRINT
; break;
495 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
496 case GDK_Insert
: key_code
= WXK_INSERT
; break;
497 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
499 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
500 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
501 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
502 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
503 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
504 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
505 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
506 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
507 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
508 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
509 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
510 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
511 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
512 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
513 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
514 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
515 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
516 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
517 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
518 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
519 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
520 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
521 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
522 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
523 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
524 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
525 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
526 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
527 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
528 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
529 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
530 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
531 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
532 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
533 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
534 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
535 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
537 case GDK_F1
: key_code
= WXK_F1
; break;
538 case GDK_F2
: key_code
= WXK_F2
; break;
539 case GDK_F3
: key_code
= WXK_F3
; break;
540 case GDK_F4
: key_code
= WXK_F4
; break;
541 case GDK_F5
: key_code
= WXK_F5
; break;
542 case GDK_F6
: key_code
= WXK_F6
; break;
543 case GDK_F7
: key_code
= WXK_F7
; break;
544 case GDK_F8
: key_code
= WXK_F8
; break;
545 case GDK_F9
: key_code
= WXK_F9
; break;
546 case GDK_F10
: key_code
= WXK_F10
; break;
547 case GDK_F11
: key_code
= WXK_F11
; break;
548 case GDK_F12
: key_code
= WXK_F12
; break;
551 if ((keysym
& 0xF000) == 0)
553 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
554 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
555 key_code
= (guint
)keysym
;
563 static long map_to_wx_keysym( KeySym keysym
)
569 case GDK_Menu
: key_code
= WXK_MENU
; break;
570 case GDK_Help
: key_code
= WXK_HELP
; break;
571 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
572 case GDK_ISO_Left_Tab
:
573 case GDK_Tab
: key_code
= WXK_TAB
; break;
574 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
575 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
576 case GDK_Return
: key_code
= WXK_RETURN
; break;
577 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
578 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
579 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
580 case GDK_Delete
: key_code
= WXK_DELETE
; break;
581 case GDK_Home
: key_code
= WXK_HOME
; break;
582 case GDK_Left
: key_code
= WXK_LEFT
; break;
583 case GDK_Up
: key_code
= WXK_UP
; break;
584 case GDK_Right
: key_code
= WXK_RIGHT
; break;
585 case GDK_Down
: key_code
= WXK_DOWN
; break;
586 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
587 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
588 case GDK_Next
: key_code
= WXK_NEXT
; break;
589 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
590 case GDK_End
: key_code
= WXK_END
; break;
591 case GDK_Begin
: key_code
= WXK_HOME
; break;
592 case GDK_Select
: key_code
= WXK_SELECT
; break;
593 case GDK_Print
: key_code
= WXK_PRINT
; break;
594 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
595 case GDK_Insert
: key_code
= WXK_INSERT
; break;
596 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
598 case GDK_KP_0
: key_code
= '0'; break;
599 case GDK_KP_1
: key_code
= '1'; break;
600 case GDK_KP_2
: key_code
= '2'; break;
601 case GDK_KP_3
: key_code
= '3'; break;
602 case GDK_KP_4
: key_code
= '4'; break;
603 case GDK_KP_5
: key_code
= '5'; break;
604 case GDK_KP_6
: key_code
= '6'; break;
605 case GDK_KP_7
: key_code
= '7'; break;
606 case GDK_KP_8
: key_code
= '8'; break;
607 case GDK_KP_9
: key_code
= '9'; break;
608 case GDK_KP_Space
: key_code
= ' '; break;
609 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
610 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
611 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
612 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
613 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
614 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
615 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
616 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
617 case GDK_KP_Up
: key_code
= WXK_UP
; break;
618 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
619 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
620 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
621 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
622 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
623 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
624 case GDK_KP_End
: key_code
= WXK_END
; break;
625 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
626 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
627 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
628 case GDK_KP_Equal
: key_code
= '='; break;
629 case GDK_KP_Multiply
: key_code
= '*'; break;
630 case GDK_KP_Add
: key_code
= '+'; break;
631 case GDK_KP_Separator
: key_code
= ','; break;
632 case GDK_KP_Subtract
: key_code
= '-'; break;
633 case GDK_KP_Decimal
: key_code
= '.'; break;
634 case GDK_KP_Divide
: key_code
= '/'; break;
636 case GDK_F1
: key_code
= WXK_F1
; break;
637 case GDK_F2
: key_code
= WXK_F2
; break;
638 case GDK_F3
: key_code
= WXK_F3
; break;
639 case GDK_F4
: key_code
= WXK_F4
; break;
640 case GDK_F5
: key_code
= WXK_F5
; break;
641 case GDK_F6
: key_code
= WXK_F6
; break;
642 case GDK_F7
: key_code
= WXK_F7
; break;
643 case GDK_F8
: key_code
= WXK_F8
; break;
644 case GDK_F9
: key_code
= WXK_F9
; break;
645 case GDK_F10
: key_code
= WXK_F10
; break;
646 case GDK_F11
: key_code
= WXK_F11
; break;
647 case GDK_F12
: key_code
= WXK_F12
; break;
650 if ((keysym
& 0xF000) == 0)
652 key_code
= (guint
)keysym
;
660 //-----------------------------------------------------------------------------
661 // "size_request" of m_widget
662 //-----------------------------------------------------------------------------
664 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
667 win
->GetSize( &w
, &h
);
671 requisition
->height
= h
;
672 requisition
->width
= w
;
675 //-----------------------------------------------------------------------------
676 // "expose_event" of m_wxwindow
677 //-----------------------------------------------------------------------------
679 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
684 wxapp_install_idle_handler();
687 if (win->GetName() == wxT("panel"))
689 wxPrintf( wxT("OnExpose from ") );
690 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
691 wxPrintf( win->GetClassInfo()->GetClassName() );
692 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
693 (int)gdk_event->area.y,
694 (int)gdk_event->area.width,
695 (int)gdk_event->area.height );
699 GtkPizza
*pizza
= GTK_PIZZA (widget
);
701 if (win
->GetThemeEnabled())
703 wxWindow
*parent
= win
->GetParent();
704 while (parent
&& !parent
->IsTopLevel())
705 parent
= parent
->GetParent();
709 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
710 GTK_SHADOW_NONE
, &gdk_event
->area
, parent
->m_widget
, "base", 0, 0, -1, -1);
713 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
715 gdk_event
->area
.width
,
716 gdk_event
->area
.height
);
718 if (gdk_event
->count
== 0)
720 win
->m_clipPaintRegion
= TRUE
;
722 wxEraseEvent
eevent( win
->GetId() );
723 eevent
.SetEventObject( win
);
724 win
->GetEventHandler()->ProcessEvent(eevent
);
726 wxPaintEvent
event( win
->GetId() );
727 event
.SetEventObject( win
);
728 win
->GetEventHandler()->ProcessEvent( event
);
730 win
->GetUpdateRegion().Clear();
732 win
->m_clipPaintRegion
= FALSE
;
735 /* The following code will result in all window-less widgets
736 being redrawn if the wxWindows class is given a chance to
737 paint *anything* because it will then be allowed to paint
738 over the window-less widgets */
740 GList
*children
= pizza
->children
;
743 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
744 children
= children
->next
;
746 GdkEventExpose child_event
= *gdk_event
;
748 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
749 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
750 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
752 child_event
.area
.x
= child
->widget
->allocation
.x
;
753 child_event
.area
.y
= child
->widget
->allocation
.y
;
754 child_event
.area
.width
= child
->widget
->allocation
.width
;
755 child_event
.area
.height
= child
->widget
->allocation
.height
;
756 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
763 //-----------------------------------------------------------------------------
764 // "event" of m_wxwindow
765 //-----------------------------------------------------------------------------
767 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
768 expose events. We need them, of course, so we override the main event
769 procedure in GtkWidget by giving our own handler for all system events.
770 There, we look for expose events ourselves whereas all other events are
773 gint
gtk_window_event_event_callback( GtkWidget
*widget
, GdkEventExpose
*event
, wxWindow
*win
)
775 if (event
->type
== GDK_EXPOSE
)
777 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
784 //-----------------------------------------------------------------------------
785 // "draw" of m_wxwindow
786 //-----------------------------------------------------------------------------
788 /* This callback is a complete replacement of the gtk_pizza_draw() function,
791 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
796 wxapp_install_idle_handler();
798 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
799 (win
->GetChildren().GetCount() == 0))
805 if (win->GetName() == wxT("panel"))
807 wxPrintf( wxT("OnDraw from ") );
808 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
809 wxPrintf( win->GetClassInfo()->GetClassName() );
810 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
817 GtkPizza
*pizza
= GTK_PIZZA (widget
);
819 if (win
->GetThemeEnabled())
821 wxWindow
*parent
= win
->GetParent();
822 while (parent
&& !parent
->IsTopLevel())
823 parent
= parent
->GetParent();
827 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
828 GTK_SHADOW_NONE
, rect
, parent
->m_widget
, "base", 0, 0, -1, -1);
832 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
833 (pizza
->clear_on_draw
))
835 gdk_window_clear_area( pizza
->bin_window
,
836 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
839 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
841 win
->m_clipPaintRegion
= TRUE
;
843 wxEraseEvent
eevent( win
->GetId() );
844 eevent
.SetEventObject( win
);
845 win
->GetEventHandler()->ProcessEvent(eevent
);
847 wxPaintEvent
event( win
->GetId() );
848 event
.SetEventObject( win
);
849 win
->GetEventHandler()->ProcessEvent( event
);
851 win
->GetUpdateRegion().Clear();
853 win
->m_clipPaintRegion
= FALSE
;
856 GList
*children
= pizza
->children
;
859 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
860 children
= children
->next
;
862 GdkRectangle child_area
;
863 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
865 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
870 //-----------------------------------------------------------------------------
871 // "key_press_event" from any window
872 //-----------------------------------------------------------------------------
874 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
879 wxapp_install_idle_handler();
881 if (!win
->m_hasVMT
) return FALSE
;
882 if (g_blockEventsOnDrag
) return FALSE
;
887 tmp += (char)gdk_event->keyval;
888 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
889 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
894 GdkModifierType state
;
895 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
899 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
900 /* sending unknown key events doesn't really make sense */
901 if (key_code
== 0) return FALSE
;
903 wxKeyEvent
event( wxEVT_KEY_DOWN
);
904 event
.SetTimestamp( gdk_event
->time
);
905 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
906 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
907 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
908 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
909 event
.m_keyCode
= key_code
;
910 event
.m_scanCode
= gdk_event
->keyval
;
913 event
.SetEventObject( win
);
914 ret
= win
->GetEventHandler()->ProcessEvent( event
);
919 wxWindow
*ancestor
= win
;
922 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
925 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
926 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
929 if (ancestor
->IsTopLevel())
931 ancestor
= ancestor
->GetParent();
934 #endif // wxUSE_ACCEL
936 /* wxMSW doesn't send char events with Alt pressed */
937 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
938 will only be sent if it is not in an accelerator table. */
939 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
944 wxKeyEvent
event2( wxEVT_CHAR
);
945 event2
.SetTimestamp( gdk_event
->time
);
946 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
947 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
948 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
949 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
950 event2
.m_keyCode
= key_code
;
951 event2
.m_scanCode
= gdk_event
->keyval
;
954 event2
.SetEventObject( win
);
955 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
958 /* win is a control: tab can be propagated up */
960 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
961 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
962 // have this style, yet choose not to process this particular TAB in which
963 // case TAB must still work as a navigational character
965 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
967 (win
->GetParent()) &&
968 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
970 wxNavigationKeyEvent new_event
;
971 new_event
.SetEventObject( win
->GetParent() );
972 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
973 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
974 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
975 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
976 new_event
.SetCurrentFocus( win
);
977 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
980 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
982 (gdk_event
->keyval
== GDK_Escape
) )
984 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
985 new_event
.SetEventObject( win
);
986 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
989 #if (GTK_MINOR_VERSION > 0)
990 /* Pressing F10 will activate the menu bar of the top frame. */
994 (gdk_event->keyval == GDK_F10) )
996 wxWindow *ancestor = win;
999 if (wxIsKindOf(ancestor,wxFrame))
1001 wxFrame *frame = (wxFrame*) ancestor;
1002 wxMenuBar *menubar = frame->GetMenuBar();
1005 wxNode *node = menubar->GetMenus().First();
1008 wxMenu *firstMenu = (wxMenu*) node->Data();
1009 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
1015 ancestor = ancestor->GetParent();
1023 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1030 //-----------------------------------------------------------------------------
1031 // "key_release_event" from any window
1032 //-----------------------------------------------------------------------------
1034 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
1039 wxapp_install_idle_handler();
1041 if (!win
->m_hasVMT
) return FALSE
;
1042 if (g_blockEventsOnDrag
) return FALSE
;
1045 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
1046 if (gdk_event->state & GDK_SHIFT_MASK)
1047 printf( "ShiftDown.\n" );
1049 printf( "ShiftUp.\n" );
1050 if (gdk_event->state & GDK_CONTROL_MASK)
1051 printf( "ControlDown.\n" );
1053 printf( "ControlUp.\n" );
1057 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
1059 /* sending unknown key events doesn't really make sense */
1060 if (key_code
== 0) return FALSE
;
1064 GdkModifierType state
;
1065 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1067 wxKeyEvent
event( wxEVT_KEY_UP
);
1068 event
.SetTimestamp( gdk_event
->time
);
1069 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1070 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1071 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1072 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1073 event
.m_keyCode
= key_code
;
1074 event
.m_scanCode
= gdk_event
->keyval
;
1077 event
.SetEventObject( win
);
1079 if (win
->GetEventHandler()->ProcessEvent( event
))
1081 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1088 // ----------------------------------------------------------------------------
1089 // mouse event processing helper
1090 // ----------------------------------------------------------------------------
1092 static void AdjustEventButtonState(wxMouseEvent
& event
)
1094 // GDK reports the old state of the button for a button press event, but
1095 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1096 // for a LEFT_DOWN event, not FALSE, so we will invert
1097 // left/right/middleDown for the corresponding click events
1099 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1100 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1101 (event
.GetEventType() == wxEVT_LEFT_UP
))
1103 event
.m_leftDown
= !event
.m_leftDown
;
1107 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1108 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1109 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1111 event
.m_middleDown
= !event
.m_middleDown
;
1115 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1116 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1117 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1119 event
.m_rightDown
= !event
.m_rightDown
;
1124 //-----------------------------------------------------------------------------
1125 // "button_press_event"
1126 //-----------------------------------------------------------------------------
1128 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1133 wxapp_install_idle_handler();
1136 wxPrintf( wxT("1) OnButtonPress from ") );
1137 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1138 wxPrintf( win->GetClassInfo()->GetClassName() );
1139 wxPrintf( wxT(".\n") );
1141 if (!win
->m_hasVMT
) return FALSE
;
1142 if (g_blockEventsOnDrag
) return TRUE
;
1143 if (g_blockEventsOnScroll
) return TRUE
;
1145 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1147 if (win
->m_wxwindow
)
1149 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1151 gtk_widget_grab_focus (win
->m_wxwindow
);
1154 wxPrintf( wxT("GrabFocus from ") );
1155 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1156 wxPrintf( win->GetClassInfo()->GetClassName() );
1157 wxPrintf( wxT(".\n") );
1163 wxEventType event_type
= wxEVT_NULL
;
1165 if (gdk_event
->button
== 1)
1167 switch (gdk_event
->type
)
1169 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1170 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1174 else if (gdk_event
->button
== 2)
1176 switch (gdk_event
->type
)
1178 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1179 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1183 else if (gdk_event
->button
== 3)
1185 switch (gdk_event
->type
)
1187 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1188 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1193 if ( event_type
== wxEVT_NULL
)
1195 // unknown mouse button or click type
1199 wxMouseEvent
event( event_type
);
1200 event
.SetTimestamp( gdk_event
->time
);
1201 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1202 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1203 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1204 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1205 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1206 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1207 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1209 event
.m_x
= (wxCoord
)gdk_event
->x
;
1210 event
.m_y
= (wxCoord
)gdk_event
->y
;
1212 AdjustEventButtonState(event
);
1214 // Some control don't have their own X window and thus cannot get
1217 if (!g_captureWindow
)
1219 wxCoord x
= event
.m_x
;
1220 wxCoord y
= event
.m_y
;
1221 if (win
->m_wxwindow
)
1223 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1224 x
+= pizza
->xoffset
;
1225 y
+= pizza
->yoffset
;
1228 wxNode
*node
= win
->GetChildren().First();
1231 wxWindow
*child
= (wxWindow
*)node
->Data();
1233 node
= node
->Next();
1234 if (!child
->IsShown())
1237 if (child
->m_isStaticBox
)
1239 // wxStaticBox is transparent in the box itself
1240 int xx1
= child
->m_x
;
1241 int yy1
= child
->m_y
;
1242 int xx2
= child
->m_x
+ child
->m_width
;
1243 int yy2
= child
->m_x
+ child
->m_height
;
1246 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1248 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1250 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1252 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1255 event
.m_x
-= child
->m_x
;
1256 event
.m_y
-= child
->m_y
;
1263 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1264 (child
->m_x
<= x
) &&
1265 (child
->m_y
<= y
) &&
1266 (child
->m_x
+child
->m_width
>= x
) &&
1267 (child
->m_y
+child
->m_height
>= y
))
1270 event
.m_x
-= child
->m_x
;
1271 event
.m_y
-= child
->m_y
;
1278 event
.SetEventObject( win
);
1280 gs_timeLastClick
= gdk_event
->time
;
1283 wxPrintf( wxT("2) OnButtonPress from ") );
1284 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1285 wxPrintf( win->GetClassInfo()->GetClassName() );
1286 wxPrintf( wxT(".\n") );
1289 if (win
->GetEventHandler()->ProcessEvent( event
))
1291 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1298 //-----------------------------------------------------------------------------
1299 // "button_release_event"
1300 //-----------------------------------------------------------------------------
1302 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1307 wxapp_install_idle_handler();
1309 if (!win
->m_hasVMT
) return FALSE
;
1310 if (g_blockEventsOnDrag
) return FALSE
;
1311 if (g_blockEventsOnScroll
) return FALSE
;
1313 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1316 printf( "OnButtonRelease from " );
1317 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1318 printf( win->GetClassInfo()->GetClassName() );
1322 wxEventType event_type
= wxEVT_NULL
;
1324 switch (gdk_event
->button
)
1326 case 1: event_type
= wxEVT_LEFT_UP
; break;
1327 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1328 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1329 default: return FALSE
;
1332 wxMouseEvent
event( event_type
);
1333 event
.SetTimestamp( gdk_event
->time
);
1334 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1335 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1336 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1337 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1338 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1339 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1340 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1341 event
.m_x
= (wxCoord
)gdk_event
->x
;
1342 event
.m_y
= (wxCoord
)gdk_event
->y
;
1344 AdjustEventButtonState(event
);
1346 // Some control don't have their own X window and thus cannot get
1349 if (!g_captureWindow
)
1351 wxCoord x
= event
.m_x
;
1352 wxCoord y
= event
.m_y
;
1353 if (win
->m_wxwindow
)
1355 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1356 x
+= pizza
->xoffset
;
1357 y
+= pizza
->yoffset
;
1360 wxNode
*node
= win
->GetChildren().First();
1363 wxWindow
*child
= (wxWindow
*)node
->Data();
1365 node
= node
->Next();
1366 if (!child
->IsShown())
1369 if (child
->m_isStaticBox
)
1371 // wxStaticBox is transparent in the box itself
1372 int xx1
= child
->m_x
;
1373 int yy1
= child
->m_y
;
1374 int xx2
= child
->m_x
+ child
->m_width
;
1375 int yy2
= child
->m_x
+ child
->m_height
;
1378 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1380 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1382 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1384 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1387 event
.m_x
-= child
->m_x
;
1388 event
.m_y
-= child
->m_y
;
1395 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1396 (child
->m_x
<= x
) &&
1397 (child
->m_y
<= y
) &&
1398 (child
->m_x
+child
->m_width
>= x
) &&
1399 (child
->m_y
+child
->m_height
>= y
))
1402 event
.m_x
-= child
->m_x
;
1403 event
.m_y
-= child
->m_y
;
1410 event
.SetEventObject( win
);
1412 if (win
->GetEventHandler()->ProcessEvent( event
))
1414 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1421 //-----------------------------------------------------------------------------
1422 // "motion_notify_event"
1423 //-----------------------------------------------------------------------------
1425 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1430 wxapp_install_idle_handler();
1432 if (!win
->m_hasVMT
) return FALSE
;
1433 if (g_blockEventsOnDrag
) return FALSE
;
1434 if (g_blockEventsOnScroll
) return FALSE
;
1436 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1438 if (gdk_event
->is_hint
)
1442 GdkModifierType state
;
1443 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1449 printf( "OnMotion from " );
1450 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1451 printf( win->GetClassInfo()->GetClassName() );
1455 wxMouseEvent
event( wxEVT_MOTION
);
1456 event
.SetTimestamp( gdk_event
->time
);
1457 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1458 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1459 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1460 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1461 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1462 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1463 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1465 event
.m_x
= (wxCoord
)gdk_event
->x
;
1466 event
.m_y
= (wxCoord
)gdk_event
->y
;
1468 // Some control don't have their own X window and thus cannot get
1471 if (!g_captureWindow
)
1473 wxCoord x
= event
.m_x
;
1474 wxCoord y
= event
.m_y
;
1475 if (win
->m_wxwindow
)
1477 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1478 x
+= pizza
->xoffset
;
1479 y
+= pizza
->yoffset
;
1482 wxNode
*node
= win
->GetChildren().First();
1485 wxWindow
*child
= (wxWindow
*)node
->Data();
1487 node
= node
->Next();
1488 if (!child
->IsShown())
1491 if (child
->m_isStaticBox
)
1493 // wxStaticBox is transparent in the box itself
1494 int xx1
= child
->m_x
;
1495 int yy1
= child
->m_y
;
1496 int xx2
= child
->m_x
+ child
->m_width
;
1497 int yy2
= child
->m_x
+ child
->m_height
;
1500 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1502 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1504 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1506 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1509 event
.m_x
-= child
->m_x
;
1510 event
.m_y
-= child
->m_y
;
1517 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1518 (child
->m_x
<= x
) &&
1519 (child
->m_y
<= y
) &&
1520 (child
->m_x
+child
->m_width
>= x
) &&
1521 (child
->m_y
+child
->m_height
>= y
))
1524 event
.m_x
-= child
->m_x
;
1525 event
.m_y
-= child
->m_y
;
1532 event
.SetEventObject( win
);
1534 if (win
->GetEventHandler()->ProcessEvent( event
))
1536 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1543 //-----------------------------------------------------------------------------
1545 //-----------------------------------------------------------------------------
1547 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1552 wxapp_install_idle_handler();
1554 if (!win
->m_hasVMT
) return FALSE
;
1555 if (g_blockEventsOnDrag
) return FALSE
;
1557 switch ( g_sendActivateEvent
)
1560 // we've got focus from outside, synthtize wxActivateEvent
1561 g_sendActivateEvent
= 1;
1565 // another our window just lost focus, it was already ours before
1566 // - don't send any wxActivateEvent
1567 g_sendActivateEvent
= -1;
1571 g_focusWindow
= win
;
1574 printf( "OnSetFocus from " );
1575 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1576 printf( win->GetClassInfo()->GetClassName() );
1578 printf( WXSTRINGCAST win->GetLabel() );
1582 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1585 panel
->SetLastFocus(win
);
1590 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1594 // caret needs to be informed about focus change
1595 wxCaret
*caret
= win
->GetCaret();
1598 caret
->OnSetFocus();
1600 #endif // wxUSE_CARET
1602 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1603 event
.SetEventObject( win
);
1605 if (win
->GetEventHandler()->ProcessEvent( event
))
1607 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1614 //-----------------------------------------------------------------------------
1615 // "focus_out_event"
1616 //-----------------------------------------------------------------------------
1618 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1623 wxapp_install_idle_handler();
1625 if (!win
->m_hasVMT
) return FALSE
;
1626 if (g_blockEventsOnDrag
) return FALSE
;
1628 // if the focus goes out of our app alltogether, OnIdle() will send
1629 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1630 // g_sendActivateEvent to -1
1631 g_sendActivateEvent
= 0;
1633 wxWindow
*winFocus
= FindFocusedChild(win
);
1637 g_focusWindow
= (wxWindow
*)NULL
;
1640 printf( "OnKillFocus from " );
1641 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1642 printf( win->GetClassInfo()->GetClassName() );
1652 // caret needs to be informed about focus change
1653 wxCaret
*caret
= win
->GetCaret();
1656 caret
->OnKillFocus();
1658 #endif // wxUSE_CARET
1660 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1661 event
.SetEventObject( win
);
1663 if (win
->GetEventHandler()->ProcessEvent( event
))
1665 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1672 //-----------------------------------------------------------------------------
1673 // "enter_notify_event"
1674 //-----------------------------------------------------------------------------
1676 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1681 wxapp_install_idle_handler();
1683 if (!win
->m_hasVMT
) return FALSE
;
1684 if (g_blockEventsOnDrag
) return FALSE
;
1686 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1688 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1689 #if (GTK_MINOR_VERSION > 0)
1690 event
.SetTimestamp( gdk_event
->time
);
1692 event
.SetEventObject( win
);
1696 GdkModifierType state
= (GdkModifierType
)0;
1698 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1700 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1701 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1702 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1703 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1704 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1705 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1706 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1711 if (win
->GetEventHandler()->ProcessEvent( event
))
1713 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1720 //-----------------------------------------------------------------------------
1721 // "leave_notify_event"
1722 //-----------------------------------------------------------------------------
1724 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1729 wxapp_install_idle_handler();
1731 if (!win
->m_hasVMT
) return FALSE
;
1732 if (g_blockEventsOnDrag
) return FALSE
;
1734 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1736 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1737 #if (GTK_MINOR_VERSION > 0)
1738 event
.SetTimestamp( gdk_event
->time
);
1740 event
.SetEventObject( win
);
1744 GdkModifierType state
= (GdkModifierType
)0;
1746 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1748 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1749 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1750 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1751 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1752 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1753 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1754 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1759 if (win
->GetEventHandler()->ProcessEvent( event
))
1761 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1768 //-----------------------------------------------------------------------------
1769 // "value_changed" from m_vAdjust
1770 //-----------------------------------------------------------------------------
1772 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1777 wxapp_install_idle_handler();
1779 if (g_blockEventsOnDrag
) return;
1781 if (!win
->m_hasVMT
) return;
1783 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1784 if (fabs(diff
) < 0.2) return;
1786 win
->m_oldVerticalPos
= adjust
->value
;
1788 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1789 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1791 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1792 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1793 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1794 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1795 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1797 int value
= (int)(adjust
->value
+0.5);
1799 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1800 event
.SetEventObject( win
);
1801 win
->GetEventHandler()->ProcessEvent( event
);
1804 //-----------------------------------------------------------------------------
1805 // "value_changed" from m_hAdjust
1806 //-----------------------------------------------------------------------------
1808 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1813 wxapp_install_idle_handler();
1815 if (g_blockEventsOnDrag
) return;
1816 if (!win
->m_hasVMT
) return;
1818 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1819 if (fabs(diff
) < 0.2) return;
1821 win
->m_oldHorizontalPos
= adjust
->value
;
1823 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1824 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1826 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1827 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1828 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1829 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1830 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1832 int value
= (int)(adjust
->value
+0.5);
1834 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1835 event
.SetEventObject( win
);
1836 win
->GetEventHandler()->ProcessEvent( event
);
1839 //-----------------------------------------------------------------------------
1840 // "button_press_event" from scrollbar
1841 //-----------------------------------------------------------------------------
1843 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1844 GdkEventButton
*gdk_event
,
1850 wxapp_install_idle_handler();
1853 g_blockEventsOnScroll
= TRUE
;
1854 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1859 //-----------------------------------------------------------------------------
1860 // "button_release_event" from scrollbar
1861 //-----------------------------------------------------------------------------
1863 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1864 GdkEventButton
*WXUNUSED(gdk_event
),
1869 // don't test here as we can release the mouse while being over
1870 // a different window than the slider
1872 // if (gdk_event->window != widget->slider) return FALSE;
1874 g_blockEventsOnScroll
= FALSE
;
1876 if (win
->m_isScrolling
)
1878 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
1882 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1883 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1885 value
= (int)(win
->m_hAdjust
->value
+0.5);
1888 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1890 value
= (int)(win
->m_vAdjust
->value
+0.5);
1894 wxScrollWinEvent
event( command
, value
, dir
);
1895 event
.SetEventObject( win
);
1896 win
->GetEventHandler()->ProcessEvent( event
);
1899 win
->m_isScrolling
= FALSE
;
1904 // ----------------------------------------------------------------------------
1905 // this wxWindowBase function is implemented here (in platform-specific file)
1906 // because it is static and so couldn't be made virtual
1907 // ----------------------------------------------------------------------------
1909 wxWindow
*wxWindowBase::FindFocus()
1911 return g_focusWindow
;
1914 //-----------------------------------------------------------------------------
1915 // "realize" from m_widget
1916 //-----------------------------------------------------------------------------
1918 /* We cannot set colours and fonts before the widget has
1919 been realized, so we do this directly after realization. */
1922 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1927 wxapp_install_idle_handler();
1929 if (win
->m_delayedBackgroundColour
)
1930 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1932 if (win
->m_delayedForegroundColour
)
1933 win
->SetForegroundColour( win
->GetForegroundColour() );
1935 wxWindowCreateEvent
event( win
);
1936 event
.SetEventObject( win
);
1937 win
->GetEventHandler()->ProcessEvent( event
);
1942 //-----------------------------------------------------------------------------
1944 //-----------------------------------------------------------------------------
1947 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
1948 GtkAllocation
*WXUNUSED(alloc
),
1952 wxapp_install_idle_handler();
1954 if (!win
->m_hasScrolling
) return;
1956 int client_width
= 0;
1957 int client_height
= 0;
1958 win
->GetClientSize( &client_width
, &client_height
);
1959 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
1962 win
->m_oldClientWidth
= client_width
;
1963 win
->m_oldClientHeight
= client_height
;
1965 if (!win
->m_nativeSizeEvent
)
1967 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
1968 event
.SetEventObject( win
);
1969 win
->GetEventHandler()->ProcessEvent( event
);
1975 #define WXUNUSED_UNLESS_XIM(param) param
1977 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1980 /* Resize XIM window */
1983 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1984 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1985 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1988 wxapp_install_idle_handler();
1994 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1998 gdk_window_get_size (widget
->window
, &width
, &height
);
1999 win
->m_icattr
->preedit_area
.width
= width
;
2000 win
->m_icattr
->preedit_area
.height
= height
;
2001 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2006 //-----------------------------------------------------------------------------
2007 // "realize" from m_wxwindow
2008 //-----------------------------------------------------------------------------
2010 /* Initialize XIM support */
2013 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2014 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
2017 wxapp_install_idle_handler();
2020 if (win
->m_ic
) return FALSE
;
2021 if (!widget
) return FALSE
;
2022 if (!gdk_im_ready()) return FALSE
;
2024 win
->m_icattr
= gdk_ic_attr_new();
2025 if (!win
->m_icattr
) return FALSE
;
2029 GdkColormap
*colormap
;
2030 GdkICAttr
*attr
= win
->m_icattr
;
2031 unsigned attrmask
= GDK_IC_ALL_REQ
;
2033 GdkIMStyle supported_style
= (GdkIMStyle
)
2034 (GDK_IM_PREEDIT_NONE
|
2035 GDK_IM_PREEDIT_NOTHING
|
2036 GDK_IM_PREEDIT_POSITION
|
2037 GDK_IM_STATUS_NONE
|
2038 GDK_IM_STATUS_NOTHING
);
2040 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2041 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2043 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2044 attr
->client_window
= widget
->window
;
2046 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2047 gtk_widget_get_default_colormap ())
2049 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2050 attr
->preedit_colormap
= colormap
;
2053 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2054 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2055 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2056 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2058 switch (style
& GDK_IM_PREEDIT_MASK
)
2060 case GDK_IM_PREEDIT_POSITION
:
2061 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2063 g_warning ("over-the-spot style requires fontset");
2067 gdk_window_get_size (widget
->window
, &width
, &height
);
2069 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2070 attr
->spot_location
.x
= 0;
2071 attr
->spot_location
.y
= height
;
2072 attr
->preedit_area
.x
= 0;
2073 attr
->preedit_area
.y
= 0;
2074 attr
->preedit_area
.width
= width
;
2075 attr
->preedit_area
.height
= height
;
2076 attr
->preedit_fontset
= widget
->style
->font
;
2081 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2083 if (win
->m_ic
== NULL
)
2084 g_warning ("Can't create input context.");
2087 mask
= gdk_window_get_events (widget
->window
);
2088 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2089 gdk_window_set_events (widget
->window
, mask
);
2091 if (GTK_WIDGET_HAS_FOCUS(widget
))
2092 gdk_im_begin (win
->m_ic
, widget
->window
);
2099 //-----------------------------------------------------------------------------
2100 // InsertChild for wxWindow.
2101 //-----------------------------------------------------------------------------
2103 /* Callback for wxWindow. This very strange beast has to be used because
2104 * C++ has no virtual methods in a constructor. We have to emulate a
2105 * virtual function here as wxNotebook requires a different way to insert
2106 * a child in it. I had opted for creating a wxNotebookPage window class
2107 * which would have made this superfluous (such in the MDI window system),
2108 * but no-one was listening to me... */
2110 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
2112 /* the window might have been scrolled already, do we
2113 have to adapt the position */
2114 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2115 child
->m_x
+= pizza
->xoffset
;
2116 child
->m_y
+= pizza
->yoffset
;
2118 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2119 GTK_WIDGET(child
->m_widget
),
2126 //-----------------------------------------------------------------------------
2128 //-----------------------------------------------------------------------------
2130 wxWindow
* wxGetActiveWindow()
2132 return g_focusWindow
;
2135 //-----------------------------------------------------------------------------
2137 //-----------------------------------------------------------------------------
2139 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2141 void wxWindow::Init()
2147 m_widget
= (GtkWidget
*) NULL
;
2148 m_wxwindow
= (GtkWidget
*) NULL
;
2158 m_needParent
= TRUE
;
2159 m_isBeingDeleted
= FALSE
;
2162 m_nativeSizeEvent
= FALSE
;
2164 m_hasScrolling
= FALSE
;
2165 m_isScrolling
= FALSE
;
2167 m_hAdjust
= (GtkAdjustment
*) NULL
;
2168 m_vAdjust
= (GtkAdjustment
*) NULL
;
2169 m_oldHorizontalPos
= 0.0;
2170 m_oldVerticalPos
= 0.0;
2173 m_widgetStyle
= (GtkStyle
*) NULL
;
2175 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2177 m_isStaticBox
= FALSE
;
2178 m_isRadioButton
= FALSE
;
2180 m_acceptsFocus
= FALSE
;
2182 m_clipPaintRegion
= FALSE
;
2184 m_cursor
= *wxSTANDARD_CURSOR
;
2186 m_delayedForegroundColour
= FALSE
;
2187 m_delayedBackgroundColour
= FALSE
;
2190 m_ic
= (GdkIC
*) NULL
;
2191 m_icattr
= (GdkICAttr
*) NULL
;
2195 wxWindow::wxWindow()
2200 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
2201 const wxPoint
&pos
, const wxSize
&size
,
2202 long style
, const wxString
&name
)
2206 Create( parent
, id
, pos
, size
, style
, name
);
2209 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
2210 const wxPoint
&pos
, const wxSize
&size
,
2211 long style
, const wxString
&name
)
2213 if (!PreCreation( parent
, pos
, size
) ||
2214 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2216 wxFAIL_MSG( wxT("wxWindow creation failed") );
2220 m_insertCallback
= wxInsertChildInWindow
;
2222 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2223 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2225 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2227 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2228 scroll_class
->scrollbar_spacing
= 0;
2230 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2232 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2233 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2235 m_wxwindow
= gtk_pizza_new();
2237 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2239 #if (GTK_MINOR_VERSION > 0)
2240 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2242 if (HasFlag(wxRAISED_BORDER
))
2244 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2246 else if (HasFlag(wxSUNKEN_BORDER
))
2248 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2250 else if (HasFlag(wxSIMPLE_BORDER
))
2252 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2256 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2258 #else // GTK_MINOR_VERSION == 0
2259 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2261 if (HasFlag(wxRAISED_BORDER
))
2263 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2265 else if (HasFlag(wxSUNKEN_BORDER
))
2267 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2271 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2273 #endif // GTK_MINOR_VERSION
2275 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2276 m_acceptsFocus
= TRUE
;
2278 #if (GTK_MINOR_VERSION == 0)
2279 // shut the viewport up
2280 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2281 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2282 #endif // GTK_MINOR_VERSION == 0
2284 // I _really_ don't want scrollbars in the beginning
2285 m_vAdjust
->lower
= 0.0;
2286 m_vAdjust
->upper
= 1.0;
2287 m_vAdjust
->value
= 0.0;
2288 m_vAdjust
->step_increment
= 1.0;
2289 m_vAdjust
->page_increment
= 1.0;
2290 m_vAdjust
->page_size
= 5.0;
2291 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2292 m_hAdjust
->lower
= 0.0;
2293 m_hAdjust
->upper
= 1.0;
2294 m_hAdjust
->value
= 0.0;
2295 m_hAdjust
->step_increment
= 1.0;
2296 m_hAdjust
->page_increment
= 1.0;
2297 m_hAdjust
->page_size
= 5.0;
2298 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2300 // these handlers block mouse events to any window during scrolling such as
2301 // motion events and prevent GTK and wxWindows from fighting over where the
2304 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2305 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2307 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2308 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2310 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2311 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2313 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2314 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2316 // these handlers get notified when screen updates are required either when
2317 // scrolling or when the window size (and therefore scrollbar configuration)
2320 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2321 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2322 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2323 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2325 gtk_widget_show( m_wxwindow
);
2328 m_parent
->DoAddChild( this );
2337 wxWindow::~wxWindow()
2339 if (g_focusWindow
== this)
2340 g_focusWindow
= NULL
;
2342 m_isBeingDeleted
= TRUE
;
2351 m_parent
->RemoveChild( this );
2355 gdk_ic_destroy (m_ic
);
2357 gdk_ic_attr_destroy (m_icattr
);
2362 #if DISABLE_STYLE_IF_BROKEN_THEME
2363 // don't delete if it's a pixmap theme style
2364 if (!m_widgetStyle
->engine_data
)
2365 gtk_style_unref( m_widgetStyle
);
2367 m_widgetStyle
= (GtkStyle
*) NULL
;
2372 gtk_widget_destroy( m_wxwindow
);
2373 m_wxwindow
= (GtkWidget
*) NULL
;
2378 gtk_widget_destroy( m_widget
);
2379 m_widget
= (GtkWidget
*) NULL
;
2383 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2385 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2387 /* this turns -1 into 20 so that a minimal window is
2388 visible even although -1,-1 has been given as the
2389 size of the window. the same trick is used in other
2390 ports and should make debugging easier */
2391 m_width
= WidthDefault(size
.x
);
2392 m_height
= HeightDefault(size
.y
);
2397 /* some reasonable defaults */
2402 m_x
= (gdk_screen_width () - m_width
) / 2;
2403 if (m_x
< 10) m_x
= 10;
2407 m_y
= (gdk_screen_height () - m_height
) / 2;
2408 if (m_y
< 10) m_y
= 10;
2415 void wxWindow::PostCreation()
2417 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2423 /* these get reported to wxWindows -> wxPaintEvent */
2425 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2427 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2428 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2430 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2431 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2433 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2435 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2436 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2440 #if (GTK_MINOR_VERSION > 0)
2441 /* these are called when the "sunken" or "raised" borders are drawn */
2442 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2443 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2445 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2446 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2450 if (m_wxwindow
&& m_needParent
)
2452 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2453 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2455 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2456 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2460 // For dialogs and frames, we are interested mainly in
2461 // m_widget's focus.
2463 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2464 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2466 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2467 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2470 GtkWidget
*connect_widget
= GetConnectWidget();
2472 ConnectWidget( connect_widget
);
2474 /* We cannot set colours, fonts and cursors before the widget has
2475 been realized, so we do this directly after realization */
2476 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2477 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2481 // Catch native resize events
2482 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2483 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2485 // Initialize XIM support
2486 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2487 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2489 // And resize XIM window
2490 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2491 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2494 if (!GTK_IS_COMBO(m_widget
))
2496 // This is needed if we want to add our windows into native
2497 // GTK control, such as the toolbar. With this callback, the
2498 // toolbar gets to know the correct size (the one set by the
2499 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2500 // when moving to GTK 2.0.
2501 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2502 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2508 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2510 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2511 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2513 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2514 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2516 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2517 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2519 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2520 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2522 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2523 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2525 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2526 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2528 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2529 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2532 bool wxWindow::Destroy()
2534 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2538 return wxWindowBase::Destroy();
2541 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2543 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2546 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2548 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2549 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2551 if (m_resizing
) return; /* I don't like recursions */
2554 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2556 /* don't set the size for children of wxNotebook, just take the values. */
2564 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2566 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2568 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2569 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2570 if (width
!= -1) m_width
= width
;
2571 if (height
!= -1) m_height
= height
;
2575 m_x
= x
+ pizza
->xoffset
;
2576 m_y
= y
+ pizza
->yoffset
;
2581 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2583 if (width
== -1) m_width
= 80;
2586 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2588 if (height
== -1) m_height
= 26;
2591 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2592 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2593 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2594 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2597 int bottom_border
= 0;
2599 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2601 /* the default button has a border around it */
2606 DoMoveWindow( m_x
-border
,
2609 m_height
+border
+bottom_border
);
2614 /* Sometimes the client area changes size without the
2615 whole windows's size changing, but if the whole
2616 windows's size doesn't change, no wxSizeEvent will
2617 normally be sent. Here we add an extra test if
2618 the client test has been changed and this will
2620 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2624 wxPrintf( "OnSize sent from " );
2625 if (GetClassInfo() && GetClassInfo()->GetClassName())
2626 wxPrintf( GetClassInfo()->GetClassName() );
2627 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2630 if (!m_nativeSizeEvent
)
2632 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2633 event
.SetEventObject( this );
2634 GetEventHandler()->ProcessEvent( event
);
2640 void wxWindow::OnInternalIdle()
2642 if ( g_sendActivateEvent
!= -1 )
2644 bool activate
= g_sendActivateEvent
!= 0;
2647 g_sendActivateEvent
= -1;
2649 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2650 event
.SetEventObject(this);
2652 (void)GetEventHandler()->ProcessEvent(event
);
2655 wxCursor cursor
= m_cursor
;
2656 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2660 /* I now set the cursor anew in every OnInternalIdle call
2661 as setting the cursor in a parent window also effects the
2662 windows above so that checking for the current cursor is
2667 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2669 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2671 if (!g_globalCursor
.Ok())
2672 cursor
= *wxSTANDARD_CURSOR
;
2674 window
= m_widget
->window
;
2675 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2676 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2682 GdkWindow
*window
= m_widget
->window
;
2683 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2684 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2692 void wxWindow::DoGetSize( int *width
, int *height
) const
2694 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2696 if (width
) (*width
) = m_width
;
2697 if (height
) (*height
) = m_height
;
2700 void wxWindow::DoSetClientSize( int width
, int height
)
2702 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2706 SetSize( width
, height
);
2713 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2715 /* when using GTK 1.2 we set the shadow border size to 2 */
2719 if (HasFlag(wxSIMPLE_BORDER
))
2721 /* when using GTK 1.2 we set the simple border size to 1 */
2728 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2730 GtkRequisition vscroll_req
;
2731 vscroll_req
.width
= 2;
2732 vscroll_req
.height
= 2;
2733 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2734 (scroll_window
->vscrollbar
, &vscroll_req
);
2736 GtkRequisition hscroll_req
;
2737 hscroll_req
.width
= 2;
2738 hscroll_req
.height
= 2;
2739 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2740 (scroll_window
->hscrollbar
, &hscroll_req
);
2742 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2744 if (scroll_window
->vscrollbar_visible
)
2746 dw
+= vscroll_req
.width
;
2747 dw
+= scroll_class
->scrollbar_spacing
;
2750 if (scroll_window
->hscrollbar_visible
)
2752 dh
+= hscroll_req
.height
;
2753 dh
+= scroll_class
->scrollbar_spacing
;
2757 SetSize( width
+dw
, height
+dh
);
2761 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2763 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2767 if (width
) (*width
) = m_width
;
2768 if (height
) (*height
) = m_height
;
2775 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2777 /* when using GTK 1.2 we set the shadow border size to 2 */
2781 if (HasFlag(wxSIMPLE_BORDER
))
2783 /* when using GTK 1.2 we set the simple border size to 1 */
2790 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2792 GtkRequisition vscroll_req
;
2793 vscroll_req
.width
= 2;
2794 vscroll_req
.height
= 2;
2795 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2796 (scroll_window
->vscrollbar
, &vscroll_req
);
2798 GtkRequisition hscroll_req
;
2799 hscroll_req
.width
= 2;
2800 hscroll_req
.height
= 2;
2801 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2802 (scroll_window
->hscrollbar
, &hscroll_req
);
2804 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2806 if (scroll_window
->vscrollbar_visible
)
2808 dw
+= vscroll_req
.width
;
2809 dw
+= scroll_class
->scrollbar_spacing
;
2812 if (scroll_window
->hscrollbar_visible
)
2814 dh
+= hscroll_req
.height
;
2815 dh
+= scroll_class
->scrollbar_spacing
;
2819 if (width
) (*width
) = m_width
- dw
;
2820 if (height
) (*height
) = m_height
- dh
;
2824 void wxWindow::DoGetPosition( int *x
, int *y
) const
2826 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2830 if (m_parent
&& m_parent
->m_wxwindow
)
2832 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2833 dx
= pizza
->xoffset
;
2834 dy
= pizza
->yoffset
;
2837 if (x
) (*x
) = m_x
- dx
;
2838 if (y
) (*y
) = m_y
- dy
;
2841 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2843 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2845 if (!m_widget
->window
) return;
2847 GdkWindow
*source
= (GdkWindow
*) NULL
;
2849 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2851 source
= m_widget
->window
;
2855 gdk_window_get_origin( source
, &org_x
, &org_y
);
2859 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2861 org_x
+= m_widget
->allocation
.x
;
2862 org_y
+= m_widget
->allocation
.y
;
2870 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2872 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2874 if (!m_widget
->window
) return;
2876 GdkWindow
*source
= (GdkWindow
*) NULL
;
2878 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2880 source
= m_widget
->window
;
2884 gdk_window_get_origin( source
, &org_x
, &org_y
);
2888 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2890 org_x
+= m_widget
->allocation
.x
;
2891 org_y
+= m_widget
->allocation
.y
;
2899 bool wxWindow::Show( bool show
)
2901 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2903 if (!wxWindowBase::Show(show
))
2910 gtk_widget_show( m_widget
);
2912 gtk_widget_hide( m_widget
);
2917 bool wxWindow::Enable( bool enable
)
2919 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2921 if (!wxWindowBase::Enable(enable
))
2927 gtk_widget_set_sensitive( m_widget
, enable
);
2929 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2934 int wxWindow::GetCharHeight() const
2936 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2938 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2940 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2942 return font
->ascent
+ font
->descent
;
2945 int wxWindow::GetCharWidth() const
2947 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2949 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2951 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2953 return gdk_string_width( font
, "H" );
2956 void wxWindow::GetTextExtent( const wxString
& string
,
2960 int *externalLeading
,
2961 const wxFont
*theFont
) const
2963 wxFont fontToUse
= m_font
;
2964 if (theFont
) fontToUse
= *theFont
;
2966 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2968 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2969 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2970 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2971 if (descent
) (*descent
) = font
->descent
;
2972 if (externalLeading
) (*externalLeading
) = 0; // ??
2975 void wxWindow::SetFocus()
2977 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2981 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2982 gtk_widget_grab_focus (m_wxwindow
);
2988 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2990 gtk_widget_grab_focus (m_widget
);
2992 else if (GTK_IS_CONTAINER(m_widget
))
2994 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
3003 bool wxWindow::AcceptsFocus() const
3005 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3008 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
3010 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3012 wxWindow
*oldParent
= m_parent
,
3013 *newParent
= (wxWindow
*)newParentBase
;
3015 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3017 if ( !wxWindowBase::Reparent(newParent
) )
3020 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3022 /* prevent GTK from deleting the widget arbitrarily */
3023 gtk_widget_ref( m_widget
);
3027 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3030 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3034 /* insert GTK representation */
3035 (*(newParent
->m_insertCallback
))(newParent
, this);
3038 /* reverse: prevent GTK from deleting the widget arbitrarily */
3039 gtk_widget_unref( m_widget
);
3044 void wxWindow::DoAddChild(wxWindow
*child
)
3046 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3048 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3050 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3055 /* insert GTK representation */
3056 (*m_insertCallback
)(this, child
);
3059 void wxWindow::Raise()
3061 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3063 if (!m_widget
->window
) return;
3065 gdk_window_raise( m_widget
->window
);
3068 void wxWindow::Lower()
3070 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3072 if (!m_widget
->window
) return;
3074 gdk_window_lower( m_widget
->window
);
3077 bool wxWindow::SetCursor( const wxCursor
&cursor
)
3079 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3081 if (cursor
== m_cursor
)
3085 wxapp_install_idle_handler();
3087 if (cursor
== wxNullCursor
)
3088 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3090 return wxWindowBase::SetCursor( cursor
);
3093 void wxWindow::WarpPointer( int x
, int y
)
3095 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3097 /* we provide this function ourselves as it is
3098 missing in GDK (top of this file) */
3100 GdkWindow
*window
= (GdkWindow
*) NULL
;
3102 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3104 window
= GetConnectWidget()->window
;
3107 gdk_window_warp_pointer( window
, x
, y
);
3110 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
3112 if (!m_widget
) return;
3113 if (!m_widget
->window
) return;
3115 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3119 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3121 rect
->width
, rect
->height
);
3125 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3129 /* there is no GTK equivalent of "draw only, don't clear" so we
3130 invent our own in the GtkPizza widget */
3138 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3139 gboolean old_clear = pizza->clear_on_draw;
3140 gtk_pizza_set_clear( pizza, FALSE );
3141 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3142 gtk_pizza_set_clear( pizza, old_clear );
3144 GdkEventExpose gdk_event
;
3145 gdk_event
.type
= GDK_EXPOSE
;
3146 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3147 gdk_event
.count
= 0;
3148 gdk_event
.area
.x
= 0;
3149 gdk_event
.area
.y
= 0;
3150 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3151 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3152 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3157 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3166 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3167 gboolean old_clear = pizza->clear_on_draw;
3168 gtk_pizza_set_clear( pizza, FALSE );
3170 GdkRectangle gdk_rect;
3171 gdk_rect.x = rect->x;
3172 gdk_rect.y = rect->y;
3173 gdk_rect.width = rect->width;
3174 gdk_rect.height = rect->height;
3175 gtk_widget_draw( m_wxwindow, &gdk_rect );
3176 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3178 gtk_pizza_set_clear( pizza, old_clear );
3180 GdkEventExpose gdk_event
;
3181 gdk_event
.type
= GDK_EXPOSE
;
3182 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3183 gdk_event
.count
= 0;
3184 gdk_event
.area
.x
= rect
->x
;
3185 gdk_event
.area
.y
= rect
->y
;
3186 gdk_event
.area
.width
= rect
->width
;
3187 gdk_event
.area
.height
= rect
->height
;
3188 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3192 GdkRectangle gdk_rect
;
3193 gdk_rect
.x
= rect
->x
;
3194 gdk_rect
.y
= rect
->y
;
3195 gdk_rect
.width
= rect
->width
;
3196 gdk_rect
.height
= rect
->height
;
3197 gtk_widget_draw( m_widget
, &gdk_rect
);
3202 void wxWindow::Clear()
3204 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3206 if (!m_widget
->window
) return;
3208 if (m_wxwindow
&& m_wxwindow
->window
)
3210 // gdk_window_clear( m_wxwindow->window );
3215 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
3217 wxWindowBase::DoSetToolTip(tip
);
3220 m_tooltip
->Apply( this );
3223 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3225 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3227 #endif // wxUSE_TOOLTIPS
3229 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
3231 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3233 if (!wxWindowBase::SetBackgroundColour(colour
))
3235 // don't leave if the GTK widget has just
3237 if (!m_delayedBackgroundColour
) return FALSE
;
3240 GdkWindow
*window
= (GdkWindow
*) NULL
;
3242 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3244 window
= GetConnectWidget()->window
;
3248 // indicate that a new style has been set
3249 // but it couldn't get applied as the
3250 // widget hasn't been realized yet.
3251 m_delayedBackgroundColour
= TRUE
;
3255 (m_wxwindow
->window
) &&
3256 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3258 /* wxMSW doesn't clear the window here. I don't do that either to
3259 provide compatibility. call Clear() to do the job. */
3261 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3262 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3270 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
3272 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3274 if (!wxWindowBase::SetForegroundColour(colour
))
3276 // don't leave if the GTK widget has just
3278 if (!m_delayedForegroundColour
) return FALSE
;
3281 GdkWindow
*window
= (GdkWindow
*) NULL
;
3283 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3285 window
= GetConnectWidget()->window
;
3289 // indicate that a new style has been set
3290 // but it couldn't get applied as the
3291 // widget hasn't been realized yet.
3292 m_delayedForegroundColour
= TRUE
;
3300 GtkStyle
*wxWindow::GetWidgetStyle()
3304 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3306 /* FIXME: is this necessary? */
3307 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3309 remake
->klass
= m_widgetStyle
->klass
;
3312 gtk_style_unref( m_widgetStyle
);
3313 m_widgetStyle
= remake
;
3317 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3320 def
= gtk_widget_get_default_style();
3322 m_widgetStyle
= gtk_style_copy( def
);
3324 /* FIXME: is this necessary? */
3325 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3327 m_widgetStyle
->klass
= def
->klass
;
3331 return m_widgetStyle
;
3334 void wxWindow::SetWidgetStyle()
3336 #if DISABLE_STYLE_IF_BROKEN_THEM
3337 if (m_widget
->style
->engine_data
)
3339 static bool s_warningPrinted
= FALSE
;
3340 if (!s_warningPrinted
)
3342 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3343 s_warningPrinted
= TRUE
;
3345 m_widgetStyle
= m_widget
->style
;
3350 GtkStyle
*style
= GetWidgetStyle();
3352 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3354 gdk_font_unref( style
->font
);
3355 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3358 if (m_foregroundColour
.Ok())
3360 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3361 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3363 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3364 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3365 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3369 // Try to restore the gtk default style. This is still a little
3370 // oversimplified for what is probably really needed here for controls
3371 // other than buttons, but is better than not being able to (re)set a
3372 // control's foreground colour to *wxBLACK -- RL
3373 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3376 def
= gtk_widget_get_default_style();
3378 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3379 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3380 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3384 if (m_backgroundColour
.Ok())
3386 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3387 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3389 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3390 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3391 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3392 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3393 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3394 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3395 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3396 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3400 // Try to restore the gtk default style. This is still a little
3401 // oversimplified for what is probably really needed here for controls
3402 // other than buttons, but is better than not being able to (re)set a
3403 // control's background colour to default grey and means resetting a
3404 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3406 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3409 def
= gtk_widget_get_default_style();
3411 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3412 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3413 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3414 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3415 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3416 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3417 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3418 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3423 void wxWindow::ApplyWidgetStyle()
3427 //-----------------------------------------------------------------------------
3428 // Pop-up menu stuff
3429 //-----------------------------------------------------------------------------
3431 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3433 *is_waiting
= FALSE
;
3436 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3438 menu
->SetInvokingWindow( win
);
3439 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3442 wxMenuItem
*menuitem
= node
->GetData();
3443 if (menuitem
->IsSubMenu())
3445 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3448 node
= node
->GetNext();
3452 static gint gs_pop_x
= 0;
3453 static gint gs_pop_y
= 0;
3455 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3459 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3464 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3466 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3468 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3470 SetInvokingWindow( menu
, this );
3477 bool is_waiting
= TRUE
;
3479 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3480 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3483 GTK_MENU(menu
->m_menu
),
3484 (GtkWidget
*) NULL
, // parent menu shell
3485 (GtkWidget
*) NULL
, // parent menu item
3486 (GtkMenuPositionFunc
) pop_pos_callback
,
3487 (gpointer
) this, // client data
3488 0, // button used to activate it
3489 gs_timeLastClick
// the time of activation
3494 while (gtk_events_pending())
3495 gtk_main_iteration();
3501 #if wxUSE_DRAG_AND_DROP
3503 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3505 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3507 GtkWidget
*dnd_widget
= GetConnectWidget();
3509 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3511 if (m_dropTarget
) delete m_dropTarget
;
3512 m_dropTarget
= dropTarget
;
3514 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3517 #endif // wxUSE_DRAG_AND_DROP
3519 GtkWidget
* wxWindow::GetConnectWidget()
3521 GtkWidget
*connect_widget
= m_widget
;
3522 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3524 return connect_widget
;
3527 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3530 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3532 return (window
== m_widget
->window
);
3535 bool wxWindow::SetFont( const wxFont
&font
)
3537 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3539 if (!wxWindowBase::SetFont(font
))
3544 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3545 if ( sysbg
== m_backgroundColour
)
3547 m_backgroundColour
= wxNullColour
;
3549 m_backgroundColour
= sysbg
;
3559 void wxWindow::CaptureMouse()
3561 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3563 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3565 GdkWindow
*window
= (GdkWindow
*) NULL
;
3567 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3569 window
= GetConnectWidget()->window
;
3571 if (!window
) return;
3573 wxCursor
* cursor
= & m_cursor
;
3575 cursor
= wxSTANDARD_CURSOR
;
3577 gdk_pointer_grab( window
, FALSE
,
3579 (GDK_BUTTON_PRESS_MASK
|
3580 GDK_BUTTON_RELEASE_MASK
|
3581 GDK_POINTER_MOTION_HINT_MASK
|
3582 GDK_POINTER_MOTION_MASK
),
3584 cursor
->GetCursor(),
3585 (guint32
)GDK_CURRENT_TIME
);
3586 g_captureWindow
= this;
3589 void wxWindow::ReleaseMouse()
3591 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3593 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3595 GdkWindow
*window
= (GdkWindow
*) NULL
;
3597 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3599 window
= GetConnectWidget()->window
;
3604 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3605 g_captureWindow
= (wxWindow
*) NULL
;
3608 bool wxWindow::IsRetained() const
3613 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3614 int range
, bool refresh
)
3616 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3618 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3620 m_hasScrolling
= TRUE
;
3622 if (orient
== wxHORIZONTAL
)
3624 float fpos
= (float)pos
;
3625 float frange
= (float)range
;
3626 float fthumb
= (float)thumbVisible
;
3627 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3628 if (fpos
< 0.0) fpos
= 0.0;
3630 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3631 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3633 SetScrollPos( orient
, pos
, refresh
);
3637 m_oldHorizontalPos
= fpos
;
3639 m_hAdjust
->lower
= 0.0;
3640 m_hAdjust
->upper
= frange
;
3641 m_hAdjust
->value
= fpos
;
3642 m_hAdjust
->step_increment
= 1.0;
3643 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3644 m_hAdjust
->page_size
= fthumb
;
3648 float fpos
= (float)pos
;
3649 float frange
= (float)range
;
3650 float fthumb
= (float)thumbVisible
;
3651 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3652 if (fpos
< 0.0) fpos
= 0.0;
3654 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3655 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3657 SetScrollPos( orient
, pos
, refresh
);
3661 m_oldVerticalPos
= fpos
;
3663 m_vAdjust
->lower
= 0.0;
3664 m_vAdjust
->upper
= frange
;
3665 m_vAdjust
->value
= fpos
;
3666 m_vAdjust
->step_increment
= 1.0;
3667 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3668 m_vAdjust
->page_size
= fthumb
;
3671 if (orient
== wxHORIZONTAL
)
3672 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3674 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3677 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3679 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3681 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3683 if (orient
== wxHORIZONTAL
)
3685 float fpos
= (float)pos
;
3686 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3687 if (fpos
< 0.0) fpos
= 0.0;
3688 m_oldHorizontalPos
= fpos
;
3690 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3691 m_hAdjust
->value
= fpos
;
3695 float fpos
= (float)pos
;
3696 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3697 if (fpos
< 0.0) fpos
= 0.0;
3698 m_oldVerticalPos
= fpos
;
3700 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3701 m_vAdjust
->value
= fpos
;
3704 if (m_wxwindow
->window
)
3706 if (orient
== wxHORIZONTAL
)
3708 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3709 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3711 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3713 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3714 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3718 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3719 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3721 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3723 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3724 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3729 int wxWindow::GetScrollThumb( int orient
) const
3731 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3733 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3735 if (orient
== wxHORIZONTAL
)
3736 return (int)(m_hAdjust
->page_size
+0.5);
3738 return (int)(m_vAdjust
->page_size
+0.5);
3741 int wxWindow::GetScrollPos( int orient
) const
3743 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3745 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3747 if (orient
== wxHORIZONTAL
)
3748 return (int)(m_hAdjust
->value
+0.5);
3750 return (int)(m_vAdjust
->value
+0.5);
3753 int wxWindow::GetScrollRange( int orient
) const
3755 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3757 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3759 if (orient
== wxHORIZONTAL
)
3760 return (int)(m_hAdjust
->upper
+0.5);
3762 return (int)(m_vAdjust
->upper
+0.5);
3765 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3767 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3769 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3771 if ((dx
== 0) && (dy
== 0)) return;
3773 m_clipPaintRegion
= TRUE
;
3774 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3775 m_clipPaintRegion
= FALSE
;
3778 if (m_children.GetCount() > 0)
3780 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3784 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3786 pizza->xoffset -= dx;
3787 pizza->yoffset -= dy;
3789 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3790 gdk_gc_set_exposures( m_scrollGC, TRUE );
3794 GetClientSize( &cw, &ch );
3795 int w = cw - abs(dx);
3796 int h = ch - abs(dy);
3798 if ((h < 0) || (w < 0))
3806 if (dx < 0) s_x = -dx;
3807 if (dy < 0) s_y = -dy;
3810 if (dx > 0) d_x = dx;
3811 if (dy > 0) d_y = dy;
3813 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3814 pizza->bin_window, s_x, s_y, w, h );
3817 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3818 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3819 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3820 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3822 Refresh( TRUE, &rect );
3825 gdk_gc_unref( m_scrollGC );
3830 // Find the wxWindow at the current mouse position, also returning the mouse
3832 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
3834 pt
= wxGetMousePosition();
3835 wxWindow
* found
= wxFindWindowAtPoint(pt
);
3839 // Get the current mouse position.
3840 wxPoint
wxGetMousePosition()
3842 /* This crashes when used within wxHelpContext,
3843 so we have to use the X-specific implementation below.
3845 GdkModifierType *mask;
3846 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
3848 return wxPoint(x, y);
3852 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
3854 return wxPoint(-999, -999);
3856 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
3857 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
3858 Window rootReturn
, childReturn
;
3859 int rootX
, rootY
, winX
, winY
;
3860 unsigned int maskReturn
;
3862 XQueryPointer (display
,
3866 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
3867 return wxPoint(rootX
, rootY
);