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( "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 void wxWindow::DoGetPosition( int *x
, int *y
) const
2897 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2901 if (m_parent
&& m_parent
->m_wxwindow
)
2903 GtkPizza
*pizza
= GTK_PIZZA(m_parent
->m_wxwindow
);
2904 dx
= pizza
->xoffset
;
2905 dy
= pizza
->yoffset
;
2908 if (x
) (*x
) = m_x
- dx
;
2909 if (y
) (*y
) = m_y
- dy
;
2912 void wxWindow::DoClientToScreen( int *x
, int *y
) const
2914 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2916 if (!m_widget
->window
) return;
2918 GdkWindow
*source
= (GdkWindow
*) NULL
;
2920 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2922 source
= m_widget
->window
;
2926 gdk_window_get_origin( source
, &org_x
, &org_y
);
2930 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2932 org_x
+= m_widget
->allocation
.x
;
2933 org_y
+= m_widget
->allocation
.y
;
2941 void wxWindow::DoScreenToClient( int *x
, int *y
) const
2943 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
2945 if (!m_widget
->window
) return;
2947 GdkWindow
*source
= (GdkWindow
*) NULL
;
2949 source
= GTK_PIZZA(m_wxwindow
)->bin_window
;
2951 source
= m_widget
->window
;
2955 gdk_window_get_origin( source
, &org_x
, &org_y
);
2959 if (GTK_WIDGET_NO_WINDOW (m_widget
))
2961 org_x
+= m_widget
->allocation
.x
;
2962 org_y
+= m_widget
->allocation
.y
;
2970 bool wxWindow::Show( bool show
)
2972 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
2974 if (!wxWindowBase::Show(show
))
2981 gtk_widget_show( m_widget
);
2983 gtk_widget_hide( m_widget
);
2988 static void wxWindowNotifyEnable(wxWindow
* win
, bool enable
)
2990 win
->OnParentEnable(enable
);
2992 // Recurse, so that children have the opportunity to Do The Right Thing
2993 // and reset colours that have been messed up by a parent's (really ancestor's)
2995 for ( wxWindowList::Node
*node
= win
->GetChildren().GetFirst();
2997 node
= node
->GetNext() )
2999 wxWindow
*child
= node
->GetData();
3000 if (!child
->IsKindOf(CLASSINFO(wxDialog
)) && !child
->IsKindOf(CLASSINFO(wxFrame
)))
3001 wxWindowNotifyEnable(child
, enable
);
3005 bool wxWindow::Enable( bool enable
)
3007 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3009 if (!wxWindowBase::Enable(enable
))
3015 gtk_widget_set_sensitive( m_widget
, enable
);
3017 gtk_widget_set_sensitive( m_wxwindow
, enable
);
3019 wxWindowNotifyEnable(this, enable
);
3024 int wxWindow::GetCharHeight() const
3026 wxCHECK_MSG( (m_widget
!= NULL
), 12, wxT("invalid window") );
3028 wxCHECK_MSG( m_font
.Ok(), 12, wxT("invalid font") );
3030 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3032 return font
->ascent
+ font
->descent
;
3035 int wxWindow::GetCharWidth() const
3037 wxCHECK_MSG( (m_widget
!= NULL
), 8, wxT("invalid window") );
3039 wxCHECK_MSG( m_font
.Ok(), 8, wxT("invalid font") );
3041 GdkFont
*font
= m_font
.GetInternalFont( 1.0 );
3043 return gdk_string_width( font
, "H" );
3046 void wxWindow::GetTextExtent( const wxString
& string
,
3050 int *externalLeading
,
3051 const wxFont
*theFont
) const
3053 wxFont fontToUse
= m_font
;
3054 if (theFont
) fontToUse
= *theFont
;
3056 wxCHECK_RET( fontToUse
.Ok(), wxT("invalid font") );
3058 GdkFont
*font
= fontToUse
.GetInternalFont( 1.0 );
3059 if (x
) (*x
) = gdk_string_width( font
, string
.mbc_str() );
3060 if (y
) (*y
) = font
->ascent
+ font
->descent
;
3061 if (descent
) (*descent
) = font
->descent
;
3062 if (externalLeading
) (*externalLeading
) = 0; // ??
3065 void wxWindow::SetFocus()
3067 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3071 if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow
))
3072 gtk_widget_grab_focus (m_wxwindow
);
3078 if (GTK_WIDGET_CAN_FOCUS(m_widget
) && !GTK_WIDGET_HAS_FOCUS (m_widget
) )
3080 gtk_widget_grab_focus (m_widget
);
3082 else if (GTK_IS_CONTAINER(m_widget
))
3084 gtk_container_focus( GTK_CONTAINER(m_widget
), GTK_DIR_TAB_FORWARD
);
3093 bool wxWindow::AcceptsFocus() const
3095 return m_acceptsFocus
&& wxWindowBase::AcceptsFocus();
3098 bool wxWindow::Reparent( wxWindowBase
*newParentBase
)
3100 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3102 wxWindow
*oldParent
= m_parent
,
3103 *newParent
= (wxWindow
*)newParentBase
;
3105 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3107 if ( !wxWindowBase::Reparent(newParent
) )
3110 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3112 /* prevent GTK from deleting the widget arbitrarily */
3113 gtk_widget_ref( m_widget
);
3117 gtk_container_remove( GTK_CONTAINER(m_widget
->parent
), m_widget
);
3120 wxASSERT( GTK_IS_WIDGET(m_widget
) );
3124 /* insert GTK representation */
3125 (*(newParent
->m_insertCallback
))(newParent
, this);
3128 /* reverse: prevent GTK from deleting the widget arbitrarily */
3129 gtk_widget_unref( m_widget
);
3134 void wxWindow::DoAddChild(wxWindow
*child
)
3136 wxASSERT_MSG( (m_widget
!= NULL
), wxT("invalid window") );
3138 wxASSERT_MSG( (child
!= NULL
), wxT("invalid child window") );
3140 wxASSERT_MSG( (m_insertCallback
!= NULL
), wxT("invalid child insertion function") );
3145 /* insert GTK representation */
3146 (*m_insertCallback
)(this, child
);
3149 void wxWindow::Raise()
3151 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3153 if (!m_widget
->window
) return;
3155 gdk_window_raise( m_widget
->window
);
3158 void wxWindow::Lower()
3160 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3162 if (!m_widget
->window
) return;
3164 gdk_window_lower( m_widget
->window
);
3167 bool wxWindow::SetCursor( const wxCursor
&cursor
)
3169 wxCHECK_MSG( (m_widget
!= NULL
), FALSE
, wxT("invalid window") );
3171 if (cursor
== m_cursor
)
3175 wxapp_install_idle_handler();
3177 if (cursor
== wxNullCursor
)
3178 return wxWindowBase::SetCursor( *wxSTANDARD_CURSOR
);
3180 return wxWindowBase::SetCursor( cursor
);
3183 void wxWindow::WarpPointer( int x
, int y
)
3185 wxCHECK_RET( (m_widget
!= NULL
), wxT("invalid window") );
3187 /* we provide this function ourselves as it is
3188 missing in GDK (top of this file) */
3190 GdkWindow
*window
= (GdkWindow
*) NULL
;
3192 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3194 window
= GetConnectWidget()->window
;
3197 gdk_window_warp_pointer( window
, x
, y
);
3200 void wxWindow::Refresh( bool eraseBackground
, const wxRect
*rect
)
3202 if (!m_widget
) return;
3203 if (!m_widget
->window
) return;
3205 if (eraseBackground
&& m_wxwindow
&& m_wxwindow
->window
)
3209 gdk_window_clear_area( GTK_PIZZA(m_wxwindow
)->bin_window
,
3211 rect
->width
, rect
->height
);
3215 gdk_window_clear( GTK_PIZZA(m_wxwindow
)->bin_window
);
3219 /* there is no GTK equivalent of "draw only, don't clear" so we
3220 invent our own in the GtkPizza widget */
3228 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3229 gboolean old_clear = pizza->clear_on_draw;
3230 gtk_pizza_set_clear( pizza, FALSE );
3231 gtk_widget_draw( m_wxwindow, (GdkRectangle*) NULL );
3232 gtk_pizza_set_clear( pizza, old_clear );
3234 GdkEventExpose gdk_event
;
3235 gdk_event
.type
= GDK_EXPOSE
;
3236 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3237 gdk_event
.count
= 0;
3238 gdk_event
.area
.x
= 0;
3239 gdk_event
.area
.y
= 0;
3240 gdk_event
.area
.width
= m_wxwindow
->allocation
.width
;
3241 gdk_event
.area
.height
= m_wxwindow
->allocation
.height
;
3242 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3247 gtk_widget_draw( m_widget
, (GdkRectangle
*) NULL
);
3256 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3257 gboolean old_clear = pizza->clear_on_draw;
3258 gtk_pizza_set_clear( pizza, FALSE );
3260 GdkRectangle gdk_rect;
3261 gdk_rect.x = rect->x;
3262 gdk_rect.y = rect->y;
3263 gdk_rect.width = rect->width;
3264 gdk_rect.height = rect->height;
3265 gtk_widget_draw( m_wxwindow, &gdk_rect );
3266 gtk_window_draw_callback( m_wxwindow, &gdk_rect, this );
3268 gtk_pizza_set_clear( pizza, old_clear );
3270 GdkEventExpose gdk_event
;
3271 gdk_event
.type
= GDK_EXPOSE
;
3272 gdk_event
.window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3273 gdk_event
.count
= 0;
3274 gdk_event
.area
.x
= rect
->x
;
3275 gdk_event
.area
.y
= rect
->y
;
3276 gdk_event
.area
.width
= rect
->width
;
3277 gdk_event
.area
.height
= rect
->height
;
3278 gtk_window_expose_callback( m_wxwindow
, &gdk_event
, this );
3282 GdkRectangle gdk_rect
;
3283 gdk_rect
.x
= rect
->x
;
3284 gdk_rect
.y
= rect
->y
;
3285 gdk_rect
.width
= rect
->width
;
3286 gdk_rect
.height
= rect
->height
;
3287 gtk_widget_draw( m_widget
, &gdk_rect
);
3292 void wxWindow::Clear()
3294 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3296 if (!m_widget
->window
) return;
3298 if (m_wxwindow
&& m_wxwindow
->window
)
3300 // gdk_window_clear( m_wxwindow->window );
3305 void wxWindow::DoSetToolTip( wxToolTip
*tip
)
3307 wxWindowBase::DoSetToolTip(tip
);
3310 m_tooltip
->Apply( this );
3313 void wxWindow::ApplyToolTip( GtkTooltips
*tips
, const wxChar
*tip
)
3315 gtk_tooltips_set_tip( tips
, GetConnectWidget(), wxConvCurrent
->cWX2MB(tip
), (gchar
*) NULL
);
3317 #endif // wxUSE_TOOLTIPS
3319 bool wxWindow::SetBackgroundColour( const wxColour
&colour
)
3321 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3323 if (!wxWindowBase::SetBackgroundColour(colour
))
3325 // don't leave if the GTK widget has just
3327 if (!m_delayedBackgroundColour
) return FALSE
;
3330 GdkWindow
*window
= (GdkWindow
*) NULL
;
3332 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3334 window
= GetConnectWidget()->window
;
3338 // indicate that a new style has been set
3339 // but it couldn't get applied as the
3340 // widget hasn't been realized yet.
3341 m_delayedBackgroundColour
= TRUE
;
3345 (m_wxwindow
->window
) &&
3346 (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
)))
3348 /* wxMSW doesn't clear the window here. I don't do that either to
3349 provide compatibility. call Clear() to do the job. */
3351 m_backgroundColour
.CalcPixel( gdk_window_get_colormap( window
) );
3352 gdk_window_set_background( window
, m_backgroundColour
.GetColor() );
3360 bool wxWindow::SetForegroundColour( const wxColour
&colour
)
3362 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3364 if (!wxWindowBase::SetForegroundColour(colour
))
3366 // don't leave if the GTK widget has just
3368 if (!m_delayedForegroundColour
) return FALSE
;
3371 GdkWindow
*window
= (GdkWindow
*) NULL
;
3373 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3375 window
= GetConnectWidget()->window
;
3379 // indicate that a new style has been set
3380 // but it couldn't get applied as the
3381 // widget hasn't been realized yet.
3382 m_delayedForegroundColour
= TRUE
;
3390 GtkStyle
*wxWindow::GetWidgetStyle()
3394 GtkStyle
*remake
= gtk_style_copy( m_widgetStyle
);
3396 /* FIXME: is this necessary? */
3397 _G_TYPE_IGC(remake
, GtkObjectClass
) = _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
);
3399 remake
->klass
= m_widgetStyle
->klass
;
3402 gtk_style_unref( m_widgetStyle
);
3403 m_widgetStyle
= remake
;
3407 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3410 def
= gtk_widget_get_default_style();
3412 m_widgetStyle
= gtk_style_copy( def
);
3414 /* FIXME: is this necessary? */
3415 _G_TYPE_IGC(m_widgetStyle
, GtkObjectClass
) = _G_TYPE_IGC(def
, GtkObjectClass
);
3417 m_widgetStyle
->klass
= def
->klass
;
3421 return m_widgetStyle
;
3424 void wxWindow::SetWidgetStyle()
3426 #if DISABLE_STYLE_IF_BROKEN_THEM
3427 if (m_widget
->style
->engine_data
)
3429 static bool s_warningPrinted
= FALSE
;
3430 if (!s_warningPrinted
)
3432 printf( "wxWindows warning: Widget styles disabled due to buggy GTK theme.\n" );
3433 s_warningPrinted
= TRUE
;
3435 m_widgetStyle
= m_widget
->style
;
3440 GtkStyle
*style
= GetWidgetStyle();
3442 if (m_font
!= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
))
3444 gdk_font_unref( style
->font
);
3445 style
->font
= gdk_font_ref( m_font
.GetInternalFont( 1.0 ) );
3448 if (m_foregroundColour
.Ok())
3450 m_foregroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3451 if (m_foregroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
))
3453 style
->fg
[GTK_STATE_NORMAL
] = *m_foregroundColour
.GetColor();
3454 style
->fg
[GTK_STATE_PRELIGHT
] = *m_foregroundColour
.GetColor();
3455 style
->fg
[GTK_STATE_ACTIVE
] = *m_foregroundColour
.GetColor();
3459 // Try to restore the gtk default style. This is still a little
3460 // oversimplified for what is probably really needed here for controls
3461 // other than buttons, but is better than not being able to (re)set a
3462 // control's foreground colour to *wxBLACK -- RL
3463 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3466 def
= gtk_widget_get_default_style();
3468 style
->fg
[GTK_STATE_NORMAL
] = def
->fg
[GTK_STATE_NORMAL
];
3469 style
->fg
[GTK_STATE_PRELIGHT
] = def
->fg
[GTK_STATE_PRELIGHT
];
3470 style
->fg
[GTK_STATE_ACTIVE
] = def
->fg
[GTK_STATE_ACTIVE
];
3474 if (m_backgroundColour
.Ok())
3476 m_backgroundColour
.CalcPixel( gtk_widget_get_colormap( m_widget
) );
3477 if (m_backgroundColour
!= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
))
3479 style
->bg
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3480 style
->base
[GTK_STATE_NORMAL
] = *m_backgroundColour
.GetColor();
3481 style
->bg
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3482 style
->base
[GTK_STATE_PRELIGHT
] = *m_backgroundColour
.GetColor();
3483 style
->bg
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3484 style
->base
[GTK_STATE_ACTIVE
] = *m_backgroundColour
.GetColor();
3485 style
->bg
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3486 style
->base
[GTK_STATE_INSENSITIVE
] = *m_backgroundColour
.GetColor();
3490 // Try to restore the gtk default style. This is still a little
3491 // oversimplified for what is probably really needed here for controls
3492 // other than buttons, but is better than not being able to (re)set a
3493 // control's background colour to default grey and means resetting a
3494 // button to wxSYS_COLOUR_BTNFACE will restore its usual highlighting
3496 GtkStyle
*def
= gtk_rc_get_style( m_widget
);
3499 def
= gtk_widget_get_default_style();
3501 style
->bg
[GTK_STATE_NORMAL
] = def
->bg
[GTK_STATE_NORMAL
];
3502 style
->base
[GTK_STATE_NORMAL
] = def
->base
[GTK_STATE_NORMAL
];
3503 style
->bg
[GTK_STATE_PRELIGHT
] = def
->bg
[GTK_STATE_PRELIGHT
];
3504 style
->base
[GTK_STATE_PRELIGHT
] = def
->base
[GTK_STATE_PRELIGHT
];
3505 style
->bg
[GTK_STATE_ACTIVE
] = def
->bg
[GTK_STATE_ACTIVE
];
3506 style
->base
[GTK_STATE_ACTIVE
] = def
->base
[GTK_STATE_ACTIVE
];
3507 style
->bg
[GTK_STATE_INSENSITIVE
] = def
->bg
[GTK_STATE_INSENSITIVE
];
3508 style
->base
[GTK_STATE_INSENSITIVE
] = def
->base
[GTK_STATE_INSENSITIVE
];
3513 void wxWindow::ApplyWidgetStyle()
3517 //-----------------------------------------------------------------------------
3518 // Pop-up menu stuff
3519 //-----------------------------------------------------------------------------
3521 static void gtk_pop_hide_callback( GtkWidget
*WXUNUSED(widget
), bool* is_waiting
)
3523 *is_waiting
= FALSE
;
3526 static void SetInvokingWindow( wxMenu
*menu
, wxWindow
*win
)
3528 menu
->SetInvokingWindow( win
);
3529 wxMenuItemList::Node
*node
= menu
->GetMenuItems().GetFirst();
3532 wxMenuItem
*menuitem
= node
->GetData();
3533 if (menuitem
->IsSubMenu())
3535 SetInvokingWindow( menuitem
->GetSubMenu(), win
);
3538 node
= node
->GetNext();
3542 static gint gs_pop_x
= 0;
3543 static gint gs_pop_y
= 0;
3545 static void pop_pos_callback( GtkMenu
* WXUNUSED(menu
),
3549 win
->ClientToScreen( &gs_pop_x
, &gs_pop_y
);
3554 bool wxWindow::DoPopupMenu( wxMenu
*menu
, int x
, int y
)
3556 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3558 wxCHECK_MSG( menu
!= NULL
, FALSE
, wxT("invalid popup-menu") );
3560 SetInvokingWindow( menu
, this );
3567 bool is_waiting
= TRUE
;
3569 gtk_signal_connect( GTK_OBJECT(menu
->m_menu
), "hide",
3570 GTK_SIGNAL_FUNC(gtk_pop_hide_callback
), (gpointer
)&is_waiting
);
3573 GTK_MENU(menu
->m_menu
),
3574 (GtkWidget
*) NULL
, // parent menu shell
3575 (GtkWidget
*) NULL
, // parent menu item
3576 (GtkMenuPositionFunc
) pop_pos_callback
,
3577 (gpointer
) this, // client data
3578 0, // button used to activate it
3579 gs_timeLastClick
// the time of activation
3584 while (gtk_events_pending())
3585 gtk_main_iteration();
3591 #if wxUSE_DRAG_AND_DROP
3593 void wxWindow::SetDropTarget( wxDropTarget
*dropTarget
)
3595 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3597 GtkWidget
*dnd_widget
= GetConnectWidget();
3599 if (m_dropTarget
) m_dropTarget
->UnregisterWidget( dnd_widget
);
3601 if (m_dropTarget
) delete m_dropTarget
;
3602 m_dropTarget
= dropTarget
;
3604 if (m_dropTarget
) m_dropTarget
->RegisterWidget( dnd_widget
);
3607 #endif // wxUSE_DRAG_AND_DROP
3609 GtkWidget
* wxWindow::GetConnectWidget()
3611 GtkWidget
*connect_widget
= m_widget
;
3612 if (m_wxwindow
) connect_widget
= m_wxwindow
;
3614 return connect_widget
;
3617 bool wxWindow::IsOwnGtkWindow( GdkWindow
*window
)
3620 return (window
== GTK_PIZZA(m_wxwindow
)->bin_window
);
3622 return (window
== m_widget
->window
);
3625 bool wxWindow::SetFont( const wxFont
&font
)
3627 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, wxT("invalid window") );
3629 if (!wxWindowBase::SetFont(font
))
3634 wxColour sysbg
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
);
3635 if ( sysbg
== m_backgroundColour
)
3637 m_backgroundColour
= wxNullColour
;
3639 m_backgroundColour
= sysbg
;
3649 void wxWindow::CaptureMouse()
3651 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3653 wxCHECK_RET( g_captureWindow
== NULL
, wxT("CaptureMouse called twice") );
3655 GdkWindow
*window
= (GdkWindow
*) NULL
;
3657 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3659 window
= GetConnectWidget()->window
;
3661 if (!window
) return;
3663 wxCursor
* cursor
= & m_cursor
;
3665 cursor
= wxSTANDARD_CURSOR
;
3667 gdk_pointer_grab( window
, FALSE
,
3669 (GDK_BUTTON_PRESS_MASK
|
3670 GDK_BUTTON_RELEASE_MASK
|
3671 GDK_POINTER_MOTION_HINT_MASK
|
3672 GDK_POINTER_MOTION_MASK
),
3674 cursor
->GetCursor(),
3675 (guint32
)GDK_CURRENT_TIME
);
3676 g_captureWindow
= this;
3679 void wxWindow::ReleaseMouse()
3681 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3683 wxCHECK_RET( g_captureWindow
, wxT("ReleaseMouse called twice") );
3685 GdkWindow
*window
= (GdkWindow
*) NULL
;
3687 window
= GTK_PIZZA(m_wxwindow
)->bin_window
;
3689 window
= GetConnectWidget()->window
;
3694 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
3695 g_captureWindow
= (wxWindow
*) NULL
;
3698 bool wxWindow::IsRetained() const
3703 void wxWindow::SetScrollbar( int orient
, int pos
, int thumbVisible
,
3704 int range
, bool refresh
)
3706 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3708 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3710 m_hasScrolling
= TRUE
;
3712 if (orient
== wxHORIZONTAL
)
3714 float fpos
= (float)pos
;
3715 float frange
= (float)range
;
3716 float fthumb
= (float)thumbVisible
;
3717 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3718 if (fpos
< 0.0) fpos
= 0.0;
3720 if ((fabs(frange
-m_hAdjust
->upper
) < 0.2) &&
3721 (fabs(fthumb
-m_hAdjust
->page_size
) < 0.2))
3723 SetScrollPos( orient
, pos
, refresh
);
3727 m_oldHorizontalPos
= fpos
;
3729 m_hAdjust
->lower
= 0.0;
3730 m_hAdjust
->upper
= frange
;
3731 m_hAdjust
->value
= fpos
;
3732 m_hAdjust
->step_increment
= 1.0;
3733 m_hAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3734 m_hAdjust
->page_size
= fthumb
;
3738 float fpos
= (float)pos
;
3739 float frange
= (float)range
;
3740 float fthumb
= (float)thumbVisible
;
3741 if (fpos
> frange
-fthumb
) fpos
= frange
-fthumb
;
3742 if (fpos
< 0.0) fpos
= 0.0;
3744 if ((fabs(frange
-m_vAdjust
->upper
) < 0.2) &&
3745 (fabs(fthumb
-m_vAdjust
->page_size
) < 0.2))
3747 SetScrollPos( orient
, pos
, refresh
);
3751 m_oldVerticalPos
= fpos
;
3753 m_vAdjust
->lower
= 0.0;
3754 m_vAdjust
->upper
= frange
;
3755 m_vAdjust
->value
= fpos
;
3756 m_vAdjust
->step_increment
= 1.0;
3757 m_vAdjust
->page_increment
= (float)(wxMax(fthumb
,0));
3758 m_vAdjust
->page_size
= fthumb
;
3761 if (orient
== wxHORIZONTAL
)
3762 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "changed" );
3764 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "changed" );
3767 void wxWindow::SetScrollPos( int orient
, int pos
, bool WXUNUSED(refresh
) )
3769 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3771 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3773 if (orient
== wxHORIZONTAL
)
3775 float fpos
= (float)pos
;
3776 if (fpos
> m_hAdjust
->upper
- m_hAdjust
->page_size
) fpos
= m_hAdjust
->upper
- m_hAdjust
->page_size
;
3777 if (fpos
< 0.0) fpos
= 0.0;
3778 m_oldHorizontalPos
= fpos
;
3780 if (fabs(fpos
-m_hAdjust
->value
) < 0.2) return;
3781 m_hAdjust
->value
= fpos
;
3785 float fpos
= (float)pos
;
3786 if (fpos
> m_vAdjust
->upper
- m_vAdjust
->page_size
) fpos
= m_vAdjust
->upper
- m_vAdjust
->page_size
;
3787 if (fpos
< 0.0) fpos
= 0.0;
3788 m_oldVerticalPos
= fpos
;
3790 if (fabs(fpos
-m_vAdjust
->value
) < 0.2) return;
3791 m_vAdjust
->value
= fpos
;
3794 if (m_wxwindow
->window
)
3796 if (orient
== wxHORIZONTAL
)
3798 gtk_signal_disconnect_by_func( GTK_OBJECT(m_hAdjust
),
3799 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3801 gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust
), "value_changed" );
3803 gtk_signal_connect( GTK_OBJECT(m_hAdjust
), "value_changed",
3804 (GtkSignalFunc
) gtk_window_hscroll_callback
, (gpointer
) this );
3808 gtk_signal_disconnect_by_func( GTK_OBJECT(m_vAdjust
),
3809 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3811 gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust
), "value_changed" );
3813 gtk_signal_connect( GTK_OBJECT(m_vAdjust
), "value_changed",
3814 (GtkSignalFunc
) gtk_window_vscroll_callback
, (gpointer
) this );
3819 int wxWindow::GetScrollThumb( int orient
) const
3821 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3823 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3825 if (orient
== wxHORIZONTAL
)
3826 return (int)(m_hAdjust
->page_size
+0.5);
3828 return (int)(m_vAdjust
->page_size
+0.5);
3831 int wxWindow::GetScrollPos( int orient
) const
3833 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3835 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3837 if (orient
== wxHORIZONTAL
)
3838 return (int)(m_hAdjust
->value
+0.5);
3840 return (int)(m_vAdjust
->value
+0.5);
3843 int wxWindow::GetScrollRange( int orient
) const
3845 wxCHECK_MSG( m_widget
!= NULL
, 0, wxT("invalid window") );
3847 wxCHECK_MSG( m_wxwindow
!= NULL
, 0, wxT("window needs client area for scrolling") );
3849 if (orient
== wxHORIZONTAL
)
3850 return (int)(m_hAdjust
->upper
+0.5);
3852 return (int)(m_vAdjust
->upper
+0.5);
3855 void wxWindow::ScrollWindow( int dx
, int dy
, const wxRect
* WXUNUSED(rect
) )
3857 wxCHECK_RET( m_widget
!= NULL
, wxT("invalid window") );
3859 wxCHECK_RET( m_wxwindow
!= NULL
, wxT("window needs client area for scrolling") );
3861 if ((dx
== 0) && (dy
== 0)) return;
3863 m_clipPaintRegion
= TRUE
;
3864 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow
), -dx
, -dy
);
3865 m_clipPaintRegion
= FALSE
;
3868 if (m_children.GetCount() > 0)
3870 gtk_pizza_scroll( GTK_PIZZA(m_wxwindow), -dx, -dy );
3874 GtkPizza *pizza = GTK_PIZZA(m_wxwindow);
3876 pizza->xoffset -= dx;
3877 pizza->yoffset -= dy;
3879 GdkGC *m_scrollGC = gdk_gc_new( pizza->bin_window );
3880 gdk_gc_set_exposures( m_scrollGC, TRUE );
3884 GetClientSize( &cw, &ch );
3885 int w = cw - abs(dx);
3886 int h = ch - abs(dy);
3888 if ((h < 0) || (w < 0))
3896 if (dx < 0) s_x = -dx;
3897 if (dy < 0) s_y = -dy;
3900 if (dx > 0) d_x = dx;
3901 if (dy > 0) d_y = dy;
3903 gdk_window_copy_area( pizza->bin_window, m_scrollGC, d_x, d_y,
3904 pizza->bin_window, s_x, s_y, w, h );
3907 if (dx < 0) rect.x = cw+dx; else rect.x = 0;
3908 if (dy < 0) rect.y = ch+dy; else rect.y = 0;
3909 if (dy != 0) rect.width = cw; else rect.width = abs(dx);
3910 if (dx != 0) rect.height = ch; else rect.height = abs(dy);
3912 Refresh( TRUE, &rect );
3915 gdk_gc_unref( m_scrollGC );
3920 // Find the wxWindow at the current mouse position, also returning the mouse
3922 wxWindow
* wxFindWindowAtPointer(wxPoint
& pt
)
3924 pt
= wxGetMousePosition();
3925 wxWindow
* found
= wxFindWindowAtPoint(pt
);
3929 // Get the current mouse position.
3930 wxPoint
wxGetMousePosition()
3932 /* This crashes when used within wxHelpContext,
3933 so we have to use the X-specific implementation below.
3935 GdkModifierType *mask;
3936 (void) gdk_window_get_pointer(NULL, &x, &y, mask);
3938 return wxPoint(x, y);
3942 GdkWindow
* windowAtPtr
= gdk_window_at_pointer(& x
, & y
);
3944 return wxPoint(-999, -999);
3946 Display
*display
= GDK_WINDOW_XDISPLAY(windowAtPtr
);
3947 Window rootWindow
= RootWindowOfScreen (DefaultScreenOfDisplay(display
));
3948 Window rootReturn
, childReturn
;
3949 int rootX
, rootY
, winX
, winY
;
3950 unsigned int maskReturn
;
3952 XQueryPointer (display
,
3956 &rootX
, &rootY
, &winX
, &winY
, &maskReturn
);
3957 return wxPoint(rootX
, rootY
);