1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/window.cpp
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "window.h"
16 #define XWarpPointer XWARPPOINTER
20 #include "wx/window.h"
22 #include "wx/dcclient.h"
25 #include "wx/layout.h"
27 #include "wx/dialog.h"
28 #include "wx/msgdlg.h"
30 #if wxUSE_DRAG_AND_DROP
35 #include "wx/tooltip.h"
43 #include "wx/statusbr.h"
45 #include "wx/settings.h"
49 #include "wx/thread.h"
56 #include <gdk/gdkprivate.h>
57 #include <gdk/gdkkeysyms.h>
61 #include <gtk/gtkprivate.h>
63 #include "wx/gtk/win_gtk.h"
65 //-----------------------------------------------------------------------------
66 // documentation on internals
67 //-----------------------------------------------------------------------------
70 I have been asked several times about writing some documentation about
71 the GTK port of wxWindows, especially its internal structures. Obviously,
72 you cannot understand wxGTK without knowing a little about the GTK, but
73 some more information about what the wxWindow, which is the base class
74 for all other window classes, does seems required as well.
78 What does wxWindow do? It contains the common interface for the following
79 jobs of its descendants:
81 1) Define the rudimentary behaviour common to all window classes, such as
82 resizing, intercepting user input (so as to make it possible to use these
83 events for special purposes in a derived class), window names etc.
85 2) Provide the possibility to contain and manage children, if the derived
86 class is allowed to contain children, which holds true for those window
87 classes which do not display a native GTK widget. To name them, these
88 classes are wxPanel, wxScrolledWindow, wxDialog, wxFrame. The MDI frame-
89 work classes are a special case and are handled a bit differently from
90 the rest. The same holds true for the wxNotebook class.
92 3) Provide the possibility to draw into a client area of a window. This,
93 too, only holds true for classes that do not display a native GTK widget
96 4) Provide the entire mechanism for scrolling widgets. This actual inter-
97 face for this is usually in wxScrolledWindow, but the GTK implementation
100 5) A multitude of helper or extra methods for special purposes, such as
101 Drag'n'Drop, managing validators etc.
103 6) Display a border (sunken, raised, simple or none).
105 Normally one might expect, that one wxWindows window would always correspond
106 to one GTK widget. Under GTK, there is no such allround widget that has all
107 the functionality. Moreover, the GTK defines a client area as a different
108 widget from the actual widget you are handling. Last but not least some
109 special classes (e.g. wxFrame) handle different categories of widgets and
110 still have the possibility to draw something in the client area.
111 It was therefore required to write a special purpose GTK widget, that would
112 represent a client area in the sense of wxWindows capable to do the jobs
113 2), 3) and 4). I have written this class and it resides in win_gtk.c of
116 All windows must have a widget, with which they interact with other under-
117 lying GTK widgets. It is this widget, e.g. that has to be resized etc and
118 thw wxWindow class has a member variable called m_widget which holds a
119 pointer to this widget. When the window class represents a GTK native widget,
120 this is (in most cases) the only GTK widget the class manages. E.g. the
121 wxStatitText class handles only a GtkLabel widget a pointer to which you
122 can find in m_widget (defined in wxWindow)
124 When the class has a client area for drawing into and for containing children
125 it has to handle the client area widget (of the type GtkPizza, defined in
126 win_gtk.c), but there could be any number of widgets, handled by a class
127 The common rule for all windows is only, that the widget that interacts with
128 the rest of GTK must be referenced in m_widget and all other widgets must be
129 children of this widget on the GTK level. The top-most widget, which also
130 represents the client area, must be in the m_wxwindow field and must be of
133 As I said, the window classes that display a GTK native widget only have
134 one widget, so in the case of e.g. the wxButton class m_widget holds a
135 pointer to a GtkButton widget. But windows with client areas (for drawing
136 and children) have a m_widget field that is a pointer to a GtkScrolled-
137 Window and a m_wxwindow field that is pointer to a GtkPizza and this
138 one is (in the GTK sense) a child of the GtkScrolledWindow.
140 If the m_wxwindow field is set, then all input to this widget is inter-
141 cepted and sent to the wxWindows class. If not, all input to the widget
142 that gets pointed to by m_widget gets intercepted and sent to the class.
146 The design of scrolling in wxWindows is markedly different from that offered
147 by the GTK itself and therefore we cannot simply take it as it is. In GTK,
148 clicking on a scrollbar belonging to scrolled window will inevitably move
149 the window. In wxWindows, the scrollbar will only emit an event, send this
150 to (normally) a wxScrolledWindow and that class will call ScrollWindow()
151 which actually moves the window and its subchildren. Note that GtkPizza
152 memorizes how much it has been scrolled but that wxWindows forgets this
153 so that the two coordinates systems have to be kept in synch. This is done
154 in various places using the pizza->xoffset and pizza->yoffset values.
158 Singularily the most broken code in GTK is the code that is supposes to
159 inform subwindows (child windows) about new positions. Very often, duplicate
160 events are sent without changes in size or position, equally often no
161 events are sent at all (All this is due to a bug in the GtkContainer code
162 which got fixed in GTK 1.2.6). For that reason, wxGTK completely ignores
163 GTK's own system and it simply waits for size events for toplevel windows
164 and then iterates down the respective size events to all window. This has
165 the disadvantage, that windows might get size events before the GTK widget
166 actually has the reported size. This doesn't normally pose any problem, but
167 the OpenGl drawing routines rely on correct behaviour. Therefore, I have
168 added the m_nativeSizeEvents flag, which is true only for the OpenGL canvas,
169 i.e. the wxGLCanvas will emit a size event, when (and not before) the X11
170 window that is used for OpenGl output really has that size (as reported by
175 If someone at some point of time feels the immense desire to have a look at,
176 change or attempt to optimse the Refresh() logic, this person will need an
177 intimate understanding of what a "draw" and what an "expose" events are and
178 what there are used for, in particular when used in connection with GTK's
179 own windowless widgets. Beware.
183 Cursors, too, have been a constant source of pleasure. The main difficulty
184 is that a GdkWindow inherits a cursor if the programmer sets a new cursor
185 for the parent. To prevent this from doing too much harm, I use idle time
186 to set the cursor over and over again, starting from the toplevel windows
187 and ending with the youngest generation (speaking of parent and child windows).
188 Also don't forget that cursors (like much else) are connected to GdkWindows,
189 not GtkWidgets and that the "window" field of a GtkWidget might very well
190 point to the GdkWindow of the parent widget (-> "window less widget") and
191 that the two obviously have very different meanings.
195 //-----------------------------------------------------------------------------
197 //-----------------------------------------------------------------------------
199 extern wxList wxPendingDelete
;
200 extern bool g_blockEventsOnDrag
;
201 extern bool g_blockEventsOnScroll
;
202 extern wxCursor g_globalCursor
;
203 static wxWindow
*g_captureWindow
= (wxWindow
*) NULL
;
205 /* extern */ wxWindow
*g_focusWindow
= (wxWindow
*) NULL
;
207 // if we detect that the app has got/lost the focus, we set this variable to
208 // either TRUE or FALSE and an activate event will be sent during the next
209 // OnIdle() call and it is reset to -1: this value means that we shouldn't
210 // send any activate events at all
211 static int g_sendActivateEvent
= -1;
213 /* hack: we need something to pass to gtk_menu_popup, so we store the time of
214 the last click here */
215 static guint32 gs_timeLastClick
= 0;
217 extern bool g_mainThreadLocked
;
219 //-----------------------------------------------------------------------------
221 //-----------------------------------------------------------------------------
224 #define DISABLE_STYLE_IF_BROKEN_THEME 1
230 # define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
232 # define DEBUG_MAIN_THREAD
235 static gint
gtk_debug_focus_in_callback( GtkWidget
*WXUNUSED(widget
),
236 GdkEvent
*WXUNUSED(event
),
237 const wxChar
*WXUNUSED(name
) )
240 static bool s_done = FALSE;
243 wxLog::AddTraceMask("focus");
246 wxLogTrace(wxT("FOCUS NOW AT: %s"), name);
252 void debug_focus_in( GtkWidget
* widget
, const wxChar
* name
, const wxChar
*window
)
254 // suppress warnings about gtk_debug_focus_in_callback being unused with
259 tmp
+= wxT(" FROM ");
262 wxChar
*s
= new wxChar
[tmp
.Length()+1];
266 gtk_signal_connect( GTK_OBJECT(widget
), "focus_in_event",
267 GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback
), (gpointer
)s
);
272 #define DEBUG_MAIN_THREAD
275 //-----------------------------------------------------------------------------
276 // missing gdk functions
277 //-----------------------------------------------------------------------------
280 gdk_window_warp_pointer (GdkWindow
*window
,
285 GdkWindowPrivate
*priv
;
289 window
= GDK_ROOT_PARENT();
292 if (!GDK_WINDOW_DESTROYED(window
))
294 XWarpPointer (GDK_WINDOW_XDISPLAY(window
),
295 None
, /* not source window -> move from anywhere */
296 GDK_WINDOW_XID(window
), /* dest window */
297 0, 0, 0, 0, /* not source window -> move from anywhere */
301 priv
= (GdkWindowPrivate
*) window
;
303 if (!priv
->destroyed
)
305 XWarpPointer (priv
->xdisplay
,
306 None
, /* not source window -> move from anywhere */
307 priv
->xwindow
, /* dest window */
308 0, 0, 0, 0, /* not source window -> move from anywhere */
314 //-----------------------------------------------------------------------------
316 //-----------------------------------------------------------------------------
318 extern void wxapp_install_idle_handler();
319 extern bool g_isIdle
;
321 //-----------------------------------------------------------------------------
322 // local code (see below)
323 //-----------------------------------------------------------------------------
325 // returns the child of win which currently has focus or NULL if not found
326 // Note: can't be static, needed by textctrl.cpp.
327 /* static */ wxWindow
*FindFocusedChild(wxWindow
*win
)
329 wxWindow
*winFocus
= wxWindow::FindFocus();
331 return (wxWindow
*)NULL
;
333 if ( winFocus
== win
)
336 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
338 node
= node
->GetNext() )
340 wxWindow
*child
= FindFocusedChild(node
->GetData());
345 return (wxWindow
*)NULL
;
348 static void draw_frame( GtkWidget
*widget
, wxWindow
*win
)
356 if (win
->m_hasScrolling
)
358 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(widget
);
360 GtkRequisition vscroll_req
;
361 vscroll_req
.width
= 2;
362 vscroll_req
.height
= 2;
363 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
364 (scroll_window
->vscrollbar
, &vscroll_req
);
366 GtkRequisition hscroll_req
;
367 hscroll_req
.width
= 2;
368 hscroll_req
.height
= 2;
369 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
370 (scroll_window
->hscrollbar
, &hscroll_req
);
372 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(widget
) );
374 if (scroll_window
->vscrollbar_visible
)
376 dw
+= vscroll_req
.width
;
377 dw
+= scroll_class
->scrollbar_spacing
;
380 if (scroll_window
->hscrollbar_visible
)
382 dh
+= hscroll_req
.height
;
383 dh
+= scroll_class
->scrollbar_spacing
;
389 if (GTK_WIDGET_NO_WINDOW (widget
))
391 dx
+= widget
->allocation
.x
;
392 dy
+= widget
->allocation
.y
;
395 if (win
->HasFlag(wxRAISED_BORDER
))
397 gtk_draw_shadow( widget
->style
,
402 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
406 if (win
->HasFlag(wxSUNKEN_BORDER
))
408 gtk_draw_shadow( widget
->style
,
413 widget
->allocation
.width
-dw
, widget
->allocation
.height
-dh
);
417 if (win
->HasFlag(wxSIMPLE_BORDER
))
420 gc
= gdk_gc_new( widget
->window
);
421 gdk_gc_set_foreground( gc
, &widget
->style
->black
);
422 gdk_draw_rectangle( widget
->window
, gc
, FALSE
,
424 widget
->allocation
.width
-dw
-1, widget
->allocation
.height
-dh
-1 );
430 //-----------------------------------------------------------------------------
431 // "expose_event" of m_widget
432 //-----------------------------------------------------------------------------
434 gint
gtk_window_own_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
436 if (gdk_event
->count
> 0) return FALSE
;
438 draw_frame( widget
, win
);
443 //-----------------------------------------------------------------------------
444 // "draw" of m_widget
445 //-----------------------------------------------------------------------------
447 static void gtk_window_own_draw_callback( GtkWidget
*widget
, GdkRectangle
*WXUNUSED(rect
), wxWindow
*win
)
449 draw_frame( widget
, win
);
452 //-----------------------------------------------------------------------------
453 // key code mapping routines
454 //-----------------------------------------------------------------------------
456 static long map_to_unmodified_wx_keysym( GdkEventKey
*event
)
458 KeySym keysym
= event
->keyval
;
464 case GDK_Shift_R
: key_code
= WXK_SHIFT
; break;
466 case GDK_Control_R
: key_code
= WXK_CONTROL
; break;
472 case GDK_Super_R
: key_code
= WXK_ALT
; break;
473 case GDK_Menu
: key_code
= WXK_MENU
; break;
474 case GDK_Help
: key_code
= WXK_HELP
; break;
475 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
476 case GDK_ISO_Left_Tab
:
477 case GDK_Tab
: key_code
= WXK_TAB
; break;
478 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
479 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
480 case GDK_Return
: key_code
= WXK_RETURN
; break;
481 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
482 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
483 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
484 case GDK_Delete
: key_code
= WXK_DELETE
; break;
485 case GDK_Home
: key_code
= WXK_HOME
; break;
486 case GDK_Left
: key_code
= WXK_LEFT
; break;
487 case GDK_Up
: key_code
= WXK_UP
; break;
488 case GDK_Right
: key_code
= WXK_RIGHT
; break;
489 case GDK_Down
: key_code
= WXK_DOWN
; break;
490 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
491 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
492 case GDK_Next
: key_code
= WXK_NEXT
; break;
493 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
494 case GDK_End
: key_code
= WXK_END
; break;
495 case GDK_Begin
: key_code
= WXK_HOME
; break;
496 case GDK_Select
: key_code
= WXK_SELECT
; break;
497 case GDK_Print
: key_code
= WXK_PRINT
; break;
498 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
499 case GDK_Insert
: key_code
= WXK_INSERT
; break;
500 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
502 case GDK_KP_0
: key_code
= WXK_NUMPAD0
; break;
503 case GDK_KP_1
: key_code
= WXK_NUMPAD1
; break;
504 case GDK_KP_2
: key_code
= WXK_NUMPAD2
; break;
505 case GDK_KP_3
: key_code
= WXK_NUMPAD3
; break;
506 case GDK_KP_4
: key_code
= WXK_NUMPAD4
; break;
507 case GDK_KP_5
: key_code
= WXK_NUMPAD5
; break;
508 case GDK_KP_6
: key_code
= WXK_NUMPAD6
; break;
509 case GDK_KP_7
: key_code
= WXK_NUMPAD7
; break;
510 case GDK_KP_8
: key_code
= WXK_NUMPAD8
; break;
511 case GDK_KP_9
: key_code
= WXK_NUMPAD9
; break;
512 case GDK_KP_Space
: key_code
= WXK_NUMPAD_SPACE
; break;
513 case GDK_KP_Tab
: key_code
= WXK_NUMPAD_TAB
; break;
514 case GDK_KP_Enter
: key_code
= WXK_NUMPAD_ENTER
; break;
515 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
516 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
517 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
518 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
519 case GDK_KP_Home
: key_code
= WXK_NUMPAD_HOME
; break;
520 case GDK_KP_Left
: key_code
= WXK_NUMPAD_LEFT
; break;
521 case GDK_KP_Up
: key_code
= WXK_NUMPAD_UP
; break;
522 case GDK_KP_Right
: key_code
= WXK_NUMPAD_RIGHT
; break;
523 case GDK_KP_Down
: key_code
= WXK_NUMPAD_DOWN
; break;
524 case GDK_KP_Prior
: key_code
= WXK_NUMPAD_PRIOR
; break;
525 // case GDK_KP_Page_Up: key_code = WXK_NUMPAD_PAGEUP; break;
526 case GDK_KP_Next
: key_code
= WXK_NUMPAD_NEXT
; break;
527 // case GDK_KP_Page_Down: key_code = WXK_NUMPAD_PAGEDOWN; break;
528 case GDK_KP_End
: key_code
= WXK_NUMPAD_END
; break;
529 case GDK_KP_Begin
: key_code
= WXK_NUMPAD_BEGIN
; break;
530 case GDK_KP_Insert
: key_code
= WXK_NUMPAD_INSERT
; break;
531 case GDK_KP_Delete
: key_code
= WXK_NUMPAD_DELETE
; break;
532 case GDK_KP_Equal
: key_code
= WXK_NUMPAD_EQUAL
; break;
533 case GDK_KP_Multiply
: key_code
= WXK_NUMPAD_MULTIPLY
; break;
534 case GDK_KP_Add
: key_code
= WXK_NUMPAD_ADD
; break;
535 case GDK_KP_Separator
: key_code
= WXK_NUMPAD_SEPARATOR
; break;
536 case GDK_KP_Subtract
: key_code
= WXK_NUMPAD_SUBTRACT
; break;
537 case GDK_KP_Decimal
: key_code
= WXK_NUMPAD_DECIMAL
; break;
538 case GDK_KP_Divide
: key_code
= WXK_NUMPAD_DIVIDE
; break;
540 case GDK_F1
: key_code
= WXK_F1
; break;
541 case GDK_F2
: key_code
= WXK_F2
; break;
542 case GDK_F3
: key_code
= WXK_F3
; break;
543 case GDK_F4
: key_code
= WXK_F4
; break;
544 case GDK_F5
: key_code
= WXK_F5
; break;
545 case GDK_F6
: key_code
= WXK_F6
; break;
546 case GDK_F7
: key_code
= WXK_F7
; break;
547 case GDK_F8
: key_code
= WXK_F8
; break;
548 case GDK_F9
: key_code
= WXK_F9
; break;
549 case GDK_F10
: key_code
= WXK_F10
; break;
550 case GDK_F11
: key_code
= WXK_F11
; break;
551 case GDK_F12
: key_code
= WXK_F12
; break;
554 if (event
->length
== 1)
556 key_code
= toupper( (unsigned char)*event
->string
);
558 else if ((keysym
& 0xFF) == keysym
)
560 guint upper
= gdk_keyval_to_upper( (guint
)keysym
);
561 keysym
= (upper
!= 0 ? upper
: keysym
); /* to be MSW compatible */
562 key_code
= (guint
)keysym
;
570 static long map_to_wx_keysym( GdkEventKey
*event
)
572 KeySym keysym
= event
->keyval
;
577 case GDK_Menu
: key_code
= WXK_MENU
; break;
578 case GDK_Help
: key_code
= WXK_HELP
; break;
579 case GDK_BackSpace
: key_code
= WXK_BACK
; break;
580 case GDK_ISO_Left_Tab
:
581 case GDK_Tab
: key_code
= WXK_TAB
; break;
582 case GDK_Linefeed
: key_code
= WXK_RETURN
; break;
583 case GDK_Clear
: key_code
= WXK_CLEAR
; break;
584 case GDK_Return
: key_code
= WXK_RETURN
; break;
585 case GDK_Pause
: key_code
= WXK_PAUSE
; break;
586 case GDK_Scroll_Lock
: key_code
= WXK_SCROLL
; break;
587 case GDK_Escape
: key_code
= WXK_ESCAPE
; break;
588 case GDK_Delete
: key_code
= WXK_DELETE
; break;
589 case GDK_Home
: key_code
= WXK_HOME
; break;
590 case GDK_Left
: key_code
= WXK_LEFT
; break;
591 case GDK_Up
: key_code
= WXK_UP
; break;
592 case GDK_Right
: key_code
= WXK_RIGHT
; break;
593 case GDK_Down
: key_code
= WXK_DOWN
; break;
594 case GDK_Prior
: key_code
= WXK_PRIOR
; break;
595 // case GDK_Page_Up: key_code = WXK_PAGEUP; break;
596 case GDK_Next
: key_code
= WXK_NEXT
; break;
597 // case GDK_Page_Down: key_code = WXK_PAGEDOWN; break;
598 case GDK_End
: key_code
= WXK_END
; break;
599 case GDK_Begin
: key_code
= WXK_HOME
; break;
600 case GDK_Select
: key_code
= WXK_SELECT
; break;
601 case GDK_Print
: key_code
= WXK_PRINT
; break;
602 case GDK_Execute
: key_code
= WXK_EXECUTE
; break;
603 case GDK_Insert
: key_code
= WXK_INSERT
; break;
604 case GDK_Num_Lock
: key_code
= WXK_NUMLOCK
; break;
606 case GDK_KP_0
: key_code
= '0'; break;
607 case GDK_KP_1
: key_code
= '1'; break;
608 case GDK_KP_2
: key_code
= '2'; break;
609 case GDK_KP_3
: key_code
= '3'; break;
610 case GDK_KP_4
: key_code
= '4'; break;
611 case GDK_KP_5
: key_code
= '5'; break;
612 case GDK_KP_6
: key_code
= '6'; break;
613 case GDK_KP_7
: key_code
= '7'; break;
614 case GDK_KP_8
: key_code
= '8'; break;
615 case GDK_KP_9
: key_code
= '9'; break;
616 case GDK_KP_Space
: key_code
= ' '; break;
617 case GDK_KP_Tab
: key_code
= WXK_TAB
; break; /* or '\t' ??? */
618 case GDK_KP_Enter
: key_code
= WXK_RETURN
; break; /* or '\r' ??? */
619 case GDK_KP_F1
: key_code
= WXK_NUMPAD_F1
; break;
620 case GDK_KP_F2
: key_code
= WXK_NUMPAD_F2
; break;
621 case GDK_KP_F3
: key_code
= WXK_NUMPAD_F3
; break;
622 case GDK_KP_F4
: key_code
= WXK_NUMPAD_F4
; break;
623 case GDK_KP_Home
: key_code
= WXK_HOME
; break;
624 case GDK_KP_Left
: key_code
= WXK_LEFT
; break;
625 case GDK_KP_Up
: key_code
= WXK_UP
; break;
626 case GDK_KP_Right
: key_code
= WXK_RIGHT
; break;
627 case GDK_KP_Down
: key_code
= WXK_DOWN
; break;
628 case GDK_KP_Prior
: key_code
= WXK_PRIOR
; break;
629 // case GDK_KP_Page_Up: key_code = WXK_PAGEUP; break;
630 case GDK_KP_Next
: key_code
= WXK_NEXT
; break;
631 // case GDK_KP_Page_Down: key_code = WXK_PAGEDOWN; break;
632 case GDK_KP_End
: key_code
= WXK_END
; break;
633 case GDK_KP_Begin
: key_code
= WXK_HOME
; break;
634 case GDK_KP_Insert
: key_code
= WXK_INSERT
; break;
635 case GDK_KP_Delete
: key_code
= WXK_DELETE
; break;
636 case GDK_KP_Equal
: key_code
= '='; break;
637 case GDK_KP_Multiply
: key_code
= '*'; break;
638 case GDK_KP_Add
: key_code
= '+'; break;
639 case GDK_KP_Separator
: key_code
= ','; break;
640 case GDK_KP_Subtract
: key_code
= '-'; break;
641 case GDK_KP_Decimal
: key_code
= '.'; break;
642 case GDK_KP_Divide
: key_code
= '/'; break;
644 case GDK_F1
: key_code
= WXK_F1
; break;
645 case GDK_F2
: key_code
= WXK_F2
; break;
646 case GDK_F3
: key_code
= WXK_F3
; break;
647 case GDK_F4
: key_code
= WXK_F4
; break;
648 case GDK_F5
: key_code
= WXK_F5
; break;
649 case GDK_F6
: key_code
= WXK_F6
; break;
650 case GDK_F7
: key_code
= WXK_F7
; break;
651 case GDK_F8
: key_code
= WXK_F8
; break;
652 case GDK_F9
: key_code
= WXK_F9
; break;
653 case GDK_F10
: key_code
= WXK_F10
; break;
654 case GDK_F11
: key_code
= WXK_F11
; break;
655 case GDK_F12
: key_code
= WXK_F12
; break;
658 if (event
->length
== 1)
660 key_code
= (unsigned char)*event
->string
;
662 else if ((keysym
& 0xFF) == keysym
)
664 key_code
= (guint
)keysym
;
672 //-----------------------------------------------------------------------------
673 // "size_request" of m_widget
674 //-----------------------------------------------------------------------------
676 static void gtk_window_size_request_callback( GtkWidget
*widget
, GtkRequisition
*requisition
, wxWindow
*win
)
679 win
->GetSize( &w
, &h
);
683 requisition
->height
= h
;
684 requisition
->width
= w
;
687 //-----------------------------------------------------------------------------
688 // "expose_event" of m_wxwindow
689 //-----------------------------------------------------------------------------
691 static int gtk_window_expose_callback( GtkWidget
*widget
, GdkEventExpose
*gdk_event
, wxWindow
*win
)
696 wxapp_install_idle_handler();
699 if (win->GetName() == wxT("panel"))
701 wxPrintf( wxT("OnExpose from ") );
702 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
703 wxPrintf( win->GetClassInfo()->GetClassName() );
704 wxPrintf( wxT(" %d %d %d %d\n"), (int)gdk_event->area.x,
705 (int)gdk_event->area.y,
706 (int)gdk_event->area.width,
707 (int)gdk_event->area.height );
711 GtkPizza
*pizza
= GTK_PIZZA (widget
);
713 if (win
->GetThemeEnabled())
715 wxWindow
*parent
= win
->GetParent();
716 while (parent
&& !parent
->IsTopLevel())
717 parent
= parent
->GetParent();
721 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
722 GTK_SHADOW_NONE
, &gdk_event
->area
, parent
->m_widget
, "base", 0, 0, -1, -1);
725 win
->GetUpdateRegion().Union( gdk_event
->area
.x
,
727 gdk_event
->area
.width
,
728 gdk_event
->area
.height
);
730 if (gdk_event
->count
== 0)
732 win
->m_clipPaintRegion
= TRUE
;
734 wxEraseEvent
eevent( win
->GetId() );
735 eevent
.SetEventObject( win
);
737 win
->GetEventHandler()->ProcessEvent(eevent
);
739 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
741 wxClientDC
dc( win
);
742 dc
.SetBrush( wxBrush( win
->GetBackgroundColour(), wxSOLID
) );
743 dc
.SetPen( *wxTRANSPARENT_PEN
);
745 wxRegionIterator
upd( win
->GetUpdateRegion() );
748 dc
.DrawRectangle( upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
754 wxPaintEvent
event( win
->GetId() );
755 event
.SetEventObject( win
);
756 win
->GetEventHandler()->ProcessEvent( event
);
758 win
->GetUpdateRegion().Clear();
760 win
->m_clipPaintRegion
= FALSE
;
763 /* The following code will result in all window-less widgets
764 being redrawn if the wxWindows class is given a chance to
765 paint *anything* because it will then be allowed to paint
766 over the window-less widgets */
768 GList
*children
= pizza
->children
;
771 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
772 children
= children
->next
;
774 GdkEventExpose child_event
= *gdk_event
;
776 if (GTK_WIDGET_NO_WINDOW (child
->widget
) &&
777 GTK_WIDGET_DRAWABLE (child
->widget
) /* &&
778 gtk_widget_intersect (child->widget, &gdk_event->area, &child_event.area)*/ )
780 child_event
.area
.x
= child
->widget
->allocation
.x
;
781 child_event
.area
.y
= child
->widget
->allocation
.y
;
782 child_event
.area
.width
= child
->widget
->allocation
.width
;
783 child_event
.area
.height
= child
->widget
->allocation
.height
;
784 gtk_widget_event (child
->widget
, (GdkEvent
*) &child_event
);
791 //-----------------------------------------------------------------------------
792 // "event" of m_wxwindow
793 //-----------------------------------------------------------------------------
795 /* GTK thinks it is clever and filters out a certain amount of "unneeded"
796 expose events. We need them, of course, so we override the main event
797 procedure in GtkWidget by giving our own handler for all system events.
798 There, we look for expose events ourselves whereas all other events are
801 gint
gtk_window_event_event_callback( GtkWidget
*widget
, GdkEventExpose
*event
, wxWindow
*win
)
803 if (event
->type
== GDK_EXPOSE
)
805 gint ret
= gtk_window_expose_callback( widget
, event
, win
);
812 //-----------------------------------------------------------------------------
813 // "draw" of m_wxwindow
814 //-----------------------------------------------------------------------------
816 /* This callback is a complete replacement of the gtk_pizza_draw() function,
819 static void gtk_window_draw_callback( GtkWidget
*widget
, GdkRectangle
*rect
, wxWindow
*win
)
824 wxapp_install_idle_handler();
826 if ((win
->HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
)) &&
827 (win
->GetChildren().GetCount() == 0))
833 if (win->GetName() == wxT("panel"))
835 wxPrintf( wxT("OnDraw from ") );
836 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
837 wxPrintf( win->GetClassInfo()->GetClassName() );
838 wxPrintf( wxT(" %d %d %d %d\n"), (int)rect->x,
845 GtkPizza
*pizza
= GTK_PIZZA (widget
);
847 if (win
->GetThemeEnabled())
849 wxWindow
*parent
= win
->GetParent();
850 while (parent
&& !parent
->IsTopLevel())
851 parent
= parent
->GetParent();
855 gtk_paint_flat_box (parent
->m_widget
->style
, pizza
->bin_window
, GTK_STATE_NORMAL
,
856 GTK_SHADOW_NONE
, rect
, parent
->m_widget
, "base", 0, 0, -1, -1);
860 if (!(GTK_WIDGET_APP_PAINTABLE (widget
)) &&
861 (pizza
->clear_on_draw
))
863 gdk_window_clear_area( pizza
->bin_window
,
864 rect
->x
, rect
->y
, rect
->width
, rect
->height
);
867 win
->GetUpdateRegion().Union( rect
->x
, rect
->y
, rect
->width
, rect
->height
);
869 win
->m_clipPaintRegion
= TRUE
;
871 wxEraseEvent
eevent( win
->GetId() );
872 eevent
.SetEventObject( win
);
875 win
->GetEventHandler()->ProcessEvent(eevent
);
877 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
879 if (!win
->GetEventHandler()->ProcessEvent(eevent
))
881 wxClientDC
dc( win
);
882 dc
.SetBrush( wxBrush( win
->GetBackgroundColour(), wxSOLID
) );
883 dc
.SetPen( *wxTRANSPARENT_PEN
);
885 wxRegionIterator
upd( win
->GetUpdateRegion() );
888 dc
.DrawRectangle( upd
.GetX(), upd
.GetY(), upd
.GetWidth(), upd
.GetHeight() );
895 wxPaintEvent
event( win
->GetId() );
896 event
.SetEventObject( win
);
897 win
->GetEventHandler()->ProcessEvent( event
);
899 win
->GetUpdateRegion().Clear();
901 win
->m_clipPaintRegion
= FALSE
;
904 GList
*children
= pizza
->children
;
907 GtkPizzaChild
*child
= (GtkPizzaChild
*) children
->data
;
908 children
= children
->next
;
910 GdkRectangle child_area
;
911 if (gtk_widget_intersect (child
->widget
, rect
, &child_area
))
913 gtk_widget_draw (child
->widget
, &child_area
/* (GdkRectangle*) NULL*/ );
918 //-----------------------------------------------------------------------------
919 // "key_press_event" from any window
920 //-----------------------------------------------------------------------------
922 static gint
gtk_window_key_press_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
927 wxapp_install_idle_handler();
929 if (!win
->m_hasVMT
) return FALSE
;
930 if (g_blockEventsOnDrag
) return FALSE
;
935 tmp += (char)gdk_event->keyval;
936 printf( "KeyDown-Code is: %s.\n", tmp.c_str() );
937 printf( "KeyDown-ScanCode is: %d.\n", gdk_event->keyval );
942 GdkModifierType state
;
943 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
947 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
948 /* sending unknown key events doesn't really make sense */
949 if (key_code
== 0) return FALSE
;
951 wxKeyEvent
event( wxEVT_KEY_DOWN
);
952 event
.SetTimestamp( gdk_event
->time
);
953 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
954 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
955 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
956 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
957 event
.m_keyCode
= key_code
;
958 event
.m_scanCode
= gdk_event
->keyval
;
961 event
.SetEventObject( win
);
962 ret
= win
->GetEventHandler()->ProcessEvent( event
);
967 wxWindow
*ancestor
= win
;
970 int command
= ancestor
->GetAcceleratorTable()->GetCommand( event
);
973 wxCommandEvent
command_event( wxEVT_COMMAND_MENU_SELECTED
, command
);
974 ret
= ancestor
->GetEventHandler()->ProcessEvent( command_event
);
977 if (ancestor
->IsTopLevel())
979 ancestor
= ancestor
->GetParent();
982 #endif // wxUSE_ACCEL
984 /* wxMSW doesn't send char events with Alt pressed */
985 /* Only send wxEVT_CHAR event if not processed yet. Thus, ALT-x
986 will only be sent if it is not in an accelerator table. */
987 key_code
= map_to_wx_keysym( gdk_event
);
992 wxKeyEvent
event2( wxEVT_CHAR
);
993 event2
.SetTimestamp( gdk_event
->time
);
994 event2
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
995 event2
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
996 event2
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
997 event2
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
998 event2
.m_keyCode
= key_code
;
999 event2
.m_scanCode
= gdk_event
->keyval
;
1002 event2
.SetEventObject( win
);
1003 ret
= win
->GetEventHandler()->ProcessEvent( event2
);
1006 /* win is a control: tab can be propagated up */
1008 ((gdk_event
->keyval
== GDK_Tab
) || (gdk_event
->keyval
== GDK_ISO_Left_Tab
)) &&
1009 // VZ: testing for wxTE_PROCESS_TAB shouldn't be done here the control may
1010 // have this style, yet choose not to process this particular TAB in which
1011 // case TAB must still work as a navigational character
1013 (!win
->HasFlag(wxTE_PROCESS_TAB
)) &&
1015 (win
->GetParent()) &&
1016 (win
->GetParent()->HasFlag( wxTAB_TRAVERSAL
)) )
1018 wxNavigationKeyEvent new_event
;
1019 new_event
.SetEventObject( win
->GetParent() );
1020 /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */
1021 new_event
.SetDirection( (gdk_event
->keyval
== GDK_Tab
) );
1022 /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */
1023 new_event
.SetWindowChange( (gdk_event
->state
& GDK_CONTROL_MASK
) );
1024 new_event
.SetCurrentFocus( win
);
1025 ret
= win
->GetParent()->GetEventHandler()->ProcessEvent( new_event
);
1028 /* generate wxID_CANCEL if <esc> has been pressed (typically in dialogs) */
1030 (gdk_event
->keyval
== GDK_Escape
) )
1032 wxCommandEvent
new_event(wxEVT_COMMAND_BUTTON_CLICKED
,wxID_CANCEL
);
1033 new_event
.SetEventObject( win
);
1034 ret
= win
->GetEventHandler()->ProcessEvent( new_event
);
1037 #if (GTK_MINOR_VERSION > 0)
1038 /* Pressing F10 will activate the menu bar of the top frame. */
1042 (gdk_event->keyval == GDK_F10) )
1044 wxWindow *ancestor = win;
1047 if (wxIsKindOf(ancestor,wxFrame))
1049 wxFrame *frame = (wxFrame*) ancestor;
1050 wxMenuBar *menubar = frame->GetMenuBar();
1053 wxNode *node = menubar->GetMenus().First();
1056 wxMenu *firstMenu = (wxMenu*) node->Data();
1057 gtk_menu_item_select( GTK_MENU_ITEM(firstMenu->m_owner) );
1063 ancestor = ancestor->GetParent();
1071 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_press_event" );
1078 //-----------------------------------------------------------------------------
1079 // "key_release_event" from any window
1080 //-----------------------------------------------------------------------------
1082 static gint
gtk_window_key_release_callback( GtkWidget
*widget
, GdkEventKey
*gdk_event
, wxWindow
*win
)
1087 wxapp_install_idle_handler();
1089 if (!win
->m_hasVMT
) return FALSE
;
1090 if (g_blockEventsOnDrag
) return FALSE
;
1093 printf( "KeyUp-ScanCode is: %d.\n", gdk_event->keyval );
1094 if (gdk_event->state & GDK_SHIFT_MASK)
1095 printf( "ShiftDown.\n" );
1097 printf( "ShiftUp.\n" );
1098 if (gdk_event->state & GDK_CONTROL_MASK)
1099 printf( "ControlDown.\n" );
1101 printf( "ControlUp.\n" );
1105 long key_code
= map_to_unmodified_wx_keysym( gdk_event
);
1107 /* sending unknown key events doesn't really make sense */
1108 if (key_code
== 0) return FALSE
;
1112 GdkModifierType state
;
1113 if (gdk_event
->window
) gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1115 wxKeyEvent
event( wxEVT_KEY_UP
);
1116 event
.SetTimestamp( gdk_event
->time
);
1117 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1118 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1119 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1120 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1121 event
.m_keyCode
= key_code
;
1122 event
.m_scanCode
= gdk_event
->keyval
;
1125 event
.SetEventObject( win
);
1127 if (win
->GetEventHandler()->ProcessEvent( event
))
1129 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "key_release_event" );
1136 // ----------------------------------------------------------------------------
1137 // mouse event processing helper
1138 // ----------------------------------------------------------------------------
1140 static void AdjustEventButtonState(wxMouseEvent
& event
)
1142 // GDK reports the old state of the button for a button press event, but
1143 // for compatibility with MSW and common sense we want m_leftDown be TRUE
1144 // for a LEFT_DOWN event, not FALSE, so we will invert
1145 // left/right/middleDown for the corresponding click events
1147 if ((event
.GetEventType() == wxEVT_LEFT_DOWN
) ||
1148 (event
.GetEventType() == wxEVT_LEFT_DCLICK
) ||
1149 (event
.GetEventType() == wxEVT_LEFT_UP
))
1151 event
.m_leftDown
= !event
.m_leftDown
;
1155 if ((event
.GetEventType() == wxEVT_MIDDLE_DOWN
) ||
1156 (event
.GetEventType() == wxEVT_MIDDLE_DCLICK
) ||
1157 (event
.GetEventType() == wxEVT_MIDDLE_UP
))
1159 event
.m_middleDown
= !event
.m_middleDown
;
1163 if ((event
.GetEventType() == wxEVT_RIGHT_DOWN
) ||
1164 (event
.GetEventType() == wxEVT_RIGHT_DCLICK
) ||
1165 (event
.GetEventType() == wxEVT_RIGHT_UP
))
1167 event
.m_rightDown
= !event
.m_rightDown
;
1172 //-----------------------------------------------------------------------------
1173 // "button_press_event"
1174 //-----------------------------------------------------------------------------
1176 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1181 wxapp_install_idle_handler();
1184 wxPrintf( wxT("1) OnButtonPress from ") );
1185 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1186 wxPrintf( win->GetClassInfo()->GetClassName() );
1187 wxPrintf( wxT(".\n") );
1189 if (!win
->m_hasVMT
) return FALSE
;
1190 if (g_blockEventsOnDrag
) return TRUE
;
1191 if (g_blockEventsOnScroll
) return TRUE
;
1193 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1195 if (win
->m_wxwindow
)
1197 if (GTK_WIDGET_CAN_FOCUS(win
->m_wxwindow
) && !GTK_WIDGET_HAS_FOCUS (win
->m_wxwindow
) )
1199 gtk_widget_grab_focus (win
->m_wxwindow
);
1202 wxPrintf( wxT("GrabFocus from ") );
1203 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1204 wxPrintf( win->GetClassInfo()->GetClassName() );
1205 wxPrintf( wxT(".\n") );
1211 wxEventType event_type
= wxEVT_NULL
;
1213 if (gdk_event
->button
== 1)
1215 switch (gdk_event
->type
)
1217 case GDK_BUTTON_PRESS
: event_type
= wxEVT_LEFT_DOWN
; break;
1218 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_LEFT_DCLICK
; break;
1222 else if (gdk_event
->button
== 2)
1224 switch (gdk_event
->type
)
1226 case GDK_BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DOWN
; break;
1227 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_MIDDLE_DCLICK
; break;
1231 else if (gdk_event
->button
== 3)
1233 switch (gdk_event
->type
)
1235 case GDK_BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DOWN
; break;
1236 case GDK_2BUTTON_PRESS
: event_type
= wxEVT_RIGHT_DCLICK
; break;
1241 if ( event_type
== wxEVT_NULL
)
1243 // unknown mouse button or click type
1247 wxMouseEvent
event( event_type
);
1248 event
.SetTimestamp( gdk_event
->time
);
1249 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1250 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1251 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1252 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1253 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1254 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1255 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1257 event
.m_x
= (wxCoord
)gdk_event
->x
;
1258 event
.m_y
= (wxCoord
)gdk_event
->y
;
1260 AdjustEventButtonState(event
);
1262 // Some control don't have their own X window and thus cannot get
1265 if (!g_captureWindow
)
1267 wxCoord x
= event
.m_x
;
1268 wxCoord y
= event
.m_y
;
1269 if (win
->m_wxwindow
)
1271 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1272 x
+= pizza
->xoffset
;
1273 y
+= pizza
->yoffset
;
1276 wxNode
*node
= win
->GetChildren().First();
1279 wxWindow
*child
= (wxWindow
*)node
->Data();
1281 node
= node
->Next();
1282 if (!child
->IsShown())
1285 if (child
->m_isStaticBox
)
1287 // wxStaticBox is transparent in the box itself
1288 int xx1
= child
->m_x
;
1289 int yy1
= child
->m_y
;
1290 int xx2
= child
->m_x
+ child
->m_width
;
1291 int yy2
= child
->m_x
+ child
->m_height
;
1294 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1296 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1298 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1300 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1303 event
.m_x
-= child
->m_x
;
1304 event
.m_y
-= child
->m_y
;
1311 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1312 (child
->m_x
<= x
) &&
1313 (child
->m_y
<= y
) &&
1314 (child
->m_x
+child
->m_width
>= x
) &&
1315 (child
->m_y
+child
->m_height
>= y
))
1318 event
.m_x
-= child
->m_x
;
1319 event
.m_y
-= child
->m_y
;
1326 event
.SetEventObject( win
);
1328 gs_timeLastClick
= gdk_event
->time
;
1331 wxPrintf( wxT("2) OnButtonPress from ") );
1332 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1333 wxPrintf( win->GetClassInfo()->GetClassName() );
1334 wxPrintf( wxT(".\n") );
1337 if (win
->GetEventHandler()->ProcessEvent( event
))
1339 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_press_event" );
1346 //-----------------------------------------------------------------------------
1347 // "button_release_event"
1348 //-----------------------------------------------------------------------------
1350 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxWindow
*win
)
1355 wxapp_install_idle_handler();
1357 if (!win
->m_hasVMT
) return FALSE
;
1358 if (g_blockEventsOnDrag
) return FALSE
;
1359 if (g_blockEventsOnScroll
) return FALSE
;
1361 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1364 printf( "OnButtonRelease from " );
1365 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1366 printf( win->GetClassInfo()->GetClassName() );
1370 wxEventType event_type
= wxEVT_NULL
;
1372 switch (gdk_event
->button
)
1374 case 1: event_type
= wxEVT_LEFT_UP
; break;
1375 case 2: event_type
= wxEVT_MIDDLE_UP
; break;
1376 case 3: event_type
= wxEVT_RIGHT_UP
; break;
1377 default: return FALSE
;
1380 wxMouseEvent
event( event_type
);
1381 event
.SetTimestamp( gdk_event
->time
);
1382 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1383 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1384 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1385 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1386 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1387 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1388 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1389 event
.m_x
= (wxCoord
)gdk_event
->x
;
1390 event
.m_y
= (wxCoord
)gdk_event
->y
;
1392 AdjustEventButtonState(event
);
1394 // Some control don't have their own X window and thus cannot get
1397 if (!g_captureWindow
)
1399 wxCoord x
= event
.m_x
;
1400 wxCoord y
= event
.m_y
;
1401 if (win
->m_wxwindow
)
1403 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1404 x
+= pizza
->xoffset
;
1405 y
+= pizza
->yoffset
;
1408 wxNode
*node
= win
->GetChildren().First();
1411 wxWindow
*child
= (wxWindow
*)node
->Data();
1413 node
= node
->Next();
1414 if (!child
->IsShown())
1417 if (child
->m_isStaticBox
)
1419 // wxStaticBox is transparent in the box itself
1420 int xx1
= child
->m_x
;
1421 int yy1
= child
->m_y
;
1422 int xx2
= child
->m_x
+ child
->m_width
;
1423 int yy2
= child
->m_x
+ child
->m_height
;
1426 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1428 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1430 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1432 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1435 event
.m_x
-= child
->m_x
;
1436 event
.m_y
-= child
->m_y
;
1443 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1444 (child
->m_x
<= x
) &&
1445 (child
->m_y
<= y
) &&
1446 (child
->m_x
+child
->m_width
>= x
) &&
1447 (child
->m_y
+child
->m_height
>= y
))
1450 event
.m_x
-= child
->m_x
;
1451 event
.m_y
-= child
->m_y
;
1458 event
.SetEventObject( win
);
1460 if (win
->GetEventHandler()->ProcessEvent( event
))
1462 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "button_release_event" );
1469 //-----------------------------------------------------------------------------
1470 // "motion_notify_event"
1471 //-----------------------------------------------------------------------------
1473 static gint
gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxWindow
*win
)
1478 wxapp_install_idle_handler();
1480 if (!win
->m_hasVMT
) return FALSE
;
1481 if (g_blockEventsOnDrag
) return FALSE
;
1482 if (g_blockEventsOnScroll
) return FALSE
;
1484 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1486 if (gdk_event
->is_hint
)
1490 GdkModifierType state
;
1491 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
1497 printf( "OnMotion from " );
1498 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1499 printf( win->GetClassInfo()->GetClassName() );
1503 wxMouseEvent
event( wxEVT_MOTION
);
1504 event
.SetTimestamp( gdk_event
->time
);
1505 event
.m_shiftDown
= (gdk_event
->state
& GDK_SHIFT_MASK
);
1506 event
.m_controlDown
= (gdk_event
->state
& GDK_CONTROL_MASK
);
1507 event
.m_altDown
= (gdk_event
->state
& GDK_MOD1_MASK
);
1508 event
.m_metaDown
= (gdk_event
->state
& GDK_MOD2_MASK
);
1509 event
.m_leftDown
= (gdk_event
->state
& GDK_BUTTON1_MASK
);
1510 event
.m_middleDown
= (gdk_event
->state
& GDK_BUTTON2_MASK
);
1511 event
.m_rightDown
= (gdk_event
->state
& GDK_BUTTON3_MASK
);
1513 event
.m_x
= (wxCoord
)gdk_event
->x
;
1514 event
.m_y
= (wxCoord
)gdk_event
->y
;
1516 // Some control don't have their own X window and thus cannot get
1519 if (!g_captureWindow
)
1521 wxCoord x
= event
.m_x
;
1522 wxCoord y
= event
.m_y
;
1523 if (win
->m_wxwindow
)
1525 GtkPizza
*pizza
= GTK_PIZZA(win
->m_wxwindow
);
1526 x
+= pizza
->xoffset
;
1527 y
+= pizza
->yoffset
;
1530 wxNode
*node
= win
->GetChildren().First();
1533 wxWindow
*child
= (wxWindow
*)node
->Data();
1535 node
= node
->Next();
1536 if (!child
->IsShown())
1539 if (child
->m_isStaticBox
)
1541 // wxStaticBox is transparent in the box itself
1542 int xx1
= child
->m_x
;
1543 int yy1
= child
->m_y
;
1544 int xx2
= child
->m_x
+ child
->m_width
;
1545 int yy2
= child
->m_x
+ child
->m_height
;
1548 if (((x
>= xx1
) && (x
<= xx1
+10) && (y
>= yy1
) && (y
<= yy2
)) ||
1550 ((x
>= xx2
-10) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy2
)) ||
1552 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy1
) && (y
<= yy1
+10)) ||
1554 ((x
>= xx1
) && (x
<= xx2
) && (y
>= yy2
-1) && (y
<= yy2
)))
1557 event
.m_x
-= child
->m_x
;
1558 event
.m_y
-= child
->m_y
;
1565 if ((child
->m_wxwindow
== (GtkWidget
*) NULL
) &&
1566 (child
->m_x
<= x
) &&
1567 (child
->m_y
<= y
) &&
1568 (child
->m_x
+child
->m_width
>= x
) &&
1569 (child
->m_y
+child
->m_height
>= y
))
1572 event
.m_x
-= child
->m_x
;
1573 event
.m_y
-= child
->m_y
;
1580 event
.SetEventObject( win
);
1582 if (win
->GetEventHandler()->ProcessEvent( event
))
1584 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "motion_notify_event" );
1591 //-----------------------------------------------------------------------------
1593 //-----------------------------------------------------------------------------
1595 static gint
gtk_window_focus_in_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1600 wxapp_install_idle_handler();
1602 if (!win
->m_hasVMT
) return FALSE
;
1603 if (g_blockEventsOnDrag
) return FALSE
;
1605 switch ( g_sendActivateEvent
)
1608 // we've got focus from outside, synthtize wxActivateEvent
1609 g_sendActivateEvent
= 1;
1613 // another our window just lost focus, it was already ours before
1614 // - don't send any wxActivateEvent
1615 g_sendActivateEvent
= -1;
1619 g_focusWindow
= win
;
1622 printf( "OnSetFocus from " );
1623 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1624 printf( win->GetClassInfo()->GetClassName() );
1626 printf( WXSTRINGCAST win->GetLabel() );
1630 wxPanel
*panel
= wxDynamicCast(win
->GetParent(), wxPanel
);
1633 panel
->SetLastFocus(win
);
1638 gdk_im_begin(win
->m_ic
, win
->m_wxwindow
->window
);
1642 // caret needs to be informed about focus change
1643 wxCaret
*caret
= win
->GetCaret();
1646 caret
->OnSetFocus();
1648 #endif // wxUSE_CARET
1650 if (win
->IsTopLevel())
1652 wxActivateEvent
event( wxEVT_ACTIVATE
, TRUE
, win
->GetId() );
1653 event
.SetEventObject( win
);
1655 // ignore return value
1656 win
->GetEventHandler()->ProcessEvent( event
);
1659 wxFocusEvent
event( wxEVT_SET_FOCUS
, win
->GetId() );
1660 event
.SetEventObject( win
);
1662 if (win
->GetEventHandler()->ProcessEvent( event
))
1664 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_in_event" );
1672 //-----------------------------------------------------------------------------
1673 // "focus_out_event"
1674 //-----------------------------------------------------------------------------
1676 static gint
gtk_window_focus_out_callback( GtkWidget
*widget
, GdkEvent
*WXUNUSED(event
), wxWindow
*win
)
1681 wxapp_install_idle_handler();
1683 if (!win
->m_hasVMT
) return FALSE
;
1684 if (g_blockEventsOnDrag
) return FALSE
;
1686 // if the focus goes out of our app alltogether, OnIdle() will send
1687 // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset
1688 // g_sendActivateEvent to -1
1689 g_sendActivateEvent
= 0;
1691 wxWindow
*winFocus
= FindFocusedChild(win
);
1695 g_focusWindow
= (wxWindow
*)NULL
;
1698 printf( "OnKillFocus from " );
1699 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
1700 printf( win->GetClassInfo()->GetClassName() );
1710 // caret needs to be informed about focus change
1711 wxCaret
*caret
= win
->GetCaret();
1714 caret
->OnKillFocus();
1716 #endif // wxUSE_CARET
1718 if (win
->IsTopLevel())
1720 wxActivateEvent
event( wxEVT_ACTIVATE
, FALSE
, win
->GetId() );
1721 event
.SetEventObject( win
);
1723 // ignore return value
1724 win
->GetEventHandler()->ProcessEvent( event
);
1727 wxFocusEvent
event( wxEVT_KILL_FOCUS
, win
->GetId() );
1728 event
.SetEventObject( win
);
1730 if (win
->GetEventHandler()->ProcessEvent( event
))
1732 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "focus_out_event" );
1739 //-----------------------------------------------------------------------------
1740 // "enter_notify_event"
1741 //-----------------------------------------------------------------------------
1743 static gint
gtk_window_enter_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1748 wxapp_install_idle_handler();
1750 if (!win
->m_hasVMT
) return FALSE
;
1751 if (g_blockEventsOnDrag
) return FALSE
;
1753 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1755 wxMouseEvent
event( wxEVT_ENTER_WINDOW
);
1756 #if (GTK_MINOR_VERSION > 0)
1757 event
.SetTimestamp( gdk_event
->time
);
1759 event
.SetEventObject( win
);
1763 GdkModifierType state
= (GdkModifierType
)0;
1765 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1767 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1768 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1769 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1770 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1771 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1772 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1773 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1778 if (win
->GetEventHandler()->ProcessEvent( event
))
1780 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "enter_notify_event" );
1787 //-----------------------------------------------------------------------------
1788 // "leave_notify_event"
1789 //-----------------------------------------------------------------------------
1791 static gint
gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxWindow
*win
)
1796 wxapp_install_idle_handler();
1798 if (!win
->m_hasVMT
) return FALSE
;
1799 if (g_blockEventsOnDrag
) return FALSE
;
1801 if (!win
->IsOwnGtkWindow( gdk_event
->window
)) return FALSE
;
1803 wxMouseEvent
event( wxEVT_LEAVE_WINDOW
);
1804 #if (GTK_MINOR_VERSION > 0)
1805 event
.SetTimestamp( gdk_event
->time
);
1807 event
.SetEventObject( win
);
1811 GdkModifierType state
= (GdkModifierType
)0;
1813 gdk_window_get_pointer( widget
->window
, &x
, &y
, &state
);
1815 event
.m_shiftDown
= (state
& GDK_SHIFT_MASK
);
1816 event
.m_controlDown
= (state
& GDK_CONTROL_MASK
);
1817 event
.m_altDown
= (state
& GDK_MOD1_MASK
);
1818 event
.m_metaDown
= (state
& GDK_MOD2_MASK
);
1819 event
.m_leftDown
= (state
& GDK_BUTTON1_MASK
);
1820 event
.m_middleDown
= (state
& GDK_BUTTON2_MASK
);
1821 event
.m_rightDown
= (state
& GDK_BUTTON3_MASK
);
1826 if (win
->GetEventHandler()->ProcessEvent( event
))
1828 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget
), "leave_notify_event" );
1835 //-----------------------------------------------------------------------------
1836 // "value_changed" from m_vAdjust
1837 //-----------------------------------------------------------------------------
1839 static void gtk_window_vscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1844 wxapp_install_idle_handler();
1846 if (g_blockEventsOnDrag
) return;
1848 if (!win
->m_hasVMT
) return;
1850 float diff
= adjust
->value
- win
->m_oldVerticalPos
;
1851 if (fabs(diff
) < 0.2) return;
1853 win
->m_oldVerticalPos
= adjust
->value
;
1855 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1856 GtkRange
*range
= GTK_RANGE( scrolledWindow
->vscrollbar
);
1858 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1859 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1860 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1861 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1862 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1864 int value
= (int)(adjust
->value
+0.5);
1866 wxScrollWinEvent
event( command
, value
, wxVERTICAL
);
1867 event
.SetEventObject( win
);
1868 win
->GetEventHandler()->ProcessEvent( event
);
1871 //-----------------------------------------------------------------------------
1872 // "value_changed" from m_hAdjust
1873 //-----------------------------------------------------------------------------
1875 static void gtk_window_hscroll_callback( GtkAdjustment
*adjust
, wxWindow
*win
)
1880 wxapp_install_idle_handler();
1882 if (g_blockEventsOnDrag
) return;
1883 if (!win
->m_hasVMT
) return;
1885 float diff
= adjust
->value
- win
->m_oldHorizontalPos
;
1886 if (fabs(diff
) < 0.2) return;
1888 win
->m_oldHorizontalPos
= adjust
->value
;
1890 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1891 GtkRange
*range
= GTK_RANGE( scrolledWindow
->hscrollbar
);
1893 wxEventType command
= wxEVT_SCROLLWIN_THUMBTRACK
;
1894 if (range
->scroll_type
== GTK_SCROLL_STEP_BACKWARD
) command
= wxEVT_SCROLLWIN_LINEUP
;
1895 else if (range
->scroll_type
== GTK_SCROLL_STEP_FORWARD
) command
= wxEVT_SCROLLWIN_LINEDOWN
;
1896 else if (range
->scroll_type
== GTK_SCROLL_PAGE_BACKWARD
) command
= wxEVT_SCROLLWIN_PAGEUP
;
1897 else if (range
->scroll_type
== GTK_SCROLL_PAGE_FORWARD
) command
= wxEVT_SCROLLWIN_PAGEDOWN
;
1899 int value
= (int)(adjust
->value
+0.5);
1901 wxScrollWinEvent
event( command
, value
, wxHORIZONTAL
);
1902 event
.SetEventObject( win
);
1903 win
->GetEventHandler()->ProcessEvent( event
);
1906 //-----------------------------------------------------------------------------
1907 // "button_press_event" from scrollbar
1908 //-----------------------------------------------------------------------------
1910 static gint
gtk_scrollbar_button_press_callback( GtkRange
*widget
,
1911 GdkEventButton
*gdk_event
,
1917 wxapp_install_idle_handler();
1920 g_blockEventsOnScroll
= TRUE
;
1921 win
->m_isScrolling
= (gdk_event
->window
== widget
->slider
);
1926 //-----------------------------------------------------------------------------
1927 // "button_release_event" from scrollbar
1928 //-----------------------------------------------------------------------------
1930 static gint
gtk_scrollbar_button_release_callback( GtkRange
*widget
,
1931 GdkEventButton
*WXUNUSED(gdk_event
),
1936 // don't test here as we can release the mouse while being over
1937 // a different window than the slider
1939 // if (gdk_event->window != widget->slider) return FALSE;
1941 g_blockEventsOnScroll
= FALSE
;
1943 if (win
->m_isScrolling
)
1945 wxEventType command
= wxEVT_SCROLLWIN_THUMBRELEASE
;
1949 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(win
->m_widget
);
1950 if (widget
== GTK_RANGE(scrolledWindow
->hscrollbar
))
1952 value
= (int)(win
->m_hAdjust
->value
+0.5);
1955 if (widget
== GTK_RANGE(scrolledWindow
->vscrollbar
))
1957 value
= (int)(win
->m_vAdjust
->value
+0.5);
1961 wxScrollWinEvent
event( command
, value
, dir
);
1962 event
.SetEventObject( win
);
1963 win
->GetEventHandler()->ProcessEvent( event
);
1966 win
->m_isScrolling
= FALSE
;
1971 // ----------------------------------------------------------------------------
1972 // this wxWindowBase function is implemented here (in platform-specific file)
1973 // because it is static and so couldn't be made virtual
1974 // ----------------------------------------------------------------------------
1976 wxWindow
*wxWindowBase::FindFocus()
1978 return g_focusWindow
;
1981 //-----------------------------------------------------------------------------
1982 // "realize" from m_widget
1983 //-----------------------------------------------------------------------------
1985 /* We cannot set colours and fonts before the widget has
1986 been realized, so we do this directly after realization. */
1989 gtk_window_realized_callback( GtkWidget
*WXUNUSED(m_widget
), wxWindow
*win
)
1994 wxapp_install_idle_handler();
1996 if (win
->m_delayedBackgroundColour
)
1997 win
->SetBackgroundColour( win
->GetBackgroundColour() );
1999 if (win
->m_delayedForegroundColour
)
2000 win
->SetForegroundColour( win
->GetForegroundColour() );
2002 wxWindowCreateEvent
event( win
);
2003 event
.SetEventObject( win
);
2004 win
->GetEventHandler()->ProcessEvent( event
);
2009 //-----------------------------------------------------------------------------
2011 //-----------------------------------------------------------------------------
2014 void gtk_window_size_callback( GtkWidget
*WXUNUSED(widget
),
2015 GtkAllocation
*WXUNUSED(alloc
),
2019 wxapp_install_idle_handler();
2021 if (!win
->m_hasScrolling
) return;
2023 int client_width
= 0;
2024 int client_height
= 0;
2025 win
->GetClientSize( &client_width
, &client_height
);
2026 if ((client_width
== win
->m_oldClientWidth
) && (client_height
== win
->m_oldClientHeight
))
2029 win
->m_oldClientWidth
= client_width
;
2030 win
->m_oldClientHeight
= client_height
;
2032 if (!win
->m_nativeSizeEvent
)
2034 wxSizeEvent
event( win
->GetSize(), win
->GetId() );
2035 event
.SetEventObject( win
);
2036 win
->GetEventHandler()->ProcessEvent( event
);
2042 #define WXUNUSED_UNLESS_XIM(param) param
2044 #define WXUNUSED_UNLESS_XIM(param) WXUNUSED(param)
2047 /* Resize XIM window */
2050 void gtk_wxwindow_size_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2051 GtkAllocation
* WXUNUSED_UNLESS_XIM(alloc
),
2052 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
2055 wxapp_install_idle_handler();
2061 if (gdk_ic_get_style (win
->m_ic
) & GDK_IM_PREEDIT_POSITION
)
2065 gdk_window_get_size (widget
->window
, &width
, &height
);
2066 win
->m_icattr
->preedit_area
.width
= width
;
2067 win
->m_icattr
->preedit_area
.height
= height
;
2068 gdk_ic_set_attr (win
->m_ic
, win
->m_icattr
, GDK_IC_PREEDIT_AREA
);
2073 //-----------------------------------------------------------------------------
2074 // "realize" from m_wxwindow
2075 //-----------------------------------------------------------------------------
2077 /* Initialize XIM support */
2080 gtk_wxwindow_realized_callback( GtkWidget
* WXUNUSED_UNLESS_XIM(widget
),
2081 wxWindow
* WXUNUSED_UNLESS_XIM(win
) )
2084 wxapp_install_idle_handler();
2087 if (win
->m_ic
) return FALSE
;
2088 if (!widget
) return FALSE
;
2089 if (!gdk_im_ready()) return FALSE
;
2091 win
->m_icattr
= gdk_ic_attr_new();
2092 if (!win
->m_icattr
) return FALSE
;
2096 GdkColormap
*colormap
;
2097 GdkICAttr
*attr
= win
->m_icattr
;
2098 unsigned attrmask
= GDK_IC_ALL_REQ
;
2100 GdkIMStyle supported_style
= (GdkIMStyle
)
2101 (GDK_IM_PREEDIT_NONE
|
2102 GDK_IM_PREEDIT_NOTHING
|
2103 GDK_IM_PREEDIT_POSITION
|
2104 GDK_IM_STATUS_NONE
|
2105 GDK_IM_STATUS_NOTHING
);
2107 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2108 supported_style
= (GdkIMStyle
)(supported_style
& ~GDK_IM_PREEDIT_POSITION
);
2110 attr
->style
= style
= gdk_im_decide_style (supported_style
);
2111 attr
->client_window
= widget
->window
;
2113 if ((colormap
= gtk_widget_get_colormap (widget
)) !=
2114 gtk_widget_get_default_colormap ())
2116 attrmask
|= GDK_IC_PREEDIT_COLORMAP
;
2117 attr
->preedit_colormap
= colormap
;
2120 attrmask
|= GDK_IC_PREEDIT_FOREGROUND
;
2121 attrmask
|= GDK_IC_PREEDIT_BACKGROUND
;
2122 attr
->preedit_foreground
= widget
->style
->fg
[GTK_STATE_NORMAL
];
2123 attr
->preedit_background
= widget
->style
->base
[GTK_STATE_NORMAL
];
2125 switch (style
& GDK_IM_PREEDIT_MASK
)
2127 case GDK_IM_PREEDIT_POSITION
:
2128 if (widget
->style
&& widget
->style
->font
->type
!= GDK_FONT_FONTSET
)
2130 g_warning ("over-the-spot style requires fontset");
2134 gdk_window_get_size (widget
->window
, &width
, &height
);
2136 attrmask
|= GDK_IC_PREEDIT_POSITION_REQ
;
2137 attr
->spot_location
.x
= 0;
2138 attr
->spot_location
.y
= height
;
2139 attr
->preedit_area
.x
= 0;
2140 attr
->preedit_area
.y
= 0;
2141 attr
->preedit_area
.width
= width
;
2142 attr
->preedit_area
.height
= height
;
2143 attr
->preedit_fontset
= widget
->style
->font
;
2148 win
->m_ic
= gdk_ic_new (attr
, (GdkICAttributesType
)attrmask
);
2150 if (win
->m_ic
== NULL
)
2151 g_warning ("Can't create input context.");
2154 mask
= gdk_window_get_events (widget
->window
);
2155 mask
= (GdkEventMask
)(mask
| gdk_ic_get_events (win
->m_ic
));
2156 gdk_window_set_events (widget
->window
, mask
);
2158 if (GTK_WIDGET_HAS_FOCUS(widget
))
2159 gdk_im_begin (win
->m_ic
, widget
->window
);
2166 //-----------------------------------------------------------------------------
2167 // InsertChild for wxWindow.
2168 //-----------------------------------------------------------------------------
2170 /* Callback for wxWindow. This very strange beast has to be used because
2171 * C++ has no virtual methods in a constructor. We have to emulate a
2172 * virtual function here as wxNotebook requires a different way to insert
2173 * a child in it. I had opted for creating a wxNotebookPage window class
2174 * which would have made this superfluous (such in the MDI window system),
2175 * but no-one was listening to me... */
2177 static void wxInsertChildInWindow( wxWindow
* parent
, wxWindow
* child
)
2179 /* the window might have been scrolled already, do we
2180 have to adapt the position */
2181 GtkPizza
*pizza
= GTK_PIZZA(parent
->m_wxwindow
);
2182 child
->m_x
+= pizza
->xoffset
;
2183 child
->m_y
+= pizza
->yoffset
;
2185 gtk_pizza_put( GTK_PIZZA(parent
->m_wxwindow
),
2186 GTK_WIDGET(child
->m_widget
),
2193 //-----------------------------------------------------------------------------
2195 //-----------------------------------------------------------------------------
2197 wxWindow
* wxGetActiveWindow()
2199 return g_focusWindow
;
2202 //-----------------------------------------------------------------------------
2204 //-----------------------------------------------------------------------------
2206 IMPLEMENT_DYNAMIC_CLASS(wxWindow
, wxWindowBase
)
2208 void wxWindow::Init()
2214 m_widget
= (GtkWidget
*) NULL
;
2215 m_wxwindow
= (GtkWidget
*) NULL
;
2225 m_needParent
= TRUE
;
2226 m_isBeingDeleted
= FALSE
;
2229 m_nativeSizeEvent
= FALSE
;
2231 m_hasScrolling
= FALSE
;
2232 m_isScrolling
= FALSE
;
2234 m_hAdjust
= (GtkAdjustment
*) NULL
;
2235 m_vAdjust
= (GtkAdjustment
*) NULL
;
2236 m_oldHorizontalPos
= 0.0;
2237 m_oldVerticalPos
= 0.0;
2240 m_widgetStyle
= (GtkStyle
*) NULL
;
2242 m_insertCallback
= (wxInsertChildFunction
) NULL
;
2244 m_isStaticBox
= FALSE
;
2245 m_isRadioButton
= FALSE
;
2247 m_acceptsFocus
= FALSE
;
2249 m_clipPaintRegion
= FALSE
;
2251 m_cursor
= *wxSTANDARD_CURSOR
;
2253 m_delayedForegroundColour
= FALSE
;
2254 m_delayedBackgroundColour
= FALSE
;
2257 m_ic
= (GdkIC
*) NULL
;
2258 m_icattr
= (GdkICAttr
*) NULL
;
2262 wxWindow::wxWindow()
2267 wxWindow::wxWindow( wxWindow
*parent
, wxWindowID id
,
2268 const wxPoint
&pos
, const wxSize
&size
,
2269 long style
, const wxString
&name
)
2273 Create( parent
, id
, pos
, size
, style
, name
);
2276 bool wxWindow::Create( wxWindow
*parent
, wxWindowID id
,
2277 const wxPoint
&pos
, const wxSize
&size
,
2278 long style
, const wxString
&name
)
2280 if (!PreCreation( parent
, pos
, size
) ||
2281 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
))
2283 wxFAIL_MSG( wxT("wxWindow creation failed") );
2287 m_insertCallback
= wxInsertChildInWindow
;
2289 m_widget
= gtk_scrolled_window_new( (GtkAdjustment
*) NULL
, (GtkAdjustment
*) NULL
);
2290 GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_FOCUS
);
2292 GtkScrolledWindow
*scrolledWindow
= GTK_SCROLLED_WINDOW(m_widget
);
2294 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2295 scroll_class
->scrollbar_spacing
= 0;
2297 gtk_scrolled_window_set_policy( scrolledWindow
, GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2299 m_hAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->hscrollbar
) );
2300 m_vAdjust
= gtk_range_get_adjustment( GTK_RANGE(scrolledWindow
->vscrollbar
) );
2302 m_wxwindow
= gtk_pizza_new();
2304 gtk_container_add( GTK_CONTAINER(m_widget
), m_wxwindow
);
2306 #if (GTK_MINOR_VERSION > 0)
2307 GtkPizza
*pizza
= GTK_PIZZA(m_wxwindow
);
2309 if (HasFlag(wxRAISED_BORDER
))
2311 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_OUT
);
2313 else if (HasFlag(wxSUNKEN_BORDER
))
2315 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_IN
);
2317 else if (HasFlag(wxSIMPLE_BORDER
))
2319 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_THIN
);
2323 gtk_pizza_set_shadow_type( pizza
, GTK_MYSHADOW_NONE
);
2325 #else // GTK_MINOR_VERSION == 0
2326 GtkViewport
*viewport
= GTK_VIEWPORT(scrolledWindow
->viewport
);
2328 if (HasFlag(wxRAISED_BORDER
))
2330 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_OUT
);
2332 else if (HasFlag(wxSUNKEN_BORDER
))
2334 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_IN
);
2338 gtk_viewport_set_shadow_type( viewport
, GTK_SHADOW_NONE
);
2340 #endif // GTK_MINOR_VERSION
2342 GTK_WIDGET_SET_FLAGS( m_wxwindow
, GTK_CAN_FOCUS
);
2343 m_acceptsFocus
= TRUE
;
2345 #if (GTK_MINOR_VERSION == 0)
2346 // shut the viewport up
2347 gtk_viewport_set_hadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2348 gtk_viewport_set_vadjustment( viewport
, (GtkAdjustment
*) gtk_adjustment_new( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) );
2349 #endif // GTK_MINOR_VERSION == 0
2351 // I _really_ don't want scrollbars in the beginning
2352 m_vAdjust
->lower
= 0.0;
2353 m_vAdjust
->upper
= 1.0;
2354 m_vAdjust
->value
= 0.0;
2355 m_vAdjust
->step_increment
= 1.0;
2356 m_vAdjust
->page_increment
= 1.0;
2357 m_vAdjust
->page_size
= 5.0;
2358 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
2359 m_hAdjust
->lower
= 0.0;
2360 m_hAdjust
->upper
= 1.0;
2361 m_hAdjust
->value
= 0.0;
2362 m_hAdjust
->step_increment
= 1.0;
2363 m_hAdjust
->page_increment
= 1.0;
2364 m_hAdjust
->page_size
= 5.0;
2365 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
2367 // these handlers block mouse events to any window during scrolling such as
2368 // motion events and prevent GTK and wxWindows from fighting over where the
2371 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_press_event",
2372 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2374 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_press_event",
2375 (GtkSignalFunc
)gtk_scrollbar_button_press_callback
, (gpointer
) this );
2377 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->vscrollbar
), "button_release_event",
2378 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2380 gtk_signal_connect( GTK_OBJECT(scrolledWindow
->hscrollbar
), "button_release_event",
2381 (GtkSignalFunc
)gtk_scrollbar_button_release_callback
, (gpointer
) this );
2383 // these handlers get notified when screen updates are required either when
2384 // scrolling or when the window size (and therefore scrollbar configuration)
2387 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
2388 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
2389 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
2390 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
2392 gtk_widget_show( m_wxwindow
);
2395 m_parent
->DoAddChild( this );
2404 wxWindow::~wxWindow()
2406 if (g_focusWindow
== this)
2407 g_focusWindow
= NULL
;
2409 m_isBeingDeleted
= TRUE
;
2418 m_parent
->RemoveChild( this );
2422 gdk_ic_destroy (m_ic
);
2424 gdk_ic_attr_destroy (m_icattr
);
2429 #if DISABLE_STYLE_IF_BROKEN_THEME
2430 // don't delete if it's a pixmap theme style
2431 if (!m_widgetStyle
->engine_data
)
2432 gtk_style_unref( m_widgetStyle
);
2434 m_widgetStyle
= (GtkStyle
*) NULL
;
2439 gtk_widget_destroy( m_wxwindow
);
2440 m_wxwindow
= (GtkWidget
*) NULL
;
2445 gtk_widget_destroy( m_widget
);
2446 m_widget
= (GtkWidget
*) NULL
;
2450 bool wxWindow::PreCreation( wxWindow
*parent
, const wxPoint
&pos
, const wxSize
&size
)
2452 wxCHECK_MSG( !m_needParent
|| parent
, FALSE
, wxT("Need complete parent.") );
2454 /* this turns -1 into 20 so that a minimal window is
2455 visible even although -1,-1 has been given as the
2456 size of the window. the same trick is used in other
2457 ports and should make debugging easier */
2458 m_width
= WidthDefault(size
.x
);
2459 m_height
= HeightDefault(size
.y
);
2464 /* some reasonable defaults */
2469 m_x
= (gdk_screen_width () - m_width
) / 2;
2470 if (m_x
< 10) m_x
= 10;
2474 m_y
= (gdk_screen_height () - m_height
) / 2;
2475 if (m_y
< 10) m_y
= 10;
2482 void wxWindow::PostCreation()
2484 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2490 /* these get reported to wxWindows -> wxPaintEvent */
2492 gtk_pizza_set_external( GTK_PIZZA(m_wxwindow
), TRUE
);
2494 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "expose_event",
2495 GTK_SIGNAL_FUNC(gtk_window_expose_callback
), (gpointer
)this );
2497 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "draw",
2498 GTK_SIGNAL_FUNC(gtk_window_draw_callback
), (gpointer
)this );
2500 if (HasFlag(wxNO_FULL_REPAINT_ON_RESIZE
))
2502 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "event",
2503 GTK_SIGNAL_FUNC(gtk_window_event_event_callback
), (gpointer
)this );
2507 #if (GTK_MINOR_VERSION > 0)
2508 /* these are called when the "sunken" or "raised" borders are drawn */
2509 gtk_signal_connect( GTK_OBJECT(m_widget
), "expose_event",
2510 GTK_SIGNAL_FUNC(gtk_window_own_expose_callback
), (gpointer
)this );
2512 gtk_signal_connect( GTK_OBJECT(m_widget
), "draw",
2513 GTK_SIGNAL_FUNC(gtk_window_own_draw_callback
), (gpointer
)this );
2517 if (m_wxwindow
&& m_needParent
)
2519 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_in_event",
2520 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2522 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "focus_out_event",
2523 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2527 // For dialogs and frames, we are interested mainly in
2528 // m_widget's focus.
2530 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_in_event",
2531 GTK_SIGNAL_FUNC(gtk_window_focus_in_callback
), (gpointer
)this );
2533 gtk_signal_connect( GTK_OBJECT(m_widget
), "focus_out_event",
2534 GTK_SIGNAL_FUNC(gtk_window_focus_out_callback
), (gpointer
)this );
2537 GtkWidget
*connect_widget
= GetConnectWidget();
2539 ConnectWidget( connect_widget
);
2541 /* We cannot set colours, fonts and cursors before the widget has
2542 been realized, so we do this directly after realization */
2543 gtk_signal_connect( GTK_OBJECT(connect_widget
), "realize",
2544 GTK_SIGNAL_FUNC(gtk_window_realized_callback
), (gpointer
) this );
2548 // Catch native resize events
2549 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2550 GTK_SIGNAL_FUNC(gtk_window_size_callback
), (gpointer
)this );
2552 // Initialize XIM support
2553 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "realize",
2554 GTK_SIGNAL_FUNC(gtk_wxwindow_realized_callback
), (gpointer
) this );
2556 // And resize XIM window
2557 gtk_signal_connect( GTK_OBJECT(m_wxwindow
), "size_allocate",
2558 GTK_SIGNAL_FUNC(gtk_wxwindow_size_callback
), (gpointer
)this );
2561 if (!GTK_IS_COMBO(m_widget
))
2563 // This is needed if we want to add our windows into native
2564 // GTK control, such as the toolbar. With this callback, the
2565 // toolbar gets to know the correct size (the one set by the
2566 // programmer). Sadly, it misbehaves for wxComboBox. FIXME
2567 // when moving to GTK 2.0.
2568 gtk_signal_connect( GTK_OBJECT(m_widget
), "size_request",
2569 GTK_SIGNAL_FUNC(gtk_window_size_request_callback
), (gpointer
) this );
2575 void wxWindow::ConnectWidget( GtkWidget
*widget
)
2577 gtk_signal_connect( GTK_OBJECT(widget
), "key_press_event",
2578 GTK_SIGNAL_FUNC(gtk_window_key_press_callback
), (gpointer
)this );
2580 gtk_signal_connect( GTK_OBJECT(widget
), "key_release_event",
2581 GTK_SIGNAL_FUNC(gtk_window_key_release_callback
), (gpointer
)this );
2583 gtk_signal_connect( GTK_OBJECT(widget
), "button_press_event",
2584 GTK_SIGNAL_FUNC(gtk_window_button_press_callback
), (gpointer
)this );
2586 gtk_signal_connect( GTK_OBJECT(widget
), "button_release_event",
2587 GTK_SIGNAL_FUNC(gtk_window_button_release_callback
), (gpointer
)this );
2589 gtk_signal_connect( GTK_OBJECT(widget
), "motion_notify_event",
2590 GTK_SIGNAL_FUNC(gtk_window_motion_notify_callback
), (gpointer
)this );
2592 gtk_signal_connect( GTK_OBJECT(widget
), "enter_notify_event",
2593 GTK_SIGNAL_FUNC(gtk_window_enter_callback
), (gpointer
)this );
2595 gtk_signal_connect( GTK_OBJECT(widget
), "leave_notify_event",
2596 GTK_SIGNAL_FUNC(gtk_window_leave_callback
), (gpointer
)this );
2599 bool wxWindow::Destroy()
2601 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2605 return wxWindowBase::Destroy();
2608 void wxWindow::DoMoveWindow(int x
, int y
, int width
, int height
)
2610 gtk_pizza_set_size( GTK_PIZZA(m_parent
->m_wxwindow
), m_widget
, x
, y
, width
, height
);
2613 void wxWindow::DoSetSize( int x
, int y
, int width
, int height
, int sizeFlags
)
2615 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
2616 wxASSERT_MSG( (m_parent
!= NULL
), wxT("wxWindow::SetSize requires parent.\n") );
2619 printf( "DoSetSize: name %s, x,y,w,h: %d,%d,%d,%d \n", GetName().c_str(), x,y,width,height );
2622 if (m_resizing
) return; /* I don't like recursions */
2625 if (m_parent
->m_wxwindow
== NULL
) /* i.e. wxNotebook */
2627 /* don't set the size for children of wxNotebook, just take the values. */
2635 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2637 if ((sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
) == 0)
2639 if (x
!= -1) m_x
= x
+ pizza
->xoffset
;
2640 if (y
!= -1) m_y
= y
+ pizza
->yoffset
;
2641 if (width
!= -1) m_width
= width
;
2642 if (height
!= -1) m_height
= height
;
2646 m_x
= x
+ pizza
->xoffset
;
2647 m_y
= y
+ pizza
->yoffset
;
2652 if ((sizeFlags
& wxSIZE_AUTO_WIDTH
) == wxSIZE_AUTO_WIDTH
)
2654 if (width
== -1) m_width
= 80;
2657 if ((sizeFlags
& wxSIZE_AUTO_HEIGHT
) == wxSIZE_AUTO_HEIGHT
)
2659 if (height
== -1) m_height
= 26;
2662 if ((m_minWidth
!= -1) && (m_width
< m_minWidth
)) m_width
= m_minWidth
;
2663 if ((m_minHeight
!= -1) && (m_height
< m_minHeight
)) m_height
= m_minHeight
;
2664 if ((m_maxWidth
!= -1) && (m_width
> m_maxWidth
)) m_width
= m_maxWidth
;
2665 if ((m_maxHeight
!= -1) && (m_height
> m_maxHeight
)) m_height
= m_maxHeight
;
2668 int bottom_border
= 0;
2670 if (GTK_WIDGET_CAN_DEFAULT(m_widget
))
2672 /* the default button has a border around it */
2677 DoMoveWindow( m_x
-border
,
2680 m_height
+border
+bottom_border
);
2685 /* Sometimes the client area changes size without the
2686 whole windows's size changing, but if the whole
2687 windows's size doesn't change, no wxSizeEvent will
2688 normally be sent. Here we add an extra test if
2689 the client test has been changed and this will
2691 GetClientSize( &m_oldClientWidth
, &m_oldClientHeight
);
2695 wxPrintf( "OnSize sent from " );
2696 if (GetClassInfo() && GetClassInfo()->GetClassName())
2697 wxPrintf( GetClassInfo()->GetClassName() );
2698 wxPrintf( " %d %d %d %d\n", (int)m_x, (int)m_y, (int)m_width, (int)m_height );
2701 if (!m_nativeSizeEvent
)
2703 wxSizeEvent
event( wxSize(m_width
,m_height
), GetId() );
2704 event
.SetEventObject( this );
2705 GetEventHandler()->ProcessEvent( event
);
2711 void wxWindow::OnInternalIdle()
2713 if ( g_sendActivateEvent
!= -1 )
2715 bool activate
= g_sendActivateEvent
!= 0;
2718 g_sendActivateEvent
= -1;
2720 wxActivateEvent
event(wxEVT_ACTIVATE_APP
, activate
, GetId());
2721 event
.SetEventObject(this);
2723 (void)GetEventHandler()->ProcessEvent(event
);
2726 wxCursor cursor
= m_cursor
;
2727 if (g_globalCursor
.Ok()) cursor
= g_globalCursor
;
2731 /* I now set the cursor anew in every OnInternalIdle call
2732 as setting the cursor in a parent window also effects the
2733 windows above so that checking for the current cursor is
2738 GdkWindow
*window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2740 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2742 if (!g_globalCursor
.Ok())
2743 cursor
= *wxSTANDARD_CURSOR
;
2745 window
= m_widget
->window
;
2746 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2747 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2753 GdkWindow
*window
= m_widget
->window
;
2754 if ((window
) && !(GTK_WIDGET_NO_WINDOW(m_widget
)))
2755 gdk_window_set_cursor( window
, cursor
.GetCursor() );
2763 void wxWindow::DoGetSize( int *width
, int *height
) const
2765 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2767 if (width
) (*width
) = m_width
;
2768 if (height
) (*height
) = m_height
;
2771 void wxWindow::DoSetClientSize( int width
, int height
)
2773 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2777 SetSize( width
, height
);
2784 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2786 /* when using GTK 1.2 we set the shadow border size to 2 */
2790 if (HasFlag(wxSIMPLE_BORDER
))
2792 /* when using GTK 1.2 we set the simple border size to 1 */
2799 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2801 GtkRequisition vscroll_req
;
2802 vscroll_req
.width
= 2;
2803 vscroll_req
.height
= 2;
2804 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2805 (scroll_window
->vscrollbar
, &vscroll_req
);
2807 GtkRequisition hscroll_req
;
2808 hscroll_req
.width
= 2;
2809 hscroll_req
.height
= 2;
2810 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2811 (scroll_window
->hscrollbar
, &hscroll_req
);
2813 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2815 if (scroll_window
->vscrollbar_visible
)
2817 dw
+= vscroll_req
.width
;
2818 dw
+= scroll_class
->scrollbar_spacing
;
2821 if (scroll_window
->hscrollbar_visible
)
2823 dh
+= hscroll_req
.height
;
2824 dh
+= scroll_class
->scrollbar_spacing
;
2828 SetSize( width
+dw
, height
+dh
);
2832 void wxWindow::DoGetClientSize( int *width
, int *height
) const
2834 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2838 if (width
) (*width
) = m_width
;
2839 if (height
) (*height
) = m_height
;
2846 if (HasFlag(wxRAISED_BORDER
) || HasFlag(wxSUNKEN_BORDER
))
2848 /* when using GTK 1.2 we set the shadow border size to 2 */
2852 if (HasFlag(wxSIMPLE_BORDER
))
2854 /* when using GTK 1.2 we set the simple border size to 1 */
2861 GtkScrolledWindow
*scroll_window
= GTK_SCROLLED_WINDOW(m_widget
);
2863 GtkRequisition vscroll_req
;
2864 vscroll_req
.width
= 2;
2865 vscroll_req
.height
= 2;
2866 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->vscrollbar
) )->size_request
)
2867 (scroll_window
->vscrollbar
, &vscroll_req
);
2869 GtkRequisition hscroll_req
;
2870 hscroll_req
.width
= 2;
2871 hscroll_req
.height
= 2;
2872 (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(scroll_window
->hscrollbar
) )->size_request
)
2873 (scroll_window
->hscrollbar
, &hscroll_req
);
2875 GtkScrolledWindowClass
*scroll_class
= GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget
) );
2877 if (scroll_window
->vscrollbar_visible
)
2879 dw
+= vscroll_req
.width
;
2880 dw
+= scroll_class
->scrollbar_spacing
;
2883 if (scroll_window
->hscrollbar_visible
)
2885 dh
+= hscroll_req
.height
;
2886 dh
+= scroll_class
->scrollbar_spacing
;
2890 if (width
) (*width
) = m_width
- dw
;
2891 if (height
) (*height
) = m_height
- dh
;
2895 printf( "GetClientSize, name %s ", GetName().c_str() );
2896 if (width) printf( " width = %d", (*width) );
2897 if (height) printf( " height = %d", (*height) );
2902 void wxWindow::DoGetPosition( int *x
, int *y
) const
2904 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2908 if (m_parent
&& m_parent
->m_wxwindow
)
2910 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2911 dx
= pizza
->xoffset
;
2912 dy
= pizza
->yoffset
;
2915 if (x
) (*x
) = m_x
- dx
;
2916 if (y
) (*y
) = m_y
- dy
;
2919 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2921 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2923 if (!m_widget
->window
) return;
2925 GdkWindow
*source
= (GdkWindow
*) NULL
;
2927 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2929 source
= m_widget
->window
;
2933 gdk_window_get_origin( source
, &org_x
, &org_y
);
2937 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2939 org_x
+= m_widget
->allocation
.x
;
2940 org_y
+= m_widget
->allocation
.y
;
2948 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2950 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2952 if (!m_widget
->window
) return;
2954 GdkWindow
*source
= (GdkWindow
*) NULL
;
2956 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2958 source
= m_widget
->window
;
2962 gdk_window_get_origin( source
, &org_x
, &org_y
);
2966 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2968 org_x
+= m_widget
->allocation
.x
;
2969 org_y
+= m_widget
->allocation
.y
;
2977 bool wxWindow::Show( bool show
)
2979 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2981 if (!wxWindowBase::Show(show
))
2988 gtk_widget_show( m_widget
);
2990 gtk_widget_hide( m_widget
);
2995 static void wxWindowNotifyEnable(wxWindow
* win
, bool enable
)
2997 win
->OnParentEnable(enable
);
2999 // Recurse, so that children have the opportunity to Do The Right Thing
3000 // and reset colours that have been messed up by a parent's (really ancestor's)
3002 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
3004 node
= node
->GetNext() )
3006 wxWindow
*child
= node
->GetData();
3007 if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
)))
3008 wxWindowNotifyEnable(child
, enable
);
3012 bool wxWindow::Enable( bool enable
)
3014 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3016 if (!wxWindowBase::Enable(enable
))
3022 gtk_widget_set_sensitive( m_widget
, enable
);
3024 gtk_widget_set_sensitive( m_wxwindow
, enable
);
3026 wxWindowNotifyEnable(this, enable
);
3031 int wxWindow::GetCharHeight() const
3033 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
3035 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
3037 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3039 return font
->ascent
+ font
->descent
;
3042 int wxWindow::GetCharWidth() const
3044 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
3046 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
3048 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3050 return gdk_string_width( font
, "H" );
3053 void wxWindow::GetTextExtent( const wxString
& string
,
3057 int *externalLeading
,
3058 const wxFont
*theFont
) const
3060 wxFont fontToUse
= m_font
;
3061 if (theFont
) fontToUse
= *theFont
;
3063 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
3065 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
3066 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
3067 if (y
) (*y
) = font
->ascent
+ font
->descent
;
3068 if (descent
) (*descent
) = font
->descent
;
3069 if (externalLeading
) (*externalLeading
) = 0; // ??
3072 void wxWindow::SetFocus()
3074 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3078 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3079 gtk_widget_grab_focus (m_wxwindow
);
3085 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
3087 gtk_widget_grab_focus (m_widget
);
3089 else if (GTK_IS_CONTAINER(m_widget
))
3091 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
3100 bool wxWindow::AcceptsFocus() const
3102 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3105 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
3107 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3109 wxWindow
*oldParent
= m_parent
,
3110 *newParent
= (wxWindow
*)newParentBase
;
3112 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3114 if ( !wxWindowBase::Reparent(newParent
) )
3117 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3119 /* prevent GTK from deleting the widget arbitrarily */
3120 gtk_widget_ref( m_widget
);
3124 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3127 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3131 /* insert GTK representation */
3132 (*(newParent
->m_insertCallback
))(newParent
, this);
3135 /* reverse: prevent GTK from deleting the widget arbitrarily */
3136 gtk_widget_unref( m_widget
);
3141 void wxWindow::DoAddChild(wxWindow
*child
)
3143 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3145 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3147 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3152 /* insert GTK representation */
3153 (*m_insertCallback
)(this, child
);
3156 void wxWindow::Raise()
3158 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3160 if (!m_widget
->window
) return;
3162 gdk_window_raise( m_widget
->window
);
3165 void wxWindow::Lower()
3167 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3169 if (!m_widget
->window
) return;
3171 gdk_window_lower( m_widget
->window
);
3174 bool wxWindow::SetCursor( const wxCursor
&cursor
)
3176 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3178 if (cursor
== m_cursor
)
3182 wxapp_install_idle_handler();
3184 if (cursor
== wxNullCursor
)
3185 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3187 return wxWindowBase::SetCursor( cursor
);
3190 void wxWindow::WarpPointer( int x
, int y
)
3192 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3194 /* we provide this function ourselves as it is
3195 missing in GDK (top of this file) */
3197 GdkWindow
*window
= (GdkWindow
*) NULL
;
3199 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3201 window
= GetConnectWidget()->window
;
3204 gdk_window_warp_pointer( window
, x
, y
);
3207 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
3209 if (!m_widget
) return;
3210 if (!m_widget
->window
) return;
3212 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3216 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3218 rect
->width
, rect
->height
);
3222 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3226 /* there is no GTK equivalent of "draw only, don't clear" so we
3227 invent our own in the GtkPizza widget */
3235 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3236 gboolean old_clear = pizza->clear_on_draw;
3237 gtk_pizza_set_clear( pizza, FALSE );
3238 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3239 gtk_pizza_set_clear( pizza, old_clear );
3241 GdkEventExpose gdk_event
;
3242 gdk_event
.type
= GDK_EXPOSE
;
3243 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3244 gdk_event
.count
= 0;
3245 gdk_event
.area
.x
= 0;
3246 gdk_event
.area
.y
= 0;
3247 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3248 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3249 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3254 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3263 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3264 gboolean old_clear = pizza->clear_on_draw;
3265 gtk_pizza_set_clear( pizza, FALSE );
3267 GdkRectangle gdk_rect;
3268 gdk_rect.x = rect->x;
3269 gdk_rect.y = rect->y;
3270 gdk_rect.width = rect->width;
3271 gdk_rect.height = rect->height;
3272 gtk_widget_draw( m_wxwindow, &gdk_rect );
3273 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3275 gtk_pizza_set_clear( pizza, old_clear );
3277 GdkEventExpose gdk_event
;
3278 gdk_event
.type
= GDK_EXPOSE
;
3279 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3280 gdk_event
.count
= 0;
3281 gdk_event
.area
.x
= rect
->x
;
3282 gdk_event
.area
.y
= rect
->y
;
3283 gdk_event
.area
.width
= rect
->width
;
3284 gdk_event
.area
.height
= rect
->height
;
3285 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3289 GdkRectangle gdk_rect
;
3290 gdk_rect
.x
= rect
->x
;
3291 gdk_rect
.y
= rect
->y
;
3292 gdk_rect
.width
= rect
->width
;
3293 gdk_rect
.height
= rect
->height
;
3294 gtk_widget_draw( m_widget
, &gdk_rect
);
3299 void wxWindow::Clear()
3301 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3303 if (!m_widget
->window
) return;
3305 if (m_wxwindow
&& m_wxwindow
->window
)
3307 // gdk_window_clear( m_wxwindow->window );
3312 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
3314 wxWindowBase::DoSetToolTip(tip
);
3317 m_tooltip
->Apply( this );
3320 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3322 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3324 #endif // wxUSE_TOOLTIPS
3326 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
3328 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3330 if (!wxWindowBase::SetBackgroundColour(colour
))
3332 // don't leave if the GTK widget has just
3334 if (!m_delayedBackgroundColour
) return FALSE
;
3337 GdkWindow
*window
= (GdkWindow
*) NULL
;
3339 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3341 window
= GetConnectWidget()->window
;
3345 // indicate that a new style has been set
3346 // but it couldn't get applied as the
3347 // widget hasn't been realized yet.
3348 m_delayedBackgroundColour
= TRUE
;
3352 (m_wxwindow
->window
) &&
3353 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3355 /* wxMSW doesn't clear the window here. I don't do that either to
3356 provide compatibility. call Clear() to do the job. */
3358 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3359 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3367 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
3369 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3371 if (!wxWindowBase::SetForegroundColour(colour
))
3373 // don't leave if the GTK widget has just
3375 if (!m_delayedForegroundColour
) return FALSE
;
3378 GdkWindow
*window
= (GdkWindow
*) NULL
;
3380 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3382 window
= GetConnectWidget()->window
;
3386 // indicate that a new style has been set
3387 // but it couldn't get applied as the
3388 // widget hasn't been realized yet.
3389 m_delayedForegroundColour
= TRUE
;
3397 GtkStyle
*wxWindow::GetWidgetStyle()
3401 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3403 /* FIXME: is this necessary? */
3404 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3406 remake
->klass
= m_widgetStyle
->klass
;
3409 gtk_style_unref( m_widgetStyle
);
3410 m_widgetStyle
= remake
;
3414 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3417 def
= gtk_widget_get_default_style();
3419 m_widgetStyle
= gtk_style_copy( def
);
3421 /* FIXME: is this necessary? */
3422 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3424 m_widgetStyle
->klass
= def
->klass
;
3428 return m_widgetStyle
;
3431 void wxWindow::SetWidgetStyle()
3433 #if DISABLE_STYLE_IF_BROKEN_THEM
3434 if (m_widget
->style
->engine_data
)
3436 static bool s_warningPrinted
= FALSE
;
3437 if (!s_warningPrinted
)
3439 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3440 s_warningPrinted
= TRUE
;
3442 m_widgetStyle
= m_widget
->style
;
3447 GtkStyle
*style
= GetWidgetStyle();
3449 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3451 gdk_font_unref( style
->font
);
3452 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3455 if (m_foregroundColour
.Ok())
3457 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3458 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3460 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3461 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3462 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3466 // Try to restore the gtk default style. This is still a little
3467 // oversimplified for what is probably really needed here for controls
3468 // other than buttons, but is better than not being able to (re)set a
3469 // control's foreground colour to *wxBLACK -- RL
3470 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3473 def
= gtk_widget_get_default_style();
3475 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3476 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3477 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3481 if (m_backgroundColour
.Ok())
3483 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3484 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3486 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3487 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3488 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3489 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3490 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3491 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3492 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3493 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3497 // Try to restore the gtk default style. This is still a little
3498 // oversimplified for what is probably really needed here for controls
3499 // other than buttons, but is better than not being able to (re)set a
3500 // control's background colour to default grey and means resetting a
3501 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3503 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3506 def
= gtk_widget_get_default_style();
3508 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3509 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3510 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3511 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3512 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3513 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3514 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3515 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3520 void wxWindow::ApplyWidgetStyle()
3524 //-----------------------------------------------------------------------------
3525 // Pop-up menu stuff
3526 //-----------------------------------------------------------------------------
3528 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3530 *is_waiting
= FALSE
;
3533 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3535 menu
->SetInvokingWindow( win
);
3536 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3539 wxMenuItem
*menuitem
= node
->GetData();
3540 if (menuitem
->IsSubMenu())
3542 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3545 node
= node
->GetNext();
3549 static gint gs_pop_x
= 0;
3550 static gint gs_pop_y
= 0;
3552 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3556 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3561 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3563 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3565 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3567 SetInvokingWindow( menu
, this );
3574 bool is_waiting
= TRUE
;
3576 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3577 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3580 GTK_MENU(menu
->m_menu
),
3581 (GtkWidget
*) NULL
, // parent menu shell
3582 (GtkWidget
*) NULL
, // parent menu item
3583 (GtkMenuPositionFunc
) pop_pos_callback
,
3584 (gpointer
) this, // client data
3585 0, // button used to activate it
3586 gs_timeLastClick
// the time of activation
3591 while (gtk_events_pending())
3592 gtk_main_iteration();
3598 #if wxUSE_DRAG_AND_DROP
3600 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3602 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3604 GtkWidget
*dnd_widget
= GetConnectWidget();
3606 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3608 if (m_dropTarget
) delete m_dropTarget
;
3609 m_dropTarget
= dropTarget
;
3611 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3614 #endif // wxUSE_DRAG_AND_DROP
3616 GtkWidget
* wxWindow::GetConnectWidget()
3618 GtkWidget
*connect_widget
= m_widget
;
3619 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3621 return connect_widget
;
3624 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3627 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3629 return (window
== m_widget
->window
);
3632 bool wxWindow::SetFont( const wxFont
&font
)
3634 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3636 if (!wxWindowBase::SetFont(font
))
3641 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3642 if ( sysbg
== m_backgroundColour
)
3644 m_backgroundColour
= wxNullColour
;
3646 m_backgroundColour
= sysbg
;
3656 void wxWindow::CaptureMouse()
3658 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3660 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3662 GdkWindow
*window
= (GdkWindow
*) NULL
;
3664 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3666 window
= GetConnectWidget()->window
;
3668 if (!window
) return;
3670 wxCursor
* cursor
= & m_cursor
;
3672 cursor
= wxSTANDARD_CURSOR
;
3674 gdk_pointer_grab( window
, FALSE
,
3676 (GDK_BUTTON_PRESS_MASK
|
3677 GDK_BUTTON_RELEASE_MASK
|
3678 GDK_POINTER_MOTION_HINT_MASK
|
3679 GDK_POINTER_MOTION_MASK
),
3681 cursor
->GetCursor(),
3682 (guint32
)GDK_CURRENT_TIME
);
3683 g_captureWindow
= this;
3686 void wxWindow::ReleaseMouse()
3688 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3690 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3692 GdkWindow
*window
= (GdkWindow
*) NULL
;
3694 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3696 window
= GetConnectWidget()->window
;
3701 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3702 g_captureWindow
= (wxWindow
*) NULL
;
3705 bool wxWindow::IsRetained() const
3710 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3711 int range
, bool refresh
)
3713 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3715 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3717 m_hasScrolling
= TRUE
;
3719 if (orient
== wxHORIZONTAL
)
3721 float fpos
= (float)pos
;
3722 float frange
= (float)range
;
3723 float fthumb
= (float)thumbVisible
;
3724 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3725 if (fpos
< 0.0) fpos
= 0.0;
3727 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3728 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3730 SetScrollPos( orient
, pos
, refresh
);
3734 m_oldHorizontalPos
= fpos
;
3736 m_hAdjust
->lower
= 0.0;
3737 m_hAdjust
->upper
= frange
;
3738 m_hAdjust
->value
= fpos
;
3739 m_hAdjust
->step_increment
= 1.0;
3740 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3741 m_hAdjust
->page_size
= fthumb
;
3745 float fpos
= (float)pos
;
3746 float frange
= (float)range
;
3747 float fthumb
= (float)thumbVisible
;
3748 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3749 if (fpos
< 0.0) fpos
= 0.0;
3751 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3752 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3754 SetScrollPos( orient
, pos
, refresh
);
3758 m_oldVerticalPos
= fpos
;
3760 m_vAdjust
->lower
= 0.0;
3761 m_vAdjust
->upper
= frange
;
3762 m_vAdjust
->value
= fpos
;
3763 m_vAdjust
->step_increment
= 1.0;
3764 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3765 m_vAdjust
->page_size
= fthumb
;
3768 if (orient
== wxHORIZONTAL
)
3769 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3771 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3774 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3776 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3778 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3780 if (orient
== wxHORIZONTAL
)
3782 float fpos
= (float)pos
;
3783 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3784 if (fpos
< 0.0) fpos
= 0.0;
3785 m_oldHorizontalPos
= fpos
;
3787 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3788 m_hAdjust
->value
= fpos
;
3792 float fpos
= (float)pos
;
3793 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3794 if (fpos
< 0.0) fpos
= 0.0;
3795 m_oldVerticalPos
= fpos
;
3797 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3798 m_vAdjust
->value
= fpos
;
3801 if (m_wxwindow
->window
)
3803 if (orient
== wxHORIZONTAL
)
3805 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3806 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3808 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3810 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3811 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3815 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3816 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3818 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3820 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3821 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3826 int wxWindow::GetScrollThumb( int orient
) const
3828 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3830 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3832 if (orient
== wxHORIZONTAL
)
3833 return (int)(m_hAdjust
->page_size
+0.5);
3835 return (int)(m_vAdjust
->page_size
+0.5);
3838 int wxWindow::GetScrollPos( int orient
) const
3840 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3842 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3844 if (orient
== wxHORIZONTAL
)
3845 return (int)(m_hAdjust
->value
+0.5);
3847 return (int)(m_vAdjust
->value
+0.5);
3850 int wxWindow::GetScrollRange( int orient
) const
3852 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3854 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3856 if (orient
== wxHORIZONTAL
)
3857 return (int)(m_hAdjust
->upper
+0.5);
3859 return (int)(m_vAdjust
->upper
+0.5);
3862 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3864 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3866 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3868 if ((dx
== 0) && (dy
== 0)) return;
3870 m_clipPaintRegion
= TRUE
;
3871 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3872 m_clipPaintRegion
= FALSE
;
3875 if (m_children.GetCount() > 0)
3877 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3881 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3883 pizza->xoffset -= dx;
3884 pizza->yoffset -= dy;
3886 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3887 gdk_gc_set_exposures( m_scrollGC, TRUE );
3891 GetClientSize( &cw, &ch );
3892 int w = cw - abs(dx);
3893 int h = ch - abs(dy);
3895 if ((h < 0) || (w < 0))
3903 if (dx < 0) s_x = -dx;
3904 if (dy < 0) s_y = -dy;
3907 if (dx > 0) d_x = dx;
3908 if (dy > 0) d_y = dy;
3910 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3911 pizza->bin_window, s_x, s_y, w, h );
3914 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3915 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3916 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3917 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3919 Refresh( TRUE, &rect );
3922 gdk_gc_unref( m_scrollGC );
3927 // Find the wxWindow at the current mouse position, also returning the mouse
3929 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
3931 pt
= wxGetMousePosition();
3932 wxWindow
* found
= wxFindWindowAtPoint(pt
);
3936 // Get the current mouse position.
3937 wxPoint
wxGetMousePosition()
3939 /* This crashes when used within wxHelpContext,
3940 so we have to use the X-specific implementation below.
3942 GdkModifierType *mask;
3943 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
3945 return wxPoint(x, y);
3949 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
3951 return wxPoint(-999, -999);
3953 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
3954 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
3955 Window rootReturn
, childReturn
;
3956 int rootX
, rootY
, winX
, winY
;
3957 unsigned int maskReturn
;
3959 XQueryPointer (display
,
3963 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
3964 return wxPoint(rootX
, rootY
);