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
,
278 GdkWindowPrivate
*priv
;
282 window
= GDK_ROOT_PARENT();
285 if (!GDK_WINDOW_DESTROYED(window
))
287 XWarpPointer (GDK_WINDOW_XDISPLAY(window
),
288 None
, /* not source window -> move from anywhere */
289 GDK_WINDOW_XID(window
), /* dest window */
290 0, 0, 0, 0, /* not source window -> move from anywhere */
294 priv
= (GdkWindowPrivate
*) window
;
296 if (!priv
->destroyed
)
298 XWarpPointer (priv
->xdisplay
,
299 None
, /* not source window -> move from anywhere */
300 priv
->xwindow
, /* dest window */
301 0, 0, 0, 0, /* not source window -> move from anywhere */
307 //-----------------------------------------------------------------------------
309 //-----------------------------------------------------------------------------
311 extern void wxapp_install_idle_handler();
312 extern bool g_isIdle
;
314 //-----------------------------------------------------------------------------
315 // local code (see below)
316 //-----------------------------------------------------------------------------
318 // returns the child of win which currently has focus or NULL if not found
319 static wxWindow
*FindFocusedChild(wxWindow
*win
)
321 wxWindow
*winFocus
= wxWindow::FindFocus();
323 return (wxWindow
*)NULL
;
325 if ( winFocus
== win
)
328 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
330 node
= node
->GetNext() )
332 wxWindow
*child
= FindFocusedChild(node
->GetData());
337 return (wxWindow
*)NULL
;
340 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
348 if (win
->m_hasScrolling
)
350 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
352 GtkRequisition vscroll_req
;
353 vscroll_req
.width
= 2;
354 vscroll_req
.height
= 2;
355 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
356 (scroll_window
->vscrollbar
, &vscroll_req
);
358 GtkRequisition hscroll_req
;
359 hscroll_req
.width
= 2;
360 hscroll_req
.height
= 2;
361 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
362 (scroll_window
->hscrollbar
, &hscroll_req
);
364 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) );
366 if (scroll_window
->vscrollbar_visible
)
368 dw
+= vscroll_req
.width
;
369 dw
+= scroll_class
->scrollbar_spacing
;
372 if (scroll_window
->hscrollbar_visible
)
374 dh
+= hscroll_req
.height
;
375 dh
+= scroll_class
->scrollbar_spacing
;
381 if (GTK_WIDGET_NO_WINDOW (widget
))
383 dx
+= widget
->allocation
.x
;
384 dy
+= widget
->allocation
.y
;
387 if (win
->HasFlag(wxRAISED_BORDER
))
389 gtk_draw_shadow( widget
->style
,
394 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
398 if (win
->HasFlag(wxSUNKEN_BORDER
))
400 gtk_draw_shadow( widget
->style
,
405 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
409 if (win
->HasFlag(wxSIMPLE_BORDER
))
412 gc
= gdk_gc_new( widget
->window
);
413 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
414 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
416 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
422 //-----------------------------------------------------------------------------
423 // "expose_event" of m_widget
424 //-----------------------------------------------------------------------------
426 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
428 if (gdk_event
->count
> 0) return FALSE
;
430 draw_frame( widget
, win
);
435 //-----------------------------------------------------------------------------
436 // "draw" of m_widget
437 //-----------------------------------------------------------------------------
439 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
441 draw_frame( widget
, win
);
444 //-----------------------------------------------------------------------------
445 // key code mapping routines
446 //-----------------------------------------------------------------------------
448 static long map_to_unmodified_wx_keysym( KeySym keysym
)
455 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
457 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
463 case GDK_Super_R
: key_code
= WXK_ALT
; break;
464 case GDK_Menu
: key_code
= WXK_MENU
; break;
465 case GDK_Help
: key_code
= WXK_HELP
; break;
466 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
467 case GDK_ISO_Left_Tab
:
468 case GDK_Tab
: key_code
= WXK_TAB
; break;
469 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
470 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
471 case GDK_Return
: key_code
= WXK_RETURN
; break;
472 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
473 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
474 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
475 case GDK_Delete
: key_code
= WXK_DELETE
; break;
476 case GDK_Home
: key_code
= WXK_HOME
; break;
477 case GDK_Left
: key_code
= WXK_LEFT
; break;
478 case GDK_Up
: key_code
= WXK_UP
; break;
479 case GDK_Right
: key_code
= WXK_RIGHT
; break;
480 case GDK_Down
: key_code
= WXK_DOWN
; break;
481 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
482 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
483 case GDK_Next
: key_code
= WXK_NEXT
; break;
484 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
485 case GDK_End
: key_code
= WXK_END
; break;
486 case GDK_Begin
: key_code
= WXK_HOME
; break;
487 case GDK_Select
: key_code
= WXK_SELECT
; break;
488 case GDK_Print
: key_code
= WXK_PRINT
; break;
489 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
490 case GDK_Insert
: key_code
= WXK_INSERT
; break;
491 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
493 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
494 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
495 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
496 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
497 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
498 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
499 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
500 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
501 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
502 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
503 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
504 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
505 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
506 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
507 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
508 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
509 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
510 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
511 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
512 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
513 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
514 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
515 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
516 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
517 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
518 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
519 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
520 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
521 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
522 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
523 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
524 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
525 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
526 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
527 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
528 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
529 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
531 case GDK_F1
: key_code
= WXK_F1
; break;
532 case GDK_F2
: key_code
= WXK_F2
; break;
533 case GDK_F3
: key_code
= WXK_F3
; break;
534 case GDK_F4
: key_code
= WXK_F4
; break;
535 case GDK_F5
: key_code
= WXK_F5
; break;
536 case GDK_F6
: key_code
= WXK_F6
; break;
537 case GDK_F7
: key_code
= WXK_F7
; break;
538 case GDK_F8
: key_code
= WXK_F8
; break;
539 case GDK_F9
: key_code
= WXK_F9
; break;
540 case GDK_F10
: key_code
= WXK_F10
; break;
541 case GDK_F11
: key_code
= WXK_F11
; break;
542 case GDK_F12
: key_code
= WXK_F12
; break;
545 if ((keysym
& 0xF000) == 0)
547 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
548 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
549 key_code
= (guint
)keysym
;
557 static long map_to_wx_keysym( KeySym keysym
)
563 case GDK_Menu
: key_code
= WXK_MENU
; break;
564 case GDK_Help
: key_code
= WXK_HELP
; break;
565 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
566 case GDK_ISO_Left_Tab
:
567 case GDK_Tab
: key_code
= WXK_TAB
; break;
568 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
569 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
570 case GDK_Return
: key_code
= WXK_RETURN
; break;
571 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
572 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
573 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
574 case GDK_Delete
: key_code
= WXK_DELETE
; break;
575 case GDK_Home
: key_code
= WXK_HOME
; break;
576 case GDK_Left
: key_code
= WXK_LEFT
; break;
577 case GDK_Up
: key_code
= WXK_UP
; break;
578 case GDK_Right
: key_code
= WXK_RIGHT
; break;
579 case GDK_Down
: key_code
= WXK_DOWN
; break;
580 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
581 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
582 case GDK_Next
: key_code
= WXK_NEXT
; break;
583 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
584 case GDK_End
: key_code
= WXK_END
; break;
585 case GDK_Begin
: key_code
= WXK_HOME
; break;
586 case GDK_Select
: key_code
= WXK_SELECT
; break;
587 case GDK_Print
: key_code
= WXK_PRINT
; break;
588 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
589 case GDK_Insert
: key_code
= WXK_INSERT
; break;
590 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
592 case GDK_KP_0
: key_code
= '0'; break;
593 case GDK_KP_1
: key_code
= '1'; break;
594 case GDK_KP_2
: key_code
= '2'; break;
595 case GDK_KP_3
: key_code
= '3'; break;
596 case GDK_KP_4
: key_code
= '4'; break;
597 case GDK_KP_5
: key_code
= '5'; break;
598 case GDK_KP_6
: key_code
= '6'; break;
599 case GDK_KP_7
: key_code
= '7'; break;
600 case GDK_KP_8
: key_code
= '8'; break;
601 case GDK_KP_9
: key_code
= '9'; break;
602 case GDK_KP_Space
: key_code
= ' '; break;
603 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
604 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
605 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
606 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
607 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
608 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
609 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
610 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
611 case GDK_KP_Up
: key_code
= WXK_UP
; break;
612 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
613 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
614 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
615 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
616 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
617 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
618 case GDK_KP_End
: key_code
= WXK_END
; break;
619 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
620 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
621 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
622 case GDK_KP_Equal
: key_code
= '='; break;
623 case GDK_KP_Multiply
: key_code
= '*'; break;
624 case GDK_KP_Add
: key_code
= '+'; break;
625 case GDK_KP_Separator
: key_code
= ','; break;
626 case GDK_KP_Subtract
: key_code
= '-'; break;
627 case GDK_KP_Decimal
: key_code
= '.'; break;
628 case GDK_KP_Divide
: key_code
= '/'; break;
630 case GDK_F1
: key_code
= WXK_F1
; break;
631 case GDK_F2
: key_code
= WXK_F2
; break;
632 case GDK_F3
: key_code
= WXK_F3
; break;
633 case GDK_F4
: key_code
= WXK_F4
; break;
634 case GDK_F5
: key_code
= WXK_F5
; break;
635 case GDK_F6
: key_code
= WXK_F6
; break;
636 case GDK_F7
: key_code
= WXK_F7
; break;
637 case GDK_F8
: key_code
= WXK_F8
; break;
638 case GDK_F9
: key_code
= WXK_F9
; break;
639 case GDK_F10
: key_code
= WXK_F10
; break;
640 case GDK_F11
: key_code
= WXK_F11
; break;
641 case GDK_F12
: key_code
= WXK_F12
; break;
644 if ((keysym
& 0xF000) == 0)
646 key_code
= (guint
)keysym
;
654 //-----------------------------------------------------------------------------
655 // "expose_event" of m_wxwindow
656 //-----------------------------------------------------------------------------
658 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
663 wxapp_install_idle_handler();
666 if (win->GetName() == wxT("panel"))
668 wxPrintf( wxT("OnExpose from ") );
669 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
670 wxPrintf( win->GetClassInfo()->GetClassName() );
671 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
672 (int)gdk_event->area.y,
673 (int)gdk_event->area.width,
674 (int)gdk_event->area.height );
678 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
680 gdk_event
->area
.width
,
681 gdk_event
->area
.height
);
683 if (gdk_event
->count
== 0)
685 wxEraseEvent
eevent( win
->GetId() );
686 eevent
.SetEventObject( win
);
687 win
->GetEventHandler()->ProcessEvent(eevent
);
689 wxPaintEvent
event( win
->GetId() );
690 event
.SetEventObject( win
);
691 win
->GetEventHandler()->ProcessEvent( event
);
693 win
->GetUpdateRegion().Clear();
696 /* The following code will result in all window-less widgets
697 being redrawn if the wxWindows class is given a chance to
698 paint *anything* because it will then be allowed to paint
699 over the window-less widgets */
701 GtkPizza
*pizza
= GTK_PIZZA (widget
);
703 GList
*children
= pizza
->children
;
706 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
707 children
= children
->next
;
709 GdkEventExpose child_event
= *gdk_event
;
711 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
712 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
713 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
715 child_event
.area
.x
= child
->widget
->allocation
.x
;
716 child_event
.area
.y
= child
->widget
->allocation
.y
;
717 child_event
.area
.width
= child
->widget
->allocation
.width
;
718 child_event
.area
.height
= child
->widget
->allocation
.height
;
719 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
726 //-----------------------------------------------------------------------------
727 // "event" of m_wxwindow
728 //-----------------------------------------------------------------------------
730 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
731 expose events. We need them, of course, so we override the main event
732 procedure in GtkWidget by giving our own handler for all system events.
733 There, we look for expose events ourselves whereas all other events are
736 gint
gtk_window_event_event_callback( GtkWidget
*widget
, GdkEventExpose
*event
, wxWindow
*win
)
738 if (event
->type
== GDK_EXPOSE
)
740 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
747 //-----------------------------------------------------------------------------
748 // "draw" of m_wxwindow
749 //-----------------------------------------------------------------------------
751 /* This callback is a complete replacement of the gtk_pizza_draw() function,
754 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
759 wxapp_install_idle_handler();
762 if (win->GetName() == wxT("panel"))
764 wxPrintf( wxT("OnDraw from ") );
765 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
766 wxPrintf( win->GetClassInfo()->GetClassName() );
767 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
774 GtkPizza
*pizza
= GTK_PIZZA (widget
);
776 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
777 (pizza
->clear_on_draw
))
779 gdk_window_clear_area( pizza
->bin_window
,
780 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
783 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
785 win
->m_clipPaintRegion
= TRUE
;
787 wxEraseEvent
eevent( win
->GetId() );
788 eevent
.SetEventObject( win
);
789 win
->GetEventHandler()->ProcessEvent(eevent
);
791 wxPaintEvent
event( win
->GetId() );
792 event
.SetEventObject( win
);
793 win
->GetEventHandler()->ProcessEvent( event
);
795 win
->GetUpdateRegion().Clear();
797 win
->m_clipPaintRegion
= FALSE
;
800 GList
*children
= pizza
->children
;
803 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
804 children
= children
->next
;
806 GdkRectangle child_area
;
807 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
809 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
814 //-----------------------------------------------------------------------------
815 // "key_press_event" from any window
816 //-----------------------------------------------------------------------------
818 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
823 wxapp_install_idle_handler();
825 if (!win
->m_hasVMT
) return FALSE
;
826 if (g_blockEventsOnDrag
) return FALSE
;
831 tmp += (char)gdk_event->keyval;
832 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
833 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
838 GdkModifierType state
;
839 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
843 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
844 /* sending unknown key events doesn't really make sense */
845 if (key_code
== 0) return FALSE
;
847 wxKeyEvent
event( wxEVT_KEY_DOWN
);
848 event
.SetTimestamp( gdk_event
->time
);
849 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
850 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
851 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
852 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
853 event
.m_keyCode
= key_code
;
854 event
.m_scanCode
= gdk_event
->keyval
;
857 event
.SetEventObject( win
);
858 ret
= win
->GetEventHandler()->ProcessEvent( event
);
863 wxWindow
*ancestor
= win
;
866 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
869 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
870 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
873 if (ancestor
->IsTopLevel())
875 ancestor
= ancestor
->GetParent();
878 #endif // wxUSE_ACCEL
880 /* wxMSW doesn't send char events with Alt pressed */
881 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
882 will only be sent if it is not in an accelerator table. */
883 key_code
= map_to_wx_keysym( gdk_event
->keyval
);
888 wxKeyEvent
event2( wxEVT_CHAR
);
889 event2
.SetTimestamp( gdk_event
->time
);
890 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
891 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
892 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
893 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
894 event2
.m_keyCode
= key_code
;
895 event2
.m_scanCode
= gdk_event
->keyval
;
898 event2
.SetEventObject( win
);
899 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
902 /* win is a control: tab can be propagated up */
904 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
905 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
906 // have this style, yet choose not to process this particular TAB in which
907 // case TAB must still work as a navigational character
909 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
911 (win
->GetParent()) &&
912 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
914 wxNavigationKeyEvent new_event
;
915 new_event
.SetEventObject( win
->GetParent() );
916 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
917 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
918 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
919 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
920 new_event
.SetCurrentFocus( win
);
921 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
924 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
926 (gdk_event
->keyval
== GDK_Escape
) )
928 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
929 new_event
.SetEventObject( win
);
930 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
933 #if (GTK_MINOR_VERSION > 0)
934 /* Pressing F10 will activate the menu bar of the top frame. */
938 (gdk_event->keyval == GDK_F10) )
940 wxWindow *ancestor = win;
943 if (wxIsKindOf(ancestor,wxFrame))
945 wxFrame *frame = (wxFrame*) ancestor;
946 wxMenuBar *menubar = frame->GetMenuBar();
949 wxNode *node = menubar->GetMenus().First();
952 wxMenu *firstMenu = (wxMenu*) node->Data();
953 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
959 ancestor = ancestor->GetParent();
967 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
974 //-----------------------------------------------------------------------------
975 // "key_release_event" from any window
976 //-----------------------------------------------------------------------------
978 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
983 wxapp_install_idle_handler();
985 if (!win
->m_hasVMT
) return FALSE
;
986 if (g_blockEventsOnDrag
) return FALSE
;
989 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
990 if (gdk_event->state & GDK_SHIFT_MASK)
991 printf( "ShiftDown.\n" );
993 printf( "ShiftUp.\n" );
994 if (gdk_event->state & GDK_CONTROL_MASK)
995 printf( "ControlDown.\n" );
997 printf( "ControlUp.\n" );
1001 long key_code
= map_to_unmodified_wx_keysym( gdk_event
->keyval
);
1003 /* sending unknown key events doesn't really make sense */
1004 if (key_code
== 0) return FALSE
;
1008 GdkModifierType state
;
1009 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1011 wxKeyEvent
event( wxEVT_KEY_UP
);
1012 event
.SetTimestamp( gdk_event
->time
);
1013 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1014 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1015 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1016 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1017 event
.m_keyCode
= key_code
;
1018 event
.m_scanCode
= gdk_event
->keyval
;
1021 event
.SetEventObject( win
);
1023 if (win
->GetEventHandler()->ProcessEvent( event
))
1025 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1032 // ----------------------------------------------------------------------------
1033 // mouse event processing helper
1034 // ----------------------------------------------------------------------------
1036 static void AdjustEventButtonState(wxMouseEvent
& event
)
1038 // GDK reports the old state of the button for a button press event, but
1039 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1040 // for a LEFT_DOWN event, not FALSE, so we will invert
1041 // left/right/middleDown for the corresponding click events
1042 switch ( event
.GetEventType() )
1044 case wxEVT_LEFT_DOWN
:
1045 case wxEVT_LEFT_DCLICK
:
1047 event
.m_leftDown
= !event
.m_leftDown
;
1050 case wxEVT_MIDDLE_DOWN
:
1051 case wxEVT_MIDDLE_DCLICK
:
1052 case wxEVT_MIDDLE_UP
:
1053 event
.m_middleDown
= !event
.m_middleDown
;
1056 case wxEVT_RIGHT_DOWN
:
1057 case wxEVT_RIGHT_DCLICK
:
1058 case wxEVT_RIGHT_UP
:
1059 event
.m_rightDown
= !event
.m_rightDown
;
1064 //-----------------------------------------------------------------------------
1065 // "button_press_event"
1066 //-----------------------------------------------------------------------------
1068 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1073 wxapp_install_idle_handler();
1076 wxPrintf( wxT("1) OnButtonPress from ") );
1077 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1078 wxPrintf( win->GetClassInfo()->GetClassName() );
1079 wxPrintf( wxT(".\n") );
1081 if (!win
->m_hasVMT
) return FALSE
;
1082 if (g_blockEventsOnDrag
) return TRUE
;
1083 if (g_blockEventsOnScroll
) return TRUE
;
1085 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1087 if (win
->m_wxwindow
)
1089 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1091 gtk_widget_grab_focus (win
->m_wxwindow
);
1094 wxPrintf( wxT("GrabFocus from ") );
1095 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1096 wxPrintf( win->GetClassInfo()->GetClassName() );
1097 wxPrintf( wxT(".\n") );
1103 wxEventType event_type
= wxEVT_NULL
;
1105 if (gdk_event
->button
== 1)
1107 switch (gdk_event
->type
)
1109 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1110 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1114 else if (gdk_event
->button
== 2)
1116 switch (gdk_event
->type
)
1118 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1119 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1123 else if (gdk_event
->button
== 3)
1125 switch (gdk_event
->type
)
1127 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1128 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1133 if ( event_type
== wxEVT_NULL
)
1135 // unknown mouse button or click type
1139 wxMouseEvent
event( event_type
);
1140 event
.SetTimestamp( gdk_event
->time
);
1141 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1142 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1143 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1144 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1145 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1146 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1147 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1149 event
.m_x
= (wxCoord
)gdk_event
->x
;
1150 event
.m_y
= (wxCoord
)gdk_event
->y
;
1152 AdjustEventButtonState(event
);
1154 // Some control don't have their own X window and thus cannot get
1157 if (!g_captureWindow
)
1159 wxCoord x
= event
.m_x
;
1160 wxCoord y
= event
.m_y
;
1161 if (win
->m_wxwindow
)
1163 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1164 x
+= pizza
->xoffset
;
1165 y
+= pizza
->yoffset
;
1168 wxNode
*node
= win
->GetChildren().First();
1171 wxWindow
*child
= (wxWindow
*)node
->Data();
1173 node
= node
->Next();
1174 if (!child
->IsShown())
1177 if (child
->m_isStaticBox
)
1179 // wxStaticBox is transparent in the box itself
1180 int xx1
= child
->m_x
;
1181 int yy1
= child
->m_y
;
1182 int xx2
= child
->m_x
+ child
->m_width
;
1183 int yy2
= child
->m_x
+ child
->m_height
;
1186 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1188 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1190 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1192 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1195 event
.m_x
-= child
->m_x
;
1196 event
.m_y
-= child
->m_y
;
1203 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1204 (child
->m_x
<= x
) &&
1205 (child
->m_y
<= y
) &&
1206 (child
->m_x
+child
->m_width
>= x
) &&
1207 (child
->m_y
+child
->m_height
>= y
))
1210 event
.m_x
-= child
->m_x
;
1211 event
.m_y
-= child
->m_y
;
1218 event
.SetEventObject( win
);
1220 gs_timeLastClick
= gdk_event
->time
;
1223 wxPrintf( wxT("2) OnButtonPress from ") );
1224 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1225 wxPrintf( win->GetClassInfo()->GetClassName() );
1226 wxPrintf( wxT(".\n") );
1229 if (win
->GetEventHandler()->ProcessEvent( event
))
1231 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1238 //-----------------------------------------------------------------------------
1239 // "button_release_event"
1240 //-----------------------------------------------------------------------------
1242 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1247 wxapp_install_idle_handler();
1249 if (!win
->m_hasVMT
) return FALSE
;
1250 if (g_blockEventsOnDrag
) return FALSE
;
1251 if (g_blockEventsOnScroll
) return FALSE
;
1253 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1256 printf( "OnButtonRelease from " );
1257 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1258 printf( win->GetClassInfo()->GetClassName() );
1262 wxEventType event_type
= wxEVT_NULL
;
1264 switch (gdk_event
->button
)
1266 case 1: event_type
= wxEVT_LEFT_UP
; break;
1267 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1268 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1269 default: return FALSE
;
1272 wxMouseEvent
event( event_type
);
1273 event
.SetTimestamp( gdk_event
->time
);
1274 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1275 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1276 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1277 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1278 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1279 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1280 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1281 event
.m_x
= (wxCoord
)gdk_event
->x
;
1282 event
.m_y
= (wxCoord
)gdk_event
->y
;
1284 AdjustEventButtonState(event
);
1286 // Some control don't have their own X window and thus cannot get
1289 if (!g_captureWindow
)
1291 wxCoord x
= event
.m_x
;
1292 wxCoord y
= event
.m_y
;
1293 if (win
->m_wxwindow
)
1295 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1296 x
+= pizza
->xoffset
;
1297 y
+= pizza
->yoffset
;
1300 wxNode
*node
= win
->GetChildren().First();
1303 wxWindow
*child
= (wxWindow
*)node
->Data();
1305 node
= node
->Next();
1306 if (!child
->IsShown())
1309 if (child
->m_isStaticBox
)
1311 // wxStaticBox is transparent in the box itself
1312 int xx1
= child
->m_x
;
1313 int yy1
= child
->m_y
;
1314 int xx2
= child
->m_x
+ child
->m_width
;
1315 int yy2
= child
->m_x
+ child
->m_height
;
1318 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1320 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1322 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1324 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1327 event
.m_x
-= child
->m_x
;
1328 event
.m_y
-= child
->m_y
;
1335 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1336 (child
->m_x
<= x
) &&
1337 (child
->m_y
<= y
) &&
1338 (child
->m_x
+child
->m_width
>= x
) &&
1339 (child
->m_y
+child
->m_height
>= y
))
1342 event
.m_x
-= child
->m_x
;
1343 event
.m_y
-= child
->m_y
;
1350 event
.SetEventObject( win
);
1352 if (win
->GetEventHandler()->ProcessEvent( event
))
1354 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1361 //-----------------------------------------------------------------------------
1362 // "motion_notify_event"
1363 //-----------------------------------------------------------------------------
1365 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1370 wxapp_install_idle_handler();
1372 if (!win
->m_hasVMT
) return FALSE
;
1373 if (g_blockEventsOnDrag
) return FALSE
;
1374 if (g_blockEventsOnScroll
) return FALSE
;
1376 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1378 if (gdk_event
->is_hint
)
1382 GdkModifierType state
;
1383 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1389 printf( "OnMotion from " );
1390 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1391 printf( win->GetClassInfo()->GetClassName() );
1395 wxMouseEvent
event( wxEVT_MOTION
);
1396 event
.SetTimestamp( gdk_event
->time
);
1397 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1398 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1399 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1400 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1401 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1402 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1403 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1405 event
.m_x
= (wxCoord
)gdk_event
->x
;
1406 event
.m_y
= (wxCoord
)gdk_event
->y
;
1408 // Some control don't have their own X window and thus cannot get
1411 if (!g_captureWindow
)
1413 wxCoord x
= event
.m_x
;
1414 wxCoord y
= event
.m_y
;
1415 if (win
->m_wxwindow
)
1417 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1418 x
+= pizza
->xoffset
;
1419 y
+= pizza
->yoffset
;
1422 wxNode
*node
= win
->GetChildren().First();
1425 wxWindow
*child
= (wxWindow
*)node
->Data();
1427 node
= node
->Next();
1428 if (!child
->IsShown())
1431 if (child
->m_isStaticBox
)
1433 // wxStaticBox is transparent in the box itself
1434 int xx1
= child
->m_x
;
1435 int yy1
= child
->m_y
;
1436 int xx2
= child
->m_x
+ child
->m_width
;
1437 int yy2
= child
->m_x
+ child
->m_height
;
1440 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1442 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1444 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1446 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1449 event
.m_x
-= child
->m_x
;
1450 event
.m_y
-= child
->m_y
;
1457 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1458 (child
->m_x
<= x
) &&
1459 (child
->m_y
<= y
) &&
1460 (child
->m_x
+child
->m_width
>= x
) &&
1461 (child
->m_y
+child
->m_height
>= y
))
1464 event
.m_x
-= child
->m_x
;
1465 event
.m_y
-= child
->m_y
;
1472 event
.SetEventObject( win
);
1474 if (win
->GetEventHandler()->ProcessEvent( event
))
1476 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1483 //-----------------------------------------------------------------------------
1485 //-----------------------------------------------------------------------------
1487 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1492 wxapp_install_idle_handler();
1494 if (!win
->m_hasVMT
) return FALSE
;
1495 if (g_blockEventsOnDrag
) return FALSE
;
1497 switch ( g_sendActivateEvent
)
1500 // we've got focus from outside, synthtize wxActivateEvent
1501 g_sendActivateEvent
= 1;
1505 // another our window just lost focus, it was already ours before
1506 // - don't send any wxActivateEvent
1507 g_sendActivateEvent
= -1;
1511 g_focusWindow
= win
;
1514 printf( "OnSetFocus from " );
1515 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1516 printf( win->GetClassInfo()->GetClassName() );
1518 printf( WXSTRINGCAST win->GetLabel() );
1522 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1525 panel
->SetLastFocus(win
);
1530 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1534 // caret needs to be informed about focus change
1535 wxCaret
*caret
= win
->GetCaret();
1538 caret
->OnSetFocus();
1540 #endif // wxUSE_CARET
1542 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1543 event
.SetEventObject( win
);
1545 if (win
->GetEventHandler()->ProcessEvent( event
))
1547 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1554 //-----------------------------------------------------------------------------
1555 // "focus_out_event"
1556 //-----------------------------------------------------------------------------
1558 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1563 wxapp_install_idle_handler();
1565 if (!win
->m_hasVMT
) return FALSE
;
1566 if (g_blockEventsOnDrag
) return FALSE
;
1568 // if the focus goes out of our app alltogether, OnIdle() will send
1569 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1570 // g_sendActivateEvent to -1
1571 g_sendActivateEvent
= 0;
1573 wxWindow
*winFocus
= FindFocusedChild(win
);
1577 g_focusWindow
= (wxWindow
*)NULL
;
1580 printf( "OnKillFocus from " );
1581 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1582 printf( win->GetClassInfo()->GetClassName() );
1592 // caret needs to be informed about focus change
1593 wxCaret
*caret
= win
->GetCaret();
1596 caret
->OnKillFocus();
1598 #endif // wxUSE_CARET
1600 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1601 event
.SetEventObject( win
);
1603 if (win
->GetEventHandler()->ProcessEvent( event
))
1605 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1612 //-----------------------------------------------------------------------------
1613 // "enter_notify_event"
1614 //-----------------------------------------------------------------------------
1616 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1621 wxapp_install_idle_handler();
1623 if (!win
->m_hasVMT
) return FALSE
;
1624 if (g_blockEventsOnDrag
) return FALSE
;
1626 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1628 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1629 #if (GTK_MINOR_VERSION > 0)
1630 event
.SetTimestamp( gdk_event
->time
);
1632 event
.SetEventObject( win
);
1636 GdkModifierType state
= (GdkModifierType
)0;
1638 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1640 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1641 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1642 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1643 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1644 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1645 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1646 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1651 if (win
->GetEventHandler()->ProcessEvent( event
))
1653 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1660 //-----------------------------------------------------------------------------
1661 // "leave_notify_event"
1662 //-----------------------------------------------------------------------------
1664 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1669 wxapp_install_idle_handler();
1671 if (!win
->m_hasVMT
) return FALSE
;
1672 if (g_blockEventsOnDrag
) return FALSE
;
1674 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1676 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1677 #if (GTK_MINOR_VERSION > 0)
1678 event
.SetTimestamp( gdk_event
->time
);
1680 event
.SetEventObject( win
);
1684 GdkModifierType state
= (GdkModifierType
)0;
1686 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1688 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1689 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1690 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1691 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1692 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1693 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1694 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1699 if (win
->GetEventHandler()->ProcessEvent( event
))
1701 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1708 //-----------------------------------------------------------------------------
1709 // "value_changed" from m_vAdjust
1710 //-----------------------------------------------------------------------------
1712 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1717 wxapp_install_idle_handler();
1719 if (g_blockEventsOnDrag
) return;
1721 if (!win
->m_hasVMT
) return;
1723 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1724 if (fabs(diff
) < 0.2) return;
1726 win
->m_oldVerticalPos
= adjust
->value
;
1728 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1729 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1731 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1732 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1733 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1734 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1735 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1737 int value
= (int)(adjust
->value
+0.5);
1739 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1740 event
.SetEventObject( win
);
1741 win
->GetEventHandler()->ProcessEvent( event
);
1744 //-----------------------------------------------------------------------------
1745 // "value_changed" from m_hAdjust
1746 //-----------------------------------------------------------------------------
1748 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1753 wxapp_install_idle_handler();
1755 if (g_blockEventsOnDrag
) return;
1756 if (!win
->m_hasVMT
) return;
1758 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1759 if (fabs(diff
) < 0.2) return;
1761 win
->m_oldHorizontalPos
= adjust
->value
;
1763 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1764 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1766 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1767 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1768 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1769 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1770 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1772 int value
= (int)(adjust
->value
+0.5);
1774 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1775 event
.SetEventObject( win
);
1776 win
->GetEventHandler()->ProcessEvent( event
);
1779 //-----------------------------------------------------------------------------
1780 // "button_press_event" from scrollbar
1781 //-----------------------------------------------------------------------------
1783 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1784 GdkEventButton
*gdk_event
,
1790 wxapp_install_idle_handler();
1793 g_blockEventsOnScroll
= TRUE
;
1794 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1799 //-----------------------------------------------------------------------------
1800 // "button_release_event" from scrollbar
1801 //-----------------------------------------------------------------------------
1803 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1804 GdkEventButton
*WXUNUSED(gdk_event
),
1809 // don't test here as we can release the mouse while being over
1810 // a different window than the slider
1812 // if (gdk_event->window != widget->slider) return FALSE;
1814 g_blockEventsOnScroll
= FALSE
;
1816 if (win
->m_isScrolling
)
1818 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
1822 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1823 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1825 value
= (int)(win
->m_hAdjust
->value
+0.5);
1828 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1830 value
= (int)(win
->m_vAdjust
->value
+0.5);
1834 wxScrollWinEvent
event( command
, value
, dir
);
1835 event
.SetEventObject( win
);
1836 win
->GetEventHandler()->ProcessEvent( event
);
1839 win
->m_isScrolling
= FALSE
;
1844 // ----------------------------------------------------------------------------
1845 // this wxWindowBase function is implemented here (in platform-specific file)
1846 // because it is static and so couldn't be made virtual
1847 // ----------------------------------------------------------------------------
1849 wxWindow
*wxWindowBase::FindFocus()
1851 return g_focusWindow
;
1854 //-----------------------------------------------------------------------------
1855 // "realize" from m_widget
1856 //-----------------------------------------------------------------------------
1858 /* We cannot set colours and fonts before the widget has
1859 been realized, so we do this directly after realization. */
1862 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1867 wxapp_install_idle_handler();
1869 if (win
->m_delayedBackgroundColour
)
1870 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1872 if (win
->m_delayedForegroundColour
)
1873 win
->SetForegroundColour( win
->GetForegroundColour() );
1875 wxWindowCreateEvent
event( win
);
1876 event
.SetEventObject( win
);
1877 win
->GetEventHandler()->ProcessEvent( event
);
1882 //-----------------------------------------------------------------------------
1884 //-----------------------------------------------------------------------------
1887 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
1888 GtkAllocation
*WXUNUSED(alloc
),
1892 wxapp_install_idle_handler();
1894 if (!win
->m_hasScrolling
) return;
1896 int client_width
= 0;
1897 int client_height
= 0;
1898 win
->GetClientSize( &client_width
, &client_height
);
1899 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
1902 win
->m_oldClientWidth
= client_width
;
1903 win
->m_oldClientHeight
= client_height
;
1905 if (!win
->m_nativeSizeEvent
)
1907 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
1908 event
.SetEventObject( win
);
1909 win
->GetEventHandler()->ProcessEvent( event
);
1915 #define WXUNUSED_UNLESS_XIM(param) param
1917 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
1920 /* Resize XIM window */
1923 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1924 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
1925 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1928 wxapp_install_idle_handler();
1934 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
1938 gdk_window_get_size (widget
->window
, &width
, &height
);
1939 win
->m_icattr
->preedit_area
.width
= width
;
1940 win
->m_icattr
->preedit_area
.height
= height
;
1941 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
1946 //-----------------------------------------------------------------------------
1947 // "realize" from m_wxwindow
1948 //-----------------------------------------------------------------------------
1950 /* Initialize XIM support */
1953 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
1954 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
1957 wxapp_install_idle_handler();
1960 if (win
->m_ic
) return FALSE
;
1961 if (!widget
) return FALSE
;
1962 if (!gdk_im_ready()) return FALSE
;
1964 win
->m_icattr
= gdk_ic_attr_new();
1965 if (!win
->m_icattr
) return FALSE
;
1969 GdkColormap
*colormap
;
1970 GdkICAttr
*attr
= win
->m_icattr
;
1971 unsigned attrmask
= GDK_IC_ALL_REQ
;
1973 GdkIMStyle supported_style
= (GdkIMStyle
)
1974 (GDK_IM_PREEDIT_NONE
|
1975 GDK_IM_PREEDIT_NOTHING
|
1976 GDK_IM_PREEDIT_POSITION
|
1977 GDK_IM_STATUS_NONE
|
1978 GDK_IM_STATUS_NOTHING
);
1980 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
1981 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
1983 attr
->style
= style
= gdk_im_decide_style (supported_style
);
1984 attr
->client_window
= widget
->window
;
1986 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
1987 gtk_widget_get_default_colormap ())
1989 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
1990 attr
->preedit_colormap
= colormap
;
1993 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
1994 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
1995 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
1996 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
1998 switch (style
& GDK_IM_PREEDIT_MASK
)
2000 case GDK_IM_PREEDIT_POSITION
:
2001 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2003 g_warning ("over-the-spot style requires fontset");
2007 gdk_window_get_size (widget
->window
, &width
, &height
);
2009 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2010 attr
->spot_location
.x
= 0;
2011 attr
->spot_location
.y
= height
;
2012 attr
->preedit_area
.x
= 0;
2013 attr
->preedit_area
.y
= 0;
2014 attr
->preedit_area
.width
= width
;
2015 attr
->preedit_area
.height
= height
;
2016 attr
->preedit_fontset
= widget
->style
->font
;
2021 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2023 if (win
->m_ic
== NULL
)
2024 g_warning ("Can't create input context.");
2027 mask
= gdk_window_get_events (widget
->window
);
2028 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2029 gdk_window_set_events (widget
->window
, mask
);
2031 if (GTK_WIDGET_HAS_FOCUS(widget
))
2032 gdk_im_begin (win
->m_ic
, widget
->window
);
2039 //-----------------------------------------------------------------------------
2040 // InsertChild for wxWindow.
2041 //-----------------------------------------------------------------------------
2043 /* Callback for wxWindow. This very strange beast has to be used because
2044 * C++ has no virtual methods in a constructor. We have to emulate a
2045 * virtual function here as wxNotebook requires a different way to insert
2046 * a child in it. I had opted for creating a wxNotebookPage window class
2047 * which would have made this superfluous (such in the MDI window system),
2048 * but no-one was listening to me... */
2050 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
2052 /* the window might have been scrolled already, do we
2053 have to adapt the position */
2054 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2055 child
->m_x
+= pizza
->xoffset
;
2056 child
->m_y
+= pizza
->yoffset
;
2058 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2059 GTK_WIDGET(child
->m_widget
),
2066 //-----------------------------------------------------------------------------
2068 //-----------------------------------------------------------------------------
2070 wxWindow
* wxGetActiveWindow()
2072 return g_focusWindow
;
2075 //-----------------------------------------------------------------------------
2077 //-----------------------------------------------------------------------------
2079 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2081 void wxWindow::Init()
2087 m_widget
= (GtkWidget
*) NULL
;
2088 m_wxwindow
= (GtkWidget
*) NULL
;
2098 m_needParent
= TRUE
;
2099 m_isBeingDeleted
= FALSE
;
2102 m_nativeSizeEvent
= FALSE
;
2104 m_hasScrolling
= FALSE
;
2105 m_isScrolling
= FALSE
;
2107 m_hAdjust
= (GtkAdjustment
*) NULL
;
2108 m_vAdjust
= (GtkAdjustment
*) NULL
;
2109 m_oldHorizontalPos
= 0.0;
2110 m_oldVerticalPos
= 0.0;
2113 m_widgetStyle
= (GtkStyle
*) NULL
;
2115 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2117 m_isStaticBox
= FALSE
;
2118 m_isRadioButton
= FALSE
;
2120 m_acceptsFocus
= FALSE
;
2122 m_clipPaintRegion
= FALSE
;
2124 m_cursor
= *wxSTANDARD_CURSOR
;
2126 m_delayedForegroundColour
= FALSE
;
2127 m_delayedBackgroundColour
= FALSE
;
2130 m_ic
= (GdkIC
*) NULL
;
2131 m_icattr
= (GdkICAttr
*) NULL
;
2135 wxWindow::wxWindow()
2140 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
2141 const wxPoint
&pos
, const wxSize
&size
,
2142 long style
, const wxString
&name
)
2146 Create( parent
, id
, pos
, size
, style
, name
);
2149 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
2150 const wxPoint
&pos
, const wxSize
&size
,
2151 long style
, const wxString
&name
)
2153 if (!PreCreation( parent
, pos
, size
) ||
2154 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2156 wxFAIL_MSG( wxT("wxWindow creation failed") );
2160 m_insertCallback
= wxInsertChildInWindow
;
2162 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2163 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2165 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2167 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2168 scroll_class
->scrollbar_spacing
= 0;
2170 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2172 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2173 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2175 m_wxwindow
= gtk_pizza_new();
2177 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2179 #if (GTK_MINOR_VERSION > 0)
2180 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2182 if (HasFlag(wxRAISED_BORDER
))
2184 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2186 else if (HasFlag(wxSUNKEN_BORDER
))
2188 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2190 else if (HasFlag(wxSIMPLE_BORDER
))
2192 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2196 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2198 #else // GTK_MINOR_VERSION == 0
2199 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2201 if (HasFlag(wxRAISED_BORDER
))
2203 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2205 else if (HasFlag(wxSUNKEN_BORDER
))
2207 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2211 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2213 #endif // GTK_MINOR_VERSION
2215 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2216 m_acceptsFocus
= TRUE
;
2218 #if (GTK_MINOR_VERSION == 0)
2219 // shut the viewport up
2220 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2221 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2222 #endif // GTK_MINOR_VERSION == 0
2224 // I _really_ don't want scrollbars in the beginning
2225 m_vAdjust
->lower
= 0.0;
2226 m_vAdjust
->upper
= 1.0;
2227 m_vAdjust
->value
= 0.0;
2228 m_vAdjust
->step_increment
= 1.0;
2229 m_vAdjust
->page_increment
= 1.0;
2230 m_vAdjust
->page_size
= 5.0;
2231 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2232 m_hAdjust
->lower
= 0.0;
2233 m_hAdjust
->upper
= 1.0;
2234 m_hAdjust
->value
= 0.0;
2235 m_hAdjust
->step_increment
= 1.0;
2236 m_hAdjust
->page_increment
= 1.0;
2237 m_hAdjust
->page_size
= 5.0;
2238 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2240 // these handlers block mouse events to any window during scrolling such as
2241 // motion events and prevent GTK and wxWindows from fighting over where the
2244 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2245 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2247 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2248 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2250 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2251 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2253 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2254 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2256 // these handlers get notified when screen updates are required either when
2257 // scrolling or when the window size (and therefore scrollbar configuration)
2260 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2261 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2262 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2263 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2265 gtk_widget_show( m_wxwindow
);
2268 m_parent
->DoAddChild( this );
2277 wxWindow::~wxWindow()
2279 m_isBeingDeleted
= TRUE
;
2288 m_parent
->RemoveChild( this );
2292 gdk_ic_destroy (m_ic
);
2294 gdk_ic_attr_destroy (m_icattr
);
2299 #if DISABLE_STYLE_IF_BROKEN_THEME
2300 // don't delete if it's a pixmap theme style
2301 if (!m_widgetStyle
->engine_data
)
2302 gtk_style_unref( m_widgetStyle
);
2304 m_widgetStyle
= (GtkStyle
*) NULL
;
2309 gtk_widget_destroy( m_wxwindow
);
2310 m_wxwindow
= (GtkWidget
*) NULL
;
2315 gtk_widget_destroy( m_widget
);
2316 m_widget
= (GtkWidget
*) NULL
;
2320 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2322 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2324 /* this turns -1 into 20 so that a minimal window is
2325 visible even although -1,-1 has been given as the
2326 size of the window. the same trick is used in other
2327 ports and should make debugging easier */
2328 m_width
= WidthDefault(size
.x
);
2329 m_height
= HeightDefault(size
.y
);
2334 /* some reasonable defaults */
2339 m_x
= (gdk_screen_width () - m_width
) / 2;
2340 if (m_x
< 10) m_x
= 10;
2344 m_y
= (gdk_screen_height () - m_height
) / 2;
2345 if (m_y
< 10) m_y
= 10;
2352 void wxWindow::PostCreation()
2354 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2360 /* these get reported to wxWindows -> wxPaintEvent */
2362 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2364 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2365 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2367 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2368 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2370 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2371 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2374 #if (GTK_MINOR_VERSION > 0)
2375 /* these are called when the "sunken" or "raised" borders are drawn */
2376 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2377 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2379 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2380 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2384 if (m_wxwindow
&& m_needParent
)
2386 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2387 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2389 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2390 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2394 // For dialogs and frames, we are interested mainly in
2395 // m_widget's focus.
2397 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2398 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2400 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2401 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2404 GtkWidget
*connect_widget
= GetConnectWidget();
2406 ConnectWidget( connect_widget
);
2408 /* We cannot set colours, fonts and cursors before the widget has
2409 been realized, so we do this directly after realization */
2410 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2411 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2415 /* Catch native resize events. */
2416 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2417 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2419 /* Initialize XIM support. */
2420 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2421 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2423 /* And resize XIM window. */
2424 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2425 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2431 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2433 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2434 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2436 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2437 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2439 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2440 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2442 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2443 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2445 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2446 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2448 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2449 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2451 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2452 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2455 bool wxWindow::Destroy()
2457 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2461 return wxWindowBase::Destroy();
2464 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2466 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2469 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2471 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2472 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2474 if (m_resizing
) return; /* I don't like recursions */
2477 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2479 /* don't set the size for children of wxNotebook, just take the values. */
2487 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2489 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2491 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2492 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2493 if (width
!= -1) m_width
= width
;
2494 if (height
!= -1) m_height
= height
;
2498 m_x
= x
+ pizza
->xoffset
;
2499 m_y
= y
+ pizza
->yoffset
;
2504 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2506 if (width
== -1) m_width
= 80;
2509 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2511 if (height
== -1) m_height
= 26;
2514 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2515 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2516 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2517 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2520 int bottom_border
= 0;
2522 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2524 /* the default button has a border around it */
2529 DoMoveWindow( m_x
-border
,
2532 m_height
+border
+bottom_border
);
2537 /* Sometimes the client area changes size without the
2538 whole windows's size changing, but if the whole
2539 windows's size doesn't change, no wxSizeEvent will
2540 normally be sent. Here we add an extra test if
2541 the client test has been changed and this will
2543 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2547 wxPrintf( "OnSize sent from " );
2548 if (GetClassInfo() && GetClassInfo()->GetClassName())
2549 wxPrintf( GetClassInfo()->GetClassName() );
2550 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2553 if (!m_nativeSizeEvent
)
2555 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2556 event
.SetEventObject( this );
2557 GetEventHandler()->ProcessEvent( event
);
2563 void wxWindow::OnInternalIdle()
2565 if ( g_sendActivateEvent
!= -1 )
2567 bool activate
= g_sendActivateEvent
!= 0;
2570 g_sendActivateEvent
= -1;
2572 wxActivateEvent
event(wxEVT_ACTIVATE
, activate
, GetId());
2573 event
.SetEventObject(this);
2575 (void)GetEventHandler()->ProcessEvent(event
);
2578 wxCursor cursor
= m_cursor
;
2579 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2583 /* I now set the cursor anew in every OnInternalIdle call
2584 as setting the cursor in a parent window also effects the
2585 windows above so that checking for the current cursor is
2590 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2592 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2594 if (!g_globalCursor
.Ok())
2595 cursor
= *wxSTANDARD_CURSOR
;
2597 window
= m_widget
->window
;
2598 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2599 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2605 GdkWindow
*window
= m_widget
->window
;
2606 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2607 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2615 void wxWindow::DoGetSize( int *width
, int *height
) const
2617 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2619 if (width
) (*width
) = m_width
;
2620 if (height
) (*height
) = m_height
;
2623 void wxWindow::DoSetClientSize( int width
, int height
)
2625 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2629 SetSize( width
, height
);
2636 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2638 /* when using GTK 1.2 we set the shadow border size to 2 */
2642 if (HasFlag(wxSIMPLE_BORDER
))
2644 /* when using GTK 1.2 we set the simple border size to 1 */
2651 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2653 GtkRequisition vscroll_req
;
2654 vscroll_req
.width
= 2;
2655 vscroll_req
.height
= 2;
2656 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2657 (scroll_window
->vscrollbar
, &vscroll_req
);
2659 GtkRequisition hscroll_req
;
2660 hscroll_req
.width
= 2;
2661 hscroll_req
.height
= 2;
2662 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2663 (scroll_window
->hscrollbar
, &hscroll_req
);
2665 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2667 if (scroll_window
->vscrollbar_visible
)
2669 dw
+= vscroll_req
.width
;
2670 dw
+= scroll_class
->scrollbar_spacing
;
2673 if (scroll_window
->hscrollbar_visible
)
2675 dh
+= hscroll_req
.height
;
2676 dh
+= scroll_class
->scrollbar_spacing
;
2680 SetSize( width
+dw
, height
+dh
);
2684 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2686 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2690 if (width
) (*width
) = m_width
;
2691 if (height
) (*height
) = m_height
;
2698 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2700 /* when using GTK 1.2 we set the shadow border size to 2 */
2704 if (HasFlag(wxSIMPLE_BORDER
))
2706 /* when using GTK 1.2 we set the simple border size to 1 */
2713 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2715 GtkRequisition vscroll_req
;
2716 vscroll_req
.width
= 2;
2717 vscroll_req
.height
= 2;
2718 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2719 (scroll_window
->vscrollbar
, &vscroll_req
);
2721 GtkRequisition hscroll_req
;
2722 hscroll_req
.width
= 2;
2723 hscroll_req
.height
= 2;
2724 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2725 (scroll_window
->hscrollbar
, &hscroll_req
);
2727 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2729 if (scroll_window
->vscrollbar_visible
)
2731 dw
+= vscroll_req
.width
;
2732 dw
+= scroll_class
->scrollbar_spacing
;
2735 if (scroll_window
->hscrollbar_visible
)
2737 dh
+= hscroll_req
.height
;
2738 dh
+= scroll_class
->scrollbar_spacing
;
2742 if (width
) (*width
) = m_width
- dw
;
2743 if (height
) (*height
) = m_height
- dh
;
2747 void wxWindow::DoGetPosition( int *x
, int *y
) const
2749 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2753 if (m_parent
&& m_parent
->m_wxwindow
)
2755 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2756 dx
= pizza
->xoffset
;
2757 dy
= pizza
->yoffset
;
2760 if (x
) (*x
) = m_x
- dx
;
2761 if (y
) (*y
) = m_y
- dy
;
2764 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2766 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2768 if (!m_widget
->window
) return;
2770 GdkWindow
*source
= (GdkWindow
*) NULL
;
2772 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2774 source
= m_widget
->window
;
2778 gdk_window_get_origin( source
, &org_x
, &org_y
);
2782 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2784 org_x
+= m_widget
->allocation
.x
;
2785 org_y
+= m_widget
->allocation
.y
;
2793 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2795 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2797 if (!m_widget
->window
) return;
2799 GdkWindow
*source
= (GdkWindow
*) NULL
;
2801 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2803 source
= m_widget
->window
;
2807 gdk_window_get_origin( source
, &org_x
, &org_y
);
2811 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2813 org_x
+= m_widget
->allocation
.x
;
2814 org_y
+= m_widget
->allocation
.y
;
2822 bool wxWindow::Show( bool show
)
2824 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2826 if (!wxWindowBase::Show(show
))
2833 gtk_widget_show( m_widget
);
2835 gtk_widget_hide( m_widget
);
2840 bool wxWindow::Enable( bool enable
)
2842 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2844 if (!wxWindowBase::Enable(enable
))
2850 gtk_widget_set_sensitive( m_widget
, enable
);
2852 gtk_widget_set_sensitive( m_wxwindow
, enable
);
2857 int wxWindow::GetCharHeight() const
2859 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
2861 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
2863 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2865 return font
->ascent
+ font
->descent
;
2868 int wxWindow::GetCharWidth() const
2870 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
2872 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
2874 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
2876 return gdk_string_width( font
, "H" );
2879 void wxWindow::GetTextExtent( const wxString
& string
,
2883 int *externalLeading
,
2884 const wxFont
*theFont
) const
2886 wxFont fontToUse
= m_font
;
2887 if (theFont
) fontToUse
= *theFont
;
2889 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
2891 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
2892 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
2893 if (y
) (*y
) = font
->ascent
+ font
->descent
;
2894 if (descent
) (*descent
) = font
->descent
;
2895 if (externalLeading
) (*externalLeading
) = 0; // ??
2898 void wxWindow::SetFocus()
2900 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2904 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
2905 gtk_widget_grab_focus (m_wxwindow
);
2911 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
2913 gtk_widget_grab_focus (m_widget
);
2915 else if (GTK_IS_CONTAINER(m_widget
))
2917 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
2926 bool wxWindow::AcceptsFocus() const
2928 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
2931 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
2933 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2935 wxWindow
*oldParent
= m_parent
,
2936 *newParent
= (wxWindow
*)newParentBase
;
2938 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2940 if ( !wxWindowBase::Reparent(newParent
) )
2943 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2945 /* prevent GTK from deleting the widget arbitrarily */
2946 gtk_widget_ref( m_widget
);
2950 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
2953 wxASSERT( GTK_IS_WIDGET(m_widget
) );
2957 /* insert GTK representation */
2958 (*(newParent
->m_insertCallback
))(newParent
, this);
2961 /* reverse: prevent GTK from deleting the widget arbitrarily */
2962 gtk_widget_unref( m_widget
);
2967 void wxWindow::DoAddChild(wxWindow
*child
)
2969 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2971 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
2973 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
2978 /* insert GTK representation */
2979 (*m_insertCallback
)(this, child
);
2982 void wxWindow::Raise()
2984 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2986 if (!m_widget
->window
) return;
2988 gdk_window_raise( m_widget
->window
);
2991 void wxWindow::Lower()
2993 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2995 if (!m_widget
->window
) return;
2997 gdk_window_lower( m_widget
->window
);
3000 bool wxWindow::SetCursor( const wxCursor
&cursor
)
3002 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3004 if (cursor
== m_cursor
)
3008 wxapp_install_idle_handler();
3010 if (cursor
== wxNullCursor
)
3011 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3013 return wxWindowBase::SetCursor( cursor
);
3016 void wxWindow::WarpPointer( int x
, int y
)
3018 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3020 /* we provide this function ourselves as it is
3021 missing in GDK (top of this file) */
3023 GdkWindow
*window
= (GdkWindow
*) NULL
;
3025 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3027 window
= GetConnectWidget()->window
;
3030 gdk_window_warp_pointer( window
, x
, y
);
3033 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
3035 if (!m_widget
) return;
3036 if (!m_widget
->window
) return;
3038 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3042 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3044 rect
->width
, rect
->height
);
3048 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3052 /* there is no GTK equivalent of "draw only, don't clear" so we
3053 invent our own in the GtkPizza widget */
3061 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3062 gboolean old_clear = pizza->clear_on_draw;
3063 gtk_pizza_set_clear( pizza, FALSE );
3064 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3065 gtk_pizza_set_clear( pizza, old_clear );
3067 GdkEventExpose gdk_event
;
3068 gdk_event
.type
= GDK_EXPOSE
;
3069 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3070 gdk_event
.count
= 0;
3071 gdk_event
.area
.x
= 0;
3072 gdk_event
.area
.y
= 0;
3073 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3074 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3075 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3080 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3089 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3090 gboolean old_clear = pizza->clear_on_draw;
3091 gtk_pizza_set_clear( pizza, FALSE );
3093 GdkRectangle gdk_rect;
3094 gdk_rect.x = rect->x;
3095 gdk_rect.y = rect->y;
3096 gdk_rect.width = rect->width;
3097 gdk_rect.height = rect->height;
3098 gtk_widget_draw( m_wxwindow, &gdk_rect );
3099 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3101 gtk_pizza_set_clear( pizza, old_clear );
3103 GdkEventExpose gdk_event
;
3104 gdk_event
.type
= GDK_EXPOSE
;
3105 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3106 gdk_event
.count
= 0;
3107 gdk_event
.area
.x
= rect
->x
;
3108 gdk_event
.area
.y
= rect
->y
;
3109 gdk_event
.area
.width
= rect
->width
;
3110 gdk_event
.area
.height
= rect
->height
;
3111 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3115 GdkRectangle gdk_rect
;
3116 gdk_rect
.x
= rect
->x
;
3117 gdk_rect
.y
= rect
->y
;
3118 gdk_rect
.width
= rect
->width
;
3119 gdk_rect
.height
= rect
->height
;
3120 gtk_widget_draw( m_widget
, &gdk_rect
);
3125 void wxWindow::Clear()
3127 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3129 if (!m_widget
->window
) return;
3131 if (m_wxwindow
&& m_wxwindow
->window
)
3133 // gdk_window_clear( m_wxwindow->window );
3138 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
3140 wxWindowBase::DoSetToolTip(tip
);
3143 m_tooltip
->Apply( this );
3146 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3148 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3150 #endif // wxUSE_TOOLTIPS
3152 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
3154 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3156 if (!wxWindowBase::SetBackgroundColour(colour
))
3158 // don't leave if the GTK widget has just
3160 if (!m_delayedBackgroundColour
) return FALSE
;
3163 GdkWindow
*window
= (GdkWindow
*) NULL
;
3165 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3167 window
= GetConnectWidget()->window
;
3171 // indicate that a new style has been set
3172 // but it couldn't get applied as the
3173 // widget hasn't been realized yet.
3174 m_delayedBackgroundColour
= TRUE
;
3178 (m_wxwindow
->window
) &&
3179 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3181 /* wxMSW doesn't clear the window here. I don't do that either to
3182 provide compatibility. call Clear() to do the job. */
3184 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3185 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3193 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
3195 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3197 if (!wxWindowBase::SetForegroundColour(colour
))
3199 // don't leave if the GTK widget has just
3201 if (!m_delayedForegroundColour
) return FALSE
;
3204 GdkWindow
*window
= (GdkWindow
*) NULL
;
3206 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3208 window
= GetConnectWidget()->window
;
3212 // indicate that a new style has been set
3213 // but it couldn't get applied as the
3214 // widget hasn't been realized yet.
3215 m_delayedForegroundColour
= TRUE
;
3223 GtkStyle
*wxWindow::GetWidgetStyle()
3227 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3229 /* FIXME: is this necessary? */
3230 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3232 remake
->klass
= m_widgetStyle
->klass
;
3235 gtk_style_unref( m_widgetStyle
);
3236 m_widgetStyle
= remake
;
3240 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3243 def
= gtk_widget_get_default_style();
3245 m_widgetStyle
= gtk_style_copy( def
);
3247 /* FIXME: is this necessary? */
3248 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3250 m_widgetStyle
->klass
= def
->klass
;
3254 return m_widgetStyle
;
3257 void wxWindow::SetWidgetStyle()
3259 #if DISABLE_STYLE_IF_BROKEN_THEM
3260 if (m_widget
->style
->engine_data
)
3262 static bool s_warningPrinted
= FALSE
;
3263 if (!s_warningPrinted
)
3265 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3266 s_warningPrinted
= TRUE
;
3268 m_widgetStyle
= m_widget
->style
;
3273 GtkStyle
*style
= GetWidgetStyle();
3275 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3277 gdk_font_unref( style
->font
);
3278 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3281 if (m_foregroundColour
.Ok())
3283 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3284 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3286 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3287 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3288 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3292 // Try to restore the gtk default style. This is still a little
3293 // oversimplified for what is probably really needed here for controls
3294 // other than buttons, but is better than not being able to (re)set a
3295 // control's foreground colour to *wxBLACK -- RL
3296 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3299 def
= gtk_widget_get_default_style();
3301 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3302 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3303 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3307 if (m_backgroundColour
.Ok())
3309 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3310 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3312 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3313 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3314 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3315 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3316 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3317 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3318 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3319 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3323 // Try to restore the gtk default style. This is still a little
3324 // oversimplified for what is probably really needed here for controls
3325 // other than buttons, but is better than not being able to (re)set a
3326 // control's background colour to default grey and means resetting a
3327 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3329 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3332 def
= gtk_widget_get_default_style();
3334 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3335 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3336 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3337 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3338 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3339 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3340 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3341 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3346 void wxWindow::ApplyWidgetStyle()
3350 //-----------------------------------------------------------------------------
3351 // Pop-up menu stuff
3352 //-----------------------------------------------------------------------------
3354 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3356 *is_waiting
= FALSE
;
3359 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3361 menu
->SetInvokingWindow( win
);
3362 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3365 wxMenuItem
*menuitem
= node
->GetData();
3366 if (menuitem
->IsSubMenu())
3368 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3371 node
= node
->GetNext();
3375 static gint gs_pop_x
= 0;
3376 static gint gs_pop_y
= 0;
3378 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3382 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3387 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3389 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3391 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3393 SetInvokingWindow( menu
, this );
3400 bool is_waiting
= TRUE
;
3402 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3403 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3406 GTK_MENU(menu
->m_menu
),
3407 (GtkWidget
*) NULL
, // parent menu shell
3408 (GtkWidget
*) NULL
, // parent menu item
3409 (GtkMenuPositionFunc
) pop_pos_callback
,
3410 (gpointer
) this, // client data
3411 0, // button used to activate it
3412 gs_timeLastClick
// the time of activation
3417 while (gtk_events_pending())
3418 gtk_main_iteration();
3424 #if wxUSE_DRAG_AND_DROP
3426 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3428 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3430 GtkWidget
*dnd_widget
= GetConnectWidget();
3432 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3434 if (m_dropTarget
) delete m_dropTarget
;
3435 m_dropTarget
= dropTarget
;
3437 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3440 #endif // wxUSE_DRAG_AND_DROP
3442 GtkWidget
* wxWindow::GetConnectWidget()
3444 GtkWidget
*connect_widget
= m_widget
;
3445 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3447 return connect_widget
;
3450 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3453 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3455 return (window
== m_widget
->window
);
3458 bool wxWindow::SetFont( const wxFont
&font
)
3460 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3462 if (!wxWindowBase::SetFont(font
))
3467 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3468 if ( sysbg
== m_backgroundColour
)
3470 m_backgroundColour
= wxNullColour
;
3472 m_backgroundColour
= sysbg
;
3482 void wxWindow::CaptureMouse()
3484 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3486 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3488 GdkWindow
*window
= (GdkWindow
*) NULL
;
3490 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3492 window
= GetConnectWidget()->window
;
3494 if (!window
) return;
3496 wxCursor
* cursor
= & m_cursor
;
3498 cursor
= wxSTANDARD_CURSOR
;
3500 gdk_pointer_grab( window
, FALSE
,
3502 (GDK_BUTTON_PRESS_MASK
|
3503 GDK_BUTTON_RELEASE_MASK
|
3504 GDK_POINTER_MOTION_HINT_MASK
|
3505 GDK_POINTER_MOTION_MASK
),
3507 cursor
->GetCursor(),
3508 (guint32
)GDK_CURRENT_TIME
);
3509 g_captureWindow
= this;
3512 void wxWindow::ReleaseMouse()
3514 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3516 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3518 GdkWindow
*window
= (GdkWindow
*) NULL
;
3520 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3522 window
= GetConnectWidget()->window
;
3527 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3528 g_captureWindow
= (wxWindow
*) NULL
;
3531 bool wxWindow::IsRetained() const
3536 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3537 int range
, bool refresh
)
3539 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3541 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3543 m_hasScrolling
= TRUE
;
3545 if (orient
== wxHORIZONTAL
)
3547 float fpos
= (float)pos
;
3548 float frange
= (float)range
;
3549 float fthumb
= (float)thumbVisible
;
3550 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3551 if (fpos
< 0.0) fpos
= 0.0;
3553 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3554 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3556 SetScrollPos( orient
, pos
, refresh
);
3560 m_oldHorizontalPos
= fpos
;
3562 m_hAdjust
->lower
= 0.0;
3563 m_hAdjust
->upper
= frange
;
3564 m_hAdjust
->value
= fpos
;
3565 m_hAdjust
->step_increment
= 1.0;
3566 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3567 m_hAdjust
->page_size
= fthumb
;
3571 float fpos
= (float)pos
;
3572 float frange
= (float)range
;
3573 float fthumb
= (float)thumbVisible
;
3574 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3575 if (fpos
< 0.0) fpos
= 0.0;
3577 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3578 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3580 SetScrollPos( orient
, pos
, refresh
);
3584 m_oldVerticalPos
= fpos
;
3586 m_vAdjust
->lower
= 0.0;
3587 m_vAdjust
->upper
= frange
;
3588 m_vAdjust
->value
= fpos
;
3589 m_vAdjust
->step_increment
= 1.0;
3590 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3591 m_vAdjust
->page_size
= fthumb
;
3594 if (orient
== wxHORIZONTAL
)
3595 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3597 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3600 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3602 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3604 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3606 if (orient
== wxHORIZONTAL
)
3608 float fpos
= (float)pos
;
3609 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3610 if (fpos
< 0.0) fpos
= 0.0;
3611 m_oldHorizontalPos
= fpos
;
3613 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3614 m_hAdjust
->value
= fpos
;
3618 float fpos
= (float)pos
;
3619 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3620 if (fpos
< 0.0) fpos
= 0.0;
3621 m_oldVerticalPos
= fpos
;
3623 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3624 m_vAdjust
->value
= fpos
;
3627 if (m_wxwindow
->window
)
3629 if (orient
== wxHORIZONTAL
)
3631 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3632 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3634 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3636 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3637 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3641 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3642 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3644 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3646 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3647 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3652 int wxWindow::GetScrollThumb( int orient
) const
3654 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3656 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3658 if (orient
== wxHORIZONTAL
)
3659 return (int)(m_hAdjust
->page_size
+0.5);
3661 return (int)(m_vAdjust
->page_size
+0.5);
3664 int wxWindow::GetScrollPos( int orient
) const
3666 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3668 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3670 if (orient
== wxHORIZONTAL
)
3671 return (int)(m_hAdjust
->value
+0.5);
3673 return (int)(m_vAdjust
->value
+0.5);
3676 int wxWindow::GetScrollRange( int orient
) const
3678 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3680 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3682 if (orient
== wxHORIZONTAL
)
3683 return (int)(m_hAdjust
->upper
+0.5);
3685 return (int)(m_vAdjust
->upper
+0.5);
3688 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3690 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3692 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3694 if ((dx
== 0) && (dy
== 0)) return;
3696 m_clipPaintRegion
= TRUE
;
3697 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3698 m_clipPaintRegion
= FALSE
;
3701 if (m_children.GetCount() > 0)
3703 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3707 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3709 pizza->xoffset -= dx;
3710 pizza->yoffset -= dy;
3712 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3713 gdk_gc_set_exposures( m_scrollGC, TRUE );
3717 GetClientSize( &cw, &ch );
3718 int w = cw - abs(dx);
3719 int h = ch - abs(dy);
3721 if ((h < 0) || (w < 0))
3729 if (dx < 0) s_x = -dx;
3730 if (dy < 0) s_y = -dy;
3733 if (dx > 0) d_x = dx;
3734 if (dy > 0) d_y = dy;
3736 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3737 pizza->bin_window, s_x, s_y, w, h );
3740 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3741 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3742 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3743 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3745 Refresh( TRUE, &rect );
3748 gdk_gc_unref( m_scrollGC );