1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/window.cpp
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #define XWarpPointer XWARPPOINTER
20 #include "wx/window.h"
24 #include "wx/layout.h"
26 #include "wx/dialog.h"
27 #include "wx/msgdlg.h"
29 #if wxUSE_DRAG_AND_DROP
34 #include "wx/tooltip.h"
42 #include "wx/statusbr.h"
44 #include "wx/settings.h"
48 #include "wx/thread.h"
55 #include <gdk/gdkprivate.h>
56 #include <gdk/gdkkeysyms.h>
60 #include <gtk/gtkprivate.h>
62 #include "wx/gtk/win_gtk.h"
64 //-----------------------------------------------------------------------------
65 // documentation on internals
66 //-----------------------------------------------------------------------------
69 I have been asked several times about writing some documentation about
70 the GTK port of wxWindows, especially its internal structures. Obviously,
71 you cannot understand wxGTK without knowing a little about the GTK, but
72 some more information about what the wxWindow, which is the base class
73 for all other window classes, does seems required as well.
77 What does wxWindow do? It contains the common interface for the following
78 jobs of its descendants:
80 1) Define the rudimentary behaviour common to all window classes, such as
81 resizing, intercepting user input (so as to make it possible to use these
82 events for special purposes in a derived class), window names etc.
84 2) Provide the possibility to contain and manage children, if the derived
85 class is allowed to contain children, which holds true for those window
86 classes which do not display a native GTK widget. To name them, these
87 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
88 work classes are a special case and are handled a bit differently from
89 the rest. The same holds true for the wxNotebook class.
91 3) Provide the possibility to draw into a client area of a window. This,
92 too, only holds true for classes that do not display a native GTK widget
95 4) Provide the entire mechanism for scrolling widgets. This actual inter-
96 face for this is usually in wxScrolledWindow, but the GTK implementation
99 5) A multitude of helper or extra methods for special purposes, such as
100 Drag'n'Drop, managing validators etc.
102 6) Display a border (sunken, raised, simple or none).
104 Normally one might expect, that one wxWindows window would always correspond
105 to one GTK widget. Under GTK, there is no such allround widget that has all
106 the functionality. Moreover, the GTK defines a client area as a different
107 widget from the actual widget you are handling. Last but not least some
108 special classes (e.g. wxFrame) handle different categories of widgets and
109 still have the possibility to draw something in the client area.
110 It was therefore required to write a special purpose GTK widget, that would
111 represent a client area in the sense of wxWindows capable to do the jobs
112 2), 3) and 4). I have written this class and it resides in win_gtk.c of
115 All windows must have a widget, with which they interact with other under-
116 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
117 thw wxWindow class has a member variable called m_widget which holds a
118 pointer to this widget. When the window class represents a GTK native widget,
119 this is (in most cases) the only GTK widget the class manages. E.g. the
120 wxStatitText class handles only a GtkLabel widget a pointer to which you
121 can find in m_widget (defined in wxWindow)
123 When the class has a client area for drawing into and for containing children
124 it has to handle the client area widget (of the type GtkPizza, defined in
125 win_gtk.c), but there could be any number of widgets, handled by a class
126 The common rule for all windows is only, that the widget that interacts with
127 the rest of GTK must be referenced in m_widget and all other widgets must be
128 children of this widget on the GTK level. The top-most widget, which also
129 represents the client area, must be in the m_wxwindow field and must be of
132 As I said, the window classes that display a GTK native widget only have
133 one widget, so in the case of e.g. the wxButton class m_widget holds a
134 pointer to a GtkButton widget. But windows with client areas (for drawing
135 and children) have a m_widget field that is a pointer to a GtkScrolled-
136 Window and a m_wxwindow field that is pointer to a GtkPizza and this
137 one is (in the GTK sense) a child of the GtkScrolledWindow.
139 If the m_wxwindow field is set, then all input to this widget is inter-
140 cepted and sent to the wxWindows class. If not, all input to the widget
141 that gets pointed to by m_widget gets intercepted and sent to the class.
145 The design of scrolling in wxWindows is markedly different from that offered
146 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
147 clicking on a scrollbar belonging to scrolled window will inevitably move
148 the window. In wxWindows, the scrollbar will only emit an event, send this
149 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
150 which actually moves the window and its subchildren. Note that GtkPizza
151 memorizes how much it has been scrolled but that wxWindows forgets this
152 so that the two coordinates systems have to be kept in synch. This is done
153 in various places using the pizza->xoffset and pizza->yoffset values.
157 Singularily the most broken code in GTK is the code that is supposes to
158 inform subwindows (child windows) about new positions. Very often, duplicate
159 events are sent without changes in size or position, equally often no
160 events are sent at all (All this is due to a bug in the GtkContainer code
161 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
162 GTK's own system and it simply waits for size events for toplevel windows
163 and then iterates down the respective size events to all window. This has
164 the disadvantage, that windows might get size events before the GTK widget
165 actually has the reported size. This doesn't normally pose any problem, but
166 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
167 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
168 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
169 window that is used for OpenGl output really has that size (as reported by
174 If someone at some point of time feels the immense desire to have a look at,
175 change or attempt to optimse the Refresh() logic, this person will need an
176 intimate understanding of what a "draw" and what an "expose" events are and
177 what there are used for, in particular when used in connection with GTK's
178 own windowless widgets. Beware.
182 Cursors, too, have been a constant source of pleasure. The main difficulty
183 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
184 for the parent. To prevent this from doing too much harm, I use idle time
185 to set the cursor over and over again, starting from the toplevel windows
186 and ending with the youngest generation (speaking of parent and child windows).
187 Also don't forget that cursors (like much else) are connected to GdkWindows,
188 not GtkWidgets and that the "window" field of a GtkWidget might very well
189 point to the GdkWindow of the parent widget (-> "window less widget") and
190 that the two obviously have very different meanings.
194 //-----------------------------------------------------------------------------
196 //-----------------------------------------------------------------------------
198 extern wxList wxPendingDelete
;
199 extern bool g_blockEventsOnDrag
;
200 extern bool g_blockEventsOnScroll
;
201 extern wxCursor g_globalCursor
;
202 static wxWindow
*g_captureWindow
= (wxWindow
*) NULL
;
204 /* extern */ wxWindow
*g_focusWindow
= (wxWindow
*) NULL
;
206 // if we detect that the app has got/lost the focus, we set this variable to
207 // either TRUE or FALSE and an activate event will be sent during the next
208 // OnIdle() call and it is reset to -1: this value means that we shouldn't
209 // send any activate events at all
210 static int g_sendActivateEvent
= -1;
212 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
213 the last click here */
214 static guint32 gs_timeLastClick
= 0;
216 extern bool g_mainThreadLocked
;
218 //-----------------------------------------------------------------------------
220 //-----------------------------------------------------------------------------
222 #define DISABLE_STYLE_IF_BROKEN_THEME 1
227 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
229 # define DEBUG_MAIN_THREAD
232 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
233 GdkEvent
*WXUNUSED(event
),
234 const wxChar
*WXUNUSED(name
) )
237 static bool s_done = FALSE;
240 wxLog::AddTraceMask("focus");
243 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
249 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
251 // suppress warnings about gtk_debug_focus_in_callback being unused with
256 tmp
+= wxT(" FROM ");
259 wxChar
*s
= new wxChar
[tmp
.Length()+1];
263 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
264 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
269 #define DEBUG_MAIN_THREAD
272 //-----------------------------------------------------------------------------
273 // missing gdk functions
274 //-----------------------------------------------------------------------------
277 gdk_window_warp_pointer (GdkWindow
*window
,
282 GdkWindowPrivate
*priv
;
286 window
= GDK_ROOT_PARENT();
289 if (!GDK_WINDOW_DESTROYED(window
))
291 XWarpPointer (GDK_WINDOW_XDISPLAY(window
),
292 None
, /* not source window -> move from anywhere */
293 GDK_WINDOW_XID(window
), /* dest window */
294 0, 0, 0, 0, /* not source window -> move from anywhere */
298 priv
= (GdkWindowPrivate
*) window
;
300 if (!priv
->destroyed
)
302 XWarpPointer (priv
->xdisplay
,
303 None
, /* not source window -> move from anywhere */
304 priv
->xwindow
, /* dest window */
305 0, 0, 0, 0, /* not source window -> move from anywhere */
311 //-----------------------------------------------------------------------------
313 //-----------------------------------------------------------------------------
315 extern void wxapp_install_idle_handler();
316 extern bool g_isIdle
;
318 //-----------------------------------------------------------------------------
319 // local code (see below)
320 //-----------------------------------------------------------------------------
322 // returns the child of win which currently has focus or NULL if not found
323 static wxWindow
*FindFocusedChild(wxWindow
*win
)
325 wxWindow
*winFocus
= wxWindow::FindFocus();
327 return (wxWindow
*)NULL
;
329 if ( winFocus
== win
)
332 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
334 node
= node
->GetNext() )
336 wxWindow
*child
= FindFocusedChild(node
->GetData());
341 return (wxWindow
*)NULL
;
344 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
352 if (win
->m_hasScrolling
)
354 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
356 GtkRequisition vscroll_req
;
357 vscroll_req
.width
= 2;
358 vscroll_req
.height
= 2;
359 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
360 (scroll_window
->vscrollbar
, &vscroll_req
);
362 GtkRequisition hscroll_req
;
363 hscroll_req
.width
= 2;
364 hscroll_req
.height
= 2;
365 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
366 (scroll_window
->hscrollbar
, &hscroll_req
);
368 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) );
370 if (scroll_window
->vscrollbar_visible
)
372 dw
+= vscroll_req
.width
;
373 dw
+= scroll_class
->scrollbar_spacing
;
376 if (scroll_window
->hscrollbar_visible
)
378 dh
+= hscroll_req
.height
;
379 dh
+= scroll_class
->scrollbar_spacing
;
385 if (GTK_WIDGET_NO_WINDOW (widget
))
387 dx
+= widget
->allocation
.x
;
388 dy
+= widget
->allocation
.y
;
391 if (win
->HasFlag(wxRAISED_BORDER
))
393 gtk_draw_shadow( widget
->style
,
398 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
402 if (win
->HasFlag(wxSUNKEN_BORDER
))
404 gtk_draw_shadow( widget
->style
,
409 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
413 if (win
->HasFlag(wxSIMPLE_BORDER
))
416 gc
= gdk_gc_new( widget
->window
);
417 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
418 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
420 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
426 //-----------------------------------------------------------------------------
427 // "expose_event" of m_widget
428 //-----------------------------------------------------------------------------
430 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
432 if (gdk_event
->count
> 0) return FALSE
;
434 draw_frame( widget
, win
);
439 //-----------------------------------------------------------------------------
440 // "draw" of m_widget
441 //-----------------------------------------------------------------------------
443 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
445 draw_frame( widget
, win
);
448 //-----------------------------------------------------------------------------
449 // key code mapping routines
450 //-----------------------------------------------------------------------------
452 static long map_to_unmodified_wx_keysym( KeySym keysym
)
459 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
461 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
467 case GDK_Super_R
: key_code
= WXK_ALT
; break;
468 case GDK_Menu
: key_code
= WXK_MENU
; break;
469 case GDK_Help
: key_code
= WXK_HELP
; break;
470 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
471 case GDK_ISO_Left_Tab
:
472 case GDK_Tab
: key_code
= WXK_TAB
; break;
473 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
474 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
475 case GDK_Return
: key_code
= WXK_RETURN
; break;
476 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
477 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
478 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
479 case GDK_Delete
: key_code
= WXK_DELETE
; break;
480 case GDK_Home
: key_code
= WXK_HOME
; break;
481 case GDK_Left
: key_code
= WXK_LEFT
; break;
482 case GDK_Up
: key_code
= WXK_UP
; break;
483 case GDK_Right
: key_code
= WXK_RIGHT
; break;
484 case GDK_Down
: key_code
= WXK_DOWN
; break;
485 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
486 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
487 case GDK_Next
: key_code
= WXK_NEXT
; break;
488 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
489 case GDK_End
: key_code
= WXK_END
; break;
490 case GDK_Begin
: key_code
= WXK_HOME
; break;
491 case GDK_Select
: key_code
= WXK_SELECT
; break;
492 case GDK_Print
: key_code
= WXK_PRINT
; break;
493 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
494 case GDK_Insert
: key_code
= WXK_INSERT
; break;
495 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
497 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
498 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
499 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
500 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
501 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
502 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
503 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
504 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
505 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
506 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
507 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
508 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
509 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
510 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
511 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
512 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
513 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
514 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
515 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
516 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
517 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
518 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
519 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
520 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
521 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
522 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
523 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
524 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
525 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
526 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
527 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
528 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
529 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
530 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
531 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
532 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
533 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
535 case GDK_F1
: key_code
= WXK_F1
; break;
536 case GDK_F2
: key_code
= WXK_F2
; break;
537 case GDK_F3
: key_code
= WXK_F3
; break;
538 case GDK_F4
: key_code
= WXK_F4
; break;
539 case GDK_F5
: key_code
= WXK_F5
; break;
540 case GDK_F6
: key_code
= WXK_F6
; break;
541 case GDK_F7
: key_code
= WXK_F7
; break;
542 case GDK_F8
: key_code
= WXK_F8
; break;
543 case GDK_F9
: key_code
= WXK_F9
; break;
544 case GDK_F10
: key_code
= WXK_F10
; break;
545 case GDK_F11
: key_code
= WXK_F11
; break;
546 case GDK_F12
: key_code
= WXK_F12
; break;
549 if ((keysym
& 0xF000) == 0)
551 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
552 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
553 key_code
= (guint
)keysym
;
561 static long map_to_wx_keysym( KeySym keysym
)
567 case GDK_Menu
: key_code
= WXK_MENU
; break;
568 case GDK_Help
: key_code
= WXK_HELP
; break;
569 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
570 case GDK_ISO_Left_Tab
:
571 case GDK_Tab
: key_code
= WXK_TAB
; break;
572 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
573 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
574 case GDK_Return
: key_code
= WXK_RETURN
; break;
575 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
576 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
577 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
578 case GDK_Delete
: key_code
= WXK_DELETE
; break;
579 case GDK_Home
: key_code
= WXK_HOME
; break;
580 case GDK_Left
: key_code
= WXK_LEFT
; break;
581 case GDK_Up
: key_code
= WXK_UP
; break;
582 case GDK_Right
: key_code
= WXK_RIGHT
; break;
583 case GDK_Down
: key_code
= WXK_DOWN
; break;
584 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
585 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
586 case GDK_Next
: key_code
= WXK_NEXT
; break;
587 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
588 case GDK_End
: key_code
= WXK_END
; break;
589 case GDK_Begin
: key_code
= WXK_HOME
; break;
590 case GDK_Select
: key_code
= WXK_SELECT
; break;
591 case GDK_Print
: key_code
= WXK_PRINT
; break;
592 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
593 case GDK_Insert
: key_code
= WXK_INSERT
; break;
594 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
596 case GDK_KP_0
: key_code
= '0'; break;
597 case GDK_KP_1
: key_code
= '1'; break;
598 case GDK_KP_2
: key_code
= '2'; break;
599 case GDK_KP_3
: key_code
= '3'; break;
600 case GDK_KP_4
: key_code
= '4'; break;
601 case GDK_KP_5
: key_code
= '5'; break;
602 case GDK_KP_6
: key_code
= '6'; break;
603 case GDK_KP_7
: key_code
= '7'; break;
604 case GDK_KP_8
: key_code
= '8'; break;
605 case GDK_KP_9
: key_code
= '9'; break;
606 case GDK_KP_Space
: key_code
= ' '; break;
607 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
608 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
609 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
610 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
611 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
612 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
613 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
614 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
615 case GDK_KP_Up
: key_code
= WXK_UP
; break;
616 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
617 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
618 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
619 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
620 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
621 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
622 case GDK_KP_End
: key_code
= WXK_END
; break;
623 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
624 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
625 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
626 case GDK_KP_Equal
: key_code
= '='; break;
627 case GDK_KP_Multiply
: key_code
= '*'; break;
628 case GDK_KP_Add
: key_code
= '+'; break;
629 case GDK_KP_Separator
: key_code
= ','; break;
630 case GDK_KP_Subtract
: key_code
= '-'; break;
631 case GDK_KP_Decimal
: key_code
= '.'; break;
632 case GDK_KP_Divide
: key_code
= '/'; break;
634 case GDK_F1
: key_code
= WXK_F1
; break;
635 case GDK_F2
: key_code
= WXK_F2
; break;
636 case GDK_F3
: key_code
= WXK_F3
; break;
637 case GDK_F4
: key_code
= WXK_F4
; break;
638 case GDK_F5
: key_code
= WXK_F5
; break;
639 case GDK_F6
: key_code
= WXK_F6
; break;
640 case GDK_F7
: key_code
= WXK_F7
; break;
641 case GDK_F8
: key_code
= WXK_F8
; break;
642 case GDK_F9
: key_code
= WXK_F9
; break;
643 case GDK_F10
: key_code
= WXK_F10
; break;
644 case GDK_F11
: key_code
= WXK_F11
; break;
645 case GDK_F12
: key_code
= WXK_F12
; break;
648 if ((keysym
& 0xF000) == 0)
650 key_code
= (guint
)keysym
;
658 //-----------------------------------------------------------------------------
659 // "expose_event" of m_wxwindow
660 //-----------------------------------------------------------------------------
662 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
667 wxapp_install_idle_handler();
670 if (win->GetName() == wxT("panel"))
672 wxPrintf( wxT("OnExpose from ") );
673 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
674 wxPrintf( win->GetClassInfo()->GetClassName() );
675 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
676 (int)gdk_event->area.y,
677 (int)gdk_event->area.width,
678 (int)gdk_event->area.height );
682 GtkPizza
*pizza
= GTK_PIZZA (widget
);
684 if (win
->IsTopLevel())
686 gtk_paint_flat_box (win
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
687 GTK_SHADOW_NONE
, &gdk_event
->area
, win
->m_widget
, "base", 0, 0, -1, -1);
690 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
692 gdk_event
->area
.width
,
693 gdk_event
->area
.height
);
695 if (gdk_event
->count
== 0)
697 wxEraseEvent
eevent( win
->GetId() );
698 eevent
.SetEventObject( win
);
699 win
->GetEventHandler()->ProcessEvent(eevent
);
701 wxPaintEvent
event( win
->GetId() );
702 event
.SetEventObject( win
);
703 win
->GetEventHandler()->ProcessEvent( event
);
705 win
->GetUpdateRegion().Clear();
708 /* The following code will result in all window-less widgets
709 being redrawn if the wxWindows class is given a chance to
710 paint *anything* because it will then be allowed to paint
711 over the window-less widgets */
713 GList
*children
= pizza
->children
;
716 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
717 children
= children
->next
;
719 GdkEventExpose child_event
= *gdk_event
;
721 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
722 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
723 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
725 child_event
.area
.x
= child
->widget
->allocation
.x
;
726 child_event
.area
.y
= child
->widget
->allocation
.y
;
727 child_event
.area
.width
= child
->widget
->allocation
.width
;
728 child_event
.area
.height
= child
->widget
->allocation
.height
;
729 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
736 //-----------------------------------------------------------------------------
737 // "event" of m_wxwindow
738 //-----------------------------------------------------------------------------
740 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
741 expose events. We need them, of course, so we override the main event
742 procedure in GtkWidget by giving our own handler for all system events.
743 There, we look for expose events ourselves whereas all other events are
746 gint
gtk_window_event_event_callback( GtkWidget
*widget
, GdkEventExpose
*event
, wxWindow
*win
)
748 if (event
->type
== GDK_EXPOSE
)
750 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
757 //-----------------------------------------------------------------------------
758 // "draw" of m_wxwindow
759 //-----------------------------------------------------------------------------
761 /* This callback is a complete replacement of the gtk_pizza_draw() function,
764 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
769 wxapp_install_idle_handler();
772 if (win->GetName() == wxT("panel"))
774 wxPrintf( wxT("OnDraw from ") );
775 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
776 wxPrintf( win->GetClassInfo()->GetClassName() );
777 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
784 GtkPizza
*pizza
= GTK_PIZZA (widget
);
786 if (win
->IsTopLevel())
788 gtk_paint_flat_box (win
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
789 GTK_SHADOW_NONE
, rect
, win
->m_widget
, "base", 0, 0, -1, -1);
792 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
793 (pizza
->clear_on_draw
))
795 gdk_window_clear_area( pizza
->bin_window
,
796 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
799 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
801 win
->m_clipPaintRegion
= TRUE
;
803 wxEraseEvent
eevent( win
->GetId() );
804 eevent
.SetEventObject( win
);
805 win
->GetEventHandler()->ProcessEvent(eevent
);
807 wxPaintEvent
event( win
->GetId() );
808 event
.SetEventObject( win
);
809 win
->GetEventHandler()->ProcessEvent( event
);
811 win
->GetUpdateRegion().Clear();
813 win
->m_clipPaintRegion
= FALSE
;
816 GList
*children
= pizza
->children
;
819 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
820 children
= children
->next
;
822 GdkRectangle child_area
;
823 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
825 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
830 //-----------------------------------------------------------------------------
831 // "key_press_event" from any window
832 //-----------------------------------------------------------------------------
834 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
839 wxapp_install_idle_handler();
841 if (!win
->m_hasVMT
) return FALSE
;
842 if (g_blockEventsOnDrag
) return FALSE
;
847 tmp += (char)gdk_event->keyval;
848 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
849 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
854 GdkModifierType state
;
855 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
859 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
860 /* sending unknown key events doesn't really make sense */
861 if (key_code
== 0) return FALSE
;
863 wxKeyEvent
event( wxEVT_KEY_DOWN
);
864 event
.SetTimestamp( gdk_event
->time
);
865 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
866 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
867 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
868 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
869 event
.m_keyCode
= key_code
;
870 event
.m_scanCode
= gdk_event
->keyval
;
873 event
.SetEventObject( win
);
874 ret
= win
->GetEventHandler()->ProcessEvent( event
);
879 wxWindow
*ancestor
= win
;
882 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
885 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
886 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
889 if (ancestor
->IsTopLevel())
891 ancestor
= ancestor
->GetParent();
894 #endif // wxUSE_ACCEL
896 /* wxMSW doesn't send char events with Alt pressed */
897 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
898 will only be sent if it is not in an accelerator table. */
899 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
904 wxKeyEvent
event2( wxEVT_CHAR
);
905 event2
.SetTimestamp( gdk_event
->time
);
906 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
907 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
908 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
909 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
910 event2
.m_keyCode
= key_code
;
911 event2
.m_scanCode
= gdk_event
->keyval
;
914 event2
.SetEventObject( win
);
915 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
918 /* win is a control: tab can be propagated up */
920 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
921 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
922 // have this style, yet choose not to process this particular TAB in which
923 // case TAB must still work as a navigational character
925 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
927 (win
->GetParent()) &&
928 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
930 wxNavigationKeyEvent new_event
;
931 new_event
.SetEventObject( win
->GetParent() );
932 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
933 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
934 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
935 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
936 new_event
.SetCurrentFocus( win
);
937 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
940 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
942 (gdk_event
->keyval
== GDK_Escape
) )
944 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
945 new_event
.SetEventObject( win
);
946 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
949 #if (GTK_MINOR_VERSION > 0)
950 /* Pressing F10 will activate the menu bar of the top frame. */
954 (gdk_event->keyval == GDK_F10) )
956 wxWindow *ancestor = win;
959 if (wxIsKindOf(ancestor,wxFrame))
961 wxFrame *frame = (wxFrame*) ancestor;
962 wxMenuBar *menubar = frame->GetMenuBar();
965 wxNode *node = menubar->GetMenus().First();
968 wxMenu *firstMenu = (wxMenu*) node->Data();
969 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
975 ancestor = ancestor->GetParent();
983 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
990 //-----------------------------------------------------------------------------
991 // "key_release_event" from any window
992 //-----------------------------------------------------------------------------
994 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
999 wxapp_install_idle_handler();
1001 if (!win
->m_hasVMT
) return FALSE
;
1002 if (g_blockEventsOnDrag
) return FALSE
;
1005 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
1006 if (gdk_event->state & GDK_SHIFT_MASK)
1007 printf( "ShiftDown.\n" );
1009 printf( "ShiftUp.\n" );
1010 if (gdk_event->state & GDK_CONTROL_MASK)
1011 printf( "ControlDown.\n" );
1013 printf( "ControlUp.\n" );
1017 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
1019 /* sending unknown key events doesn't really make sense */
1020 if (key_code
== 0) return FALSE
;
1024 GdkModifierType state
;
1025 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1027 wxKeyEvent
event( wxEVT_KEY_UP
);
1028 event
.SetTimestamp( gdk_event
->time
);
1029 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1030 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1031 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1032 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1033 event
.m_keyCode
= key_code
;
1034 event
.m_scanCode
= gdk_event
->keyval
;
1037 event
.SetEventObject( win
);
1039 if (win
->GetEventHandler()->ProcessEvent( event
))
1041 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1048 // ----------------------------------------------------------------------------
1049 // mouse event processing helper
1050 // ----------------------------------------------------------------------------
1052 static void AdjustEventButtonState(wxMouseEvent
& event
)
1054 // GDK reports the old state of the button for a button press event, but
1055 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1056 // for a LEFT_DOWN event, not FALSE, so we will invert
1057 // left/right/middleDown for the corresponding click events
1058 switch ( event
.GetEventType() )
1060 case wxEVT_LEFT_DOWN
:
1061 case wxEVT_LEFT_DCLICK
:
1063 event
.m_leftDown
= !event
.m_leftDown
;
1066 case wxEVT_MIDDLE_DOWN
:
1067 case wxEVT_MIDDLE_DCLICK
:
1068 case wxEVT_MIDDLE_UP
:
1069 event
.m_middleDown
= !event
.m_middleDown
;
1072 case wxEVT_RIGHT_DOWN
:
1073 case wxEVT_RIGHT_DCLICK
:
1074 case wxEVT_RIGHT_UP
:
1075 event
.m_rightDown
= !event
.m_rightDown
;
1080 //-----------------------------------------------------------------------------
1081 // "button_press_event"
1082 //-----------------------------------------------------------------------------
1084 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1089 wxapp_install_idle_handler();
1092 wxPrintf( wxT("1) OnButtonPress from ") );
1093 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1094 wxPrintf( win->GetClassInfo()->GetClassName() );
1095 wxPrintf( wxT(".\n") );
1097 if (!win
->m_hasVMT
) return FALSE
;
1098 if (g_blockEventsOnDrag
) return TRUE
;
1099 if (g_blockEventsOnScroll
) return TRUE
;
1101 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1103 if (win
->m_wxwindow
)
1105 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1107 gtk_widget_grab_focus (win
->m_wxwindow
);
1110 wxPrintf( wxT("GrabFocus from ") );
1111 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1112 wxPrintf( win->GetClassInfo()->GetClassName() );
1113 wxPrintf( wxT(".\n") );
1119 wxEventType event_type
= wxEVT_NULL
;
1121 if (gdk_event
->button
== 1)
1123 switch (gdk_event
->type
)
1125 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1126 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1130 else if (gdk_event
->button
== 2)
1132 switch (gdk_event
->type
)
1134 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1135 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1139 else if (gdk_event
->button
== 3)
1141 switch (gdk_event
->type
)
1143 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1144 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1149 if ( event_type
== wxEVT_NULL
)
1151 // unknown mouse button or click type
1155 wxMouseEvent
event( event_type
);
1156 event
.SetTimestamp( gdk_event
->time
);
1157 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1158 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1159 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1160 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1161 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1162 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1163 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1165 event
.m_x
= (wxCoord
)gdk_event
->x
;
1166 event
.m_y
= (wxCoord
)gdk_event
->y
;
1168 AdjustEventButtonState(event
);
1170 // Some control don't have their own X window and thus cannot get
1173 if (!g_captureWindow
)
1175 wxCoord x
= event
.m_x
;
1176 wxCoord y
= event
.m_y
;
1177 if (win
->m_wxwindow
)
1179 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1180 x
+= pizza
->xoffset
;
1181 y
+= pizza
->yoffset
;
1184 wxNode
*node
= win
->GetChildren().First();
1187 wxWindow
*child
= (wxWindow
*)node
->Data();
1189 node
= node
->Next();
1190 if (!child
->IsShown())
1193 if (child
->m_isStaticBox
)
1195 // wxStaticBox is transparent in the box itself
1196 int xx1
= child
->m_x
;
1197 int yy1
= child
->m_y
;
1198 int xx2
= child
->m_x
+ child
->m_width
;
1199 int yy2
= child
->m_x
+ child
->m_height
;
1202 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1204 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1206 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1208 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1211 event
.m_x
-= child
->m_x
;
1212 event
.m_y
-= child
->m_y
;
1219 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1220 (child
->m_x
<= x
) &&
1221 (child
->m_y
<= y
) &&
1222 (child
->m_x
+child
->m_width
>= x
) &&
1223 (child
->m_y
+child
->m_height
>= y
))
1226 event
.m_x
-= child
->m_x
;
1227 event
.m_y
-= child
->m_y
;
1234 event
.SetEventObject( win
);
1236 gs_timeLastClick
= gdk_event
->time
;
1239 wxPrintf( wxT("2) OnButtonPress from ") );
1240 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1241 wxPrintf( win->GetClassInfo()->GetClassName() );
1242 wxPrintf( wxT(".\n") );
1245 if (win
->GetEventHandler()->ProcessEvent( event
))
1247 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1254 //-----------------------------------------------------------------------------
1255 // "button_release_event"
1256 //-----------------------------------------------------------------------------
1258 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1263 wxapp_install_idle_handler();
1265 if (!win
->m_hasVMT
) return FALSE
;
1266 if (g_blockEventsOnDrag
) return FALSE
;
1267 if (g_blockEventsOnScroll
) return FALSE
;
1269 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1272 printf( "OnButtonRelease from " );
1273 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1274 printf( win->GetClassInfo()->GetClassName() );
1278 wxEventType event_type
= wxEVT_NULL
;
1280 switch (gdk_event
->button
)
1282 case 1: event_type
= wxEVT_LEFT_UP
; break;
1283 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1284 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1285 default: return FALSE
;
1288 wxMouseEvent
event( event_type
);
1289 event
.SetTimestamp( gdk_event
->time
);
1290 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1291 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1292 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1293 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1294 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1295 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1296 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1297 event
.m_x
= (wxCoord
)gdk_event
->x
;
1298 event
.m_y
= (wxCoord
)gdk_event
->y
;
1300 AdjustEventButtonState(event
);
1302 // Some control don't have their own X window and thus cannot get
1305 if (!g_captureWindow
)
1307 wxCoord x
= event
.m_x
;
1308 wxCoord y
= event
.m_y
;
1309 if (win
->m_wxwindow
)
1311 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1312 x
+= pizza
->xoffset
;
1313 y
+= pizza
->yoffset
;
1316 wxNode
*node
= win
->GetChildren().First();
1319 wxWindow
*child
= (wxWindow
*)node
->Data();
1321 node
= node
->Next();
1322 if (!child
->IsShown())
1325 if (child
->m_isStaticBox
)
1327 // wxStaticBox is transparent in the box itself
1328 int xx1
= child
->m_x
;
1329 int yy1
= child
->m_y
;
1330 int xx2
= child
->m_x
+ child
->m_width
;
1331 int yy2
= child
->m_x
+ child
->m_height
;
1334 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1336 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1338 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1340 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1343 event
.m_x
-= child
->m_x
;
1344 event
.m_y
-= child
->m_y
;
1351 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1352 (child
->m_x
<= x
) &&
1353 (child
->m_y
<= y
) &&
1354 (child
->m_x
+child
->m_width
>= x
) &&
1355 (child
->m_y
+child
->m_height
>= y
))
1358 event
.m_x
-= child
->m_x
;
1359 event
.m_y
-= child
->m_y
;
1366 event
.SetEventObject( win
);
1368 if (win
->GetEventHandler()->ProcessEvent( event
))
1370 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1377 //-----------------------------------------------------------------------------
1378 // "motion_notify_event"
1379 //-----------------------------------------------------------------------------
1381 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1386 wxapp_install_idle_handler();
1388 if (!win
->m_hasVMT
) return FALSE
;
1389 if (g_blockEventsOnDrag
) return FALSE
;
1390 if (g_blockEventsOnScroll
) return FALSE
;
1392 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1394 if (gdk_event
->is_hint
)
1398 GdkModifierType state
;
1399 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1405 printf( "OnMotion from " );
1406 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1407 printf( win->GetClassInfo()->GetClassName() );
1411 wxMouseEvent
event( wxEVT_MOTION
);
1412 event
.SetTimestamp( gdk_event
->time
);
1413 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1414 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1415 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1416 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1417 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1418 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1419 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1421 event
.m_x
= (wxCoord
)gdk_event
->x
;
1422 event
.m_y
= (wxCoord
)gdk_event
->y
;
1424 // Some control don't have their own X window and thus cannot get
1427 if (!g_captureWindow
)
1429 wxCoord x
= event
.m_x
;
1430 wxCoord y
= event
.m_y
;
1431 if (win
->m_wxwindow
)
1433 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1434 x
+= pizza
->xoffset
;
1435 y
+= pizza
->yoffset
;
1438 wxNode
*node
= win
->GetChildren().First();
1441 wxWindow
*child
= (wxWindow
*)node
->Data();
1443 node
= node
->Next();
1444 if (!child
->IsShown())
1447 if (child
->m_isStaticBox
)
1449 // wxStaticBox is transparent in the box itself
1450 int xx1
= child
->m_x
;
1451 int yy1
= child
->m_y
;
1452 int xx2
= child
->m_x
+ child
->m_width
;
1453 int yy2
= child
->m_x
+ child
->m_height
;
1456 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1458 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1460 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1462 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1465 event
.m_x
-= child
->m_x
;
1466 event
.m_y
-= child
->m_y
;
1473 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1474 (child
->m_x
<= x
) &&
1475 (child
->m_y
<= y
) &&
1476 (child
->m_x
+child
->m_width
>= x
) &&
1477 (child
->m_y
+child
->m_height
>= y
))
1480 event
.m_x
-= child
->m_x
;
1481 event
.m_y
-= child
->m_y
;
1488 event
.SetEventObject( win
);
1490 if (win
->GetEventHandler()->ProcessEvent( event
))
1492 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1499 //-----------------------------------------------------------------------------
1501 //-----------------------------------------------------------------------------
1503 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1508 wxapp_install_idle_handler();
1510 if (!win
->m_hasVMT
) return FALSE
;
1511 if (g_blockEventsOnDrag
) return FALSE
;
1513 switch ( g_sendActivateEvent
)
1516 // we've got focus from outside, synthtize wxActivateEvent
1517 g_sendActivateEvent
= 1;
1521 // another our window just lost focus, it was already ours before
1522 // - don't send any wxActivateEvent
1523 g_sendActivateEvent
= -1;
1527 g_focusWindow
= win
;
1530 printf( "OnSetFocus from " );
1531 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1532 printf( win->GetClassInfo()->GetClassName() );
1534 printf( WXSTRINGCAST win->GetLabel() );
1538 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1541 panel
->SetLastFocus(win
);
1546 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1550 // caret needs to be informed about focus change
1551 wxCaret
*caret
= win
->GetCaret();
1554 caret
->OnSetFocus();
1556 #endif // wxUSE_CARET
1558 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1559 event
.SetEventObject( win
);
1561 if (win
->GetEventHandler()->ProcessEvent( event
))
1563 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1570 //-----------------------------------------------------------------------------
1571 // "focus_out_event"
1572 //-----------------------------------------------------------------------------
1574 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1579 wxapp_install_idle_handler();
1581 if (!win
->m_hasVMT
) return FALSE
;
1582 if (g_blockEventsOnDrag
) return FALSE
;
1584 // if the focus goes out of our app alltogether, OnIdle() will send
1585 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1586 // g_sendActivateEvent to -1
1587 g_sendActivateEvent
= 0;
1589 wxWindow
*winFocus
= FindFocusedChild(win
);
1593 g_focusWindow
= (wxWindow
*)NULL
;
1596 printf( "OnKillFocus from " );
1597 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1598 printf( win->GetClassInfo()->GetClassName() );
1608 // caret needs to be informed about focus change
1609 wxCaret
*caret
= win
->GetCaret();
1612 caret
->OnKillFocus();
1614 #endif // wxUSE_CARET
1616 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1617 event
.SetEventObject( win
);
1619 if (win
->GetEventHandler()->ProcessEvent( event
))
1621 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1628 //-----------------------------------------------------------------------------
1629 // "enter_notify_event"
1630 //-----------------------------------------------------------------------------
1632 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1637 wxapp_install_idle_handler();
1639 if (!win
->m_hasVMT
) return FALSE
;
1640 if (g_blockEventsOnDrag
) return FALSE
;
1642 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1644 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1645 #if (GTK_MINOR_VERSION > 0)
1646 event
.SetTimestamp( gdk_event
->time
);
1648 event
.SetEventObject( win
);
1652 GdkModifierType state
= (GdkModifierType
)0;
1654 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1656 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1657 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1658 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1659 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1660 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1661 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1662 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1667 if (win
->GetEventHandler()->ProcessEvent( event
))
1669 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1676 //-----------------------------------------------------------------------------
1677 // "leave_notify_event"
1678 //-----------------------------------------------------------------------------
1680 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1685 wxapp_install_idle_handler();
1687 if (!win
->m_hasVMT
) return FALSE
;
1688 if (g_blockEventsOnDrag
) return FALSE
;
1690 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1692 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1693 #if (GTK_MINOR_VERSION > 0)
1694 event
.SetTimestamp( gdk_event
->time
);
1696 event
.SetEventObject( win
);
1700 GdkModifierType state
= (GdkModifierType
)0;
1702 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1704 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1705 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1706 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1707 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1708 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1709 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1710 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1715 if (win
->GetEventHandler()->ProcessEvent( event
))
1717 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1724 //-----------------------------------------------------------------------------
1725 // "value_changed" from m_vAdjust
1726 //-----------------------------------------------------------------------------
1728 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1733 wxapp_install_idle_handler();
1735 if (g_blockEventsOnDrag
) return;
1737 if (!win
->m_hasVMT
) return;
1739 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1740 if (fabs(diff
) < 0.2) return;
1742 win
->m_oldVerticalPos
= adjust
->value
;
1744 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1745 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1747 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1748 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1749 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1750 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1751 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1753 int value
= (int)(adjust
->value
+0.5);
1755 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1756 event
.SetEventObject( win
);
1757 win
->GetEventHandler()->ProcessEvent( event
);
1760 //-----------------------------------------------------------------------------
1761 // "value_changed" from m_hAdjust
1762 //-----------------------------------------------------------------------------
1764 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1769 wxapp_install_idle_handler();
1771 if (g_blockEventsOnDrag
) return;
1772 if (!win
->m_hasVMT
) return;
1774 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1775 if (fabs(diff
) < 0.2) return;
1777 win
->m_oldHorizontalPos
= adjust
->value
;
1779 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1780 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1782 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1783 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1784 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1785 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1786 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1788 int value
= (int)(adjust
->value
+0.5);
1790 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1791 event
.SetEventObject( win
);
1792 win
->GetEventHandler()->ProcessEvent( event
);
1795 //-----------------------------------------------------------------------------
1796 // "button_press_event" from scrollbar
1797 //-----------------------------------------------------------------------------
1799 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1800 GdkEventButton
*gdk_event
,
1806 wxapp_install_idle_handler();
1809 g_blockEventsOnScroll
= TRUE
;
1810 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1815 //-----------------------------------------------------------------------------
1816 // "button_release_event" from scrollbar
1817 //-----------------------------------------------------------------------------
1819 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1820 GdkEventButton
*WXUNUSED(gdk_event
),
1825 // don't test here as we can release the mouse while being over
1826 // a different window than the slider
1828 // if (gdk_event->window != widget->slider) return FALSE;
1830 g_blockEventsOnScroll
= FALSE
;
1832 if (win
->m_isScrolling
)
1834 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
1838 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1839 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1841 value
= (int)(win
->m_hAdjust
->value
+0.5);
1844 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1846 value
= (int)(win
->m_vAdjust
->value
+0.5);
1850 wxScrollWinEvent
event( command
, value
, dir
);
1851 event
.SetEventObject( win
);
1852 win
->GetEventHandler()->ProcessEvent( event
);
1855 win
->m_isScrolling
= FALSE
;
1860 // ----------------------------------------------------------------------------
1861 // this wxWindowBase function is implemented here (in platform-specific file)
1862 // because it is static and so couldn't be made virtual
1863 // ----------------------------------------------------------------------------
1865 wxWindow
*wxWindowBase::FindFocus()
1867 return g_focusWindow
;
1870 //-----------------------------------------------------------------------------
1871 // "realize" from m_widget
1872 //-----------------------------------------------------------------------------
1874 /* We cannot set colours and fonts before the widget has
1875 been realized, so we do this directly after realization. */
1878 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1883 wxapp_install_idle_handler();
1885 if (win
->m_delayedBackgroundColour
)
1886 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1888 if (win
->m_delayedForegroundColour
)
1889 win
->SetForegroundColour( win
->GetForegroundColour() );
1891 wxWindowCreateEvent
event( win
);
1892 event
.SetEventObject( win
);
1893 win
->GetEventHandler()->ProcessEvent( event
);
1898 //-----------------------------------------------------------------------------
1900 //-----------------------------------------------------------------------------
1903 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
1904 GtkAllocation
*WXUNUSED(alloc
),
1908 wxapp_install_idle_handler();
1910 if (!win
->m_hasScrolling
) return;
1912 int client_width
= 0;
1913 int client_height
= 0;
1914 win
->GetClientSize( &client_width
, &client_height
);
1915 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
1918 win
->m_oldClientWidth
= client_width
;
1919 win
->m_oldClientHeight
= client_height
;
1921 if (!win
->m_nativeSizeEvent
)
1923 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
1924 event
.SetEventObject( win
);
1925 win
->GetEventHandler()->ProcessEvent( event
);
1931 #define WXUNUSED_UNLESS_XIM(param) param
1933 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1936 /* Resize XIM window */
1939 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1940 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1941 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1944 wxapp_install_idle_handler();
1950 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1954 gdk_window_get_size (widget
->window
, &width
, &height
);
1955 win
->m_icattr
->preedit_area
.width
= width
;
1956 win
->m_icattr
->preedit_area
.height
= height
;
1957 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
1962 //-----------------------------------------------------------------------------
1963 // "realize" from m_wxwindow
1964 //-----------------------------------------------------------------------------
1966 /* Initialize XIM support */
1969 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1970 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1973 wxapp_install_idle_handler();
1976 if (win
->m_ic
) return FALSE
;
1977 if (!widget
) return FALSE
;
1978 if (!gdk_im_ready()) return FALSE
;
1980 win
->m_icattr
= gdk_ic_attr_new();
1981 if (!win
->m_icattr
) return FALSE
;
1985 GdkColormap
*colormap
;
1986 GdkICAttr
*attr
= win
->m_icattr
;
1987 unsigned attrmask
= GDK_IC_ALL_REQ
;
1989 GdkIMStyle supported_style
= (GdkIMStyle
)
1990 (GDK_IM_PREEDIT_NONE
|
1991 GDK_IM_PREEDIT_NOTHING
|
1992 GDK_IM_PREEDIT_POSITION
|
1993 GDK_IM_STATUS_NONE
|
1994 GDK_IM_STATUS_NOTHING
);
1996 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1997 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
1999 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2000 attr
->client_window
= widget
->window
;
2002 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2003 gtk_widget_get_default_colormap ())
2005 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2006 attr
->preedit_colormap
= colormap
;
2009 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2010 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2011 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2012 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2014 switch (style
& GDK_IM_PREEDIT_MASK
)
2016 case GDK_IM_PREEDIT_POSITION
:
2017 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2019 g_warning ("over-the-spot style requires fontset");
2023 gdk_window_get_size (widget
->window
, &width
, &height
);
2025 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2026 attr
->spot_location
.x
= 0;
2027 attr
->spot_location
.y
= height
;
2028 attr
->preedit_area
.x
= 0;
2029 attr
->preedit_area
.y
= 0;
2030 attr
->preedit_area
.width
= width
;
2031 attr
->preedit_area
.height
= height
;
2032 attr
->preedit_fontset
= widget
->style
->font
;
2037 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2039 if (win
->m_ic
== NULL
)
2040 g_warning ("Can't create input context.");
2043 mask
= gdk_window_get_events (widget
->window
);
2044 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2045 gdk_window_set_events (widget
->window
, mask
);
2047 if (GTK_WIDGET_HAS_FOCUS(widget
))
2048 gdk_im_begin (win
->m_ic
, widget
->window
);
2055 //-----------------------------------------------------------------------------
2056 // InsertChild for wxWindow.
2057 //-----------------------------------------------------------------------------
2059 /* Callback for wxWindow. This very strange beast has to be used because
2060 * C++ has no virtual methods in a constructor. We have to emulate a
2061 * virtual function here as wxNotebook requires a different way to insert
2062 * a child in it. I had opted for creating a wxNotebookPage window class
2063 * which would have made this superfluous (such in the MDI window system),
2064 * but no-one was listening to me... */
2066 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
2068 /* the window might have been scrolled already, do we
2069 have to adapt the position */
2070 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2071 child
->m_x
+= pizza
->xoffset
;
2072 child
->m_y
+= pizza
->yoffset
;
2074 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2075 GTK_WIDGET(child
->m_widget
),
2082 //-----------------------------------------------------------------------------
2084 //-----------------------------------------------------------------------------
2086 wxWindow
* wxGetActiveWindow()
2088 return g_focusWindow
;
2091 //-----------------------------------------------------------------------------
2093 //-----------------------------------------------------------------------------
2095 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2097 void wxWindow::Init()
2103 m_widget
= (GtkWidget
*) NULL
;
2104 m_wxwindow
= (GtkWidget
*) NULL
;
2114 m_needParent
= TRUE
;
2115 m_isBeingDeleted
= FALSE
;
2118 m_nativeSizeEvent
= FALSE
;
2120 m_hasScrolling
= FALSE
;
2121 m_isScrolling
= FALSE
;
2123 m_hAdjust
= (GtkAdjustment
*) NULL
;
2124 m_vAdjust
= (GtkAdjustment
*) NULL
;
2125 m_oldHorizontalPos
= 0.0;
2126 m_oldVerticalPos
= 0.0;
2129 m_widgetStyle
= (GtkStyle
*) NULL
;
2131 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2133 m_isStaticBox
= FALSE
;
2134 m_isRadioButton
= FALSE
;
2136 m_acceptsFocus
= FALSE
;
2138 m_clipPaintRegion
= FALSE
;
2140 m_cursor
= *wxSTANDARD_CURSOR
;
2142 m_delayedForegroundColour
= FALSE
;
2143 m_delayedBackgroundColour
= FALSE
;
2146 m_ic
= (GdkIC
*) NULL
;
2147 m_icattr
= (GdkICAttr
*) NULL
;
2151 wxWindow::wxWindow()
2156 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
2157 const wxPoint
&pos
, const wxSize
&size
,
2158 long style
, const wxString
&name
)
2162 Create( parent
, id
, pos
, size
, style
, name
);
2165 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
2166 const wxPoint
&pos
, const wxSize
&size
,
2167 long style
, const wxString
&name
)
2169 if (!PreCreation( parent
, pos
, size
) ||
2170 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2172 wxFAIL_MSG( wxT("wxWindow creation failed") );
2176 m_insertCallback
= wxInsertChildInWindow
;
2178 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2179 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2181 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2183 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2184 scroll_class
->scrollbar_spacing
= 0;
2186 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2188 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2189 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2191 m_wxwindow
= gtk_pizza_new();
2193 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2195 #if (GTK_MINOR_VERSION > 0)
2196 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2198 if (HasFlag(wxRAISED_BORDER
))
2200 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2202 else if (HasFlag(wxSUNKEN_BORDER
))
2204 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2206 else if (HasFlag(wxSIMPLE_BORDER
))
2208 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2212 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2214 #else // GTK_MINOR_VERSION == 0
2215 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2217 if (HasFlag(wxRAISED_BORDER
))
2219 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2221 else if (HasFlag(wxSUNKEN_BORDER
))
2223 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2227 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2229 #endif // GTK_MINOR_VERSION
2231 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2232 m_acceptsFocus
= TRUE
;
2234 #if (GTK_MINOR_VERSION == 0)
2235 // shut the viewport up
2236 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2237 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2238 #endif // GTK_MINOR_VERSION == 0
2240 // I _really_ don't want scrollbars in the beginning
2241 m_vAdjust
->lower
= 0.0;
2242 m_vAdjust
->upper
= 1.0;
2243 m_vAdjust
->value
= 0.0;
2244 m_vAdjust
->step_increment
= 1.0;
2245 m_vAdjust
->page_increment
= 1.0;
2246 m_vAdjust
->page_size
= 5.0;
2247 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2248 m_hAdjust
->lower
= 0.0;
2249 m_hAdjust
->upper
= 1.0;
2250 m_hAdjust
->value
= 0.0;
2251 m_hAdjust
->step_increment
= 1.0;
2252 m_hAdjust
->page_increment
= 1.0;
2253 m_hAdjust
->page_size
= 5.0;
2254 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2256 // these handlers block mouse events to any window during scrolling such as
2257 // motion events and prevent GTK and wxWindows from fighting over where the
2260 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2261 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2263 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2264 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2266 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2267 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2269 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2270 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2272 // these handlers get notified when screen updates are required either when
2273 // scrolling or when the window size (and therefore scrollbar configuration)
2276 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2277 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2278 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2279 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2281 gtk_widget_show( m_wxwindow
);
2284 m_parent
->DoAddChild( this );
2293 wxWindow::~wxWindow()
2295 m_isBeingDeleted
= TRUE
;
2304 m_parent
->RemoveChild( this );
2308 gdk_ic_destroy (m_ic
);
2310 gdk_ic_attr_destroy (m_icattr
);
2315 #if DISABLE_STYLE_IF_BROKEN_THEME
2316 // don't delete if it's a pixmap theme style
2317 if (!m_widgetStyle
->engine_data
)
2318 gtk_style_unref( m_widgetStyle
);
2320 m_widgetStyle
= (GtkStyle
*) NULL
;
2325 gtk_widget_destroy( m_wxwindow
);
2326 m_wxwindow
= (GtkWidget
*) NULL
;
2331 gtk_widget_destroy( m_widget
);
2332 m_widget
= (GtkWidget
*) NULL
;
2336 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2338 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2340 /* this turns -1 into 20 so that a minimal window is
2341 visible even although -1,-1 has been given as the
2342 size of the window. the same trick is used in other
2343 ports and should make debugging easier */
2344 m_width
= WidthDefault(size
.x
);
2345 m_height
= HeightDefault(size
.y
);
2350 /* some reasonable defaults */
2355 m_x
= (gdk_screen_width () - m_width
) / 2;
2356 if (m_x
< 10) m_x
= 10;
2360 m_y
= (gdk_screen_height () - m_height
) / 2;
2361 if (m_y
< 10) m_y
= 10;
2368 void wxWindow::PostCreation()
2370 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2376 /* these get reported to wxWindows -> wxPaintEvent */
2378 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2380 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2381 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2383 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2384 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2386 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2387 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2390 #if (GTK_MINOR_VERSION > 0)
2391 /* these are called when the "sunken" or "raised" borders are drawn */
2392 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2393 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2395 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2396 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2400 if (m_wxwindow
&& m_needParent
)
2402 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2403 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2405 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2406 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2410 // For dialogs and frames, we are interested mainly in
2411 // m_widget's focus.
2413 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2414 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2416 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2417 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2420 GtkWidget
*connect_widget
= GetConnectWidget();
2422 ConnectWidget( connect_widget
);
2424 /* We cannot set colours, fonts and cursors before the widget has
2425 been realized, so we do this directly after realization */
2426 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2427 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2431 /* Catch native resize events. */
2432 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2433 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2435 /* Initialize XIM support. */
2436 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2437 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2439 /* And resize XIM window. */
2440 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2441 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2447 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2449 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2450 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2452 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2453 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2455 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2456 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2458 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2459 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2461 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2462 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2464 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2465 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2467 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2468 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2471 bool wxWindow::Destroy()
2473 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2477 return wxWindowBase::Destroy();
2480 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2482 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2485 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2487 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2488 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2490 if (m_resizing
) return; /* I don't like recursions */
2493 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2495 /* don't set the size for children of wxNotebook, just take the values. */
2503 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2505 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2507 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2508 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2509 if (width
!= -1) m_width
= width
;
2510 if (height
!= -1) m_height
= height
;
2514 m_x
= x
+ pizza
->xoffset
;
2515 m_y
= y
+ pizza
->yoffset
;
2520 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2522 if (width
== -1) m_width
= 80;
2525 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2527 if (height
== -1) m_height
= 26;
2530 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2531 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2532 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2533 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2536 int bottom_border
= 0;
2538 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2540 /* the default button has a border around it */
2545 DoMoveWindow( m_x
-border
,
2548 m_height
+border
+bottom_border
);
2553 /* Sometimes the client area changes size without the
2554 whole windows's size changing, but if the whole
2555 windows's size doesn't change, no wxSizeEvent will
2556 normally be sent. Here we add an extra test if
2557 the client test has been changed and this will
2559 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2563 wxPrintf( "OnSize sent from " );
2564 if (GetClassInfo() && GetClassInfo()->GetClassName())
2565 wxPrintf( GetClassInfo()->GetClassName() );
2566 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2569 if (!m_nativeSizeEvent
)
2571 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2572 event
.SetEventObject( this );
2573 GetEventHandler()->ProcessEvent( event
);
2579 void wxWindow::OnInternalIdle()
2581 if ( g_sendActivateEvent
!= -1 )
2583 bool activate
= g_sendActivateEvent
!= 0;
2586 g_sendActivateEvent
= -1;
2588 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2589 event
.SetEventObject(this);
2591 (void)GetEventHandler()->ProcessEvent(event
);
2594 wxCursor cursor
= m_cursor
;
2595 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2599 /* I now set the cursor anew in every OnInternalIdle call
2600 as setting the cursor in a parent window also effects the
2601 windows above so that checking for the current cursor is
2606 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2608 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2610 if (!g_globalCursor
.Ok())
2611 cursor
= *wxSTANDARD_CURSOR
;
2613 window
= m_widget
->window
;
2614 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2615 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2621 GdkWindow
*window
= m_widget
->window
;
2622 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2623 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2631 void wxWindow::DoGetSize( int *width
, int *height
) const
2633 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2635 if (width
) (*width
) = m_width
;
2636 if (height
) (*height
) = m_height
;
2639 void wxWindow::DoSetClientSize( int width
, int height
)
2641 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2645 SetSize( width
, height
);
2652 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2654 /* when using GTK 1.2 we set the shadow border size to 2 */
2658 if (HasFlag(wxSIMPLE_BORDER
))
2660 /* when using GTK 1.2 we set the simple border size to 1 */
2667 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2669 GtkRequisition vscroll_req
;
2670 vscroll_req
.width
= 2;
2671 vscroll_req
.height
= 2;
2672 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2673 (scroll_window
->vscrollbar
, &vscroll_req
);
2675 GtkRequisition hscroll_req
;
2676 hscroll_req
.width
= 2;
2677 hscroll_req
.height
= 2;
2678 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2679 (scroll_window
->hscrollbar
, &hscroll_req
);
2681 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2683 if (scroll_window
->vscrollbar_visible
)
2685 dw
+= vscroll_req
.width
;
2686 dw
+= scroll_class
->scrollbar_spacing
;
2689 if (scroll_window
->hscrollbar_visible
)
2691 dh
+= hscroll_req
.height
;
2692 dh
+= scroll_class
->scrollbar_spacing
;
2696 SetSize( width
+dw
, height
+dh
);
2700 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2702 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2706 if (width
) (*width
) = m_width
;
2707 if (height
) (*height
) = m_height
;
2714 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2716 /* when using GTK 1.2 we set the shadow border size to 2 */
2720 if (HasFlag(wxSIMPLE_BORDER
))
2722 /* when using GTK 1.2 we set the simple border size to 1 */
2729 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2731 GtkRequisition vscroll_req
;
2732 vscroll_req
.width
= 2;
2733 vscroll_req
.height
= 2;
2734 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2735 (scroll_window
->vscrollbar
, &vscroll_req
);
2737 GtkRequisition hscroll_req
;
2738 hscroll_req
.width
= 2;
2739 hscroll_req
.height
= 2;
2740 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2741 (scroll_window
->hscrollbar
, &hscroll_req
);
2743 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2745 if (scroll_window
->vscrollbar_visible
)
2747 dw
+= vscroll_req
.width
;
2748 dw
+= scroll_class
->scrollbar_spacing
;
2751 if (scroll_window
->hscrollbar_visible
)
2753 dh
+= hscroll_req
.height
;
2754 dh
+= scroll_class
->scrollbar_spacing
;
2758 if (width
) (*width
) = m_width
- dw
;
2759 if (height
) (*height
) = m_height
- dh
;
2763 void wxWindow::DoGetPosition( int *x
, int *y
) const
2765 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2769 if (m_parent
&& m_parent
->m_wxwindow
)
2771 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2772 dx
= pizza
->xoffset
;
2773 dy
= pizza
->yoffset
;
2776 if (x
) (*x
) = m_x
- dx
;
2777 if (y
) (*y
) = m_y
- dy
;
2780 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2782 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2784 if (!m_widget
->window
) return;
2786 GdkWindow
*source
= (GdkWindow
*) NULL
;
2788 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2790 source
= m_widget
->window
;
2794 gdk_window_get_origin( source
, &org_x
, &org_y
);
2798 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2800 org_x
+= m_widget
->allocation
.x
;
2801 org_y
+= m_widget
->allocation
.y
;
2809 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2811 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2813 if (!m_widget
->window
) return;
2815 GdkWindow
*source
= (GdkWindow
*) NULL
;
2817 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2819 source
= m_widget
->window
;
2823 gdk_window_get_origin( source
, &org_x
, &org_y
);
2827 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2829 org_x
+= m_widget
->allocation
.x
;
2830 org_y
+= m_widget
->allocation
.y
;
2838 bool wxWindow::Show( bool show
)
2840 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2842 if (!wxWindowBase::Show(show
))
2849 gtk_widget_show( m_widget
);
2851 gtk_widget_hide( m_widget
);
2856 bool wxWindow::Enable( bool enable
)
2858 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2860 if (!wxWindowBase::Enable(enable
))
2866 gtk_widget_set_sensitive( m_widget
, enable
);
2868 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2873 int wxWindow::GetCharHeight() const
2875 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2877 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2879 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2881 return font
->ascent
+ font
->descent
;
2884 int wxWindow::GetCharWidth() const
2886 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2888 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2890 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2892 return gdk_string_width( font
, "H" );
2895 void wxWindow::GetTextExtent( const wxString
& string
,
2899 int *externalLeading
,
2900 const wxFont
*theFont
) const
2902 wxFont fontToUse
= m_font
;
2903 if (theFont
) fontToUse
= *theFont
;
2905 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2907 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2908 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2909 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2910 if (descent
) (*descent
) = font
->descent
;
2911 if (externalLeading
) (*externalLeading
) = 0; // ??
2914 void wxWindow::SetFocus()
2916 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2920 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2921 gtk_widget_grab_focus (m_wxwindow
);
2927 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2929 gtk_widget_grab_focus (m_widget
);
2931 else if (GTK_IS_CONTAINER(m_widget
))
2933 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2942 bool wxWindow::AcceptsFocus() const
2944 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2947 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2949 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2951 wxWindow
*oldParent
= m_parent
,
2952 *newParent
= (wxWindow
*)newParentBase
;
2954 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2956 if ( !wxWindowBase::Reparent(newParent
) )
2959 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2961 /* prevent GTK from deleting the widget arbitrarily */
2962 gtk_widget_ref( m_widget
);
2966 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2969 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2973 /* insert GTK representation */
2974 (*(newParent
->m_insertCallback
))(newParent
, this);
2977 /* reverse: prevent GTK from deleting the widget arbitrarily */
2978 gtk_widget_unref( m_widget
);
2983 void wxWindow::DoAddChild(wxWindow
*child
)
2985 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2987 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
2989 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
2994 /* insert GTK representation */
2995 (*m_insertCallback
)(this, child
);
2998 void wxWindow::Raise()
3000 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3002 if (!m_widget
->window
) return;
3004 gdk_window_raise( m_widget
->window
);
3007 void wxWindow::Lower()
3009 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3011 if (!m_widget
->window
) return;
3013 gdk_window_lower( m_widget
->window
);
3016 bool wxWindow::SetCursor( const wxCursor
&cursor
)
3018 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3020 if (cursor
== m_cursor
)
3024 wxapp_install_idle_handler();
3026 if (cursor
== wxNullCursor
)
3027 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3029 return wxWindowBase::SetCursor( cursor
);
3032 void wxWindow::WarpPointer( int x
, int y
)
3034 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3036 /* we provide this function ourselves as it is
3037 missing in GDK (top of this file) */
3039 GdkWindow
*window
= (GdkWindow
*) NULL
;
3041 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3043 window
= GetConnectWidget()->window
;
3046 gdk_window_warp_pointer( window
, x
, y
);
3049 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
3051 if (!m_widget
) return;
3052 if (!m_widget
->window
) return;
3054 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3058 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3060 rect
->width
, rect
->height
);
3064 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3068 /* there is no GTK equivalent of "draw only, don't clear" so we
3069 invent our own in the GtkPizza widget */
3077 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3078 gboolean old_clear = pizza->clear_on_draw;
3079 gtk_pizza_set_clear( pizza, FALSE );
3080 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3081 gtk_pizza_set_clear( pizza, old_clear );
3083 GdkEventExpose gdk_event
;
3084 gdk_event
.type
= GDK_EXPOSE
;
3085 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3086 gdk_event
.count
= 0;
3087 gdk_event
.area
.x
= 0;
3088 gdk_event
.area
.y
= 0;
3089 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3090 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3091 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3096 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3105 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3106 gboolean old_clear = pizza->clear_on_draw;
3107 gtk_pizza_set_clear( pizza, FALSE );
3109 GdkRectangle gdk_rect;
3110 gdk_rect.x = rect->x;
3111 gdk_rect.y = rect->y;
3112 gdk_rect.width = rect->width;
3113 gdk_rect.height = rect->height;
3114 gtk_widget_draw( m_wxwindow, &gdk_rect );
3115 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3117 gtk_pizza_set_clear( pizza, old_clear );
3119 GdkEventExpose gdk_event
;
3120 gdk_event
.type
= GDK_EXPOSE
;
3121 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3122 gdk_event
.count
= 0;
3123 gdk_event
.area
.x
= rect
->x
;
3124 gdk_event
.area
.y
= rect
->y
;
3125 gdk_event
.area
.width
= rect
->width
;
3126 gdk_event
.area
.height
= rect
->height
;
3127 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3131 GdkRectangle gdk_rect
;
3132 gdk_rect
.x
= rect
->x
;
3133 gdk_rect
.y
= rect
->y
;
3134 gdk_rect
.width
= rect
->width
;
3135 gdk_rect
.height
= rect
->height
;
3136 gtk_widget_draw( m_widget
, &gdk_rect
);
3141 void wxWindow::Clear()
3143 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3145 if (!m_widget
->window
) return;
3147 if (m_wxwindow
&& m_wxwindow
->window
)
3149 // gdk_window_clear( m_wxwindow->window );
3154 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
3156 wxWindowBase::DoSetToolTip(tip
);
3159 m_tooltip
->Apply( this );
3162 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3164 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3166 #endif // wxUSE_TOOLTIPS
3168 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
3170 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3172 if (!wxWindowBase::SetBackgroundColour(colour
))
3174 // don't leave if the GTK widget has just
3176 if (!m_delayedBackgroundColour
) return FALSE
;
3179 GdkWindow
*window
= (GdkWindow
*) NULL
;
3181 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3183 window
= GetConnectWidget()->window
;
3187 // indicate that a new style has been set
3188 // but it couldn't get applied as the
3189 // widget hasn't been realized yet.
3190 m_delayedBackgroundColour
= TRUE
;
3194 (m_wxwindow
->window
) &&
3195 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3197 /* wxMSW doesn't clear the window here. I don't do that either to
3198 provide compatibility. call Clear() to do the job. */
3200 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3201 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3209 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
3211 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3213 if (!wxWindowBase::SetForegroundColour(colour
))
3215 // don't leave if the GTK widget has just
3217 if (!m_delayedForegroundColour
) return FALSE
;
3220 GdkWindow
*window
= (GdkWindow
*) NULL
;
3222 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3224 window
= GetConnectWidget()->window
;
3228 // indicate that a new style has been set
3229 // but it couldn't get applied as the
3230 // widget hasn't been realized yet.
3231 m_delayedForegroundColour
= TRUE
;
3239 GtkStyle
*wxWindow::GetWidgetStyle()
3243 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3245 /* FIXME: is this necessary? */
3246 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3248 remake
->klass
= m_widgetStyle
->klass
;
3251 gtk_style_unref( m_widgetStyle
);
3252 m_widgetStyle
= remake
;
3256 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3259 def
= gtk_widget_get_default_style();
3261 m_widgetStyle
= gtk_style_copy( def
);
3263 /* FIXME: is this necessary? */
3264 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3266 m_widgetStyle
->klass
= def
->klass
;
3270 return m_widgetStyle
;
3273 void wxWindow::SetWidgetStyle()
3275 #if DISABLE_STYLE_IF_BROKEN_THEM
3276 if (m_widget
->style
->engine_data
)
3278 static bool s_warningPrinted
= FALSE
;
3279 if (!s_warningPrinted
)
3281 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3282 s_warningPrinted
= TRUE
;
3284 m_widgetStyle
= m_widget
->style
;
3289 GtkStyle
*style
= GetWidgetStyle();
3291 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3293 gdk_font_unref( style
->font
);
3294 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3297 if (m_foregroundColour
.Ok())
3299 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3300 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3302 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3303 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3304 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3308 // Try to restore the gtk default style. This is still a little
3309 // oversimplified for what is probably really needed here for controls
3310 // other than buttons, but is better than not being able to (re)set a
3311 // control's foreground colour to *wxBLACK -- RL
3312 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3315 def
= gtk_widget_get_default_style();
3317 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3318 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3319 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3323 if (m_backgroundColour
.Ok())
3325 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3326 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3328 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3329 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3330 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3331 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3332 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3333 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3334 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3335 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3339 // Try to restore the gtk default style. This is still a little
3340 // oversimplified for what is probably really needed here for controls
3341 // other than buttons, but is better than not being able to (re)set a
3342 // control's background colour to default grey and means resetting a
3343 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3345 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3348 def
= gtk_widget_get_default_style();
3350 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3351 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3352 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3353 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3354 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3355 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3356 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3357 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3362 void wxWindow::ApplyWidgetStyle()
3366 //-----------------------------------------------------------------------------
3367 // Pop-up menu stuff
3368 //-----------------------------------------------------------------------------
3370 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3372 *is_waiting
= FALSE
;
3375 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3377 menu
->SetInvokingWindow( win
);
3378 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3381 wxMenuItem
*menuitem
= node
->GetData();
3382 if (menuitem
->IsSubMenu())
3384 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3387 node
= node
->GetNext();
3391 static gint gs_pop_x
= 0;
3392 static gint gs_pop_y
= 0;
3394 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3398 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3403 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3405 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3407 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3409 SetInvokingWindow( menu
, this );
3416 bool is_waiting
= TRUE
;
3418 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3419 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3422 GTK_MENU(menu
->m_menu
),
3423 (GtkWidget
*) NULL
, // parent menu shell
3424 (GtkWidget
*) NULL
, // parent menu item
3425 (GtkMenuPositionFunc
) pop_pos_callback
,
3426 (gpointer
) this, // client data
3427 0, // button used to activate it
3428 gs_timeLastClick
// the time of activation
3433 while (gtk_events_pending())
3434 gtk_main_iteration();
3440 #if wxUSE_DRAG_AND_DROP
3442 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3444 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3446 GtkWidget
*dnd_widget
= GetConnectWidget();
3448 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3450 if (m_dropTarget
) delete m_dropTarget
;
3451 m_dropTarget
= dropTarget
;
3453 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3456 #endif // wxUSE_DRAG_AND_DROP
3458 GtkWidget
* wxWindow::GetConnectWidget()
3460 GtkWidget
*connect_widget
= m_widget
;
3461 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3463 return connect_widget
;
3466 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3469 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3471 return (window
== m_widget
->window
);
3474 bool wxWindow::SetFont( const wxFont
&font
)
3476 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3478 if (!wxWindowBase::SetFont(font
))
3483 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3484 if ( sysbg
== m_backgroundColour
)
3486 m_backgroundColour
= wxNullColour
;
3488 m_backgroundColour
= sysbg
;
3498 void wxWindow::CaptureMouse()
3500 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3502 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3504 GdkWindow
*window
= (GdkWindow
*) NULL
;
3506 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3508 window
= GetConnectWidget()->window
;
3510 if (!window
) return;
3512 wxCursor
* cursor
= & m_cursor
;
3514 cursor
= wxSTANDARD_CURSOR
;
3516 gdk_pointer_grab( window
, FALSE
,
3518 (GDK_BUTTON_PRESS_MASK
|
3519 GDK_BUTTON_RELEASE_MASK
|
3520 GDK_POINTER_MOTION_HINT_MASK
|
3521 GDK_POINTER_MOTION_MASK
),
3523 cursor
->GetCursor(),
3524 (guint32
)GDK_CURRENT_TIME
);
3525 g_captureWindow
= this;
3528 void wxWindow::ReleaseMouse()
3530 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3532 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3534 GdkWindow
*window
= (GdkWindow
*) NULL
;
3536 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3538 window
= GetConnectWidget()->window
;
3543 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3544 g_captureWindow
= (wxWindow
*) NULL
;
3547 bool wxWindow::IsRetained() const
3552 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3553 int range
, bool refresh
)
3555 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3557 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3559 m_hasScrolling
= TRUE
;
3561 if (orient
== wxHORIZONTAL
)
3563 float fpos
= (float)pos
;
3564 float frange
= (float)range
;
3565 float fthumb
= (float)thumbVisible
;
3566 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3567 if (fpos
< 0.0) fpos
= 0.0;
3569 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3570 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3572 SetScrollPos( orient
, pos
, refresh
);
3576 m_oldHorizontalPos
= fpos
;
3578 m_hAdjust
->lower
= 0.0;
3579 m_hAdjust
->upper
= frange
;
3580 m_hAdjust
->value
= fpos
;
3581 m_hAdjust
->step_increment
= 1.0;
3582 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3583 m_hAdjust
->page_size
= fthumb
;
3587 float fpos
= (float)pos
;
3588 float frange
= (float)range
;
3589 float fthumb
= (float)thumbVisible
;
3590 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3591 if (fpos
< 0.0) fpos
= 0.0;
3593 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3594 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3596 SetScrollPos( orient
, pos
, refresh
);
3600 m_oldVerticalPos
= fpos
;
3602 m_vAdjust
->lower
= 0.0;
3603 m_vAdjust
->upper
= frange
;
3604 m_vAdjust
->value
= fpos
;
3605 m_vAdjust
->step_increment
= 1.0;
3606 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3607 m_vAdjust
->page_size
= fthumb
;
3610 if (orient
== wxHORIZONTAL
)
3611 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3613 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3616 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3618 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3620 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3622 if (orient
== wxHORIZONTAL
)
3624 float fpos
= (float)pos
;
3625 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3626 if (fpos
< 0.0) fpos
= 0.0;
3627 m_oldHorizontalPos
= fpos
;
3629 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3630 m_hAdjust
->value
= fpos
;
3634 float fpos
= (float)pos
;
3635 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3636 if (fpos
< 0.0) fpos
= 0.0;
3637 m_oldVerticalPos
= fpos
;
3639 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3640 m_vAdjust
->value
= fpos
;
3643 if (m_wxwindow
->window
)
3645 if (orient
== wxHORIZONTAL
)
3647 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3648 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3650 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3652 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3653 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3657 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3658 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3660 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3662 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3663 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3668 int wxWindow::GetScrollThumb( int orient
) const
3670 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3672 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3674 if (orient
== wxHORIZONTAL
)
3675 return (int)(m_hAdjust
->page_size
+0.5);
3677 return (int)(m_vAdjust
->page_size
+0.5);
3680 int wxWindow::GetScrollPos( int orient
) const
3682 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3684 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3686 if (orient
== wxHORIZONTAL
)
3687 return (int)(m_hAdjust
->value
+0.5);
3689 return (int)(m_vAdjust
->value
+0.5);
3692 int wxWindow::GetScrollRange( int orient
) const
3694 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3696 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3698 if (orient
== wxHORIZONTAL
)
3699 return (int)(m_hAdjust
->upper
+0.5);
3701 return (int)(m_vAdjust
->upper
+0.5);
3704 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3706 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3708 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3710 if ((dx
== 0) && (dy
== 0)) return;
3712 m_clipPaintRegion
= TRUE
;
3713 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3714 m_clipPaintRegion
= FALSE
;
3717 if (m_children.GetCount() > 0)
3719 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3723 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3725 pizza->xoffset -= dx;
3726 pizza->yoffset -= dy;
3728 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3729 gdk_gc_set_exposures( m_scrollGC, TRUE );
3733 GetClientSize( &cw, &ch );
3734 int w = cw - abs(dx);
3735 int h = ch - abs(dy);
3737 if ((h < 0) || (w < 0))
3745 if (dx < 0) s_x = -dx;
3746 if (dy < 0) s_y = -dy;
3749 if (dx > 0) d_x = dx;
3750 if (dy > 0) d_y = dy;
3752 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3753 pizza->bin_window, s_x, s_y, w, h );
3756 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3757 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3758 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3759 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3761 Refresh( TRUE, &rect );
3764 gdk_gc_unref( m_scrollGC );
3769 // Find the wxWindow at the current mouse position, also returning the mouse
3771 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
3773 pt
= wxGetMousePosition();
3774 wxWindow
* found
= wxFindWindowAtPoint(pt
);
3778 // Get the current mouse position.
3779 wxPoint
wxGetMousePosition()
3781 /* This crashes when used within wxHelpContext,
3782 so we have to use the X-specific implementation below.
3784 GdkModifierType *mask;
3785 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
3787 return wxPoint(x, y);
3791 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
3793 return wxPoint(-999, -999);
3795 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
3796 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
3797 Window rootReturn
, childReturn
;
3798 int rootX
, rootY
, winX
, winY
;
3799 unsigned int maskReturn
;
3801 XQueryPointer (display
,
3805 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
3806 return wxPoint(rootX
, rootY
);