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 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
684 gdk_event
->area
.width
,
685 gdk_event
->area
.height
);
687 if (gdk_event
->count
== 0)
689 wxEraseEvent
eevent( win
->GetId() );
690 eevent
.SetEventObject( win
);
691 win
->GetEventHandler()->ProcessEvent(eevent
);
693 wxPaintEvent
event( win
->GetId() );
694 event
.SetEventObject( win
);
695 win
->GetEventHandler()->ProcessEvent( event
);
697 win
->GetUpdateRegion().Clear();
700 /* The following code will result in all window-less widgets
701 being redrawn if the wxWindows class is given a chance to
702 paint *anything* because it will then be allowed to paint
703 over the window-less widgets */
705 GtkPizza
*pizza
= GTK_PIZZA (widget
);
707 GList
*children
= pizza
->children
;
710 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
711 children
= children
->next
;
713 GdkEventExpose child_event
= *gdk_event
;
715 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
716 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
717 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
719 child_event
.area
.x
= child
->widget
->allocation
.x
;
720 child_event
.area
.y
= child
->widget
->allocation
.y
;
721 child_event
.area
.width
= child
->widget
->allocation
.width
;
722 child_event
.area
.height
= child
->widget
->allocation
.height
;
723 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
730 //-----------------------------------------------------------------------------
731 // "event" of m_wxwindow
732 //-----------------------------------------------------------------------------
734 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
735 expose events. We need them, of course, so we override the main event
736 procedure in GtkWidget by giving our own handler for all system events.
737 There, we look for expose events ourselves whereas all other events are
740 gint
gtk_window_event_event_callback( GtkWidget
*widget
, GdkEventExpose
*event
, wxWindow
*win
)
742 if (event
->type
== GDK_EXPOSE
)
744 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
751 //-----------------------------------------------------------------------------
752 // "draw" of m_wxwindow
753 //-----------------------------------------------------------------------------
755 /* This callback is a complete replacement of the gtk_pizza_draw() function,
758 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
763 wxapp_install_idle_handler();
766 if (win->GetName() == wxT("panel"))
768 wxPrintf( wxT("OnDraw from ") );
769 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
770 wxPrintf( win->GetClassInfo()->GetClassName() );
771 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
778 GtkPizza
*pizza
= GTK_PIZZA (widget
);
780 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
781 (pizza
->clear_on_draw
))
783 gdk_window_clear_area( pizza
->bin_window
,
784 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
787 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
789 win
->m_clipPaintRegion
= TRUE
;
791 wxEraseEvent
eevent( win
->GetId() );
792 eevent
.SetEventObject( win
);
793 win
->GetEventHandler()->ProcessEvent(eevent
);
795 wxPaintEvent
event( win
->GetId() );
796 event
.SetEventObject( win
);
797 win
->GetEventHandler()->ProcessEvent( event
);
799 win
->GetUpdateRegion().Clear();
801 win
->m_clipPaintRegion
= FALSE
;
804 GList
*children
= pizza
->children
;
807 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
808 children
= children
->next
;
810 GdkRectangle child_area
;
811 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
813 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
818 //-----------------------------------------------------------------------------
819 // "key_press_event" from any window
820 //-----------------------------------------------------------------------------
822 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
827 wxapp_install_idle_handler();
829 if (!win
->m_hasVMT
) return FALSE
;
830 if (g_blockEventsOnDrag
) return FALSE
;
835 tmp += (char)gdk_event->keyval;
836 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
837 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
842 GdkModifierType state
;
843 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
847 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
848 /* sending unknown key events doesn't really make sense */
849 if (key_code
== 0) return FALSE
;
851 wxKeyEvent
event( wxEVT_KEY_DOWN
);
852 event
.SetTimestamp( gdk_event
->time
);
853 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
854 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
855 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
856 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
857 event
.m_keyCode
= key_code
;
858 event
.m_scanCode
= gdk_event
->keyval
;
861 event
.SetEventObject( win
);
862 ret
= win
->GetEventHandler()->ProcessEvent( event
);
867 wxWindow
*ancestor
= win
;
870 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
873 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
874 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
877 if (ancestor
->IsTopLevel())
879 ancestor
= ancestor
->GetParent();
882 #endif // wxUSE_ACCEL
884 /* wxMSW doesn't send char events with Alt pressed */
885 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
886 will only be sent if it is not in an accelerator table. */
887 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
892 wxKeyEvent
event2( wxEVT_CHAR
);
893 event2
.SetTimestamp( gdk_event
->time
);
894 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
895 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
896 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
897 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
898 event2
.m_keyCode
= key_code
;
899 event2
.m_scanCode
= gdk_event
->keyval
;
902 event2
.SetEventObject( win
);
903 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
906 /* win is a control: tab can be propagated up */
908 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
909 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
910 // have this style, yet choose not to process this particular TAB in which
911 // case TAB must still work as a navigational character
913 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
915 (win
->GetParent()) &&
916 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
918 wxNavigationKeyEvent new_event
;
919 new_event
.SetEventObject( win
->GetParent() );
920 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
921 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
922 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
923 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
924 new_event
.SetCurrentFocus( win
);
925 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
928 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
930 (gdk_event
->keyval
== GDK_Escape
) )
932 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
933 new_event
.SetEventObject( win
);
934 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
937 #if (GTK_MINOR_VERSION > 0)
938 /* Pressing F10 will activate the menu bar of the top frame. */
942 (gdk_event->keyval == GDK_F10) )
944 wxWindow *ancestor = win;
947 if (wxIsKindOf(ancestor,wxFrame))
949 wxFrame *frame = (wxFrame*) ancestor;
950 wxMenuBar *menubar = frame->GetMenuBar();
953 wxNode *node = menubar->GetMenus().First();
956 wxMenu *firstMenu = (wxMenu*) node->Data();
957 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
963 ancestor = ancestor->GetParent();
971 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
978 //-----------------------------------------------------------------------------
979 // "key_release_event" from any window
980 //-----------------------------------------------------------------------------
982 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
987 wxapp_install_idle_handler();
989 if (!win
->m_hasVMT
) return FALSE
;
990 if (g_blockEventsOnDrag
) return FALSE
;
993 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
994 if (gdk_event->state & GDK_SHIFT_MASK)
995 printf( "ShiftDown.\n" );
997 printf( "ShiftUp.\n" );
998 if (gdk_event->state & GDK_CONTROL_MASK)
999 printf( "ControlDown.\n" );
1001 printf( "ControlUp.\n" );
1005 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
1007 /* sending unknown key events doesn't really make sense */
1008 if (key_code
== 0) return FALSE
;
1012 GdkModifierType state
;
1013 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1015 wxKeyEvent
event( wxEVT_KEY_UP
);
1016 event
.SetTimestamp( gdk_event
->time
);
1017 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1018 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1019 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1020 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1021 event
.m_keyCode
= key_code
;
1022 event
.m_scanCode
= gdk_event
->keyval
;
1025 event
.SetEventObject( win
);
1027 if (win
->GetEventHandler()->ProcessEvent( event
))
1029 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1036 // ----------------------------------------------------------------------------
1037 // mouse event processing helper
1038 // ----------------------------------------------------------------------------
1040 static void AdjustEventButtonState(wxMouseEvent
& event
)
1042 // GDK reports the old state of the button for a button press event, but
1043 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1044 // for a LEFT_DOWN event, not FALSE, so we will invert
1045 // left/right/middleDown for the corresponding click events
1046 switch ( event
.GetEventType() )
1048 case wxEVT_LEFT_DOWN
:
1049 case wxEVT_LEFT_DCLICK
:
1051 event
.m_leftDown
= !event
.m_leftDown
;
1054 case wxEVT_MIDDLE_DOWN
:
1055 case wxEVT_MIDDLE_DCLICK
:
1056 case wxEVT_MIDDLE_UP
:
1057 event
.m_middleDown
= !event
.m_middleDown
;
1060 case wxEVT_RIGHT_DOWN
:
1061 case wxEVT_RIGHT_DCLICK
:
1062 case wxEVT_RIGHT_UP
:
1063 event
.m_rightDown
= !event
.m_rightDown
;
1068 //-----------------------------------------------------------------------------
1069 // "button_press_event"
1070 //-----------------------------------------------------------------------------
1072 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1077 wxapp_install_idle_handler();
1080 wxPrintf( wxT("1) OnButtonPress from ") );
1081 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1082 wxPrintf( win->GetClassInfo()->GetClassName() );
1083 wxPrintf( wxT(".\n") );
1085 if (!win
->m_hasVMT
) return FALSE
;
1086 if (g_blockEventsOnDrag
) return TRUE
;
1087 if (g_blockEventsOnScroll
) return TRUE
;
1089 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1091 if (win
->m_wxwindow
)
1093 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1095 gtk_widget_grab_focus (win
->m_wxwindow
);
1098 wxPrintf( wxT("GrabFocus from ") );
1099 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1100 wxPrintf( win->GetClassInfo()->GetClassName() );
1101 wxPrintf( wxT(".\n") );
1107 wxEventType event_type
= wxEVT_NULL
;
1109 if (gdk_event
->button
== 1)
1111 switch (gdk_event
->type
)
1113 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1114 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1118 else if (gdk_event
->button
== 2)
1120 switch (gdk_event
->type
)
1122 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1123 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1127 else if (gdk_event
->button
== 3)
1129 switch (gdk_event
->type
)
1131 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1132 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1137 if ( event_type
== wxEVT_NULL
)
1139 // unknown mouse button or click type
1143 wxMouseEvent
event( event_type
);
1144 event
.SetTimestamp( gdk_event
->time
);
1145 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1146 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1147 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1148 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1149 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1150 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1151 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1153 event
.m_x
= (wxCoord
)gdk_event
->x
;
1154 event
.m_y
= (wxCoord
)gdk_event
->y
;
1156 AdjustEventButtonState(event
);
1158 // Some control don't have their own X window and thus cannot get
1161 if (!g_captureWindow
)
1163 wxCoord x
= event
.m_x
;
1164 wxCoord y
= event
.m_y
;
1165 if (win
->m_wxwindow
)
1167 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1168 x
+= pizza
->xoffset
;
1169 y
+= pizza
->yoffset
;
1172 wxNode
*node
= win
->GetChildren().First();
1175 wxWindow
*child
= (wxWindow
*)node
->Data();
1177 node
= node
->Next();
1178 if (!child
->IsShown())
1181 if (child
->m_isStaticBox
)
1183 // wxStaticBox is transparent in the box itself
1184 int xx1
= child
->m_x
;
1185 int yy1
= child
->m_y
;
1186 int xx2
= child
->m_x
+ child
->m_width
;
1187 int yy2
= child
->m_x
+ child
->m_height
;
1190 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1192 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1194 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1196 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1199 event
.m_x
-= child
->m_x
;
1200 event
.m_y
-= child
->m_y
;
1207 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1208 (child
->m_x
<= x
) &&
1209 (child
->m_y
<= y
) &&
1210 (child
->m_x
+child
->m_width
>= x
) &&
1211 (child
->m_y
+child
->m_height
>= y
))
1214 event
.m_x
-= child
->m_x
;
1215 event
.m_y
-= child
->m_y
;
1222 event
.SetEventObject( win
);
1224 gs_timeLastClick
= gdk_event
->time
;
1227 wxPrintf( wxT("2) OnButtonPress from ") );
1228 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1229 wxPrintf( win->GetClassInfo()->GetClassName() );
1230 wxPrintf( wxT(".\n") );
1233 if (win
->GetEventHandler()->ProcessEvent( event
))
1235 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1242 //-----------------------------------------------------------------------------
1243 // "button_release_event"
1244 //-----------------------------------------------------------------------------
1246 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1251 wxapp_install_idle_handler();
1253 if (!win
->m_hasVMT
) return FALSE
;
1254 if (g_blockEventsOnDrag
) return FALSE
;
1255 if (g_blockEventsOnScroll
) return FALSE
;
1257 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1260 printf( "OnButtonRelease from " );
1261 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1262 printf( win->GetClassInfo()->GetClassName() );
1266 wxEventType event_type
= wxEVT_NULL
;
1268 switch (gdk_event
->button
)
1270 case 1: event_type
= wxEVT_LEFT_UP
; break;
1271 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1272 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1273 default: return FALSE
;
1276 wxMouseEvent
event( event_type
);
1277 event
.SetTimestamp( gdk_event
->time
);
1278 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1279 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1280 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1281 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1282 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1283 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1284 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1285 event
.m_x
= (wxCoord
)gdk_event
->x
;
1286 event
.m_y
= (wxCoord
)gdk_event
->y
;
1288 AdjustEventButtonState(event
);
1290 // Some control don't have their own X window and thus cannot get
1293 if (!g_captureWindow
)
1295 wxCoord x
= event
.m_x
;
1296 wxCoord y
= event
.m_y
;
1297 if (win
->m_wxwindow
)
1299 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1300 x
+= pizza
->xoffset
;
1301 y
+= pizza
->yoffset
;
1304 wxNode
*node
= win
->GetChildren().First();
1307 wxWindow
*child
= (wxWindow
*)node
->Data();
1309 node
= node
->Next();
1310 if (!child
->IsShown())
1313 if (child
->m_isStaticBox
)
1315 // wxStaticBox is transparent in the box itself
1316 int xx1
= child
->m_x
;
1317 int yy1
= child
->m_y
;
1318 int xx2
= child
->m_x
+ child
->m_width
;
1319 int yy2
= child
->m_x
+ child
->m_height
;
1322 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1324 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1326 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1328 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1331 event
.m_x
-= child
->m_x
;
1332 event
.m_y
-= child
->m_y
;
1339 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1340 (child
->m_x
<= x
) &&
1341 (child
->m_y
<= y
) &&
1342 (child
->m_x
+child
->m_width
>= x
) &&
1343 (child
->m_y
+child
->m_height
>= y
))
1346 event
.m_x
-= child
->m_x
;
1347 event
.m_y
-= child
->m_y
;
1354 event
.SetEventObject( win
);
1356 if (win
->GetEventHandler()->ProcessEvent( event
))
1358 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1365 //-----------------------------------------------------------------------------
1366 // "motion_notify_event"
1367 //-----------------------------------------------------------------------------
1369 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1374 wxapp_install_idle_handler();
1376 if (!win
->m_hasVMT
) return FALSE
;
1377 if (g_blockEventsOnDrag
) return FALSE
;
1378 if (g_blockEventsOnScroll
) return FALSE
;
1380 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1382 if (gdk_event
->is_hint
)
1386 GdkModifierType state
;
1387 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1393 printf( "OnMotion from " );
1394 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1395 printf( win->GetClassInfo()->GetClassName() );
1399 wxMouseEvent
event( wxEVT_MOTION
);
1400 event
.SetTimestamp( gdk_event
->time
);
1401 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1402 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1403 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1404 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1405 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1406 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1407 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1409 event
.m_x
= (wxCoord
)gdk_event
->x
;
1410 event
.m_y
= (wxCoord
)gdk_event
->y
;
1412 // Some control don't have their own X window and thus cannot get
1415 if (!g_captureWindow
)
1417 wxCoord x
= event
.m_x
;
1418 wxCoord y
= event
.m_y
;
1419 if (win
->m_wxwindow
)
1421 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1422 x
+= pizza
->xoffset
;
1423 y
+= pizza
->yoffset
;
1426 wxNode
*node
= win
->GetChildren().First();
1429 wxWindow
*child
= (wxWindow
*)node
->Data();
1431 node
= node
->Next();
1432 if (!child
->IsShown())
1435 if (child
->m_isStaticBox
)
1437 // wxStaticBox is transparent in the box itself
1438 int xx1
= child
->m_x
;
1439 int yy1
= child
->m_y
;
1440 int xx2
= child
->m_x
+ child
->m_width
;
1441 int yy2
= child
->m_x
+ child
->m_height
;
1444 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1446 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1448 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1450 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1453 event
.m_x
-= child
->m_x
;
1454 event
.m_y
-= child
->m_y
;
1461 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1462 (child
->m_x
<= x
) &&
1463 (child
->m_y
<= y
) &&
1464 (child
->m_x
+child
->m_width
>= x
) &&
1465 (child
->m_y
+child
->m_height
>= y
))
1468 event
.m_x
-= child
->m_x
;
1469 event
.m_y
-= child
->m_y
;
1476 event
.SetEventObject( win
);
1478 if (win
->GetEventHandler()->ProcessEvent( event
))
1480 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1487 //-----------------------------------------------------------------------------
1489 //-----------------------------------------------------------------------------
1491 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1496 wxapp_install_idle_handler();
1498 if (!win
->m_hasVMT
) return FALSE
;
1499 if (g_blockEventsOnDrag
) return FALSE
;
1501 switch ( g_sendActivateEvent
)
1504 // we've got focus from outside, synthtize wxActivateEvent
1505 g_sendActivateEvent
= 1;
1509 // another our window just lost focus, it was already ours before
1510 // - don't send any wxActivateEvent
1511 g_sendActivateEvent
= -1;
1515 g_focusWindow
= win
;
1518 printf( "OnSetFocus from " );
1519 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1520 printf( win->GetClassInfo()->GetClassName() );
1522 printf( WXSTRINGCAST win->GetLabel() );
1526 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1529 panel
->SetLastFocus(win
);
1534 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1538 // caret needs to be informed about focus change
1539 wxCaret
*caret
= win
->GetCaret();
1542 caret
->OnSetFocus();
1544 #endif // wxUSE_CARET
1546 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1547 event
.SetEventObject( win
);
1549 if (win
->GetEventHandler()->ProcessEvent( event
))
1551 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1558 //-----------------------------------------------------------------------------
1559 // "focus_out_event"
1560 //-----------------------------------------------------------------------------
1562 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1567 wxapp_install_idle_handler();
1569 if (!win
->m_hasVMT
) return FALSE
;
1570 if (g_blockEventsOnDrag
) return FALSE
;
1572 // if the focus goes out of our app alltogether, OnIdle() will send
1573 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1574 // g_sendActivateEvent to -1
1575 g_sendActivateEvent
= 0;
1577 wxWindow
*winFocus
= FindFocusedChild(win
);
1581 g_focusWindow
= (wxWindow
*)NULL
;
1584 printf( "OnKillFocus from " );
1585 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1586 printf( win->GetClassInfo()->GetClassName() );
1596 // caret needs to be informed about focus change
1597 wxCaret
*caret
= win
->GetCaret();
1600 caret
->OnKillFocus();
1602 #endif // wxUSE_CARET
1604 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1605 event
.SetEventObject( win
);
1607 if (win
->GetEventHandler()->ProcessEvent( event
))
1609 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1616 //-----------------------------------------------------------------------------
1617 // "enter_notify_event"
1618 //-----------------------------------------------------------------------------
1620 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1625 wxapp_install_idle_handler();
1627 if (!win
->m_hasVMT
) return FALSE
;
1628 if (g_blockEventsOnDrag
) return FALSE
;
1630 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1632 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1633 #if (GTK_MINOR_VERSION > 0)
1634 event
.SetTimestamp( gdk_event
->time
);
1636 event
.SetEventObject( win
);
1640 GdkModifierType state
= (GdkModifierType
)0;
1642 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1644 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1645 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1646 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1647 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1648 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1649 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1650 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1655 if (win
->GetEventHandler()->ProcessEvent( event
))
1657 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1664 //-----------------------------------------------------------------------------
1665 // "leave_notify_event"
1666 //-----------------------------------------------------------------------------
1668 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1673 wxapp_install_idle_handler();
1675 if (!win
->m_hasVMT
) return FALSE
;
1676 if (g_blockEventsOnDrag
) return FALSE
;
1678 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1680 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1681 #if (GTK_MINOR_VERSION > 0)
1682 event
.SetTimestamp( gdk_event
->time
);
1684 event
.SetEventObject( win
);
1688 GdkModifierType state
= (GdkModifierType
)0;
1690 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1692 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1693 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1694 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1695 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1696 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1697 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1698 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1703 if (win
->GetEventHandler()->ProcessEvent( event
))
1705 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1712 //-----------------------------------------------------------------------------
1713 // "value_changed" from m_vAdjust
1714 //-----------------------------------------------------------------------------
1716 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1721 wxapp_install_idle_handler();
1723 if (g_blockEventsOnDrag
) return;
1725 if (!win
->m_hasVMT
) return;
1727 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1728 if (fabs(diff
) < 0.2) return;
1730 win
->m_oldVerticalPos
= adjust
->value
;
1732 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1733 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1735 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1736 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1737 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1738 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1739 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1741 int value
= (int)(adjust
->value
+0.5);
1743 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1744 event
.SetEventObject( win
);
1745 win
->GetEventHandler()->ProcessEvent( event
);
1748 //-----------------------------------------------------------------------------
1749 // "value_changed" from m_hAdjust
1750 //-----------------------------------------------------------------------------
1752 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1757 wxapp_install_idle_handler();
1759 if (g_blockEventsOnDrag
) return;
1760 if (!win
->m_hasVMT
) return;
1762 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1763 if (fabs(diff
) < 0.2) return;
1765 win
->m_oldHorizontalPos
= adjust
->value
;
1767 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1768 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1770 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1771 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1772 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1773 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1774 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1776 int value
= (int)(adjust
->value
+0.5);
1778 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1779 event
.SetEventObject( win
);
1780 win
->GetEventHandler()->ProcessEvent( event
);
1783 //-----------------------------------------------------------------------------
1784 // "button_press_event" from scrollbar
1785 //-----------------------------------------------------------------------------
1787 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1788 GdkEventButton
*gdk_event
,
1794 wxapp_install_idle_handler();
1797 g_blockEventsOnScroll
= TRUE
;
1798 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1803 //-----------------------------------------------------------------------------
1804 // "button_release_event" from scrollbar
1805 //-----------------------------------------------------------------------------
1807 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1808 GdkEventButton
*WXUNUSED(gdk_event
),
1813 // don't test here as we can release the mouse while being over
1814 // a different window than the slider
1816 // if (gdk_event->window != widget->slider) return FALSE;
1818 g_blockEventsOnScroll
= FALSE
;
1820 if (win
->m_isScrolling
)
1822 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
1826 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1827 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1829 value
= (int)(win
->m_hAdjust
->value
+0.5);
1832 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1834 value
= (int)(win
->m_vAdjust
->value
+0.5);
1838 wxScrollWinEvent
event( command
, value
, dir
);
1839 event
.SetEventObject( win
);
1840 win
->GetEventHandler()->ProcessEvent( event
);
1843 win
->m_isScrolling
= FALSE
;
1848 // ----------------------------------------------------------------------------
1849 // this wxWindowBase function is implemented here (in platform-specific file)
1850 // because it is static and so couldn't be made virtual
1851 // ----------------------------------------------------------------------------
1853 wxWindow
*wxWindowBase::FindFocus()
1855 return g_focusWindow
;
1858 //-----------------------------------------------------------------------------
1859 // "realize" from m_widget
1860 //-----------------------------------------------------------------------------
1862 /* We cannot set colours and fonts before the widget has
1863 been realized, so we do this directly after realization. */
1866 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1871 wxapp_install_idle_handler();
1873 if (win
->m_delayedBackgroundColour
)
1874 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1876 if (win
->m_delayedForegroundColour
)
1877 win
->SetForegroundColour( win
->GetForegroundColour() );
1879 wxWindowCreateEvent
event( win
);
1880 event
.SetEventObject( win
);
1881 win
->GetEventHandler()->ProcessEvent( event
);
1886 //-----------------------------------------------------------------------------
1888 //-----------------------------------------------------------------------------
1891 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
1892 GtkAllocation
*WXUNUSED(alloc
),
1896 wxapp_install_idle_handler();
1898 if (!win
->m_hasScrolling
) return;
1900 int client_width
= 0;
1901 int client_height
= 0;
1902 win
->GetClientSize( &client_width
, &client_height
);
1903 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
1906 win
->m_oldClientWidth
= client_width
;
1907 win
->m_oldClientHeight
= client_height
;
1909 if (!win
->m_nativeSizeEvent
)
1911 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
1912 event
.SetEventObject( win
);
1913 win
->GetEventHandler()->ProcessEvent( event
);
1919 #define WXUNUSED_UNLESS_XIM(param) param
1921 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1924 /* Resize XIM window */
1927 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1928 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1929 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1932 wxapp_install_idle_handler();
1938 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1942 gdk_window_get_size (widget
->window
, &width
, &height
);
1943 win
->m_icattr
->preedit_area
.width
= width
;
1944 win
->m_icattr
->preedit_area
.height
= height
;
1945 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
1950 //-----------------------------------------------------------------------------
1951 // "realize" from m_wxwindow
1952 //-----------------------------------------------------------------------------
1954 /* Initialize XIM support */
1957 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1958 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1961 wxapp_install_idle_handler();
1964 if (win
->m_ic
) return FALSE
;
1965 if (!widget
) return FALSE
;
1966 if (!gdk_im_ready()) return FALSE
;
1968 win
->m_icattr
= gdk_ic_attr_new();
1969 if (!win
->m_icattr
) return FALSE
;
1973 GdkColormap
*colormap
;
1974 GdkICAttr
*attr
= win
->m_icattr
;
1975 unsigned attrmask
= GDK_IC_ALL_REQ
;
1977 GdkIMStyle supported_style
= (GdkIMStyle
)
1978 (GDK_IM_PREEDIT_NONE
|
1979 GDK_IM_PREEDIT_NOTHING
|
1980 GDK_IM_PREEDIT_POSITION
|
1981 GDK_IM_STATUS_NONE
|
1982 GDK_IM_STATUS_NOTHING
);
1984 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1985 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
1987 attr
->style
= style
= gdk_im_decide_style (supported_style
);
1988 attr
->client_window
= widget
->window
;
1990 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
1991 gtk_widget_get_default_colormap ())
1993 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
1994 attr
->preedit_colormap
= colormap
;
1997 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
1998 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
1999 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2000 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2002 switch (style
& GDK_IM_PREEDIT_MASK
)
2004 case GDK_IM_PREEDIT_POSITION
:
2005 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2007 g_warning ("over-the-spot style requires fontset");
2011 gdk_window_get_size (widget
->window
, &width
, &height
);
2013 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2014 attr
->spot_location
.x
= 0;
2015 attr
->spot_location
.y
= height
;
2016 attr
->preedit_area
.x
= 0;
2017 attr
->preedit_area
.y
= 0;
2018 attr
->preedit_area
.width
= width
;
2019 attr
->preedit_area
.height
= height
;
2020 attr
->preedit_fontset
= widget
->style
->font
;
2025 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2027 if (win
->m_ic
== NULL
)
2028 g_warning ("Can't create input context.");
2031 mask
= gdk_window_get_events (widget
->window
);
2032 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2033 gdk_window_set_events (widget
->window
, mask
);
2035 if (GTK_WIDGET_HAS_FOCUS(widget
))
2036 gdk_im_begin (win
->m_ic
, widget
->window
);
2043 //-----------------------------------------------------------------------------
2044 // InsertChild for wxWindow.
2045 //-----------------------------------------------------------------------------
2047 /* Callback for wxWindow. This very strange beast has to be used because
2048 * C++ has no virtual methods in a constructor. We have to emulate a
2049 * virtual function here as wxNotebook requires a different way to insert
2050 * a child in it. I had opted for creating a wxNotebookPage window class
2051 * which would have made this superfluous (such in the MDI window system),
2052 * but no-one was listening to me... */
2054 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
2056 /* the window might have been scrolled already, do we
2057 have to adapt the position */
2058 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2059 child
->m_x
+= pizza
->xoffset
;
2060 child
->m_y
+= pizza
->yoffset
;
2062 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2063 GTK_WIDGET(child
->m_widget
),
2070 //-----------------------------------------------------------------------------
2072 //-----------------------------------------------------------------------------
2074 wxWindow
* wxGetActiveWindow()
2076 return g_focusWindow
;
2079 //-----------------------------------------------------------------------------
2081 //-----------------------------------------------------------------------------
2083 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2085 void wxWindow::Init()
2091 m_widget
= (GtkWidget
*) NULL
;
2092 m_wxwindow
= (GtkWidget
*) NULL
;
2102 m_needParent
= TRUE
;
2103 m_isBeingDeleted
= FALSE
;
2106 m_nativeSizeEvent
= FALSE
;
2108 m_hasScrolling
= FALSE
;
2109 m_isScrolling
= FALSE
;
2111 m_hAdjust
= (GtkAdjustment
*) NULL
;
2112 m_vAdjust
= (GtkAdjustment
*) NULL
;
2113 m_oldHorizontalPos
= 0.0;
2114 m_oldVerticalPos
= 0.0;
2117 m_widgetStyle
= (GtkStyle
*) NULL
;
2119 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2121 m_isStaticBox
= FALSE
;
2122 m_isRadioButton
= FALSE
;
2124 m_acceptsFocus
= FALSE
;
2126 m_clipPaintRegion
= FALSE
;
2128 m_cursor
= *wxSTANDARD_CURSOR
;
2130 m_delayedForegroundColour
= FALSE
;
2131 m_delayedBackgroundColour
= FALSE
;
2134 m_ic
= (GdkIC
*) NULL
;
2135 m_icattr
= (GdkICAttr
*) NULL
;
2139 wxWindow::wxWindow()
2144 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
2145 const wxPoint
&pos
, const wxSize
&size
,
2146 long style
, const wxString
&name
)
2150 Create( parent
, id
, pos
, size
, style
, name
);
2153 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
2154 const wxPoint
&pos
, const wxSize
&size
,
2155 long style
, const wxString
&name
)
2157 if (!PreCreation( parent
, pos
, size
) ||
2158 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2160 wxFAIL_MSG( wxT("wxWindow creation failed") );
2164 m_insertCallback
= wxInsertChildInWindow
;
2166 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2167 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2169 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2171 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2172 scroll_class
->scrollbar_spacing
= 0;
2174 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2176 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2177 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2179 m_wxwindow
= gtk_pizza_new();
2181 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2183 #if (GTK_MINOR_VERSION > 0)
2184 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2186 if (HasFlag(wxRAISED_BORDER
))
2188 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2190 else if (HasFlag(wxSUNKEN_BORDER
))
2192 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2194 else if (HasFlag(wxSIMPLE_BORDER
))
2196 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2200 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2202 #else // GTK_MINOR_VERSION == 0
2203 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2205 if (HasFlag(wxRAISED_BORDER
))
2207 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2209 else if (HasFlag(wxSUNKEN_BORDER
))
2211 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2215 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2217 #endif // GTK_MINOR_VERSION
2219 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2220 m_acceptsFocus
= TRUE
;
2222 #if (GTK_MINOR_VERSION == 0)
2223 // shut the viewport up
2224 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2225 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2226 #endif // GTK_MINOR_VERSION == 0
2228 // I _really_ don't want scrollbars in the beginning
2229 m_vAdjust
->lower
= 0.0;
2230 m_vAdjust
->upper
= 1.0;
2231 m_vAdjust
->value
= 0.0;
2232 m_vAdjust
->step_increment
= 1.0;
2233 m_vAdjust
->page_increment
= 1.0;
2234 m_vAdjust
->page_size
= 5.0;
2235 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2236 m_hAdjust
->lower
= 0.0;
2237 m_hAdjust
->upper
= 1.0;
2238 m_hAdjust
->value
= 0.0;
2239 m_hAdjust
->step_increment
= 1.0;
2240 m_hAdjust
->page_increment
= 1.0;
2241 m_hAdjust
->page_size
= 5.0;
2242 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2244 // these handlers block mouse events to any window during scrolling such as
2245 // motion events and prevent GTK and wxWindows from fighting over where the
2248 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2249 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2251 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2252 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2254 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2255 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2257 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2258 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2260 // these handlers get notified when screen updates are required either when
2261 // scrolling or when the window size (and therefore scrollbar configuration)
2264 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2265 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2266 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2267 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2269 gtk_widget_show( m_wxwindow
);
2272 m_parent
->DoAddChild( this );
2281 wxWindow::~wxWindow()
2283 m_isBeingDeleted
= TRUE
;
2292 m_parent
->RemoveChild( this );
2296 gdk_ic_destroy (m_ic
);
2298 gdk_ic_attr_destroy (m_icattr
);
2303 #if DISABLE_STYLE_IF_BROKEN_THEME
2304 // don't delete if it's a pixmap theme style
2305 if (!m_widgetStyle
->engine_data
)
2306 gtk_style_unref( m_widgetStyle
);
2308 m_widgetStyle
= (GtkStyle
*) NULL
;
2313 gtk_widget_destroy( m_wxwindow
);
2314 m_wxwindow
= (GtkWidget
*) NULL
;
2319 gtk_widget_destroy( m_widget
);
2320 m_widget
= (GtkWidget
*) NULL
;
2324 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2326 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2328 /* this turns -1 into 20 so that a minimal window is
2329 visible even although -1,-1 has been given as the
2330 size of the window. the same trick is used in other
2331 ports and should make debugging easier */
2332 m_width
= WidthDefault(size
.x
);
2333 m_height
= HeightDefault(size
.y
);
2338 /* some reasonable defaults */
2343 m_x
= (gdk_screen_width () - m_width
) / 2;
2344 if (m_x
< 10) m_x
= 10;
2348 m_y
= (gdk_screen_height () - m_height
) / 2;
2349 if (m_y
< 10) m_y
= 10;
2356 void wxWindow::PostCreation()
2358 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2364 /* these get reported to wxWindows -> wxPaintEvent */
2366 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2368 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2369 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2371 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2372 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2374 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2375 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2378 #if (GTK_MINOR_VERSION > 0)
2379 /* these are called when the "sunken" or "raised" borders are drawn */
2380 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2381 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2383 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2384 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2388 if (m_wxwindow
&& m_needParent
)
2390 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2391 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2393 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2394 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2398 // For dialogs and frames, we are interested mainly in
2399 // m_widget's focus.
2401 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2402 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2404 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2405 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2408 GtkWidget
*connect_widget
= GetConnectWidget();
2410 ConnectWidget( connect_widget
);
2412 /* We cannot set colours, fonts and cursors before the widget has
2413 been realized, so we do this directly after realization */
2414 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2415 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2419 /* Catch native resize events. */
2420 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2421 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2423 /* Initialize XIM support. */
2424 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2425 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2427 /* And resize XIM window. */
2428 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2429 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2435 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2437 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2438 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2440 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2441 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2443 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2444 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2446 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2447 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2449 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2450 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2452 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2453 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2455 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2456 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2459 bool wxWindow::Destroy()
2461 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2465 return wxWindowBase::Destroy();
2468 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2470 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2473 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2475 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2476 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2478 if (m_resizing
) return; /* I don't like recursions */
2481 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2483 /* don't set the size for children of wxNotebook, just take the values. */
2491 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2493 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2495 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2496 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2497 if (width
!= -1) m_width
= width
;
2498 if (height
!= -1) m_height
= height
;
2502 m_x
= x
+ pizza
->xoffset
;
2503 m_y
= y
+ pizza
->yoffset
;
2508 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2510 if (width
== -1) m_width
= 80;
2513 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2515 if (height
== -1) m_height
= 26;
2518 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2519 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2520 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2521 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2524 int bottom_border
= 0;
2526 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2528 /* the default button has a border around it */
2533 DoMoveWindow( m_x
-border
,
2536 m_height
+border
+bottom_border
);
2541 /* Sometimes the client area changes size without the
2542 whole windows's size changing, but if the whole
2543 windows's size doesn't change, no wxSizeEvent will
2544 normally be sent. Here we add an extra test if
2545 the client test has been changed and this will
2547 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2551 wxPrintf( "OnSize sent from " );
2552 if (GetClassInfo() && GetClassInfo()->GetClassName())
2553 wxPrintf( GetClassInfo()->GetClassName() );
2554 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2557 if (!m_nativeSizeEvent
)
2559 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2560 event
.SetEventObject( this );
2561 GetEventHandler()->ProcessEvent( event
);
2567 void wxWindow::OnInternalIdle()
2569 if ( g_sendActivateEvent
!= -1 )
2571 bool activate
= g_sendActivateEvent
!= 0;
2574 g_sendActivateEvent
= -1;
2576 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2577 event
.SetEventObject(this);
2579 (void)GetEventHandler()->ProcessEvent(event
);
2582 wxCursor cursor
= m_cursor
;
2583 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2587 /* I now set the cursor anew in every OnInternalIdle call
2588 as setting the cursor in a parent window also effects the
2589 windows above so that checking for the current cursor is
2594 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2596 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2598 if (!g_globalCursor
.Ok())
2599 cursor
= *wxSTANDARD_CURSOR
;
2601 window
= m_widget
->window
;
2602 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2603 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2609 GdkWindow
*window
= m_widget
->window
;
2610 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2611 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2619 void wxWindow::DoGetSize( int *width
, int *height
) const
2621 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2623 if (width
) (*width
) = m_width
;
2624 if (height
) (*height
) = m_height
;
2627 void wxWindow::DoSetClientSize( int width
, int height
)
2629 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2633 SetSize( width
, height
);
2640 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2642 /* when using GTK 1.2 we set the shadow border size to 2 */
2646 if (HasFlag(wxSIMPLE_BORDER
))
2648 /* when using GTK 1.2 we set the simple border size to 1 */
2655 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2657 GtkRequisition vscroll_req
;
2658 vscroll_req
.width
= 2;
2659 vscroll_req
.height
= 2;
2660 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2661 (scroll_window
->vscrollbar
, &vscroll_req
);
2663 GtkRequisition hscroll_req
;
2664 hscroll_req
.width
= 2;
2665 hscroll_req
.height
= 2;
2666 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2667 (scroll_window
->hscrollbar
, &hscroll_req
);
2669 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2671 if (scroll_window
->vscrollbar_visible
)
2673 dw
+= vscroll_req
.width
;
2674 dw
+= scroll_class
->scrollbar_spacing
;
2677 if (scroll_window
->hscrollbar_visible
)
2679 dh
+= hscroll_req
.height
;
2680 dh
+= scroll_class
->scrollbar_spacing
;
2684 SetSize( width
+dw
, height
+dh
);
2688 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2690 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2694 if (width
) (*width
) = m_width
;
2695 if (height
) (*height
) = m_height
;
2702 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2704 /* when using GTK 1.2 we set the shadow border size to 2 */
2708 if (HasFlag(wxSIMPLE_BORDER
))
2710 /* when using GTK 1.2 we set the simple border size to 1 */
2717 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2719 GtkRequisition vscroll_req
;
2720 vscroll_req
.width
= 2;
2721 vscroll_req
.height
= 2;
2722 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2723 (scroll_window
->vscrollbar
, &vscroll_req
);
2725 GtkRequisition hscroll_req
;
2726 hscroll_req
.width
= 2;
2727 hscroll_req
.height
= 2;
2728 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2729 (scroll_window
->hscrollbar
, &hscroll_req
);
2731 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2733 if (scroll_window
->vscrollbar_visible
)
2735 dw
+= vscroll_req
.width
;
2736 dw
+= scroll_class
->scrollbar_spacing
;
2739 if (scroll_window
->hscrollbar_visible
)
2741 dh
+= hscroll_req
.height
;
2742 dh
+= scroll_class
->scrollbar_spacing
;
2746 if (width
) (*width
) = m_width
- dw
;
2747 if (height
) (*height
) = m_height
- dh
;
2751 void wxWindow::DoGetPosition( int *x
, int *y
) const
2753 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2757 if (m_parent
&& m_parent
->m_wxwindow
)
2759 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2760 dx
= pizza
->xoffset
;
2761 dy
= pizza
->yoffset
;
2764 if (x
) (*x
) = m_x
- dx
;
2765 if (y
) (*y
) = m_y
- dy
;
2768 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2770 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2772 if (!m_widget
->window
) return;
2774 GdkWindow
*source
= (GdkWindow
*) NULL
;
2776 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2778 source
= m_widget
->window
;
2782 gdk_window_get_origin( source
, &org_x
, &org_y
);
2786 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2788 org_x
+= m_widget
->allocation
.x
;
2789 org_y
+= m_widget
->allocation
.y
;
2797 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2799 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2801 if (!m_widget
->window
) return;
2803 GdkWindow
*source
= (GdkWindow
*) NULL
;
2805 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2807 source
= m_widget
->window
;
2811 gdk_window_get_origin( source
, &org_x
, &org_y
);
2815 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2817 org_x
+= m_widget
->allocation
.x
;
2818 org_y
+= m_widget
->allocation
.y
;
2826 bool wxWindow::Show( bool show
)
2828 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2830 if (!wxWindowBase::Show(show
))
2837 gtk_widget_show( m_widget
);
2839 gtk_widget_hide( m_widget
);
2844 bool wxWindow::Enable( bool enable
)
2846 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2848 if (!wxWindowBase::Enable(enable
))
2854 gtk_widget_set_sensitive( m_widget
, enable
);
2856 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2861 int wxWindow::GetCharHeight() const
2863 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2865 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2867 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2869 return font
->ascent
+ font
->descent
;
2872 int wxWindow::GetCharWidth() const
2874 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2876 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2878 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2880 return gdk_string_width( font
, "H" );
2883 void wxWindow::GetTextExtent( const wxString
& string
,
2887 int *externalLeading
,
2888 const wxFont
*theFont
) const
2890 wxFont fontToUse
= m_font
;
2891 if (theFont
) fontToUse
= *theFont
;
2893 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2895 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2896 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2897 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2898 if (descent
) (*descent
) = font
->descent
;
2899 if (externalLeading
) (*externalLeading
) = 0; // ??
2902 void wxWindow::SetFocus()
2904 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2908 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2909 gtk_widget_grab_focus (m_wxwindow
);
2915 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2917 gtk_widget_grab_focus (m_widget
);
2919 else if (GTK_IS_CONTAINER(m_widget
))
2921 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2930 bool wxWindow::AcceptsFocus() const
2932 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2935 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2937 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2939 wxWindow
*oldParent
= m_parent
,
2940 *newParent
= (wxWindow
*)newParentBase
;
2942 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2944 if ( !wxWindowBase::Reparent(newParent
) )
2947 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2949 /* prevent GTK from deleting the widget arbitrarily */
2950 gtk_widget_ref( m_widget
);
2954 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2957 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2961 /* insert GTK representation */
2962 (*(newParent
->m_insertCallback
))(newParent
, this);
2965 /* reverse: prevent GTK from deleting the widget arbitrarily */
2966 gtk_widget_unref( m_widget
);
2971 void wxWindow::DoAddChild(wxWindow
*child
)
2973 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2975 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
2977 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
2982 /* insert GTK representation */
2983 (*m_insertCallback
)(this, child
);
2986 void wxWindow::Raise()
2988 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2990 if (!m_widget
->window
) return;
2992 gdk_window_raise( m_widget
->window
);
2995 void wxWindow::Lower()
2997 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2999 if (!m_widget
->window
) return;
3001 gdk_window_lower( m_widget
->window
);
3004 bool wxWindow::SetCursor( const wxCursor
&cursor
)
3006 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3008 if (cursor
== m_cursor
)
3012 wxapp_install_idle_handler();
3014 if (cursor
== wxNullCursor
)
3015 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3017 return wxWindowBase::SetCursor( cursor
);
3020 void wxWindow::WarpPointer( int x
, int y
)
3022 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3024 /* we provide this function ourselves as it is
3025 missing in GDK (top of this file) */
3027 GdkWindow
*window
= (GdkWindow
*) NULL
;
3029 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3031 window
= GetConnectWidget()->window
;
3034 gdk_window_warp_pointer( window
, x
, y
);
3037 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
3039 if (!m_widget
) return;
3040 if (!m_widget
->window
) return;
3042 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3046 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3048 rect
->width
, rect
->height
);
3052 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3056 /* there is no GTK equivalent of "draw only, don't clear" so we
3057 invent our own in the GtkPizza widget */
3065 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3066 gboolean old_clear = pizza->clear_on_draw;
3067 gtk_pizza_set_clear( pizza, FALSE );
3068 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3069 gtk_pizza_set_clear( pizza, old_clear );
3071 GdkEventExpose gdk_event
;
3072 gdk_event
.type
= GDK_EXPOSE
;
3073 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3074 gdk_event
.count
= 0;
3075 gdk_event
.area
.x
= 0;
3076 gdk_event
.area
.y
= 0;
3077 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3078 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3079 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3084 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3093 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3094 gboolean old_clear = pizza->clear_on_draw;
3095 gtk_pizza_set_clear( pizza, FALSE );
3097 GdkRectangle gdk_rect;
3098 gdk_rect.x = rect->x;
3099 gdk_rect.y = rect->y;
3100 gdk_rect.width = rect->width;
3101 gdk_rect.height = rect->height;
3102 gtk_widget_draw( m_wxwindow, &gdk_rect );
3103 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3105 gtk_pizza_set_clear( pizza, old_clear );
3107 GdkEventExpose gdk_event
;
3108 gdk_event
.type
= GDK_EXPOSE
;
3109 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3110 gdk_event
.count
= 0;
3111 gdk_event
.area
.x
= rect
->x
;
3112 gdk_event
.area
.y
= rect
->y
;
3113 gdk_event
.area
.width
= rect
->width
;
3114 gdk_event
.area
.height
= rect
->height
;
3115 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3119 GdkRectangle gdk_rect
;
3120 gdk_rect
.x
= rect
->x
;
3121 gdk_rect
.y
= rect
->y
;
3122 gdk_rect
.width
= rect
->width
;
3123 gdk_rect
.height
= rect
->height
;
3124 gtk_widget_draw( m_widget
, &gdk_rect
);
3129 void wxWindow::Clear()
3131 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3133 if (!m_widget
->window
) return;
3135 if (m_wxwindow
&& m_wxwindow
->window
)
3137 // gdk_window_clear( m_wxwindow->window );
3142 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
3144 wxWindowBase::DoSetToolTip(tip
);
3147 m_tooltip
->Apply( this );
3150 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3152 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3154 #endif // wxUSE_TOOLTIPS
3156 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
3158 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3160 if (!wxWindowBase::SetBackgroundColour(colour
))
3162 // don't leave if the GTK widget has just
3164 if (!m_delayedBackgroundColour
) return FALSE
;
3167 GdkWindow
*window
= (GdkWindow
*) NULL
;
3169 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3171 window
= GetConnectWidget()->window
;
3175 // indicate that a new style has been set
3176 // but it couldn't get applied as the
3177 // widget hasn't been realized yet.
3178 m_delayedBackgroundColour
= TRUE
;
3182 (m_wxwindow
->window
) &&
3183 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3185 /* wxMSW doesn't clear the window here. I don't do that either to
3186 provide compatibility. call Clear() to do the job. */
3188 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3189 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3197 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
3199 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3201 if (!wxWindowBase::SetForegroundColour(colour
))
3203 // don't leave if the GTK widget has just
3205 if (!m_delayedForegroundColour
) return FALSE
;
3208 GdkWindow
*window
= (GdkWindow
*) NULL
;
3210 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3212 window
= GetConnectWidget()->window
;
3216 // indicate that a new style has been set
3217 // but it couldn't get applied as the
3218 // widget hasn't been realized yet.
3219 m_delayedForegroundColour
= TRUE
;
3227 GtkStyle
*wxWindow::GetWidgetStyle()
3231 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3233 /* FIXME: is this necessary? */
3234 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3236 remake
->klass
= m_widgetStyle
->klass
;
3239 gtk_style_unref( m_widgetStyle
);
3240 m_widgetStyle
= remake
;
3244 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3247 def
= gtk_widget_get_default_style();
3249 m_widgetStyle
= gtk_style_copy( def
);
3251 /* FIXME: is this necessary? */
3252 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3254 m_widgetStyle
->klass
= def
->klass
;
3258 return m_widgetStyle
;
3261 void wxWindow::SetWidgetStyle()
3263 #if DISABLE_STYLE_IF_BROKEN_THEM
3264 if (m_widget
->style
->engine_data
)
3266 static bool s_warningPrinted
= FALSE
;
3267 if (!s_warningPrinted
)
3269 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3270 s_warningPrinted
= TRUE
;
3272 m_widgetStyle
= m_widget
->style
;
3277 GtkStyle
*style
= GetWidgetStyle();
3279 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3281 gdk_font_unref( style
->font
);
3282 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3285 if (m_foregroundColour
.Ok())
3287 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3288 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3290 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3291 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3292 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3296 // Try to restore the gtk default style. This is still a little
3297 // oversimplified for what is probably really needed here for controls
3298 // other than buttons, but is better than not being able to (re)set a
3299 // control's foreground colour to *wxBLACK -- RL
3300 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3303 def
= gtk_widget_get_default_style();
3305 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3306 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3307 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3311 if (m_backgroundColour
.Ok())
3313 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3314 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3316 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3317 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3318 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3319 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3320 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3321 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3322 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3323 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3327 // Try to restore the gtk default style. This is still a little
3328 // oversimplified for what is probably really needed here for controls
3329 // other than buttons, but is better than not being able to (re)set a
3330 // control's background colour to default grey and means resetting a
3331 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3333 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3336 def
= gtk_widget_get_default_style();
3338 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3339 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3340 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3341 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3342 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3343 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3344 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3345 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3350 void wxWindow::ApplyWidgetStyle()
3354 //-----------------------------------------------------------------------------
3355 // Pop-up menu stuff
3356 //-----------------------------------------------------------------------------
3358 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3360 *is_waiting
= FALSE
;
3363 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3365 menu
->SetInvokingWindow( win
);
3366 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3369 wxMenuItem
*menuitem
= node
->GetData();
3370 if (menuitem
->IsSubMenu())
3372 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3375 node
= node
->GetNext();
3379 static gint gs_pop_x
= 0;
3380 static gint gs_pop_y
= 0;
3382 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3386 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3391 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3393 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3395 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3397 SetInvokingWindow( menu
, this );
3404 bool is_waiting
= TRUE
;
3406 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3407 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3410 GTK_MENU(menu
->m_menu
),
3411 (GtkWidget
*) NULL
, // parent menu shell
3412 (GtkWidget
*) NULL
, // parent menu item
3413 (GtkMenuPositionFunc
) pop_pos_callback
,
3414 (gpointer
) this, // client data
3415 0, // button used to activate it
3416 gs_timeLastClick
// the time of activation
3421 while (gtk_events_pending())
3422 gtk_main_iteration();
3428 #if wxUSE_DRAG_AND_DROP
3430 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3432 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3434 GtkWidget
*dnd_widget
= GetConnectWidget();
3436 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3438 if (m_dropTarget
) delete m_dropTarget
;
3439 m_dropTarget
= dropTarget
;
3441 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3444 #endif // wxUSE_DRAG_AND_DROP
3446 GtkWidget
* wxWindow::GetConnectWidget()
3448 GtkWidget
*connect_widget
= m_widget
;
3449 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3451 return connect_widget
;
3454 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3457 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3459 return (window
== m_widget
->window
);
3462 bool wxWindow::SetFont( const wxFont
&font
)
3464 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3466 if (!wxWindowBase::SetFont(font
))
3471 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3472 if ( sysbg
== m_backgroundColour
)
3474 m_backgroundColour
= wxNullColour
;
3476 m_backgroundColour
= sysbg
;
3486 void wxWindow::CaptureMouse()
3488 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3490 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3492 GdkWindow
*window
= (GdkWindow
*) NULL
;
3494 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3496 window
= GetConnectWidget()->window
;
3498 if (!window
) return;
3500 wxCursor
* cursor
= & m_cursor
;
3502 cursor
= wxSTANDARD_CURSOR
;
3504 gdk_pointer_grab( window
, FALSE
,
3506 (GDK_BUTTON_PRESS_MASK
|
3507 GDK_BUTTON_RELEASE_MASK
|
3508 GDK_POINTER_MOTION_HINT_MASK
|
3509 GDK_POINTER_MOTION_MASK
),
3511 cursor
->GetCursor(),
3512 (guint32
)GDK_CURRENT_TIME
);
3513 g_captureWindow
= this;
3516 void wxWindow::ReleaseMouse()
3518 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3520 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3522 GdkWindow
*window
= (GdkWindow
*) NULL
;
3524 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3526 window
= GetConnectWidget()->window
;
3531 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3532 g_captureWindow
= (wxWindow
*) NULL
;
3535 bool wxWindow::IsRetained() const
3540 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3541 int range
, bool refresh
)
3543 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3545 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3547 m_hasScrolling
= TRUE
;
3549 if (orient
== wxHORIZONTAL
)
3551 float fpos
= (float)pos
;
3552 float frange
= (float)range
;
3553 float fthumb
= (float)thumbVisible
;
3554 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3555 if (fpos
< 0.0) fpos
= 0.0;
3557 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3558 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3560 SetScrollPos( orient
, pos
, refresh
);
3564 m_oldHorizontalPos
= fpos
;
3566 m_hAdjust
->lower
= 0.0;
3567 m_hAdjust
->upper
= frange
;
3568 m_hAdjust
->value
= fpos
;
3569 m_hAdjust
->step_increment
= 1.0;
3570 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3571 m_hAdjust
->page_size
= fthumb
;
3575 float fpos
= (float)pos
;
3576 float frange
= (float)range
;
3577 float fthumb
= (float)thumbVisible
;
3578 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3579 if (fpos
< 0.0) fpos
= 0.0;
3581 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3582 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3584 SetScrollPos( orient
, pos
, refresh
);
3588 m_oldVerticalPos
= fpos
;
3590 m_vAdjust
->lower
= 0.0;
3591 m_vAdjust
->upper
= frange
;
3592 m_vAdjust
->value
= fpos
;
3593 m_vAdjust
->step_increment
= 1.0;
3594 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3595 m_vAdjust
->page_size
= fthumb
;
3598 if (orient
== wxHORIZONTAL
)
3599 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3601 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3604 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3606 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3608 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3610 if (orient
== wxHORIZONTAL
)
3612 float fpos
= (float)pos
;
3613 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3614 if (fpos
< 0.0) fpos
= 0.0;
3615 m_oldHorizontalPos
= fpos
;
3617 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3618 m_hAdjust
->value
= fpos
;
3622 float fpos
= (float)pos
;
3623 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3624 if (fpos
< 0.0) fpos
= 0.0;
3625 m_oldVerticalPos
= fpos
;
3627 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3628 m_vAdjust
->value
= fpos
;
3631 if (m_wxwindow
->window
)
3633 if (orient
== wxHORIZONTAL
)
3635 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3636 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3638 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3640 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3641 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3645 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3646 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3648 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3650 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3651 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3656 int wxWindow::GetScrollThumb( int orient
) const
3658 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3660 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3662 if (orient
== wxHORIZONTAL
)
3663 return (int)(m_hAdjust
->page_size
+0.5);
3665 return (int)(m_vAdjust
->page_size
+0.5);
3668 int wxWindow::GetScrollPos( int orient
) const
3670 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3672 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3674 if (orient
== wxHORIZONTAL
)
3675 return (int)(m_hAdjust
->value
+0.5);
3677 return (int)(m_vAdjust
->value
+0.5);
3680 int wxWindow::GetScrollRange( int orient
) const
3682 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3684 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3686 if (orient
== wxHORIZONTAL
)
3687 return (int)(m_hAdjust
->upper
+0.5);
3689 return (int)(m_vAdjust
->upper
+0.5);
3692 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3694 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3696 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3698 if ((dx
== 0) && (dy
== 0)) return;
3700 m_clipPaintRegion
= TRUE
;
3701 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3702 m_clipPaintRegion
= FALSE
;
3705 if (m_children.GetCount() > 0)
3707 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3711 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3713 pizza->xoffset -= dx;
3714 pizza->yoffset -= dy;
3716 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3717 gdk_gc_set_exposures( m_scrollGC, TRUE );
3721 GetClientSize( &cw, &ch );
3722 int w = cw - abs(dx);
3723 int h = ch - abs(dy);
3725 if ((h < 0) || (w < 0))
3733 if (dx < 0) s_x = -dx;
3734 if (dy < 0) s_y = -dy;
3737 if (dx > 0) d_x = dx;
3738 if (dy > 0) d_y = dy;
3740 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3741 pizza->bin_window, s_x, s_y, w, h );
3744 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3745 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3746 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3747 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3749 Refresh( TRUE, &rect );
3752 gdk_gc_unref( m_scrollGC );