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 #include "wx/window.h"
20 #include "wx/layout.h"
22 #include "wx/dialog.h"
23 #include "wx/msgdlg.h"
25 #if wxUSE_DRAG_AND_DROP
30 #include "wx/tooltip.h"
38 #include "wx/statusbr.h"
40 #include "wx/settings.h"
44 #include "wx/thread.h"
51 #include <gdk/gdkprivate.h>
52 #include <gdk/gdkkeysyms.h>
56 #include <gtk/gtkprivate.h>
58 #include "wx/gtk/win_gtk.h"
60 //-----------------------------------------------------------------------------
61 // documentation on internals
62 //-----------------------------------------------------------------------------
65 I have been asked several times about writing some documentation about
66 the GTK port of wxWindows, especially its internal structures. Obviously,
67 you cannot understand wxGTK without knowing a little about the GTK, but
68 some more information about what the wxWindow, which is the base class
69 for all other window classes, does seems required as well.
73 What does wxWindow do? It contains the common interface for the following
74 jobs of its descendants:
76 1) Define the rudimentary behaviour common to all window classes, such as
77 resizing, intercepting user input (so as to make it possible to use these
78 events for special purposes in a derived class), window names etc.
80 2) Provide the possibility to contain and manage children, if the derived
81 class is allowed to contain children, which holds true for those window
82 classes which do not display a native GTK widget. To name them, these
83 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
84 work classes are a special case and are handled a bit differently from
85 the rest. The same holds true for the wxNotebook class.
87 3) Provide the possibility to draw into a client area of a window. This,
88 too, only holds true for classes that do not display a native GTK widget
91 4) Provide the entire mechanism for scrolling widgets. This actual inter-
92 face for this is usually in wxScrolledWindow, but the GTK implementation
95 5) A multitude of helper or extra methods for special purposes, such as
96 Drag'n'Drop, managing validators etc.
98 6) Display a border (sunken, raised, simple or none).
100 Normally one might expect, that one wxWindows window would always correspond
101 to one GTK widget. Under GTK, there is no such allround widget that has all
102 the functionality. Moreover, the GTK defines a client area as a different
103 widget from the actual widget you are handling. Last but not least some
104 special classes (e.g. wxFrame) handle different categories of widgets and
105 still have the possibility to draw something in the client area.
106 It was therefore required to write a special purpose GTK widget, that would
107 represent a client area in the sense of wxWindows capable to do the jobs
108 2), 3) and 4). I have written this class and it resides in win_gtk.c of
111 All windows must have a widget, with which they interact with other under-
112 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
113 thw wxWindow class has a member variable called m_widget which holds a
114 pointer to this widget. When the window class represents a GTK native widget,
115 this is (in most cases) the only GTK widget the class manages. E.g. the
116 wxStatitText class handles only a GtkLabel widget a pointer to which you
117 can find in m_widget (defined in wxWindow)
119 When the class has a client area for drawing into and for containing children
120 it has to handle the client area widget (of the type GtkPizza, defined in
121 win_gtk.c), but there could be any number of widgets, handled by a class
122 The common rule for all windows is only, that the widget that interacts with
123 the rest of GTK must be referenced in m_widget and all other widgets must be
124 children of this widget on the GTK level. The top-most widget, which also
125 represents the client area, must be in the m_wxwindow field and must be of
128 As I said, the window classes that display a GTK native widget only have
129 one widget, so in the case of e.g. the wxButton class m_widget holds a
130 pointer to a GtkButton widget. But windows with client areas (for drawing
131 and children) have a m_widget field that is a pointer to a GtkScrolled-
132 Window and a m_wxwindow field that is pointer to a GtkPizza and this
133 one is (in the GTK sense) a child of the GtkScrolledWindow.
135 If the m_wxwindow field is set, then all input to this widget is inter-
136 cepted and sent to the wxWindows class. If not, all input to the widget
137 that gets pointed to by m_widget gets intercepted and sent to the class.
141 The design of scrolling in wxWindows is markedly different from that offered
142 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
143 clicking on a scrollbar belonging to scrolled window will inevitably move
144 the window. In wxWindows, the scrollbar will only emit an event, send this
145 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
146 which actually moves the window and its subchildren. Note that GtkPizza
147 memorizes how much it has been scrolled but that wxWindows forgets this
148 so that the two coordinates systems have to be kept in synch. This is done
149 in various places using the pizza->xoffset and pizza->yoffset values.
153 Singularily the most broken code in GTK is the code that is supposes to
154 inform subwindows (child windows) about new positions. Very often, duplicate
155 events are sent without changes in size or position, equally often no
156 events are sent at all (All this is due to a bug in the GtkContainer code
157 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
158 GTK's own system and it simply waits for size events for toplevel windows
159 and then iterates down the respective size events to all window. This has
160 the disadvantage, that windows might get size events before the GTK widget
161 actually has the reported size. This doesn't normally pose any problem, but
162 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
163 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
164 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
165 window that is used for OpenGl output really has that size (as reported by
170 If someone at some point of time feels the immense desire to have a look at,
171 change or attempt to optimse the Refresh() logic, this person will need an
172 intimate understanding of what a "draw" and what an "expose" events are and
173 what there are used for, in particular when used in connection with GTK's
174 own windowless widgets. Beware.
178 Cursors, too, have been a constant source of pleasure. The main difficulty
179 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
180 for the parent. To prevent this from doing too much harm, I use idle time
181 to set the cursor over and over again, starting from the toplevel windows
182 and ending with the youngest generation (speaking of parent and child windows).
183 Also don't forget that cursors (like much else) are connected to GdkWindows,
184 not GtkWidgets and that the "window" field of a GtkWidget might very well
185 point to the GdkWindow of the parent widget (-> "window less widget") and
186 that the two obviously have very different meanings.
190 //-----------------------------------------------------------------------------
192 //-----------------------------------------------------------------------------
194 extern wxList wxPendingDelete
;
195 extern bool g_blockEventsOnDrag
;
196 extern bool g_blockEventsOnScroll
;
197 extern wxCursor g_globalCursor
;
198 static wxWindow
*g_captureWindow
= (wxWindow
*) NULL
;
200 /* extern */ wxWindow
*g_focusWindow
= (wxWindow
*) NULL
;
202 // if we detect that the app has got/lost the focus, we set this variable to
203 // either TRUE or FALSE and an activate event will be sent during the next
204 // OnIdle() call and it is reset to -1: this value means that we shouldn't
205 // send any activate events at all
206 static int g_sendActivateEvent
= -1;
208 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
209 the last click here */
210 static guint32 gs_timeLastClick
= 0;
212 extern bool g_mainThreadLocked
;
214 //-----------------------------------------------------------------------------
216 //-----------------------------------------------------------------------------
218 #define DISABLE_STYLE_IF_BROKEN_THEME 1
223 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
225 # define DEBUG_MAIN_THREAD
228 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
229 GdkEvent
*WXUNUSED(event
),
230 const wxChar
*WXUNUSED(name
) )
233 static bool s_done = FALSE;
236 wxLog::AddTraceMask("focus");
239 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
245 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
247 // suppress warnings about gtk_debug_focus_in_callback being unused with
252 tmp
+= wxT(" FROM ");
255 wxChar
*s
= new wxChar
[tmp
.Length()+1];
259 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
260 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
265 #define DEBUG_MAIN_THREAD
268 //-----------------------------------------------------------------------------
269 // missing gdk functions
270 //-----------------------------------------------------------------------------
273 gdk_window_warp_pointer (GdkWindow
*window
,
277 GdkWindowPrivate
*priv
;
280 window
= GDK_ROOT_PARENT();
282 priv
= (GdkWindowPrivate
*) window
;
284 if (!priv
->destroyed
)
286 XWarpPointer (priv
->xdisplay
,
287 None
, /* not source window -> move from anywhere */
288 priv
->xwindow
, /* dest window */
289 0, 0, 0, 0, /* not source window -> move from anywhere */
294 //-----------------------------------------------------------------------------
296 //-----------------------------------------------------------------------------
298 extern void wxapp_install_idle_handler();
299 extern bool g_isIdle
;
301 //-----------------------------------------------------------------------------
302 // local code (see below)
303 //-----------------------------------------------------------------------------
305 // returns the child of win which currently has focus or NULL if not found
306 static wxWindow
*FindFocusedChild(wxWindow
*win
)
308 wxWindow
*winFocus
= wxWindow::FindFocus();
310 return (wxWindow
*)NULL
;
312 if ( winFocus
== win
)
315 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
317 node
= node
->GetNext() )
319 wxWindow
*child
= FindFocusedChild(node
->GetData());
324 return (wxWindow
*)NULL
;
327 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
335 if (win
->m_hasScrolling
)
337 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
339 GtkRequisition vscroll_req
;
340 vscroll_req
.width
= 2;
341 vscroll_req
.height
= 2;
342 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
343 (scroll_window
->vscrollbar
, &vscroll_req
);
345 GtkRequisition hscroll_req
;
346 hscroll_req
.width
= 2;
347 hscroll_req
.height
= 2;
348 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
349 (scroll_window
->hscrollbar
, &hscroll_req
);
351 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(widget
)->klass
);
353 if (scroll_window
->vscrollbar_visible
)
355 dw
+= vscroll_req
.width
;
356 dw
+= scroll_class
->scrollbar_spacing
;
359 if (scroll_window
->hscrollbar_visible
)
361 dh
+= hscroll_req
.height
;
362 dh
+= scroll_class
->scrollbar_spacing
;
368 if (GTK_WIDGET_NO_WINDOW (widget
))
370 dx
+= widget
->allocation
.x
;
371 dy
+= widget
->allocation
.y
;
374 if (win
->HasFlag(wxRAISED_BORDER
))
376 gtk_draw_shadow( widget
->style
,
381 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
385 if (win
->HasFlag(wxSUNKEN_BORDER
))
387 gtk_draw_shadow( widget
->style
,
392 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
396 if (win
->HasFlag(wxSIMPLE_BORDER
))
399 gc
= gdk_gc_new( widget
->window
);
400 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
401 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
403 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
409 //-----------------------------------------------------------------------------
410 // "expose_event" of m_widget
411 //-----------------------------------------------------------------------------
413 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
415 if (gdk_event
->count
> 0) return FALSE
;
417 draw_frame( widget
, win
);
422 //-----------------------------------------------------------------------------
423 // "draw" of m_widget
424 //-----------------------------------------------------------------------------
426 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
428 draw_frame( widget
, win
);
431 //-----------------------------------------------------------------------------
432 // key code mapping routines
433 //-----------------------------------------------------------------------------
435 static long map_to_unmodified_wx_keysym( KeySym keysym
)
442 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
444 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
450 case GDK_Super_R
: key_code
= WXK_ALT
; break;
451 case GDK_Menu
: key_code
= WXK_MENU
; break;
452 case GDK_Help
: key_code
= WXK_HELP
; break;
453 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
454 case GDK_ISO_Left_Tab
:
455 case GDK_Tab
: key_code
= WXK_TAB
; break;
456 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
457 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
458 case GDK_Return
: key_code
= WXK_RETURN
; break;
459 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
460 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
461 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
462 case GDK_Delete
: key_code
= WXK_DELETE
; break;
463 case GDK_Home
: key_code
= WXK_HOME
; break;
464 case GDK_Left
: key_code
= WXK_LEFT
; break;
465 case GDK_Up
: key_code
= WXK_UP
; break;
466 case GDK_Right
: key_code
= WXK_RIGHT
; break;
467 case GDK_Down
: key_code
= WXK_DOWN
; break;
468 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
469 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
470 case GDK_Next
: key_code
= WXK_NEXT
; break;
471 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
472 case GDK_End
: key_code
= WXK_END
; break;
473 case GDK_Begin
: key_code
= WXK_HOME
; break;
474 case GDK_Select
: key_code
= WXK_SELECT
; break;
475 case GDK_Print
: key_code
= WXK_PRINT
; break;
476 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
477 case GDK_Insert
: key_code
= WXK_INSERT
; break;
478 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
480 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
481 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
482 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
483 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
484 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
485 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
486 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
487 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
488 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
489 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
490 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
491 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
492 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
493 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
494 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
495 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
496 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
497 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
498 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
499 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
500 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
501 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
502 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
503 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
504 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
505 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
506 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
507 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
508 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
509 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
510 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
511 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
512 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
513 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
514 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
515 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
516 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
518 case GDK_F1
: key_code
= WXK_F1
; break;
519 case GDK_F2
: key_code
= WXK_F2
; break;
520 case GDK_F3
: key_code
= WXK_F3
; break;
521 case GDK_F4
: key_code
= WXK_F4
; break;
522 case GDK_F5
: key_code
= WXK_F5
; break;
523 case GDK_F6
: key_code
= WXK_F6
; break;
524 case GDK_F7
: key_code
= WXK_F7
; break;
525 case GDK_F8
: key_code
= WXK_F8
; break;
526 case GDK_F9
: key_code
= WXK_F9
; break;
527 case GDK_F10
: key_code
= WXK_F10
; break;
528 case GDK_F11
: key_code
= WXK_F11
; break;
529 case GDK_F12
: key_code
= WXK_F12
; break;
532 if ((keysym
& 0xF000) == 0)
534 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
535 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
536 key_code
= (guint
)keysym
;
544 static long map_to_wx_keysym( KeySym keysym
)
550 case GDK_Menu
: key_code
= WXK_MENU
; break;
551 case GDK_Help
: key_code
= WXK_HELP
; break;
552 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
553 case GDK_ISO_Left_Tab
:
554 case GDK_Tab
: key_code
= WXK_TAB
; break;
555 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
556 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
557 case GDK_Return
: key_code
= WXK_RETURN
; break;
558 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
559 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
560 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
561 case GDK_Delete
: key_code
= WXK_DELETE
; break;
562 case GDK_Home
: key_code
= WXK_HOME
; break;
563 case GDK_Left
: key_code
= WXK_LEFT
; break;
564 case GDK_Up
: key_code
= WXK_UP
; break;
565 case GDK_Right
: key_code
= WXK_RIGHT
; break;
566 case GDK_Down
: key_code
= WXK_DOWN
; break;
567 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
568 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
569 case GDK_Next
: key_code
= WXK_NEXT
; break;
570 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
571 case GDK_End
: key_code
= WXK_END
; break;
572 case GDK_Begin
: key_code
= WXK_HOME
; break;
573 case GDK_Select
: key_code
= WXK_SELECT
; break;
574 case GDK_Print
: key_code
= WXK_PRINT
; break;
575 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
576 case GDK_Insert
: key_code
= WXK_INSERT
; break;
577 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
579 case GDK_KP_0
: key_code
= '0'; break;
580 case GDK_KP_1
: key_code
= '1'; break;
581 case GDK_KP_2
: key_code
= '2'; break;
582 case GDK_KP_3
: key_code
= '3'; break;
583 case GDK_KP_4
: key_code
= '4'; break;
584 case GDK_KP_5
: key_code
= '5'; break;
585 case GDK_KP_6
: key_code
= '6'; break;
586 case GDK_KP_7
: key_code
= '7'; break;
587 case GDK_KP_8
: key_code
= '8'; break;
588 case GDK_KP_9
: key_code
= '9'; break;
589 case GDK_KP_Space
: key_code
= ' '; break;
590 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
591 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
592 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
593 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
594 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
595 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
596 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
597 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
598 case GDK_KP_Up
: key_code
= WXK_UP
; break;
599 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
600 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
601 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
602 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
603 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
604 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
605 case GDK_KP_End
: key_code
= WXK_END
; break;
606 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
607 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
608 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
609 case GDK_KP_Equal
: key_code
= '='; break;
610 case GDK_KP_Multiply
: key_code
= '*'; break;
611 case GDK_KP_Add
: key_code
= '+'; break;
612 case GDK_KP_Separator
: key_code
= ','; break;
613 case GDK_KP_Subtract
: key_code
= '-'; break;
614 case GDK_KP_Decimal
: key_code
= '.'; break;
615 case GDK_KP_Divide
: key_code
= '/'; break;
617 case GDK_F1
: key_code
= WXK_F1
; break;
618 case GDK_F2
: key_code
= WXK_F2
; break;
619 case GDK_F3
: key_code
= WXK_F3
; break;
620 case GDK_F4
: key_code
= WXK_F4
; break;
621 case GDK_F5
: key_code
= WXK_F5
; break;
622 case GDK_F6
: key_code
= WXK_F6
; break;
623 case GDK_F7
: key_code
= WXK_F7
; break;
624 case GDK_F8
: key_code
= WXK_F8
; break;
625 case GDK_F9
: key_code
= WXK_F9
; break;
626 case GDK_F10
: key_code
= WXK_F10
; break;
627 case GDK_F11
: key_code
= WXK_F11
; break;
628 case GDK_F12
: key_code
= WXK_F12
; break;
631 if ((keysym
& 0xF000) == 0)
633 key_code
= (guint
)keysym
;
641 //-----------------------------------------------------------------------------
642 // "expose_event" of m_wxwindow
643 //-----------------------------------------------------------------------------
645 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
650 wxapp_install_idle_handler();
653 if (win->GetName() == wxT("panel"))
655 wxPrintf( wxT("OnExpose from ") );
656 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
657 wxPrintf( win->GetClassInfo()->GetClassName() );
658 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
659 (int)gdk_event->area.y,
660 (int)gdk_event->area.width,
661 (int)gdk_event->area.height );
665 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
667 gdk_event
->area
.width
,
668 gdk_event
->area
.height
);
670 if (gdk_event
->count
== 0)
672 wxEraseEvent
eevent( win
->GetId() );
673 eevent
.SetEventObject( win
);
674 win
->GetEventHandler()->ProcessEvent(eevent
);
676 wxPaintEvent
event( win
->GetId() );
677 event
.SetEventObject( win
);
678 win
->GetEventHandler()->ProcessEvent( event
);
680 win
->GetUpdateRegion().Clear();
683 /* The following code will result in all window-less widgets
684 being redrawn if the wxWindows class is given a chance to
685 paint *anything* because it will then be allowed to paint
686 over the window-less widgets */
688 GtkPizza
*pizza
= GTK_PIZZA (widget
);
690 GList
*children
= pizza
->children
;
693 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
694 children
= children
->next
;
696 GdkEventExpose child_event
= *gdk_event
;
698 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
699 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
700 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
702 child_event
.area
.x
= child
->widget
->allocation
.x
;
703 child_event
.area
.y
= child
->widget
->allocation
.y
;
704 child_event
.area
.width
= child
->widget
->allocation
.width
;
705 child_event
.area
.height
= child
->widget
->allocation
.height
;
706 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
713 //-----------------------------------------------------------------------------
714 // "event" of m_wxwindow
715 //-----------------------------------------------------------------------------
717 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
718 expose events. We need them, of course, so we override the main event
719 procedure in GtkWidget by giving our own handler for all system events.
720 There, we look for expose events ourselves whereas all other events are
723 gint
gtk_window_event_event_callback( GtkWidget
*widget
, GdkEventExpose
*event
, wxWindow
*win
)
725 if (event
->type
== GDK_EXPOSE
)
727 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
734 //-----------------------------------------------------------------------------
735 // "draw" of m_wxwindow
736 //-----------------------------------------------------------------------------
738 /* This callback is a complete replacement of the gtk_pizza_draw() function,
741 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
746 wxapp_install_idle_handler();
749 if (win->GetName() == wxT("panel"))
751 wxPrintf( wxT("OnDraw from ") );
752 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
753 wxPrintf( win->GetClassInfo()->GetClassName() );
754 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
761 GtkPizza
*pizza
= GTK_PIZZA (widget
);
763 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
764 (pizza
->clear_on_draw
))
766 gdk_window_clear_area( pizza
->bin_window
,
767 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
770 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
772 win
->m_clipPaintRegion
= TRUE
;
774 wxEraseEvent
eevent( win
->GetId() );
775 eevent
.SetEventObject( win
);
776 win
->GetEventHandler()->ProcessEvent(eevent
);
778 wxPaintEvent
event( win
->GetId() );
779 event
.SetEventObject( win
);
780 win
->GetEventHandler()->ProcessEvent( event
);
782 win
->GetUpdateRegion().Clear();
784 win
->m_clipPaintRegion
= FALSE
;
787 GList
*children
= pizza
->children
;
790 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
791 children
= children
->next
;
793 GdkRectangle child_area
;
794 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
796 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
801 //-----------------------------------------------------------------------------
802 // "key_press_event" from any window
803 //-----------------------------------------------------------------------------
805 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
810 wxapp_install_idle_handler();
812 if (!win
->m_hasVMT
) return FALSE
;
813 if (g_blockEventsOnDrag
) return FALSE
;
818 tmp += (char)gdk_event->keyval;
819 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
820 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
825 GdkModifierType state
;
826 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
830 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
831 /* sending unknown key events doesn't really make sense */
832 if (key_code
== 0) return FALSE
;
834 wxKeyEvent
event( wxEVT_KEY_DOWN
);
835 event
.SetTimestamp( gdk_event
->time
);
836 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
837 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
838 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
839 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
840 event
.m_keyCode
= key_code
;
841 event
.m_scanCode
= gdk_event
->keyval
;
844 event
.SetEventObject( win
);
845 ret
= win
->GetEventHandler()->ProcessEvent( event
);
850 wxWindow
*ancestor
= win
;
853 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
856 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
857 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
860 if (ancestor
->IsTopLevel())
862 ancestor
= ancestor
->GetParent();
865 #endif // wxUSE_ACCEL
867 /* wxMSW doesn't send char events with Alt pressed */
868 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
869 will only be sent if it is not in an accelerator table. */
870 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
875 wxKeyEvent
event2( wxEVT_CHAR
);
876 event2
.SetTimestamp( gdk_event
->time
);
877 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
878 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
879 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
880 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
881 event2
.m_keyCode
= key_code
;
882 event2
.m_scanCode
= gdk_event
->keyval
;
885 event2
.SetEventObject( win
);
886 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
889 /* win is a control: tab can be propagated up */
891 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
892 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
893 // have this style, yet choose not to process this particular TAB in which
894 // case TAB must still work as a navigational character
896 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
898 (win
->GetParent()) &&
899 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
901 wxNavigationKeyEvent new_event
;
902 new_event
.SetEventObject( win
->GetParent() );
903 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
904 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
905 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
906 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
907 new_event
.SetCurrentFocus( win
);
908 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
911 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
913 (gdk_event
->keyval
== GDK_Escape
) )
915 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
916 new_event
.SetEventObject( win
);
917 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
920 #if (GTK_MINOR_VERSION > 0)
921 /* Pressing F10 will activate the menu bar of the top frame. */
925 (gdk_event->keyval == GDK_F10) )
927 wxWindow *ancestor = win;
930 if (wxIsKindOf(ancestor,wxFrame))
932 wxFrame *frame = (wxFrame*) ancestor;
933 wxMenuBar *menubar = frame->GetMenuBar();
936 wxNode *node = menubar->GetMenus().First();
939 wxMenu *firstMenu = (wxMenu*) node->Data();
940 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
946 ancestor = ancestor->GetParent();
954 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
961 //-----------------------------------------------------------------------------
962 // "key_release_event" from any window
963 //-----------------------------------------------------------------------------
965 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
970 wxapp_install_idle_handler();
972 if (!win
->m_hasVMT
) return FALSE
;
973 if (g_blockEventsOnDrag
) return FALSE
;
976 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
977 if (gdk_event->state & GDK_SHIFT_MASK)
978 printf( "ShiftDown.\n" );
980 printf( "ShiftUp.\n" );
981 if (gdk_event->state & GDK_CONTROL_MASK)
982 printf( "ControlDown.\n" );
984 printf( "ControlUp.\n" );
988 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
990 /* sending unknown key events doesn't really make sense */
991 if (key_code
== 0) return FALSE
;
995 GdkModifierType state
;
996 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
998 wxKeyEvent
event( wxEVT_KEY_UP
);
999 event
.SetTimestamp( gdk_event
->time
);
1000 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1001 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1002 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1003 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1004 event
.m_keyCode
= key_code
;
1005 event
.m_scanCode
= gdk_event
->keyval
;
1008 event
.SetEventObject( win
);
1010 if (win
->GetEventHandler()->ProcessEvent( event
))
1012 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1019 // ----------------------------------------------------------------------------
1020 // mouse event processing helper
1021 // ----------------------------------------------------------------------------
1023 static void AdjustEventButtonState(wxMouseEvent
& event
)
1025 // GDK reports the old state of the button for a button press event, but
1026 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1027 // for a LEFT_DOWN event, not FALSE, so we will invert
1028 // left/right/middleDown for the corresponding click events
1029 switch ( event
.GetEventType() )
1031 case wxEVT_LEFT_DOWN
:
1032 case wxEVT_LEFT_DCLICK
:
1034 event
.m_leftDown
= !event
.m_leftDown
;
1037 case wxEVT_MIDDLE_DOWN
:
1038 case wxEVT_MIDDLE_DCLICK
:
1039 case wxEVT_MIDDLE_UP
:
1040 event
.m_middleDown
= !event
.m_middleDown
;
1043 case wxEVT_RIGHT_DOWN
:
1044 case wxEVT_RIGHT_DCLICK
:
1045 case wxEVT_RIGHT_UP
:
1046 event
.m_rightDown
= !event
.m_rightDown
;
1051 //-----------------------------------------------------------------------------
1052 // "button_press_event"
1053 //-----------------------------------------------------------------------------
1055 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1060 wxapp_install_idle_handler();
1063 wxPrintf( wxT("1) OnButtonPress from ") );
1064 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1065 wxPrintf( win->GetClassInfo()->GetClassName() );
1066 wxPrintf( wxT(".\n") );
1068 if (!win
->m_hasVMT
) return FALSE
;
1069 if (g_blockEventsOnDrag
) return TRUE
;
1070 if (g_blockEventsOnScroll
) return TRUE
;
1072 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1074 if (win
->m_wxwindow
)
1076 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1078 gtk_widget_grab_focus (win
->m_wxwindow
);
1081 wxPrintf( wxT("GrabFocus from ") );
1082 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1083 wxPrintf( win->GetClassInfo()->GetClassName() );
1084 wxPrintf( wxT(".\n") );
1090 wxEventType event_type
= wxEVT_NULL
;
1092 if (gdk_event
->button
== 1)
1094 switch (gdk_event
->type
)
1096 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1097 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1101 else if (gdk_event
->button
== 2)
1103 switch (gdk_event
->type
)
1105 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1106 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1110 else if (gdk_event
->button
== 3)
1112 switch (gdk_event
->type
)
1114 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1115 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1120 if ( event_type
== wxEVT_NULL
)
1122 // unknown mouse button or click type
1126 wxMouseEvent
event( event_type
);
1127 event
.SetTimestamp( gdk_event
->time
);
1128 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1129 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1130 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1131 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1132 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1133 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1134 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1136 event
.m_x
= (wxCoord
)gdk_event
->x
;
1137 event
.m_y
= (wxCoord
)gdk_event
->y
;
1139 AdjustEventButtonState(event
);
1141 // Some control don't have their own X window and thus cannot get
1144 if (!g_captureWindow
)
1146 wxCoord x
= event
.m_x
;
1147 wxCoord y
= event
.m_y
;
1148 if (win
->m_wxwindow
)
1150 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1151 x
+= pizza
->xoffset
;
1152 y
+= pizza
->yoffset
;
1155 wxNode
*node
= win
->GetChildren().First();
1158 wxWindow
*child
= (wxWindow
*)node
->Data();
1160 node
= node
->Next();
1161 if (!child
->IsShown())
1164 if (child
->m_isStaticBox
)
1166 // wxStaticBox is transparent in the box itself
1167 int xx1
= child
->m_x
;
1168 int yy1
= child
->m_y
;
1169 int xx2
= child
->m_x
+ child
->m_width
;
1170 int yy2
= child
->m_x
+ child
->m_height
;
1173 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1175 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1177 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1179 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1182 event
.m_x
-= child
->m_x
;
1183 event
.m_y
-= child
->m_y
;
1190 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1191 (child
->m_x
<= x
) &&
1192 (child
->m_y
<= y
) &&
1193 (child
->m_x
+child
->m_width
>= x
) &&
1194 (child
->m_y
+child
->m_height
>= y
))
1197 event
.m_x
-= child
->m_x
;
1198 event
.m_y
-= child
->m_y
;
1205 event
.SetEventObject( win
);
1207 gs_timeLastClick
= gdk_event
->time
;
1210 wxPrintf( wxT("2) OnButtonPress from ") );
1211 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1212 wxPrintf( win->GetClassInfo()->GetClassName() );
1213 wxPrintf( wxT(".\n") );
1216 if (win
->GetEventHandler()->ProcessEvent( event
))
1218 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1225 //-----------------------------------------------------------------------------
1226 // "button_release_event"
1227 //-----------------------------------------------------------------------------
1229 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1234 wxapp_install_idle_handler();
1236 if (!win
->m_hasVMT
) return FALSE
;
1237 if (g_blockEventsOnDrag
) return FALSE
;
1238 if (g_blockEventsOnScroll
) return FALSE
;
1240 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1243 printf( "OnButtonRelease from " );
1244 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1245 printf( win->GetClassInfo()->GetClassName() );
1249 wxEventType event_type
= wxEVT_NULL
;
1251 switch (gdk_event
->button
)
1253 case 1: event_type
= wxEVT_LEFT_UP
; break;
1254 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1255 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1256 default: return FALSE
;
1259 wxMouseEvent
event( event_type
);
1260 event
.SetTimestamp( gdk_event
->time
);
1261 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1262 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1263 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1264 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1265 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1266 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1267 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1268 event
.m_x
= (wxCoord
)gdk_event
->x
;
1269 event
.m_y
= (wxCoord
)gdk_event
->y
;
1271 AdjustEventButtonState(event
);
1273 // Some control don't have their own X window and thus cannot get
1276 if (!g_captureWindow
)
1278 wxCoord x
= event
.m_x
;
1279 wxCoord y
= event
.m_y
;
1280 if (win
->m_wxwindow
)
1282 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1283 x
+= pizza
->xoffset
;
1284 y
+= pizza
->yoffset
;
1287 wxNode
*node
= win
->GetChildren().First();
1290 wxWindow
*child
= (wxWindow
*)node
->Data();
1292 node
= node
->Next();
1293 if (!child
->IsShown())
1296 if (child
->m_isStaticBox
)
1298 // wxStaticBox is transparent in the box itself
1299 int xx1
= child
->m_x
;
1300 int yy1
= child
->m_y
;
1301 int xx2
= child
->m_x
+ child
->m_width
;
1302 int yy2
= child
->m_x
+ child
->m_height
;
1305 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1307 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1309 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1311 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1314 event
.m_x
-= child
->m_x
;
1315 event
.m_y
-= child
->m_y
;
1322 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1323 (child
->m_x
<= x
) &&
1324 (child
->m_y
<= y
) &&
1325 (child
->m_x
+child
->m_width
>= x
) &&
1326 (child
->m_y
+child
->m_height
>= y
))
1329 event
.m_x
-= child
->m_x
;
1330 event
.m_y
-= child
->m_y
;
1337 event
.SetEventObject( win
);
1339 if (win
->GetEventHandler()->ProcessEvent( event
))
1341 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1348 //-----------------------------------------------------------------------------
1349 // "motion_notify_event"
1350 //-----------------------------------------------------------------------------
1352 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1357 wxapp_install_idle_handler();
1359 if (!win
->m_hasVMT
) return FALSE
;
1360 if (g_blockEventsOnDrag
) return FALSE
;
1361 if (g_blockEventsOnScroll
) return FALSE
;
1363 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1365 if (gdk_event
->is_hint
)
1369 GdkModifierType state
;
1370 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1376 printf( "OnMotion from " );
1377 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1378 printf( win->GetClassInfo()->GetClassName() );
1382 wxMouseEvent
event( wxEVT_MOTION
);
1383 event
.SetTimestamp( gdk_event
->time
);
1384 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1385 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1386 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1387 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1388 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1389 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1390 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1392 event
.m_x
= (wxCoord
)gdk_event
->x
;
1393 event
.m_y
= (wxCoord
)gdk_event
->y
;
1395 // Some control don't have their own X window and thus cannot get
1398 if (!g_captureWindow
)
1400 wxCoord x
= event
.m_x
;
1401 wxCoord y
= event
.m_y
;
1402 if (win
->m_wxwindow
)
1404 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1405 x
+= pizza
->xoffset
;
1406 y
+= pizza
->yoffset
;
1409 wxNode
*node
= win
->GetChildren().First();
1412 wxWindow
*child
= (wxWindow
*)node
->Data();
1414 node
= node
->Next();
1415 if (!child
->IsShown())
1418 if (child
->m_isStaticBox
)
1420 // wxStaticBox is transparent in the box itself
1421 int xx1
= child
->m_x
;
1422 int yy1
= child
->m_y
;
1423 int xx2
= child
->m_x
+ child
->m_width
;
1424 int yy2
= child
->m_x
+ child
->m_height
;
1427 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1429 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1431 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1433 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1436 event
.m_x
-= child
->m_x
;
1437 event
.m_y
-= child
->m_y
;
1444 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1445 (child
->m_x
<= x
) &&
1446 (child
->m_y
<= y
) &&
1447 (child
->m_x
+child
->m_width
>= x
) &&
1448 (child
->m_y
+child
->m_height
>= y
))
1451 event
.m_x
-= child
->m_x
;
1452 event
.m_y
-= child
->m_y
;
1459 event
.SetEventObject( win
);
1461 if (win
->GetEventHandler()->ProcessEvent( event
))
1463 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1470 //-----------------------------------------------------------------------------
1472 //-----------------------------------------------------------------------------
1474 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1479 wxapp_install_idle_handler();
1481 if (!win
->m_hasVMT
) return FALSE
;
1482 if (g_blockEventsOnDrag
) return FALSE
;
1484 switch ( g_sendActivateEvent
)
1487 // we've got focus from outside, synthtize wxActivateEvent
1488 g_sendActivateEvent
= 1;
1492 // another our window just lost focus, it was already ours before
1493 // - don't send any wxActivateEvent
1494 g_sendActivateEvent
= -1;
1498 g_focusWindow
= win
;
1501 printf( "OnSetFocus from " );
1502 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1503 printf( win->GetClassInfo()->GetClassName() );
1505 printf( WXSTRINGCAST win->GetLabel() );
1509 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1512 panel
->SetLastFocus(win
);
1517 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1521 // caret needs to be informed about focus change
1522 wxCaret
*caret
= win
->GetCaret();
1525 caret
->OnSetFocus();
1527 #endif // wxUSE_CARET
1529 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1530 event
.SetEventObject( win
);
1532 if (win
->GetEventHandler()->ProcessEvent( event
))
1534 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1541 //-----------------------------------------------------------------------------
1542 // "focus_out_event"
1543 //-----------------------------------------------------------------------------
1545 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1550 wxapp_install_idle_handler();
1552 if (!win
->m_hasVMT
) return FALSE
;
1553 if (g_blockEventsOnDrag
) return FALSE
;
1555 // if the focus goes out of our app alltogether, OnIdle() will send
1556 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1557 // g_sendActivateEvent to -1
1558 g_sendActivateEvent
= 0;
1560 wxWindow
*winFocus
= FindFocusedChild(win
);
1564 g_focusWindow
= (wxWindow
*)NULL
;
1567 printf( "OnKillFocus from " );
1568 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1569 printf( win->GetClassInfo()->GetClassName() );
1579 // caret needs to be informed about focus change
1580 wxCaret
*caret
= win
->GetCaret();
1583 caret
->OnKillFocus();
1585 #endif // wxUSE_CARET
1587 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1588 event
.SetEventObject( win
);
1590 if (win
->GetEventHandler()->ProcessEvent( event
))
1592 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1599 //-----------------------------------------------------------------------------
1600 // "enter_notify_event"
1601 //-----------------------------------------------------------------------------
1603 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1608 wxapp_install_idle_handler();
1610 if (!win
->m_hasVMT
) return FALSE
;
1611 if (g_blockEventsOnDrag
) return FALSE
;
1613 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1615 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1616 #if (GTK_MINOR_VERSION > 0)
1617 event
.SetTimestamp( gdk_event
->time
);
1619 event
.SetEventObject( win
);
1623 GdkModifierType state
= (GdkModifierType
)0;
1625 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1627 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1628 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1629 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1630 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1631 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1632 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1633 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1638 if (win
->GetEventHandler()->ProcessEvent( event
))
1640 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1647 //-----------------------------------------------------------------------------
1648 // "leave_notify_event"
1649 //-----------------------------------------------------------------------------
1651 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1656 wxapp_install_idle_handler();
1658 if (!win
->m_hasVMT
) return FALSE
;
1659 if (g_blockEventsOnDrag
) return FALSE
;
1661 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1663 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1664 #if (GTK_MINOR_VERSION > 0)
1665 event
.SetTimestamp( gdk_event
->time
);
1667 event
.SetEventObject( win
);
1671 GdkModifierType state
= (GdkModifierType
)0;
1673 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1675 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1676 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1677 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1678 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1679 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1680 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1681 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1686 if (win
->GetEventHandler()->ProcessEvent( event
))
1688 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1695 //-----------------------------------------------------------------------------
1696 // "value_changed" from m_vAdjust
1697 //-----------------------------------------------------------------------------
1699 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1704 wxapp_install_idle_handler();
1706 if (g_blockEventsOnDrag
) return;
1708 if (!win
->m_hasVMT
) return;
1710 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1711 if (fabs(diff
) < 0.2) return;
1713 win
->m_oldVerticalPos
= adjust
->value
;
1715 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1716 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1718 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1719 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1720 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1721 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1722 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1724 int value
= (int)(adjust
->value
+0.5);
1726 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1727 event
.SetEventObject( win
);
1728 win
->GetEventHandler()->ProcessEvent( event
);
1731 //-----------------------------------------------------------------------------
1732 // "value_changed" from m_hAdjust
1733 //-----------------------------------------------------------------------------
1735 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1740 wxapp_install_idle_handler();
1742 if (g_blockEventsOnDrag
) return;
1743 if (!win
->m_hasVMT
) return;
1745 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1746 if (fabs(diff
) < 0.2) return;
1748 win
->m_oldHorizontalPos
= adjust
->value
;
1750 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1751 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1753 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1754 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1755 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1756 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1757 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1759 int value
= (int)(adjust
->value
+0.5);
1761 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1762 event
.SetEventObject( win
);
1763 win
->GetEventHandler()->ProcessEvent( event
);
1766 //-----------------------------------------------------------------------------
1767 // "button_press_event" from scrollbar
1768 //-----------------------------------------------------------------------------
1770 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1771 GdkEventButton
*gdk_event
,
1777 wxapp_install_idle_handler();
1780 g_blockEventsOnScroll
= TRUE
;
1781 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1786 //-----------------------------------------------------------------------------
1787 // "button_release_event" from scrollbar
1788 //-----------------------------------------------------------------------------
1790 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1791 GdkEventButton
*WXUNUSED(gdk_event
),
1796 // don't test here as we can release the mouse while being over
1797 // a different window than the slider
1799 // if (gdk_event->window != widget->slider) return FALSE;
1801 g_blockEventsOnScroll
= FALSE
;
1803 if (win
->m_isScrolling
)
1805 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
1809 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1810 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1812 value
= (int)(win
->m_hAdjust
->value
+0.5);
1815 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1817 value
= (int)(win
->m_vAdjust
->value
+0.5);
1821 wxScrollWinEvent
event( command
, value
, dir
);
1822 event
.SetEventObject( win
);
1823 win
->GetEventHandler()->ProcessEvent( event
);
1826 win
->m_isScrolling
= FALSE
;
1831 // ----------------------------------------------------------------------------
1832 // this wxWindowBase function is implemented here (in platform-specific file)
1833 // because it is static and so couldn't be made virtual
1834 // ----------------------------------------------------------------------------
1836 wxWindow
*wxWindowBase::FindFocus()
1838 return g_focusWindow
;
1841 //-----------------------------------------------------------------------------
1842 // "realize" from m_widget
1843 //-----------------------------------------------------------------------------
1845 /* We cannot set colours and fonts before the widget has
1846 been realized, so we do this directly after realization. */
1849 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1854 wxapp_install_idle_handler();
1856 if (win
->m_delayedBackgroundColour
)
1857 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1859 if (win
->m_delayedForegroundColour
)
1860 win
->SetForegroundColour( win
->GetForegroundColour() );
1862 wxWindowCreateEvent
event( win
);
1863 event
.SetEventObject( win
);
1864 win
->GetEventHandler()->ProcessEvent( event
);
1869 //-----------------------------------------------------------------------------
1871 //-----------------------------------------------------------------------------
1874 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
1875 GtkAllocation
*WXUNUSED(alloc
),
1879 wxapp_install_idle_handler();
1881 if (!win
->m_hasScrolling
) return;
1883 int client_width
= 0;
1884 int client_height
= 0;
1885 win
->GetClientSize( &client_width
, &client_height
);
1886 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
1889 win
->m_oldClientWidth
= client_width
;
1890 win
->m_oldClientHeight
= client_height
;
1892 if (!win
->m_nativeSizeEvent
)
1894 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
1895 event
.SetEventObject( win
);
1896 win
->GetEventHandler()->ProcessEvent( event
);
1902 #define WXUNUSED_UNLESS_XIM(param) param
1904 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1907 /* Resize XIM window */
1910 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1911 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1912 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1915 wxapp_install_idle_handler();
1921 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1925 gdk_window_get_size (widget
->window
, &width
, &height
);
1926 win
->m_icattr
->preedit_area
.width
= width
;
1927 win
->m_icattr
->preedit_area
.height
= height
;
1928 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
1933 //-----------------------------------------------------------------------------
1934 // "realize" from m_wxwindow
1935 //-----------------------------------------------------------------------------
1937 /* Initialize XIM support */
1940 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1941 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1944 wxapp_install_idle_handler();
1947 if (win
->m_ic
) return FALSE
;
1948 if (!widget
) return FALSE
;
1949 if (!gdk_im_ready()) return FALSE
;
1951 win
->m_icattr
= gdk_ic_attr_new();
1952 if (!win
->m_icattr
) return FALSE
;
1956 GdkColormap
*colormap
;
1957 GdkICAttr
*attr
= win
->m_icattr
;
1958 unsigned attrmask
= GDK_IC_ALL_REQ
;
1960 GdkIMStyle supported_style
= (GdkIMStyle
)
1961 (GDK_IM_PREEDIT_NONE
|
1962 GDK_IM_PREEDIT_NOTHING
|
1963 GDK_IM_PREEDIT_POSITION
|
1964 GDK_IM_STATUS_NONE
|
1965 GDK_IM_STATUS_NOTHING
);
1967 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1968 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
1970 attr
->style
= style
= gdk_im_decide_style (supported_style
);
1971 attr
->client_window
= widget
->window
;
1973 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
1974 gtk_widget_get_default_colormap ())
1976 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
1977 attr
->preedit_colormap
= colormap
;
1980 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
1981 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
1982 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
1983 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
1985 switch (style
& GDK_IM_PREEDIT_MASK
)
1987 case GDK_IM_PREEDIT_POSITION
:
1988 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1990 g_warning ("over-the-spot style requires fontset");
1994 gdk_window_get_size (widget
->window
, &width
, &height
);
1996 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
1997 attr
->spot_location
.x
= 0;
1998 attr
->spot_location
.y
= height
;
1999 attr
->preedit_area
.x
= 0;
2000 attr
->preedit_area
.y
= 0;
2001 attr
->preedit_area
.width
= width
;
2002 attr
->preedit_area
.height
= height
;
2003 attr
->preedit_fontset
= widget
->style
->font
;
2008 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2010 if (win
->m_ic
== NULL
)
2011 g_warning ("Can't create input context.");
2014 mask
= gdk_window_get_events (widget
->window
);
2015 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2016 gdk_window_set_events (widget
->window
, mask
);
2018 if (GTK_WIDGET_HAS_FOCUS(widget
))
2019 gdk_im_begin (win
->m_ic
, widget
->window
);
2026 //-----------------------------------------------------------------------------
2027 // InsertChild for wxWindow.
2028 //-----------------------------------------------------------------------------
2030 /* Callback for wxWindow. This very strange beast has to be used because
2031 * C++ has no virtual methods in a constructor. We have to emulate a
2032 * virtual function here as wxNotebook requires a different way to insert
2033 * a child in it. I had opted for creating a wxNotebookPage window class
2034 * which would have made this superfluous (such in the MDI window system),
2035 * but no-one was listening to me... */
2037 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
2039 /* the window might have been scrolled already, do we
2040 have to adapt the position */
2041 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2042 child
->m_x
+= pizza
->xoffset
;
2043 child
->m_y
+= pizza
->yoffset
;
2045 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2046 GTK_WIDGET(child
->m_widget
),
2053 //-----------------------------------------------------------------------------
2055 //-----------------------------------------------------------------------------
2057 wxWindow
* wxGetActiveWindow()
2059 return g_focusWindow
;
2062 //-----------------------------------------------------------------------------
2064 //-----------------------------------------------------------------------------
2066 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2068 void wxWindow::Init()
2074 m_widget
= (GtkWidget
*) NULL
;
2075 m_wxwindow
= (GtkWidget
*) NULL
;
2085 m_needParent
= TRUE
;
2086 m_isBeingDeleted
= FALSE
;
2089 m_nativeSizeEvent
= FALSE
;
2091 m_hasScrolling
= FALSE
;
2092 m_isScrolling
= FALSE
;
2094 m_hAdjust
= (GtkAdjustment
*) NULL
;
2095 m_vAdjust
= (GtkAdjustment
*) NULL
;
2096 m_oldHorizontalPos
= 0.0;
2097 m_oldVerticalPos
= 0.0;
2100 m_widgetStyle
= (GtkStyle
*) NULL
;
2102 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2104 m_isStaticBox
= FALSE
;
2105 m_isRadioButton
= FALSE
;
2107 m_acceptsFocus
= FALSE
;
2109 m_clipPaintRegion
= FALSE
;
2111 m_cursor
= *wxSTANDARD_CURSOR
;
2113 m_delayedForegroundColour
= FALSE
;
2114 m_delayedBackgroundColour
= FALSE
;
2117 m_ic
= (GdkIC
*) NULL
;
2118 m_icattr
= (GdkICAttr
*) NULL
;
2122 wxWindow::wxWindow()
2127 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
2128 const wxPoint
&pos
, const wxSize
&size
,
2129 long style
, const wxString
&name
)
2133 Create( parent
, id
, pos
, size
, style
, name
);
2136 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
2137 const wxPoint
&pos
, const wxSize
&size
,
2138 long style
, const wxString
&name
)
2140 if (!PreCreation( parent
, pos
, size
) ||
2141 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2143 wxFAIL_MSG( wxT("wxWindow creation failed") );
2147 m_insertCallback
= wxInsertChildInWindow
;
2149 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2150 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2152 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2154 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2155 scroll_class
->scrollbar_spacing
= 0;
2157 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2159 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2160 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2162 m_wxwindow
= gtk_pizza_new();
2164 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2166 #if (GTK_MINOR_VERSION > 0)
2167 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2169 if (HasFlag(wxRAISED_BORDER
))
2171 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2173 else if (HasFlag(wxSUNKEN_BORDER
))
2175 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2177 else if (HasFlag(wxSIMPLE_BORDER
))
2179 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2183 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2185 #else // GTK_MINOR_VERSION == 0
2186 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2188 if (HasFlag(wxRAISED_BORDER
))
2190 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2192 else if (HasFlag(wxSUNKEN_BORDER
))
2194 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2198 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2200 #endif // GTK_MINOR_VERSION
2202 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2203 m_acceptsFocus
= TRUE
;
2205 #if (GTK_MINOR_VERSION == 0)
2206 // shut the viewport up
2207 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2208 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2209 #endif // GTK_MINOR_VERSION == 0
2211 // I _really_ don't want scrollbars in the beginning
2212 m_vAdjust
->lower
= 0.0;
2213 m_vAdjust
->upper
= 1.0;
2214 m_vAdjust
->value
= 0.0;
2215 m_vAdjust
->step_increment
= 1.0;
2216 m_vAdjust
->page_increment
= 1.0;
2217 m_vAdjust
->page_size
= 5.0;
2218 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2219 m_hAdjust
->lower
= 0.0;
2220 m_hAdjust
->upper
= 1.0;
2221 m_hAdjust
->value
= 0.0;
2222 m_hAdjust
->step_increment
= 1.0;
2223 m_hAdjust
->page_increment
= 1.0;
2224 m_hAdjust
->page_size
= 5.0;
2225 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2227 // these handlers block mouse events to any window during scrolling such as
2228 // motion events and prevent GTK and wxWindows from fighting over where the
2231 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2232 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2234 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2235 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2237 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2238 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2240 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2241 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2243 // these handlers get notified when screen updates are required either when
2244 // scrolling or when the window size (and therefore scrollbar configuration)
2247 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2248 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2249 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2250 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2252 gtk_widget_show( m_wxwindow
);
2255 m_parent
->DoAddChild( this );
2264 wxWindow::~wxWindow()
2266 m_isBeingDeleted
= TRUE
;
2275 m_parent
->RemoveChild( this );
2279 gdk_ic_destroy (m_ic
);
2281 gdk_ic_attr_destroy (m_icattr
);
2286 #if DISABLE_STYLE_IF_BROKEN_THEME
2287 // don't delete if it's a pixmap theme style
2288 if (!m_widgetStyle
->engine_data
)
2289 gtk_style_unref( m_widgetStyle
);
2291 m_widgetStyle
= (GtkStyle
*) NULL
;
2296 gtk_widget_destroy( m_wxwindow
);
2297 m_wxwindow
= (GtkWidget
*) NULL
;
2302 gtk_widget_destroy( m_widget
);
2303 m_widget
= (GtkWidget
*) NULL
;
2307 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2309 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2311 /* this turns -1 into 20 so that a minimal window is
2312 visible even although -1,-1 has been given as the
2313 size of the window. the same trick is used in other
2314 ports and should make debugging easier */
2315 m_width
= WidthDefault(size
.x
);
2316 m_height
= HeightDefault(size
.y
);
2321 /* some reasonable defaults */
2326 m_x
= (gdk_screen_width () - m_width
) / 2;
2327 if (m_x
< 10) m_x
= 10;
2331 m_y
= (gdk_screen_height () - m_height
) / 2;
2332 if (m_y
< 10) m_y
= 10;
2339 void wxWindow::PostCreation()
2341 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2347 /* these get reported to wxWindows -> wxPaintEvent */
2349 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2351 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2352 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2354 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2355 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2357 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2358 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2361 #if (GTK_MINOR_VERSION > 0)
2362 /* these are called when the "sunken" or "raised" borders are drawn */
2363 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2364 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2366 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2367 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2371 if (m_wxwindow
&& m_needParent
)
2373 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2374 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2376 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2377 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2381 // For dialogs and frames, we are interested mainly in
2382 // m_widget's focus.
2384 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2385 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2387 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2388 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2391 GtkWidget
*connect_widget
= GetConnectWidget();
2393 ConnectWidget( connect_widget
);
2395 /* We cannot set colours, fonts and cursors before the widget has
2396 been realized, so we do this directly after realization */
2397 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2398 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2402 /* Catch native resize events. */
2403 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2404 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2406 /* Initialize XIM support. */
2407 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2408 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2410 /* And resize XIM window. */
2411 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2412 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2418 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2420 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2421 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2423 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2424 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2426 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2427 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2429 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2430 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2432 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2433 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2435 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2436 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2438 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2439 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2442 bool wxWindow::Destroy()
2444 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2448 return wxWindowBase::Destroy();
2451 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2453 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2456 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2458 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2459 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2461 if (m_resizing
) return; /* I don't like recursions */
2464 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2466 /* don't set the size for children of wxNotebook, just take the values. */
2474 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2476 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2478 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2479 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2480 if (width
!= -1) m_width
= width
;
2481 if (height
!= -1) m_height
= height
;
2485 m_x
= x
+ pizza
->xoffset
;
2486 m_y
= y
+ pizza
->yoffset
;
2491 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2493 if (width
== -1) m_width
= 80;
2496 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2498 if (height
== -1) m_height
= 26;
2501 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2502 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2503 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2504 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2507 int bottom_border
= 0;
2509 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2511 /* the default button has a border around it */
2516 DoMoveWindow( m_x
-border
,
2519 m_height
+border
+bottom_border
);
2524 /* Sometimes the client area changes size without the
2525 whole windows's size changing, but if the whole
2526 windows's size doesn't change, no wxSizeEvent will
2527 normally be sent. Here we add an extra test if
2528 the client test has been changed and this will
2530 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2534 wxPrintf( "OnSize sent from " );
2535 if (GetClassInfo() && GetClassInfo()->GetClassName())
2536 wxPrintf( GetClassInfo()->GetClassName() );
2537 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2540 if (!m_nativeSizeEvent
)
2542 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2543 event
.SetEventObject( this );
2544 GetEventHandler()->ProcessEvent( event
);
2550 void wxWindow::OnInternalIdle()
2552 if ( g_sendActivateEvent
!= -1 )
2554 bool activate
= g_sendActivateEvent
!= 0;
2557 g_sendActivateEvent
= -1;
2559 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2560 event
.SetEventObject(this);
2562 (void)GetEventHandler()->ProcessEvent(event
);
2565 wxCursor cursor
= m_cursor
;
2566 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2570 /* I now set the cursor anew in every OnInternalIdle call
2571 as setting the cursor in a parent window also effects the
2572 windows above so that checking for the current cursor is
2577 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2579 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2581 if (!g_globalCursor
.Ok())
2582 cursor
= *wxSTANDARD_CURSOR
;
2584 window
= m_widget
->window
;
2585 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2586 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2592 GdkWindow
*window
= m_widget
->window
;
2593 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2594 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2602 void wxWindow::DoGetSize( int *width
, int *height
) const
2604 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2606 if (width
) (*width
) = m_width
;
2607 if (height
) (*height
) = m_height
;
2610 void wxWindow::DoSetClientSize( int width
, int height
)
2612 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2616 SetSize( width
, height
);
2623 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2625 /* when using GTK 1.2 we set the shadow border size to 2 */
2629 if (HasFlag(wxSIMPLE_BORDER
))
2631 /* when using GTK 1.2 we set the simple border size to 1 */
2638 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2640 GtkRequisition vscroll_req
;
2641 vscroll_req
.width
= 2;
2642 vscroll_req
.height
= 2;
2643 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
2644 (scroll_window
->vscrollbar
, &vscroll_req
);
2646 GtkRequisition hscroll_req
;
2647 hscroll_req
.width
= 2;
2648 hscroll_req
.height
= 2;
2649 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
2650 (scroll_window
->hscrollbar
, &hscroll_req
);
2652 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2654 if (scroll_window
->vscrollbar_visible
)
2656 dw
+= vscroll_req
.width
;
2657 dw
+= scroll_class
->scrollbar_spacing
;
2660 if (scroll_window
->hscrollbar_visible
)
2662 dh
+= hscroll_req
.height
;
2663 dh
+= scroll_class
->scrollbar_spacing
;
2667 SetSize( width
+dw
, height
+dh
);
2671 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2673 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2677 if (width
) (*width
) = m_width
;
2678 if (height
) (*height
) = m_height
;
2685 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2687 /* when using GTK 1.2 we set the shadow border size to 2 */
2691 if (HasFlag(wxSIMPLE_BORDER
))
2693 /* when using GTK 1.2 we set the simple border size to 1 */
2700 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2702 GtkRequisition vscroll_req
;
2703 vscroll_req
.width
= 2;
2704 vscroll_req
.height
= 2;
2705 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->vscrollbar
)->klass
)->size_request
)
2706 (scroll_window
->vscrollbar
, &vscroll_req
);
2708 GtkRequisition hscroll_req
;
2709 hscroll_req
.width
= 2;
2710 hscroll_req
.height
= 2;
2711 (* GTK_WIDGET_CLASS( GTK_OBJECT(scroll_window
->hscrollbar
)->klass
)->size_request
)
2712 (scroll_window
->hscrollbar
, &hscroll_req
);
2714 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT(m_widget
)->klass
);
2716 if (scroll_window
->vscrollbar_visible
)
2718 dw
+= vscroll_req
.width
;
2719 dw
+= scroll_class
->scrollbar_spacing
;
2722 if (scroll_window
->hscrollbar_visible
)
2724 dh
+= hscroll_req
.height
;
2725 dh
+= scroll_class
->scrollbar_spacing
;
2729 if (width
) (*width
) = m_width
- dw
;
2730 if (height
) (*height
) = m_height
- dh
;
2734 void wxWindow::DoGetPosition( int *x
, int *y
) const
2736 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2740 if (m_parent
&& m_parent
->m_wxwindow
)
2742 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2743 dx
= pizza
->xoffset
;
2744 dy
= pizza
->yoffset
;
2747 if (x
) (*x
) = m_x
- dx
;
2748 if (y
) (*y
) = m_y
- dy
;
2751 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2753 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2755 if (!m_widget
->window
) return;
2757 GdkWindow
*source
= (GdkWindow
*) NULL
;
2759 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2761 source
= m_widget
->window
;
2765 gdk_window_get_origin( source
, &org_x
, &org_y
);
2769 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2771 org_x
+= m_widget
->allocation
.x
;
2772 org_y
+= m_widget
->allocation
.y
;
2780 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2782 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2784 if (!m_widget
->window
) return;
2786 GdkWindow
*source
= (GdkWindow
*) NULL
;
2788 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2790 source
= m_widget
->window
;
2794 gdk_window_get_origin( source
, &org_x
, &org_y
);
2798 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2800 org_x
+= m_widget
->allocation
.x
;
2801 org_y
+= m_widget
->allocation
.y
;
2809 bool wxWindow::Show( bool show
)
2811 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2813 if (!wxWindowBase::Show(show
))
2820 gtk_widget_show( m_widget
);
2822 gtk_widget_hide( m_widget
);
2827 bool wxWindow::Enable( bool enable
)
2829 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2831 if (!wxWindowBase::Enable(enable
))
2837 gtk_widget_set_sensitive( m_widget
, enable
);
2839 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2844 int wxWindow::GetCharHeight() const
2846 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2848 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2850 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2852 return font
->ascent
+ font
->descent
;
2855 int wxWindow::GetCharWidth() const
2857 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2859 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2861 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2863 return gdk_string_width( font
, "H" );
2866 void wxWindow::GetTextExtent( const wxString
& string
,
2870 int *externalLeading
,
2871 const wxFont
*theFont
) const
2873 wxFont fontToUse
= m_font
;
2874 if (theFont
) fontToUse
= *theFont
;
2876 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2878 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2879 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2880 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2881 if (descent
) (*descent
) = font
->descent
;
2882 if (externalLeading
) (*externalLeading
) = 0; // ??
2885 void wxWindow::SetFocus()
2887 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2891 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2892 gtk_widget_grab_focus (m_wxwindow
);
2898 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2900 gtk_widget_grab_focus (m_widget
);
2902 else if (GTK_IS_CONTAINER(m_widget
))
2904 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2913 bool wxWindow::AcceptsFocus() const
2915 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2918 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2920 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2922 wxWindow
*oldParent
= m_parent
,
2923 *newParent
= (wxWindow
*)newParentBase
;
2925 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2927 if ( !wxWindowBase::Reparent(newParent
) )
2930 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2932 /* prevent GTK from deleting the widget arbitrarily */
2933 gtk_widget_ref( m_widget
);
2937 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2940 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2944 /* insert GTK representation */
2945 (*(newParent
->m_insertCallback
))(newParent
, this);
2948 /* reverse: prevent GTK from deleting the widget arbitrarily */
2949 gtk_widget_unref( m_widget
);
2954 void wxWindow::DoAddChild(wxWindow
*child
)
2956 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2958 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
2960 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
2965 /* insert GTK representation */
2966 (*m_insertCallback
)(this, child
);
2969 void wxWindow::Raise()
2971 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2973 if (!m_widget
->window
) return;
2975 gdk_window_raise( m_widget
->window
);
2978 void wxWindow::Lower()
2980 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2982 if (!m_widget
->window
) return;
2984 gdk_window_lower( m_widget
->window
);
2987 bool wxWindow::SetCursor( const wxCursor
&cursor
)
2989 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2991 if (cursor
== m_cursor
)
2995 wxapp_install_idle_handler();
2997 if (cursor
== wxNullCursor
)
2998 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3000 return wxWindowBase::SetCursor( cursor
);
3003 void wxWindow::WarpPointer( int x
, int y
)
3005 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3007 /* we provide this function ourselves as it is
3008 missing in GDK (top of this file) */
3010 GdkWindow
*window
= (GdkWindow
*) NULL
;
3012 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3014 window
= GetConnectWidget()->window
;
3017 gdk_window_warp_pointer( window
, x
, y
);
3020 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
3022 if (!m_widget
) return;
3023 if (!m_widget
->window
) return;
3025 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3029 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3031 rect
->width
, rect
->height
);
3035 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3039 /* there is no GTK equivalent of "draw only, don't clear" so we
3040 invent our own in the GtkPizza widget */
3048 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3049 gboolean old_clear = pizza->clear_on_draw;
3050 gtk_pizza_set_clear( pizza, FALSE );
3051 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3052 gtk_pizza_set_clear( pizza, old_clear );
3054 GdkEventExpose gdk_event
;
3055 gdk_event
.type
= GDK_EXPOSE
;
3056 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3057 gdk_event
.count
= 0;
3058 gdk_event
.area
.x
= 0;
3059 gdk_event
.area
.y
= 0;
3060 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3061 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3062 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3067 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3076 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3077 gboolean old_clear = pizza->clear_on_draw;
3078 gtk_pizza_set_clear( pizza, FALSE );
3080 GdkRectangle gdk_rect;
3081 gdk_rect.x = rect->x;
3082 gdk_rect.y = rect->y;
3083 gdk_rect.width = rect->width;
3084 gdk_rect.height = rect->height;
3085 gtk_widget_draw( m_wxwindow, &gdk_rect );
3086 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3088 gtk_pizza_set_clear( pizza, old_clear );
3090 GdkEventExpose gdk_event
;
3091 gdk_event
.type
= GDK_EXPOSE
;
3092 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3093 gdk_event
.count
= 0;
3094 gdk_event
.area
.x
= rect
->x
;
3095 gdk_event
.area
.y
= rect
->y
;
3096 gdk_event
.area
.width
= rect
->width
;
3097 gdk_event
.area
.height
= rect
->height
;
3098 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3102 GdkRectangle gdk_rect
;
3103 gdk_rect
.x
= rect
->x
;
3104 gdk_rect
.y
= rect
->y
;
3105 gdk_rect
.width
= rect
->width
;
3106 gdk_rect
.height
= rect
->height
;
3107 gtk_widget_draw( m_widget
, &gdk_rect
);
3112 void wxWindow::Clear()
3114 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3116 if (!m_widget
->window
) return;
3118 if (m_wxwindow
&& m_wxwindow
->window
)
3120 // gdk_window_clear( m_wxwindow->window );
3125 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
3127 wxWindowBase::DoSetToolTip(tip
);
3130 m_tooltip
->Apply( this );
3133 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3135 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3137 #endif // wxUSE_TOOLTIPS
3139 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
3141 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3143 if (!wxWindowBase::SetBackgroundColour(colour
))
3145 // don't leave if the GTK widget has just
3147 if (!m_delayedBackgroundColour
) return FALSE
;
3150 GdkWindow
*window
= (GdkWindow
*) NULL
;
3152 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3154 window
= GetConnectWidget()->window
;
3158 // indicate that a new style has been set
3159 // but it couldn't get applied as the
3160 // widget hasn't been realized yet.
3161 m_delayedBackgroundColour
= TRUE
;
3165 (m_wxwindow
->window
) &&
3166 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3168 /* wxMSW doesn't clear the window here. I don't do that either to
3169 provide compatibility. call Clear() to do the job. */
3171 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3172 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3180 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
3182 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3184 if (!wxWindowBase::SetForegroundColour(colour
))
3186 // don't leave if the GTK widget has just
3188 if (!m_delayedForegroundColour
) return FALSE
;
3191 GdkWindow
*window
= (GdkWindow
*) NULL
;
3193 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3195 window
= GetConnectWidget()->window
;
3199 // indicate that a new style has been set
3200 // but it couldn't get applied as the
3201 // widget hasn't been realized yet.
3202 m_delayedForegroundColour
= TRUE
;
3210 GtkStyle
*wxWindow::GetWidgetStyle()
3214 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3215 remake
->klass
= m_widgetStyle
->klass
;
3217 gtk_style_unref( m_widgetStyle
);
3218 m_widgetStyle
= remake
;
3222 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3225 def
= gtk_widget_get_default_style();
3227 m_widgetStyle
= gtk_style_copy( def
);
3228 m_widgetStyle
->klass
= def
->klass
;
3231 return m_widgetStyle
;
3234 void wxWindow::SetWidgetStyle()
3236 #if DISABLE_STYLE_IF_BROKEN_THEM
3237 if (m_widget
->style
->engine_data
)
3239 static bool s_warningPrinted
= FALSE
;
3240 if (!s_warningPrinted
)
3242 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3243 s_warningPrinted
= TRUE
;
3245 m_widgetStyle
= m_widget
->style
;
3250 GtkStyle
*style
= GetWidgetStyle();
3252 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3254 gdk_font_unref( style
->font
);
3255 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3258 if (m_foregroundColour
.Ok())
3260 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3261 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3263 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3264 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3265 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3269 // Try to restore the gtk default style. This is still a little
3270 // oversimplified for what is probably really needed here for controls
3271 // other than buttons, but is better than not being able to (re)set a
3272 // control's foreground colour to *wxBLACK -- RL
3273 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3276 def
= gtk_widget_get_default_style();
3278 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3279 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3280 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3284 if (m_backgroundColour
.Ok())
3286 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3287 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3289 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3290 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3291 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3292 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3293 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3294 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3295 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3296 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3300 // Try to restore the gtk default style. This is still a little
3301 // oversimplified for what is probably really needed here for controls
3302 // other than buttons, but is better than not being able to (re)set a
3303 // control's background colour to default grey and means resetting a
3304 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3306 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3309 def
= gtk_widget_get_default_style();
3311 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3312 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3313 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3314 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3315 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3316 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3317 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3318 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3323 void wxWindow::ApplyWidgetStyle()
3327 //-----------------------------------------------------------------------------
3328 // Pop-up menu stuff
3329 //-----------------------------------------------------------------------------
3331 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3333 *is_waiting
= FALSE
;
3336 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3338 menu
->SetInvokingWindow( win
);
3339 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3342 wxMenuItem
*menuitem
= node
->GetData();
3343 if (menuitem
->IsSubMenu())
3345 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3348 node
= node
->GetNext();
3352 static gint gs_pop_x
= 0;
3353 static gint gs_pop_y
= 0;
3355 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3359 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3364 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3366 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3368 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3370 SetInvokingWindow( menu
, this );
3377 bool is_waiting
= TRUE
;
3379 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3380 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3383 GTK_MENU(menu
->m_menu
),
3384 (GtkWidget
*) NULL
, // parent menu shell
3385 (GtkWidget
*) NULL
, // parent menu item
3386 (GtkMenuPositionFunc
) pop_pos_callback
,
3387 (gpointer
) this, // client data
3388 0, // button used to activate it
3389 gs_timeLastClick
// the time of activation
3394 while (gtk_events_pending())
3395 gtk_main_iteration();
3401 #if wxUSE_DRAG_AND_DROP
3403 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3405 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3407 GtkWidget
*dnd_widget
= GetConnectWidget();
3409 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3411 if (m_dropTarget
) delete m_dropTarget
;
3412 m_dropTarget
= dropTarget
;
3414 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3417 #endif // wxUSE_DRAG_AND_DROP
3419 GtkWidget
* wxWindow::GetConnectWidget()
3421 GtkWidget
*connect_widget
= m_widget
;
3422 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3424 return connect_widget
;
3427 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3430 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3432 return (window
== m_widget
->window
);
3435 bool wxWindow::SetFont( const wxFont
&font
)
3437 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3439 if (!wxWindowBase::SetFont(font
))
3444 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3445 if ( sysbg
== m_backgroundColour
)
3447 m_backgroundColour
= wxNullColour
;
3449 m_backgroundColour
= sysbg
;
3459 void wxWindow::CaptureMouse()
3461 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3463 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3465 GdkWindow
*window
= (GdkWindow
*) NULL
;
3467 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3469 window
= GetConnectWidget()->window
;
3471 if (!window
) return;
3473 wxCursor
* cursor
= & m_cursor
;
3475 cursor
= wxSTANDARD_CURSOR
;
3477 gdk_pointer_grab( window
, FALSE
,
3479 (GDK_BUTTON_PRESS_MASK
|
3480 GDK_BUTTON_RELEASE_MASK
|
3481 GDK_POINTER_MOTION_HINT_MASK
|
3482 GDK_POINTER_MOTION_MASK
),
3484 cursor
->GetCursor(),
3485 (guint32
)GDK_CURRENT_TIME
);
3486 g_captureWindow
= this;
3489 void wxWindow::ReleaseMouse()
3491 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3493 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3495 GdkWindow
*window
= (GdkWindow
*) NULL
;
3497 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3499 window
= GetConnectWidget()->window
;
3504 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3505 g_captureWindow
= (wxWindow
*) NULL
;
3508 bool wxWindow::IsRetained() const
3513 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3514 int range
, bool refresh
)
3516 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3518 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3520 m_hasScrolling
= TRUE
;
3522 if (orient
== wxHORIZONTAL
)
3524 float fpos
= (float)pos
;
3525 float frange
= (float)range
;
3526 float fthumb
= (float)thumbVisible
;
3527 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3528 if (fpos
< 0.0) fpos
= 0.0;
3530 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3531 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3533 SetScrollPos( orient
, pos
, refresh
);
3537 m_oldHorizontalPos
= fpos
;
3539 m_hAdjust
->lower
= 0.0;
3540 m_hAdjust
->upper
= frange
;
3541 m_hAdjust
->value
= fpos
;
3542 m_hAdjust
->step_increment
= 1.0;
3543 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3544 m_hAdjust
->page_size
= fthumb
;
3548 float fpos
= (float)pos
;
3549 float frange
= (float)range
;
3550 float fthumb
= (float)thumbVisible
;
3551 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3552 if (fpos
< 0.0) fpos
= 0.0;
3554 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3555 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3557 SetScrollPos( orient
, pos
, refresh
);
3561 m_oldVerticalPos
= fpos
;
3563 m_vAdjust
->lower
= 0.0;
3564 m_vAdjust
->upper
= frange
;
3565 m_vAdjust
->value
= fpos
;
3566 m_vAdjust
->step_increment
= 1.0;
3567 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3568 m_vAdjust
->page_size
= fthumb
;
3571 if (orient
== wxHORIZONTAL
)
3572 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3574 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3577 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3579 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3581 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3583 if (orient
== wxHORIZONTAL
)
3585 float fpos
= (float)pos
;
3586 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3587 if (fpos
< 0.0) fpos
= 0.0;
3588 m_oldHorizontalPos
= fpos
;
3590 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3591 m_hAdjust
->value
= fpos
;
3595 float fpos
= (float)pos
;
3596 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3597 if (fpos
< 0.0) fpos
= 0.0;
3598 m_oldVerticalPos
= fpos
;
3600 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3601 m_vAdjust
->value
= fpos
;
3604 if (m_wxwindow
->window
)
3606 if (orient
== wxHORIZONTAL
)
3608 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3609 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3611 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3613 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3614 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3618 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3619 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3621 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3623 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3624 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3629 int wxWindow::GetScrollThumb( int orient
) const
3631 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3633 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3635 if (orient
== wxHORIZONTAL
)
3636 return (int)(m_hAdjust
->page_size
+0.5);
3638 return (int)(m_vAdjust
->page_size
+0.5);
3641 int wxWindow::GetScrollPos( int orient
) const
3643 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3645 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3647 if (orient
== wxHORIZONTAL
)
3648 return (int)(m_hAdjust
->value
+0.5);
3650 return (int)(m_vAdjust
->value
+0.5);
3653 int wxWindow::GetScrollRange( int orient
) const
3655 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3657 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3659 if (orient
== wxHORIZONTAL
)
3660 return (int)(m_hAdjust
->upper
+0.5);
3662 return (int)(m_vAdjust
->upper
+0.5);
3665 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3667 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3669 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3671 if ((dx
== 0) && (dy
== 0)) return;
3673 m_clipPaintRegion
= TRUE
;
3674 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3675 m_clipPaintRegion
= FALSE
;
3678 if (m_children.GetCount() > 0)
3680 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3684 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3686 pizza->xoffset -= dx;
3687 pizza->yoffset -= dy;
3689 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3690 gdk_gc_set_exposures( m_scrollGC, TRUE );
3694 GetClientSize( &cw, &ch );
3695 int w = cw - abs(dx);
3696 int h = ch - abs(dy);
3698 if ((h < 0) || (w < 0))
3706 if (dx < 0) s_x = -dx;
3707 if (dy < 0) s_y = -dy;
3710 if (dx > 0) d_x = dx;
3711 if (dy > 0) d_y = dy;
3713 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3714 pizza->bin_window, s_x, s_y, w, h );
3717 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3718 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3719 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3720 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3722 Refresh( TRUE, &rect );
3725 gdk_gc_unref( m_scrollGC );