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
->GetThemeEnabled())
686 wxWindow
*parent
= win
->GetParent();
687 while (parent
&& !parent
->IsTopLevel())
688 parent
= parent
->GetParent();
692 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
693 GTK_SHADOW_NONE
, &gdk_event
->area
, parent
->m_widget
, "base", 0, 0, -1, -1);
696 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
698 gdk_event
->area
.width
,
699 gdk_event
->area
.height
);
701 if (gdk_event
->count
== 0)
703 wxEraseEvent
eevent( win
->GetId() );
704 eevent
.SetEventObject( win
);
705 win
->GetEventHandler()->ProcessEvent(eevent
);
707 wxPaintEvent
event( win
->GetId() );
708 event
.SetEventObject( win
);
709 win
->GetEventHandler()->ProcessEvent( event
);
711 win
->GetUpdateRegion().Clear();
714 /* The following code will result in all window-less widgets
715 being redrawn if the wxWindows class is given a chance to
716 paint *anything* because it will then be allowed to paint
717 over the window-less widgets */
719 GList
*children
= pizza
->children
;
722 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
723 children
= children
->next
;
725 GdkEventExpose child_event
= *gdk_event
;
727 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
728 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
729 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
731 child_event
.area
.x
= child
->widget
->allocation
.x
;
732 child_event
.area
.y
= child
->widget
->allocation
.y
;
733 child_event
.area
.width
= child
->widget
->allocation
.width
;
734 child_event
.area
.height
= child
->widget
->allocation
.height
;
735 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
742 //-----------------------------------------------------------------------------
743 // "event" of m_wxwindow
744 //-----------------------------------------------------------------------------
746 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
747 expose events. We need them, of course, so we override the main event
748 procedure in GtkWidget by giving our own handler for all system events.
749 There, we look for expose events ourselves whereas all other events are
752 gint
gtk_window_event_event_callback( GtkWidget
*widget
, GdkEventExpose
*event
, wxWindow
*win
)
754 if (event
->type
== GDK_EXPOSE
)
756 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
763 //-----------------------------------------------------------------------------
764 // "draw" of m_wxwindow
765 //-----------------------------------------------------------------------------
767 /* This callback is a complete replacement of the gtk_pizza_draw() function,
770 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
775 wxapp_install_idle_handler();
778 if (win->GetName() == wxT("panel"))
780 wxPrintf( wxT("OnDraw from ") );
781 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
782 wxPrintf( win->GetClassInfo()->GetClassName() );
783 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
790 GtkPizza
*pizza
= GTK_PIZZA (widget
);
792 if (win
->GetThemeEnabled())
794 wxWindow
*parent
= win
->GetParent();
795 while (parent
&& !parent
->IsTopLevel())
796 parent
= parent
->GetParent();
800 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
801 GTK_SHADOW_NONE
, rect
, parent
->m_widget
, "base", 0, 0, -1, -1);
805 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
806 (pizza
->clear_on_draw
))
808 gdk_window_clear_area( pizza
->bin_window
,
809 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
812 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
814 win
->m_clipPaintRegion
= TRUE
;
816 wxEraseEvent
eevent( win
->GetId() );
817 eevent
.SetEventObject( win
);
818 win
->GetEventHandler()->ProcessEvent(eevent
);
820 wxPaintEvent
event( win
->GetId() );
821 event
.SetEventObject( win
);
822 win
->GetEventHandler()->ProcessEvent( event
);
824 win
->GetUpdateRegion().Clear();
826 win
->m_clipPaintRegion
= FALSE
;
829 GList
*children
= pizza
->children
;
832 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
833 children
= children
->next
;
835 GdkRectangle child_area
;
836 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
838 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
843 //-----------------------------------------------------------------------------
844 // "key_press_event" from any window
845 //-----------------------------------------------------------------------------
847 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
852 wxapp_install_idle_handler();
854 if (!win
->m_hasVMT
) return FALSE
;
855 if (g_blockEventsOnDrag
) return FALSE
;
860 tmp += (char)gdk_event->keyval;
861 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
862 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
867 GdkModifierType state
;
868 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
872 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
873 /* sending unknown key events doesn't really make sense */
874 if (key_code
== 0) return FALSE
;
876 wxKeyEvent
event( wxEVT_KEY_DOWN
);
877 event
.SetTimestamp( gdk_event
->time
);
878 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
879 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
880 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
881 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
882 event
.m_keyCode
= key_code
;
883 event
.m_scanCode
= gdk_event
->keyval
;
886 event
.SetEventObject( win
);
887 ret
= win
->GetEventHandler()->ProcessEvent( event
);
892 wxWindow
*ancestor
= win
;
895 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
898 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
899 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
902 if (ancestor
->IsTopLevel())
904 ancestor
= ancestor
->GetParent();
907 #endif // wxUSE_ACCEL
909 /* wxMSW doesn't send char events with Alt pressed */
910 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
911 will only be sent if it is not in an accelerator table. */
912 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
917 wxKeyEvent
event2( wxEVT_CHAR
);
918 event2
.SetTimestamp( gdk_event
->time
);
919 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
920 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
921 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
922 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
923 event2
.m_keyCode
= key_code
;
924 event2
.m_scanCode
= gdk_event
->keyval
;
927 event2
.SetEventObject( win
);
928 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
931 /* win is a control: tab can be propagated up */
933 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
934 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
935 // have this style, yet choose not to process this particular TAB in which
936 // case TAB must still work as a navigational character
938 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
940 (win
->GetParent()) &&
941 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
943 wxNavigationKeyEvent new_event
;
944 new_event
.SetEventObject( win
->GetParent() );
945 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
946 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
947 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
948 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
949 new_event
.SetCurrentFocus( win
);
950 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
953 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
955 (gdk_event
->keyval
== GDK_Escape
) )
957 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
958 new_event
.SetEventObject( win
);
959 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
962 #if (GTK_MINOR_VERSION > 0)
963 /* Pressing F10 will activate the menu bar of the top frame. */
967 (gdk_event->keyval == GDK_F10) )
969 wxWindow *ancestor = win;
972 if (wxIsKindOf(ancestor,wxFrame))
974 wxFrame *frame = (wxFrame*) ancestor;
975 wxMenuBar *menubar = frame->GetMenuBar();
978 wxNode *node = menubar->GetMenus().First();
981 wxMenu *firstMenu = (wxMenu*) node->Data();
982 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
988 ancestor = ancestor->GetParent();
996 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1003 //-----------------------------------------------------------------------------
1004 // "key_release_event" from any window
1005 //-----------------------------------------------------------------------------
1007 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
1012 wxapp_install_idle_handler();
1014 if (!win
->m_hasVMT
) return FALSE
;
1015 if (g_blockEventsOnDrag
) return FALSE
;
1018 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
1019 if (gdk_event->state & GDK_SHIFT_MASK)
1020 printf( "ShiftDown.\n" );
1022 printf( "ShiftUp.\n" );
1023 if (gdk_event->state & GDK_CONTROL_MASK)
1024 printf( "ControlDown.\n" );
1026 printf( "ControlUp.\n" );
1030 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
1032 /* sending unknown key events doesn't really make sense */
1033 if (key_code
== 0) return FALSE
;
1037 GdkModifierType state
;
1038 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1040 wxKeyEvent
event( wxEVT_KEY_UP
);
1041 event
.SetTimestamp( gdk_event
->time
);
1042 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1043 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1044 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1045 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1046 event
.m_keyCode
= key_code
;
1047 event
.m_scanCode
= gdk_event
->keyval
;
1050 event
.SetEventObject( win
);
1052 if (win
->GetEventHandler()->ProcessEvent( event
))
1054 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1061 // ----------------------------------------------------------------------------
1062 // mouse event processing helper
1063 // ----------------------------------------------------------------------------
1065 static void AdjustEventButtonState(wxMouseEvent
& event
)
1067 // GDK reports the old state of the button for a button press event, but
1068 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1069 // for a LEFT_DOWN event, not FALSE, so we will invert
1070 // left/right/middleDown for the corresponding click events
1071 switch ( event
.GetEventType() )
1073 case wxEVT_LEFT_DOWN
:
1074 case wxEVT_LEFT_DCLICK
:
1076 event
.m_leftDown
= !event
.m_leftDown
;
1079 case wxEVT_MIDDLE_DOWN
:
1080 case wxEVT_MIDDLE_DCLICK
:
1081 case wxEVT_MIDDLE_UP
:
1082 event
.m_middleDown
= !event
.m_middleDown
;
1085 case wxEVT_RIGHT_DOWN
:
1086 case wxEVT_RIGHT_DCLICK
:
1087 case wxEVT_RIGHT_UP
:
1088 event
.m_rightDown
= !event
.m_rightDown
;
1093 //-----------------------------------------------------------------------------
1094 // "button_press_event"
1095 //-----------------------------------------------------------------------------
1097 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1102 wxapp_install_idle_handler();
1105 wxPrintf( wxT("1) OnButtonPress from ") );
1106 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1107 wxPrintf( win->GetClassInfo()->GetClassName() );
1108 wxPrintf( wxT(".\n") );
1110 if (!win
->m_hasVMT
) return FALSE
;
1111 if (g_blockEventsOnDrag
) return TRUE
;
1112 if (g_blockEventsOnScroll
) return TRUE
;
1114 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1116 if (win
->m_wxwindow
)
1118 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1120 gtk_widget_grab_focus (win
->m_wxwindow
);
1123 wxPrintf( wxT("GrabFocus from ") );
1124 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1125 wxPrintf( win->GetClassInfo()->GetClassName() );
1126 wxPrintf( wxT(".\n") );
1132 wxEventType event_type
= wxEVT_NULL
;
1134 if (gdk_event
->button
== 1)
1136 switch (gdk_event
->type
)
1138 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1139 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1143 else if (gdk_event
->button
== 2)
1145 switch (gdk_event
->type
)
1147 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1148 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1152 else if (gdk_event
->button
== 3)
1154 switch (gdk_event
->type
)
1156 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1157 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1162 if ( event_type
== wxEVT_NULL
)
1164 // unknown mouse button or click type
1168 wxMouseEvent
event( event_type
);
1169 event
.SetTimestamp( gdk_event
->time
);
1170 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1171 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1172 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1173 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1174 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1175 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1176 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1178 event
.m_x
= (wxCoord
)gdk_event
->x
;
1179 event
.m_y
= (wxCoord
)gdk_event
->y
;
1181 AdjustEventButtonState(event
);
1183 // Some control don't have their own X window and thus cannot get
1186 if (!g_captureWindow
)
1188 wxCoord x
= event
.m_x
;
1189 wxCoord y
= event
.m_y
;
1190 if (win
->m_wxwindow
)
1192 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1193 x
+= pizza
->xoffset
;
1194 y
+= pizza
->yoffset
;
1197 wxNode
*node
= win
->GetChildren().First();
1200 wxWindow
*child
= (wxWindow
*)node
->Data();
1202 node
= node
->Next();
1203 if (!child
->IsShown())
1206 if (child
->m_isStaticBox
)
1208 // wxStaticBox is transparent in the box itself
1209 int xx1
= child
->m_x
;
1210 int yy1
= child
->m_y
;
1211 int xx2
= child
->m_x
+ child
->m_width
;
1212 int yy2
= child
->m_x
+ child
->m_height
;
1215 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1217 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1219 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1221 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1224 event
.m_x
-= child
->m_x
;
1225 event
.m_y
-= child
->m_y
;
1232 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1233 (child
->m_x
<= x
) &&
1234 (child
->m_y
<= y
) &&
1235 (child
->m_x
+child
->m_width
>= x
) &&
1236 (child
->m_y
+child
->m_height
>= y
))
1239 event
.m_x
-= child
->m_x
;
1240 event
.m_y
-= child
->m_y
;
1247 event
.SetEventObject( win
);
1249 gs_timeLastClick
= gdk_event
->time
;
1252 wxPrintf( wxT("2) OnButtonPress from ") );
1253 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1254 wxPrintf( win->GetClassInfo()->GetClassName() );
1255 wxPrintf( wxT(".\n") );
1258 if (win
->GetEventHandler()->ProcessEvent( event
))
1260 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1267 //-----------------------------------------------------------------------------
1268 // "button_release_event"
1269 //-----------------------------------------------------------------------------
1271 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1276 wxapp_install_idle_handler();
1278 if (!win
->m_hasVMT
) return FALSE
;
1279 if (g_blockEventsOnDrag
) return FALSE
;
1280 if (g_blockEventsOnScroll
) return FALSE
;
1282 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1285 printf( "OnButtonRelease from " );
1286 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1287 printf( win->GetClassInfo()->GetClassName() );
1291 wxEventType event_type
= wxEVT_NULL
;
1293 switch (gdk_event
->button
)
1295 case 1: event_type
= wxEVT_LEFT_UP
; break;
1296 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1297 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1298 default: return FALSE
;
1301 wxMouseEvent
event( event_type
);
1302 event
.SetTimestamp( gdk_event
->time
);
1303 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1304 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1305 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1306 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1307 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1308 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1309 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1310 event
.m_x
= (wxCoord
)gdk_event
->x
;
1311 event
.m_y
= (wxCoord
)gdk_event
->y
;
1313 AdjustEventButtonState(event
);
1315 // Some control don't have their own X window and thus cannot get
1318 if (!g_captureWindow
)
1320 wxCoord x
= event
.m_x
;
1321 wxCoord y
= event
.m_y
;
1322 if (win
->m_wxwindow
)
1324 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1325 x
+= pizza
->xoffset
;
1326 y
+= pizza
->yoffset
;
1329 wxNode
*node
= win
->GetChildren().First();
1332 wxWindow
*child
= (wxWindow
*)node
->Data();
1334 node
= node
->Next();
1335 if (!child
->IsShown())
1338 if (child
->m_isStaticBox
)
1340 // wxStaticBox is transparent in the box itself
1341 int xx1
= child
->m_x
;
1342 int yy1
= child
->m_y
;
1343 int xx2
= child
->m_x
+ child
->m_width
;
1344 int yy2
= child
->m_x
+ child
->m_height
;
1347 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1349 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1351 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1353 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1356 event
.m_x
-= child
->m_x
;
1357 event
.m_y
-= child
->m_y
;
1364 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1365 (child
->m_x
<= x
) &&
1366 (child
->m_y
<= y
) &&
1367 (child
->m_x
+child
->m_width
>= x
) &&
1368 (child
->m_y
+child
->m_height
>= y
))
1371 event
.m_x
-= child
->m_x
;
1372 event
.m_y
-= child
->m_y
;
1379 event
.SetEventObject( win
);
1381 if (win
->GetEventHandler()->ProcessEvent( event
))
1383 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1390 //-----------------------------------------------------------------------------
1391 // "motion_notify_event"
1392 //-----------------------------------------------------------------------------
1394 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1399 wxapp_install_idle_handler();
1401 if (!win
->m_hasVMT
) return FALSE
;
1402 if (g_blockEventsOnDrag
) return FALSE
;
1403 if (g_blockEventsOnScroll
) return FALSE
;
1405 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1407 if (gdk_event
->is_hint
)
1411 GdkModifierType state
;
1412 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1418 printf( "OnMotion from " );
1419 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1420 printf( win->GetClassInfo()->GetClassName() );
1424 wxMouseEvent
event( wxEVT_MOTION
);
1425 event
.SetTimestamp( gdk_event
->time
);
1426 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1427 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1428 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1429 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1430 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1431 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1432 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1434 event
.m_x
= (wxCoord
)gdk_event
->x
;
1435 event
.m_y
= (wxCoord
)gdk_event
->y
;
1437 // Some control don't have their own X window and thus cannot get
1440 if (!g_captureWindow
)
1442 wxCoord x
= event
.m_x
;
1443 wxCoord y
= event
.m_y
;
1444 if (win
->m_wxwindow
)
1446 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1447 x
+= pizza
->xoffset
;
1448 y
+= pizza
->yoffset
;
1451 wxNode
*node
= win
->GetChildren().First();
1454 wxWindow
*child
= (wxWindow
*)node
->Data();
1456 node
= node
->Next();
1457 if (!child
->IsShown())
1460 if (child
->m_isStaticBox
)
1462 // wxStaticBox is transparent in the box itself
1463 int xx1
= child
->m_x
;
1464 int yy1
= child
->m_y
;
1465 int xx2
= child
->m_x
+ child
->m_width
;
1466 int yy2
= child
->m_x
+ child
->m_height
;
1469 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1471 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1473 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1475 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1478 event
.m_x
-= child
->m_x
;
1479 event
.m_y
-= child
->m_y
;
1486 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1487 (child
->m_x
<= x
) &&
1488 (child
->m_y
<= y
) &&
1489 (child
->m_x
+child
->m_width
>= x
) &&
1490 (child
->m_y
+child
->m_height
>= y
))
1493 event
.m_x
-= child
->m_x
;
1494 event
.m_y
-= child
->m_y
;
1501 event
.SetEventObject( win
);
1503 if (win
->GetEventHandler()->ProcessEvent( event
))
1505 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1512 //-----------------------------------------------------------------------------
1514 //-----------------------------------------------------------------------------
1516 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1521 wxapp_install_idle_handler();
1523 if (!win
->m_hasVMT
) return FALSE
;
1524 if (g_blockEventsOnDrag
) return FALSE
;
1526 switch ( g_sendActivateEvent
)
1529 // we've got focus from outside, synthtize wxActivateEvent
1530 g_sendActivateEvent
= 1;
1534 // another our window just lost focus, it was already ours before
1535 // - don't send any wxActivateEvent
1536 g_sendActivateEvent
= -1;
1540 g_focusWindow
= win
;
1543 printf( "OnSetFocus from " );
1544 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1545 printf( win->GetClassInfo()->GetClassName() );
1547 printf( WXSTRINGCAST win->GetLabel() );
1551 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1554 panel
->SetLastFocus(win
);
1559 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1563 // caret needs to be informed about focus change
1564 wxCaret
*caret
= win
->GetCaret();
1567 caret
->OnSetFocus();
1569 #endif // wxUSE_CARET
1571 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1572 event
.SetEventObject( win
);
1574 if (win
->GetEventHandler()->ProcessEvent( event
))
1576 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1583 //-----------------------------------------------------------------------------
1584 // "focus_out_event"
1585 //-----------------------------------------------------------------------------
1587 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1592 wxapp_install_idle_handler();
1594 if (!win
->m_hasVMT
) return FALSE
;
1595 if (g_blockEventsOnDrag
) return FALSE
;
1597 // if the focus goes out of our app alltogether, OnIdle() will send
1598 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1599 // g_sendActivateEvent to -1
1600 g_sendActivateEvent
= 0;
1602 wxWindow
*winFocus
= FindFocusedChild(win
);
1606 g_focusWindow
= (wxWindow
*)NULL
;
1609 printf( "OnKillFocus from " );
1610 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1611 printf( win->GetClassInfo()->GetClassName() );
1621 // caret needs to be informed about focus change
1622 wxCaret
*caret
= win
->GetCaret();
1625 caret
->OnKillFocus();
1627 #endif // wxUSE_CARET
1629 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1630 event
.SetEventObject( win
);
1632 if (win
->GetEventHandler()->ProcessEvent( event
))
1634 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1641 //-----------------------------------------------------------------------------
1642 // "enter_notify_event"
1643 //-----------------------------------------------------------------------------
1645 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1650 wxapp_install_idle_handler();
1652 if (!win
->m_hasVMT
) return FALSE
;
1653 if (g_blockEventsOnDrag
) return FALSE
;
1655 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1657 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1658 #if (GTK_MINOR_VERSION > 0)
1659 event
.SetTimestamp( gdk_event
->time
);
1661 event
.SetEventObject( win
);
1665 GdkModifierType state
= (GdkModifierType
)0;
1667 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1669 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1670 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1671 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1672 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1673 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1674 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1675 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1680 if (win
->GetEventHandler()->ProcessEvent( event
))
1682 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1689 //-----------------------------------------------------------------------------
1690 // "leave_notify_event"
1691 //-----------------------------------------------------------------------------
1693 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1698 wxapp_install_idle_handler();
1700 if (!win
->m_hasVMT
) return FALSE
;
1701 if (g_blockEventsOnDrag
) return FALSE
;
1703 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1705 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1706 #if (GTK_MINOR_VERSION > 0)
1707 event
.SetTimestamp( gdk_event
->time
);
1709 event
.SetEventObject( win
);
1713 GdkModifierType state
= (GdkModifierType
)0;
1715 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1717 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1718 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1719 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1720 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1721 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1722 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1723 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1728 if (win
->GetEventHandler()->ProcessEvent( event
))
1730 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1737 //-----------------------------------------------------------------------------
1738 // "value_changed" from m_vAdjust
1739 //-----------------------------------------------------------------------------
1741 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1746 wxapp_install_idle_handler();
1748 if (g_blockEventsOnDrag
) return;
1750 if (!win
->m_hasVMT
) return;
1752 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1753 if (fabs(diff
) < 0.2) return;
1755 win
->m_oldVerticalPos
= adjust
->value
;
1757 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1758 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1760 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1761 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1762 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1763 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1764 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1766 int value
= (int)(adjust
->value
+0.5);
1768 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1769 event
.SetEventObject( win
);
1770 win
->GetEventHandler()->ProcessEvent( event
);
1773 //-----------------------------------------------------------------------------
1774 // "value_changed" from m_hAdjust
1775 //-----------------------------------------------------------------------------
1777 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1782 wxapp_install_idle_handler();
1784 if (g_blockEventsOnDrag
) return;
1785 if (!win
->m_hasVMT
) return;
1787 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1788 if (fabs(diff
) < 0.2) return;
1790 win
->m_oldHorizontalPos
= adjust
->value
;
1792 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1793 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1795 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1796 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1797 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1798 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1799 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1801 int value
= (int)(adjust
->value
+0.5);
1803 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1804 event
.SetEventObject( win
);
1805 win
->GetEventHandler()->ProcessEvent( event
);
1808 //-----------------------------------------------------------------------------
1809 // "button_press_event" from scrollbar
1810 //-----------------------------------------------------------------------------
1812 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1813 GdkEventButton
*gdk_event
,
1819 wxapp_install_idle_handler();
1822 g_blockEventsOnScroll
= TRUE
;
1823 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1828 //-----------------------------------------------------------------------------
1829 // "button_release_event" from scrollbar
1830 //-----------------------------------------------------------------------------
1832 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1833 GdkEventButton
*WXUNUSED(gdk_event
),
1838 // don't test here as we can release the mouse while being over
1839 // a different window than the slider
1841 // if (gdk_event->window != widget->slider) return FALSE;
1843 g_blockEventsOnScroll
= FALSE
;
1845 if (win
->m_isScrolling
)
1847 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
1851 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1852 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1854 value
= (int)(win
->m_hAdjust
->value
+0.5);
1857 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1859 value
= (int)(win
->m_vAdjust
->value
+0.5);
1863 wxScrollWinEvent
event( command
, value
, dir
);
1864 event
.SetEventObject( win
);
1865 win
->GetEventHandler()->ProcessEvent( event
);
1868 win
->m_isScrolling
= FALSE
;
1873 // ----------------------------------------------------------------------------
1874 // this wxWindowBase function is implemented here (in platform-specific file)
1875 // because it is static and so couldn't be made virtual
1876 // ----------------------------------------------------------------------------
1878 wxWindow
*wxWindowBase::FindFocus()
1880 return g_focusWindow
;
1883 //-----------------------------------------------------------------------------
1884 // "realize" from m_widget
1885 //-----------------------------------------------------------------------------
1887 /* We cannot set colours and fonts before the widget has
1888 been realized, so we do this directly after realization. */
1891 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1896 wxapp_install_idle_handler();
1898 if (win
->m_delayedBackgroundColour
)
1899 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1901 if (win
->m_delayedForegroundColour
)
1902 win
->SetForegroundColour( win
->GetForegroundColour() );
1904 wxWindowCreateEvent
event( win
);
1905 event
.SetEventObject( win
);
1906 win
->GetEventHandler()->ProcessEvent( event
);
1911 //-----------------------------------------------------------------------------
1913 //-----------------------------------------------------------------------------
1916 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
1917 GtkAllocation
*WXUNUSED(alloc
),
1921 wxapp_install_idle_handler();
1923 if (!win
->m_hasScrolling
) return;
1925 int client_width
= 0;
1926 int client_height
= 0;
1927 win
->GetClientSize( &client_width
, &client_height
);
1928 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
1931 win
->m_oldClientWidth
= client_width
;
1932 win
->m_oldClientHeight
= client_height
;
1934 if (!win
->m_nativeSizeEvent
)
1936 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
1937 event
.SetEventObject( win
);
1938 win
->GetEventHandler()->ProcessEvent( event
);
1944 #define WXUNUSED_UNLESS_XIM(param) param
1946 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1949 /* Resize XIM window */
1952 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1953 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1954 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1957 wxapp_install_idle_handler();
1963 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1967 gdk_window_get_size (widget
->window
, &width
, &height
);
1968 win
->m_icattr
->preedit_area
.width
= width
;
1969 win
->m_icattr
->preedit_area
.height
= height
;
1970 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
1975 //-----------------------------------------------------------------------------
1976 // "realize" from m_wxwindow
1977 //-----------------------------------------------------------------------------
1979 /* Initialize XIM support */
1982 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1983 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1986 wxapp_install_idle_handler();
1989 if (win
->m_ic
) return FALSE
;
1990 if (!widget
) return FALSE
;
1991 if (!gdk_im_ready()) return FALSE
;
1993 win
->m_icattr
= gdk_ic_attr_new();
1994 if (!win
->m_icattr
) return FALSE
;
1998 GdkColormap
*colormap
;
1999 GdkICAttr
*attr
= win
->m_icattr
;
2000 unsigned attrmask
= GDK_IC_ALL_REQ
;
2002 GdkIMStyle supported_style
= (GdkIMStyle
)
2003 (GDK_IM_PREEDIT_NONE
|
2004 GDK_IM_PREEDIT_NOTHING
|
2005 GDK_IM_PREEDIT_POSITION
|
2006 GDK_IM_STATUS_NONE
|
2007 GDK_IM_STATUS_NOTHING
);
2009 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2010 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2012 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2013 attr
->client_window
= widget
->window
;
2015 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2016 gtk_widget_get_default_colormap ())
2018 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2019 attr
->preedit_colormap
= colormap
;
2022 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2023 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2024 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2025 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2027 switch (style
& GDK_IM_PREEDIT_MASK
)
2029 case GDK_IM_PREEDIT_POSITION
:
2030 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2032 g_warning ("over-the-spot style requires fontset");
2036 gdk_window_get_size (widget
->window
, &width
, &height
);
2038 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2039 attr
->spot_location
.x
= 0;
2040 attr
->spot_location
.y
= height
;
2041 attr
->preedit_area
.x
= 0;
2042 attr
->preedit_area
.y
= 0;
2043 attr
->preedit_area
.width
= width
;
2044 attr
->preedit_area
.height
= height
;
2045 attr
->preedit_fontset
= widget
->style
->font
;
2050 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2052 if (win
->m_ic
== NULL
)
2053 g_warning ("Can't create input context.");
2056 mask
= gdk_window_get_events (widget
->window
);
2057 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2058 gdk_window_set_events (widget
->window
, mask
);
2060 if (GTK_WIDGET_HAS_FOCUS(widget
))
2061 gdk_im_begin (win
->m_ic
, widget
->window
);
2068 //-----------------------------------------------------------------------------
2069 // InsertChild for wxWindow.
2070 //-----------------------------------------------------------------------------
2072 /* Callback for wxWindow. This very strange beast has to be used because
2073 * C++ has no virtual methods in a constructor. We have to emulate a
2074 * virtual function here as wxNotebook requires a different way to insert
2075 * a child in it. I had opted for creating a wxNotebookPage window class
2076 * which would have made this superfluous (such in the MDI window system),
2077 * but no-one was listening to me... */
2079 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
2081 /* the window might have been scrolled already, do we
2082 have to adapt the position */
2083 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2084 child
->m_x
+= pizza
->xoffset
;
2085 child
->m_y
+= pizza
->yoffset
;
2087 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2088 GTK_WIDGET(child
->m_widget
),
2095 //-----------------------------------------------------------------------------
2097 //-----------------------------------------------------------------------------
2099 wxWindow
* wxGetActiveWindow()
2101 return g_focusWindow
;
2104 //-----------------------------------------------------------------------------
2106 //-----------------------------------------------------------------------------
2108 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2110 void wxWindow::Init()
2116 m_widget
= (GtkWidget
*) NULL
;
2117 m_wxwindow
= (GtkWidget
*) NULL
;
2127 m_needParent
= TRUE
;
2128 m_isBeingDeleted
= FALSE
;
2131 m_nativeSizeEvent
= FALSE
;
2133 m_hasScrolling
= FALSE
;
2134 m_isScrolling
= FALSE
;
2136 m_hAdjust
= (GtkAdjustment
*) NULL
;
2137 m_vAdjust
= (GtkAdjustment
*) NULL
;
2138 m_oldHorizontalPos
= 0.0;
2139 m_oldVerticalPos
= 0.0;
2142 m_widgetStyle
= (GtkStyle
*) NULL
;
2144 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2146 m_isStaticBox
= FALSE
;
2147 m_isRadioButton
= FALSE
;
2149 m_acceptsFocus
= FALSE
;
2151 m_clipPaintRegion
= FALSE
;
2153 m_cursor
= *wxSTANDARD_CURSOR
;
2155 m_delayedForegroundColour
= FALSE
;
2156 m_delayedBackgroundColour
= FALSE
;
2159 m_ic
= (GdkIC
*) NULL
;
2160 m_icattr
= (GdkICAttr
*) NULL
;
2164 wxWindow::wxWindow()
2169 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
2170 const wxPoint
&pos
, const wxSize
&size
,
2171 long style
, const wxString
&name
)
2175 Create( parent
, id
, pos
, size
, style
, name
);
2178 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
2179 const wxPoint
&pos
, const wxSize
&size
,
2180 long style
, const wxString
&name
)
2182 if (!PreCreation( parent
, pos
, size
) ||
2183 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2185 wxFAIL_MSG( wxT("wxWindow creation failed") );
2189 m_insertCallback
= wxInsertChildInWindow
;
2191 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2192 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2194 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2196 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2197 scroll_class
->scrollbar_spacing
= 0;
2199 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2201 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2202 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2204 m_wxwindow
= gtk_pizza_new();
2206 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2208 #if (GTK_MINOR_VERSION > 0)
2209 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2211 if (HasFlag(wxRAISED_BORDER
))
2213 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2215 else if (HasFlag(wxSUNKEN_BORDER
))
2217 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2219 else if (HasFlag(wxSIMPLE_BORDER
))
2221 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2225 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2227 #else // GTK_MINOR_VERSION == 0
2228 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2230 if (HasFlag(wxRAISED_BORDER
))
2232 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2234 else if (HasFlag(wxSUNKEN_BORDER
))
2236 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2240 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2242 #endif // GTK_MINOR_VERSION
2244 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2245 m_acceptsFocus
= TRUE
;
2247 #if (GTK_MINOR_VERSION == 0)
2248 // shut the viewport up
2249 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2250 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2251 #endif // GTK_MINOR_VERSION == 0
2253 // I _really_ don't want scrollbars in the beginning
2254 m_vAdjust
->lower
= 0.0;
2255 m_vAdjust
->upper
= 1.0;
2256 m_vAdjust
->value
= 0.0;
2257 m_vAdjust
->step_increment
= 1.0;
2258 m_vAdjust
->page_increment
= 1.0;
2259 m_vAdjust
->page_size
= 5.0;
2260 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2261 m_hAdjust
->lower
= 0.0;
2262 m_hAdjust
->upper
= 1.0;
2263 m_hAdjust
->value
= 0.0;
2264 m_hAdjust
->step_increment
= 1.0;
2265 m_hAdjust
->page_increment
= 1.0;
2266 m_hAdjust
->page_size
= 5.0;
2267 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2269 // these handlers block mouse events to any window during scrolling such as
2270 // motion events and prevent GTK and wxWindows from fighting over where the
2273 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2274 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2276 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2277 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2279 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2280 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2282 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2283 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2285 // these handlers get notified when screen updates are required either when
2286 // scrolling or when the window size (and therefore scrollbar configuration)
2289 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2290 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2291 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2292 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2294 gtk_widget_show( m_wxwindow
);
2297 m_parent
->DoAddChild( this );
2306 wxWindow::~wxWindow()
2308 m_isBeingDeleted
= TRUE
;
2317 m_parent
->RemoveChild( this );
2321 gdk_ic_destroy (m_ic
);
2323 gdk_ic_attr_destroy (m_icattr
);
2328 #if DISABLE_STYLE_IF_BROKEN_THEME
2329 // don't delete if it's a pixmap theme style
2330 if (!m_widgetStyle
->engine_data
)
2331 gtk_style_unref( m_widgetStyle
);
2333 m_widgetStyle
= (GtkStyle
*) NULL
;
2338 gtk_widget_destroy( m_wxwindow
);
2339 m_wxwindow
= (GtkWidget
*) NULL
;
2344 gtk_widget_destroy( m_widget
);
2345 m_widget
= (GtkWidget
*) NULL
;
2349 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2351 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2353 /* this turns -1 into 20 so that a minimal window is
2354 visible even although -1,-1 has been given as the
2355 size of the window. the same trick is used in other
2356 ports and should make debugging easier */
2357 m_width
= WidthDefault(size
.x
);
2358 m_height
= HeightDefault(size
.y
);
2363 /* some reasonable defaults */
2368 m_x
= (gdk_screen_width () - m_width
) / 2;
2369 if (m_x
< 10) m_x
= 10;
2373 m_y
= (gdk_screen_height () - m_height
) / 2;
2374 if (m_y
< 10) m_y
= 10;
2381 void wxWindow::PostCreation()
2383 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2389 /* these get reported to wxWindows -> wxPaintEvent */
2391 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2393 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2394 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2396 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2397 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2399 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2400 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2403 #if (GTK_MINOR_VERSION > 0)
2404 /* these are called when the "sunken" or "raised" borders are drawn */
2405 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2406 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2408 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2409 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2413 if (m_wxwindow
&& m_needParent
)
2415 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2416 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2418 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2419 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2423 // For dialogs and frames, we are interested mainly in
2424 // m_widget's focus.
2426 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2427 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2429 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2430 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2433 GtkWidget
*connect_widget
= GetConnectWidget();
2435 ConnectWidget( connect_widget
);
2437 /* We cannot set colours, fonts and cursors before the widget has
2438 been realized, so we do this directly after realization */
2439 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2440 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2444 /* Catch native resize events. */
2445 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2446 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2448 /* Initialize XIM support. */
2449 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2450 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2452 /* And resize XIM window. */
2453 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2454 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2460 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2462 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2463 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2465 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2466 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2468 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2469 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2471 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2472 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2474 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2475 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2477 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2478 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2480 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2481 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2484 bool wxWindow::Destroy()
2486 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2490 return wxWindowBase::Destroy();
2493 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2495 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2498 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2500 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2501 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2503 if (m_resizing
) return; /* I don't like recursions */
2506 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2508 /* don't set the size for children of wxNotebook, just take the values. */
2516 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2518 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2520 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2521 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2522 if (width
!= -1) m_width
= width
;
2523 if (height
!= -1) m_height
= height
;
2527 m_x
= x
+ pizza
->xoffset
;
2528 m_y
= y
+ pizza
->yoffset
;
2533 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2535 if (width
== -1) m_width
= 80;
2538 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2540 if (height
== -1) m_height
= 26;
2543 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2544 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2545 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2546 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2549 int bottom_border
= 0;
2551 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2553 /* the default button has a border around it */
2558 DoMoveWindow( m_x
-border
,
2561 m_height
+border
+bottom_border
);
2566 /* Sometimes the client area changes size without the
2567 whole windows's size changing, but if the whole
2568 windows's size doesn't change, no wxSizeEvent will
2569 normally be sent. Here we add an extra test if
2570 the client test has been changed and this will
2572 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2576 wxPrintf( "OnSize sent from " );
2577 if (GetClassInfo() && GetClassInfo()->GetClassName())
2578 wxPrintf( GetClassInfo()->GetClassName() );
2579 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2582 if (!m_nativeSizeEvent
)
2584 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2585 event
.SetEventObject( this );
2586 GetEventHandler()->ProcessEvent( event
);
2592 void wxWindow::OnInternalIdle()
2594 if ( g_sendActivateEvent
!= -1 )
2596 bool activate
= g_sendActivateEvent
!= 0;
2599 g_sendActivateEvent
= -1;
2601 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2602 event
.SetEventObject(this);
2604 (void)GetEventHandler()->ProcessEvent(event
);
2607 wxCursor cursor
= m_cursor
;
2608 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2612 /* I now set the cursor anew in every OnInternalIdle call
2613 as setting the cursor in a parent window also effects the
2614 windows above so that checking for the current cursor is
2619 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2621 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2623 if (!g_globalCursor
.Ok())
2624 cursor
= *wxSTANDARD_CURSOR
;
2626 window
= m_widget
->window
;
2627 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2628 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2634 GdkWindow
*window
= m_widget
->window
;
2635 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2636 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2644 void wxWindow::DoGetSize( int *width
, int *height
) const
2646 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2648 if (width
) (*width
) = m_width
;
2649 if (height
) (*height
) = m_height
;
2652 void wxWindow::DoSetClientSize( int width
, int height
)
2654 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2658 SetSize( width
, height
);
2665 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2667 /* when using GTK 1.2 we set the shadow border size to 2 */
2671 if (HasFlag(wxSIMPLE_BORDER
))
2673 /* when using GTK 1.2 we set the simple border size to 1 */
2680 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2682 GtkRequisition vscroll_req
;
2683 vscroll_req
.width
= 2;
2684 vscroll_req
.height
= 2;
2685 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2686 (scroll_window
->vscrollbar
, &vscroll_req
);
2688 GtkRequisition hscroll_req
;
2689 hscroll_req
.width
= 2;
2690 hscroll_req
.height
= 2;
2691 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2692 (scroll_window
->hscrollbar
, &hscroll_req
);
2694 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2696 if (scroll_window
->vscrollbar_visible
)
2698 dw
+= vscroll_req
.width
;
2699 dw
+= scroll_class
->scrollbar_spacing
;
2702 if (scroll_window
->hscrollbar_visible
)
2704 dh
+= hscroll_req
.height
;
2705 dh
+= scroll_class
->scrollbar_spacing
;
2709 SetSize( width
+dw
, height
+dh
);
2713 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2715 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2719 if (width
) (*width
) = m_width
;
2720 if (height
) (*height
) = m_height
;
2727 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2729 /* when using GTK 1.2 we set the shadow border size to 2 */
2733 if (HasFlag(wxSIMPLE_BORDER
))
2735 /* when using GTK 1.2 we set the simple border size to 1 */
2742 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2744 GtkRequisition vscroll_req
;
2745 vscroll_req
.width
= 2;
2746 vscroll_req
.height
= 2;
2747 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2748 (scroll_window
->vscrollbar
, &vscroll_req
);
2750 GtkRequisition hscroll_req
;
2751 hscroll_req
.width
= 2;
2752 hscroll_req
.height
= 2;
2753 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2754 (scroll_window
->hscrollbar
, &hscroll_req
);
2756 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2758 if (scroll_window
->vscrollbar_visible
)
2760 dw
+= vscroll_req
.width
;
2761 dw
+= scroll_class
->scrollbar_spacing
;
2764 if (scroll_window
->hscrollbar_visible
)
2766 dh
+= hscroll_req
.height
;
2767 dh
+= scroll_class
->scrollbar_spacing
;
2771 if (width
) (*width
) = m_width
- dw
;
2772 if (height
) (*height
) = m_height
- dh
;
2776 void wxWindow::DoGetPosition( int *x
, int *y
) const
2778 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2782 if (m_parent
&& m_parent
->m_wxwindow
)
2784 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2785 dx
= pizza
->xoffset
;
2786 dy
= pizza
->yoffset
;
2789 if (x
) (*x
) = m_x
- dx
;
2790 if (y
) (*y
) = m_y
- dy
;
2793 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2795 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2797 if (!m_widget
->window
) return;
2799 GdkWindow
*source
= (GdkWindow
*) NULL
;
2801 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2803 source
= m_widget
->window
;
2807 gdk_window_get_origin( source
, &org_x
, &org_y
);
2811 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2813 org_x
+= m_widget
->allocation
.x
;
2814 org_y
+= m_widget
->allocation
.y
;
2822 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2824 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2826 if (!m_widget
->window
) return;
2828 GdkWindow
*source
= (GdkWindow
*) NULL
;
2830 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2832 source
= m_widget
->window
;
2836 gdk_window_get_origin( source
, &org_x
, &org_y
);
2840 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2842 org_x
+= m_widget
->allocation
.x
;
2843 org_y
+= m_widget
->allocation
.y
;
2851 bool wxWindow::Show( bool show
)
2853 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2855 if (!wxWindowBase::Show(show
))
2862 gtk_widget_show( m_widget
);
2864 gtk_widget_hide( m_widget
);
2869 bool wxWindow::Enable( bool enable
)
2871 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2873 if (!wxWindowBase::Enable(enable
))
2879 gtk_widget_set_sensitive( m_widget
, enable
);
2881 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2886 int wxWindow::GetCharHeight() const
2888 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2890 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2892 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2894 return font
->ascent
+ font
->descent
;
2897 int wxWindow::GetCharWidth() const
2899 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2901 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2903 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2905 return gdk_string_width( font
, "H" );
2908 void wxWindow::GetTextExtent( const wxString
& string
,
2912 int *externalLeading
,
2913 const wxFont
*theFont
) const
2915 wxFont fontToUse
= m_font
;
2916 if (theFont
) fontToUse
= *theFont
;
2918 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2920 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2921 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2922 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2923 if (descent
) (*descent
) = font
->descent
;
2924 if (externalLeading
) (*externalLeading
) = 0; // ??
2927 void wxWindow::SetFocus()
2929 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2933 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2934 gtk_widget_grab_focus (m_wxwindow
);
2940 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2942 gtk_widget_grab_focus (m_widget
);
2944 else if (GTK_IS_CONTAINER(m_widget
))
2946 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2955 bool wxWindow::AcceptsFocus() const
2957 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2960 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2962 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2964 wxWindow
*oldParent
= m_parent
,
2965 *newParent
= (wxWindow
*)newParentBase
;
2967 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2969 if ( !wxWindowBase::Reparent(newParent
) )
2972 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2974 /* prevent GTK from deleting the widget arbitrarily */
2975 gtk_widget_ref( m_widget
);
2979 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2982 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2986 /* insert GTK representation */
2987 (*(newParent
->m_insertCallback
))(newParent
, this);
2990 /* reverse: prevent GTK from deleting the widget arbitrarily */
2991 gtk_widget_unref( m_widget
);
2996 void wxWindow::DoAddChild(wxWindow
*child
)
2998 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3000 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3002 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3007 /* insert GTK representation */
3008 (*m_insertCallback
)(this, child
);
3011 void wxWindow::Raise()
3013 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3015 if (!m_widget
->window
) return;
3017 gdk_window_raise( m_widget
->window
);
3020 void wxWindow::Lower()
3022 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3024 if (!m_widget
->window
) return;
3026 gdk_window_lower( m_widget
->window
);
3029 bool wxWindow::SetCursor( const wxCursor
&cursor
)
3031 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3033 if (cursor
== m_cursor
)
3037 wxapp_install_idle_handler();
3039 if (cursor
== wxNullCursor
)
3040 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3042 return wxWindowBase::SetCursor( cursor
);
3045 void wxWindow::WarpPointer( int x
, int y
)
3047 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3049 /* we provide this function ourselves as it is
3050 missing in GDK (top of this file) */
3052 GdkWindow
*window
= (GdkWindow
*) NULL
;
3054 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3056 window
= GetConnectWidget()->window
;
3059 gdk_window_warp_pointer( window
, x
, y
);
3062 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
3064 if (!m_widget
) return;
3065 if (!m_widget
->window
) return;
3067 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3071 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3073 rect
->width
, rect
->height
);
3077 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3081 /* there is no GTK equivalent of "draw only, don't clear" so we
3082 invent our own in the GtkPizza widget */
3090 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3091 gboolean old_clear = pizza->clear_on_draw;
3092 gtk_pizza_set_clear( pizza, FALSE );
3093 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3094 gtk_pizza_set_clear( pizza, old_clear );
3096 GdkEventExpose gdk_event
;
3097 gdk_event
.type
= GDK_EXPOSE
;
3098 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3099 gdk_event
.count
= 0;
3100 gdk_event
.area
.x
= 0;
3101 gdk_event
.area
.y
= 0;
3102 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3103 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3104 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3109 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3118 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3119 gboolean old_clear = pizza->clear_on_draw;
3120 gtk_pizza_set_clear( pizza, FALSE );
3122 GdkRectangle gdk_rect;
3123 gdk_rect.x = rect->x;
3124 gdk_rect.y = rect->y;
3125 gdk_rect.width = rect->width;
3126 gdk_rect.height = rect->height;
3127 gtk_widget_draw( m_wxwindow, &gdk_rect );
3128 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3130 gtk_pizza_set_clear( pizza, old_clear );
3132 GdkEventExpose gdk_event
;
3133 gdk_event
.type
= GDK_EXPOSE
;
3134 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3135 gdk_event
.count
= 0;
3136 gdk_event
.area
.x
= rect
->x
;
3137 gdk_event
.area
.y
= rect
->y
;
3138 gdk_event
.area
.width
= rect
->width
;
3139 gdk_event
.area
.height
= rect
->height
;
3140 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3144 GdkRectangle gdk_rect
;
3145 gdk_rect
.x
= rect
->x
;
3146 gdk_rect
.y
= rect
->y
;
3147 gdk_rect
.width
= rect
->width
;
3148 gdk_rect
.height
= rect
->height
;
3149 gtk_widget_draw( m_widget
, &gdk_rect
);
3154 void wxWindow::Clear()
3156 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3158 if (!m_widget
->window
) return;
3160 if (m_wxwindow
&& m_wxwindow
->window
)
3162 // gdk_window_clear( m_wxwindow->window );
3167 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
3169 wxWindowBase::DoSetToolTip(tip
);
3172 m_tooltip
->Apply( this );
3175 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3177 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3179 #endif // wxUSE_TOOLTIPS
3181 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
3183 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3185 if (!wxWindowBase::SetBackgroundColour(colour
))
3187 // don't leave if the GTK widget has just
3189 if (!m_delayedBackgroundColour
) return FALSE
;
3192 GdkWindow
*window
= (GdkWindow
*) NULL
;
3194 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3196 window
= GetConnectWidget()->window
;
3200 // indicate that a new style has been set
3201 // but it couldn't get applied as the
3202 // widget hasn't been realized yet.
3203 m_delayedBackgroundColour
= TRUE
;
3207 (m_wxwindow
->window
) &&
3208 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3210 /* wxMSW doesn't clear the window here. I don't do that either to
3211 provide compatibility. call Clear() to do the job. */
3213 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3214 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3222 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
3224 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3226 if (!wxWindowBase::SetForegroundColour(colour
))
3228 // don't leave if the GTK widget has just
3230 if (!m_delayedForegroundColour
) return FALSE
;
3233 GdkWindow
*window
= (GdkWindow
*) NULL
;
3235 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3237 window
= GetConnectWidget()->window
;
3241 // indicate that a new style has been set
3242 // but it couldn't get applied as the
3243 // widget hasn't been realized yet.
3244 m_delayedForegroundColour
= TRUE
;
3252 GtkStyle
*wxWindow::GetWidgetStyle()
3256 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3258 /* FIXME: is this necessary? */
3259 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3261 remake
->klass
= m_widgetStyle
->klass
;
3264 gtk_style_unref( m_widgetStyle
);
3265 m_widgetStyle
= remake
;
3269 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3272 def
= gtk_widget_get_default_style();
3274 m_widgetStyle
= gtk_style_copy( def
);
3276 /* FIXME: is this necessary? */
3277 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3279 m_widgetStyle
->klass
= def
->klass
;
3283 return m_widgetStyle
;
3286 void wxWindow::SetWidgetStyle()
3288 #if DISABLE_STYLE_IF_BROKEN_THEM
3289 if (m_widget
->style
->engine_data
)
3291 static bool s_warningPrinted
= FALSE
;
3292 if (!s_warningPrinted
)
3294 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3295 s_warningPrinted
= TRUE
;
3297 m_widgetStyle
= m_widget
->style
;
3302 GtkStyle
*style
= GetWidgetStyle();
3304 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3306 gdk_font_unref( style
->font
);
3307 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3310 if (m_foregroundColour
.Ok())
3312 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3313 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3315 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3316 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3317 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3321 // Try to restore the gtk default style. This is still a little
3322 // oversimplified for what is probably really needed here for controls
3323 // other than buttons, but is better than not being able to (re)set a
3324 // control's foreground colour to *wxBLACK -- RL
3325 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3328 def
= gtk_widget_get_default_style();
3330 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3331 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3332 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3336 if (m_backgroundColour
.Ok())
3338 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3339 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3341 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3342 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3343 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3344 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3345 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3346 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3347 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3348 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3352 // Try to restore the gtk default style. This is still a little
3353 // oversimplified for what is probably really needed here for controls
3354 // other than buttons, but is better than not being able to (re)set a
3355 // control's background colour to default grey and means resetting a
3356 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3358 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3361 def
= gtk_widget_get_default_style();
3363 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3364 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3365 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3366 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3367 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3368 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3369 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3370 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3375 void wxWindow::ApplyWidgetStyle()
3379 //-----------------------------------------------------------------------------
3380 // Pop-up menu stuff
3381 //-----------------------------------------------------------------------------
3383 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3385 *is_waiting
= FALSE
;
3388 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3390 menu
->SetInvokingWindow( win
);
3391 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3394 wxMenuItem
*menuitem
= node
->GetData();
3395 if (menuitem
->IsSubMenu())
3397 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3400 node
= node
->GetNext();
3404 static gint gs_pop_x
= 0;
3405 static gint gs_pop_y
= 0;
3407 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3411 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3416 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3418 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3420 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3422 SetInvokingWindow( menu
, this );
3429 bool is_waiting
= TRUE
;
3431 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3432 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3435 GTK_MENU(menu
->m_menu
),
3436 (GtkWidget
*) NULL
, // parent menu shell
3437 (GtkWidget
*) NULL
, // parent menu item
3438 (GtkMenuPositionFunc
) pop_pos_callback
,
3439 (gpointer
) this, // client data
3440 0, // button used to activate it
3441 gs_timeLastClick
// the time of activation
3446 while (gtk_events_pending())
3447 gtk_main_iteration();
3453 #if wxUSE_DRAG_AND_DROP
3455 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3457 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3459 GtkWidget
*dnd_widget
= GetConnectWidget();
3461 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3463 if (m_dropTarget
) delete m_dropTarget
;
3464 m_dropTarget
= dropTarget
;
3466 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3469 #endif // wxUSE_DRAG_AND_DROP
3471 GtkWidget
* wxWindow::GetConnectWidget()
3473 GtkWidget
*connect_widget
= m_widget
;
3474 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3476 return connect_widget
;
3479 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3482 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3484 return (window
== m_widget
->window
);
3487 bool wxWindow::SetFont( const wxFont
&font
)
3489 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3491 if (!wxWindowBase::SetFont(font
))
3496 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3497 if ( sysbg
== m_backgroundColour
)
3499 m_backgroundColour
= wxNullColour
;
3501 m_backgroundColour
= sysbg
;
3511 void wxWindow::CaptureMouse()
3513 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3515 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3517 GdkWindow
*window
= (GdkWindow
*) NULL
;
3519 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3521 window
= GetConnectWidget()->window
;
3523 if (!window
) return;
3525 wxCursor
* cursor
= & m_cursor
;
3527 cursor
= wxSTANDARD_CURSOR
;
3529 gdk_pointer_grab( window
, FALSE
,
3531 (GDK_BUTTON_PRESS_MASK
|
3532 GDK_BUTTON_RELEASE_MASK
|
3533 GDK_POINTER_MOTION_HINT_MASK
|
3534 GDK_POINTER_MOTION_MASK
),
3536 cursor
->GetCursor(),
3537 (guint32
)GDK_CURRENT_TIME
);
3538 g_captureWindow
= this;
3541 void wxWindow::ReleaseMouse()
3543 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3545 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3547 GdkWindow
*window
= (GdkWindow
*) NULL
;
3549 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3551 window
= GetConnectWidget()->window
;
3556 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3557 g_captureWindow
= (wxWindow
*) NULL
;
3560 bool wxWindow::IsRetained() const
3565 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3566 int range
, bool refresh
)
3568 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3570 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3572 m_hasScrolling
= TRUE
;
3574 if (orient
== wxHORIZONTAL
)
3576 float fpos
= (float)pos
;
3577 float frange
= (float)range
;
3578 float fthumb
= (float)thumbVisible
;
3579 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3580 if (fpos
< 0.0) fpos
= 0.0;
3582 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3583 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3585 SetScrollPos( orient
, pos
, refresh
);
3589 m_oldHorizontalPos
= fpos
;
3591 m_hAdjust
->lower
= 0.0;
3592 m_hAdjust
->upper
= frange
;
3593 m_hAdjust
->value
= fpos
;
3594 m_hAdjust
->step_increment
= 1.0;
3595 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3596 m_hAdjust
->page_size
= fthumb
;
3600 float fpos
= (float)pos
;
3601 float frange
= (float)range
;
3602 float fthumb
= (float)thumbVisible
;
3603 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3604 if (fpos
< 0.0) fpos
= 0.0;
3606 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3607 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3609 SetScrollPos( orient
, pos
, refresh
);
3613 m_oldVerticalPos
= fpos
;
3615 m_vAdjust
->lower
= 0.0;
3616 m_vAdjust
->upper
= frange
;
3617 m_vAdjust
->value
= fpos
;
3618 m_vAdjust
->step_increment
= 1.0;
3619 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3620 m_vAdjust
->page_size
= fthumb
;
3623 if (orient
== wxHORIZONTAL
)
3624 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3626 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3629 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3631 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3633 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3635 if (orient
== wxHORIZONTAL
)
3637 float fpos
= (float)pos
;
3638 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3639 if (fpos
< 0.0) fpos
= 0.0;
3640 m_oldHorizontalPos
= fpos
;
3642 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3643 m_hAdjust
->value
= fpos
;
3647 float fpos
= (float)pos
;
3648 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3649 if (fpos
< 0.0) fpos
= 0.0;
3650 m_oldVerticalPos
= fpos
;
3652 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3653 m_vAdjust
->value
= fpos
;
3656 if (m_wxwindow
->window
)
3658 if (orient
== wxHORIZONTAL
)
3660 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3661 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3663 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3665 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3666 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3670 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3671 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3673 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3675 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3676 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3681 int wxWindow::GetScrollThumb( int orient
) const
3683 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3685 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3687 if (orient
== wxHORIZONTAL
)
3688 return (int)(m_hAdjust
->page_size
+0.5);
3690 return (int)(m_vAdjust
->page_size
+0.5);
3693 int wxWindow::GetScrollPos( int orient
) const
3695 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3697 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3699 if (orient
== wxHORIZONTAL
)
3700 return (int)(m_hAdjust
->value
+0.5);
3702 return (int)(m_vAdjust
->value
+0.5);
3705 int wxWindow::GetScrollRange( int orient
) const
3707 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3709 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3711 if (orient
== wxHORIZONTAL
)
3712 return (int)(m_hAdjust
->upper
+0.5);
3714 return (int)(m_vAdjust
->upper
+0.5);
3717 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3719 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3721 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3723 if ((dx
== 0) && (dy
== 0)) return;
3725 m_clipPaintRegion
= TRUE
;
3726 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3727 m_clipPaintRegion
= FALSE
;
3730 if (m_children.GetCount() > 0)
3732 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3736 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3738 pizza->xoffset -= dx;
3739 pizza->yoffset -= dy;
3741 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3742 gdk_gc_set_exposures( m_scrollGC, TRUE );
3746 GetClientSize( &cw, &ch );
3747 int w = cw - abs(dx);
3748 int h = ch - abs(dy);
3750 if ((h < 0) || (w < 0))
3758 if (dx < 0) s_x = -dx;
3759 if (dy < 0) s_y = -dy;
3762 if (dx > 0) d_x = dx;
3763 if (dy > 0) d_y = dy;
3765 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3766 pizza->bin_window, s_x, s_y, w, h );
3769 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3770 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3771 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3772 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3774 Refresh( TRUE, &rect );
3777 gdk_gc_unref( m_scrollGC );
3782 // Find the wxWindow at the current mouse position, also returning the mouse
3784 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
3786 pt
= wxGetMousePosition();
3787 wxWindow
* found
= wxFindWindowAtPoint(pt
);
3791 // Get the current mouse position.
3792 wxPoint
wxGetMousePosition()
3794 /* This crashes when used within wxHelpContext,
3795 so we have to use the X-specific implementation below.
3797 GdkModifierType *mask;
3798 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
3800 return wxPoint(x, y);
3804 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
3806 return wxPoint(-999, -999);
3808 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
3809 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
3810 Window rootReturn
, childReturn
;
3811 int rootX
, rootY
, winX
, winY
;
3812 unsigned int maskReturn
;
3814 XQueryPointer (display
,
3818 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
3819 return wxPoint(rootX
, rootY
);