#include "wx/gtk/private/event.h"
using namespace wxGTKImpl;
+#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
+#else
+typedef guint KeySym;
+#endif
#include <gdk/gdkkeysyms.h>
#if GTK_CHECK_VERSION(3,0,0)
#include <gdk/gdkkeysyms-compat.h>
#endif
+// gdk_window_set_composited() is only supported since 2.12
+#define wxGTK_VERSION_REQUIRED_FOR_COMPOSITING 2,12,0
+#define wxGTK_HAS_COMPOSITING_SUPPORT GTK_CHECK_VERSION(2,12,0)
+
//-----------------------------------------------------------------------------
// documentation on internals
//-----------------------------------------------------------------------------
keysym = (KeySym)gdk_event->string[0];
}
+#ifdef GDK_WINDOWING_X11
// we want to always get the same key code when the same key is
// pressed regardless of the state of the modifiers, i.e. on a
// standard US keyboard pressing '5' or '%' ('5' key with
// use the normalized, i.e. lower register, keysym if we've
// got one
key_code = keysymNormalized ? keysymNormalized : keysym;
+#else
+ key_code = keysym;
+#endif
// as explained above, we want to have lower register key codes
// normally but for the letter keys we want to have the upper ones
}
}
-// find the window to send the mouse event too
+// find the window to send the mouse event to
static
wxWindowGTK *FindWindowForMouseEvent(wxWindowGTK *win, wxCoord& x, wxCoord& y)
{
else
{
if ((child->m_wxwindow == NULL) &&
+ win->IsClientAreaChild(child) &&
(child->m_x <= xx) &&
(child->m_y <= yy) &&
(child->m_x+child->m_width >= xx) &&
);
}
+ // Use composited window if background is transparent, if supported.
+ if (m_backgroundStyle == wxBG_STYLE_TRANSPARENT)
+ {
+#if wxGTK_HAS_COMPOSITING_SUPPORT
+ if (IsTransparentBackgroundSupported())
+ {
+ GdkWindow* const window = GTKGetDrawingWindow();
+ if (window)
+ gdk_window_set_composited(window, true);
+ }
+ else
+#endif // wxGTK_HAS_COMPOSITING_SUPPORT
+ {
+ // We revert to erase mode if transparency is not supported
+ m_backgroundStyle = wxBG_STYLE_ERASE;
+ }
+ }
+
+
// We cannot set colours and fonts before the widget
// been realized, so we do this directly after realization
// or otherwise in idle time
{
wxASSERT_MSG( (m_widget != NULL), wxT("invalid window") );
+#if wxGTK_HAS_COMPOSITING_SUPPORT
+ // Set RGBA visual as soon as possible to minimize the possibility that
+ // somebody uses the wrong one.
+ if ( m_backgroundStyle == wxBG_STYLE_TRANSPARENT &&
+ IsTransparentBackgroundSupported() )
+ {
+ GdkScreen *screen = gtk_widget_get_screen (m_widget);
+
+ GdkColormap *rgba_colormap = gdk_screen_get_rgba_colormap (screen);
+
+ if (rgba_colormap)
+ gtk_widget_set_colormap(m_widget, rgba_colormap);
+ }
+#endif // wxGTK_HAS_COMPOSITING_SUPPORT
+
if (m_wxwindow)
{
if (!m_noExpose)
GdkDeviceManager* manager = gdk_display_get_device_manager(display);
gdk_device_warp(gdk_device_manager_get_client_pointer(manager), screen, x, y);
#else
+#ifdef GDK_WINDOWING_X11
XWarpPointer(GDK_DISPLAY_XDISPLAY(display),
None,
GDK_WINDOW_XID(gdk_screen_get_root_window(screen)),
0, 0, 0, 0, x, y);
#endif
+#endif
}
wxWindowGTK::ScrollDir wxWindowGTK::ScrollDirFromRange(GtkRange *range) const
m_updateRegion.Clear();
return;
}
-
+#if wxGTK_HAS_COMPOSITING_SUPPORT
+ cairo_t* cr = NULL;
+#endif
// Clip to paint region in wxClientDC
m_clipPaintRegion = true;
switch ( GetBackgroundStyle() )
{
+ case wxBG_STYLE_TRANSPARENT:
+#if wxGTK_HAS_COMPOSITING_SUPPORT
+ if (IsTransparentBackgroundSupported())
+ {
+ // Set a transparent background, so that overlaying in parent
+ // might indeed let see through where this child did not
+ // explicitly paint.
+ // NB: it works also for top level windows (but this is the
+ // windows manager which then does the compositing job)
+ cr = gdk_cairo_create(m_wxwindow->window);
+ gdk_cairo_region(cr, m_nativeUpdateRegion.GetRegion());
+ cairo_clip(cr);
+
+ cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
+ cairo_paint(cr);
+ cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
+ cairo_surface_flush(cairo_get_target(cr));
+ }
+#endif // wxGTK_HAS_COMPOSITING_SUPPORT
+ break;
+
case wxBG_STYLE_ERASE:
{
wxWindowDC dc( (wxWindow*)this );
paint_event.SetEventObject( this );
HandleWindowEvent( paint_event );
+#if wxGTK_HAS_COMPOSITING_SUPPORT
+ if (IsTransparentBackgroundSupported())
+ { // now composite children which need it
+ // Overlay all our composite children on top of the painted area
+ wxWindowList::compatibility_iterator node;
+ for ( node = m_children.GetFirst(); node ; node = node->GetNext() )
+ {
+ wxWindow *compositeChild = node->GetData();
+ if (compositeChild->GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT)
+ {
+ if (cr == NULL)
+ {
+ cr = gdk_cairo_create(m_wxwindow->window);
+ gdk_cairo_region(cr, m_nativeUpdateRegion.GetRegion());
+ cairo_clip(cr);
+ }
+
+ GtkWidget *child = compositeChild->m_wxwindow;
+ GtkAllocation alloc;
+ gtk_widget_get_allocation(child, &alloc);
+
+ // The source data is the (composited) child
+ gdk_cairo_set_source_window(
+ cr, gtk_widget_get_window(child), alloc.x, alloc.y);
+
+ cairo_paint(cr);
+ }
+ }
+ if (cr)
+ cairo_destroy(cr);
+ }
+#endif // wxGTK_HAS_COMPOSITING_SUPPORT
+
m_clipPaintRegion = false;
m_updateRegion.Clear();
bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style)
{
- wxWindowBase::SetBackgroundStyle(style);
+ if (!wxWindowBase::SetBackgroundStyle(style))
+ return false;
- if ( style == wxBG_STYLE_PAINT )
+ GdkWindow *window;
+ if ( m_wxwindow )
{
- GdkWindow *window;
- if ( m_wxwindow )
- {
- window = GTKGetDrawingWindow();
- }
- else
- {
- GtkWidget * const w = GetConnectWidget();
- window = w ? gtk_widget_get_window(w) : NULL;
- }
+ window = GTKGetDrawingWindow();
+ }
+ else
+ {
+ GtkWidget * const w = GetConnectWidget();
+ window = w ? gtk_widget_get_window(w) : NULL;
+ }
+
+ bool wantNoBackPixmap = style == wxBG_STYLE_PAINT || style == wxBG_STYLE_TRANSPARENT;
+ if ( wantNoBackPixmap )
+ {
if (window)
{
// Make sure GDK/X11 doesn't refresh the window
// automatically.
- gdk_window_set_back_pixmap( window, None, False );
-#ifdef __X__
- Display* display = GDK_WINDOW_DISPLAY(window);
- XFlush(display);
-#endif
+ gdk_window_set_back_pixmap( window, NULL, FALSE );
m_needsStyleChange = false;
}
else // window not realized yet
return true;
}
+bool wxWindowGTK::IsTransparentBackgroundSupported(wxString* reason) const
+{
+#if wxGTK_HAS_COMPOSITING_SUPPORT
+ if (gtk_check_version(wxGTK_VERSION_REQUIRED_FOR_COMPOSITING) != NULL)
+ {
+ if (reason)
+ {
+ *reason = _("GTK+ installed on this machine is too old to "
+ "support screen compositing, please install "
+ "GTK+ 2.12 or later.");
+ }
+
+ return false;
+ }
+
+ // NB: We don't check here if the particular kind of widget supports
+ // transparency, we check only if it would be possible for a generic window
+
+ wxCHECK_MSG ( m_widget, false, "Window must be created first" );
+
+ if (!gdk_screen_is_composited(gtk_widget_get_screen(m_widget)))
+ {
+ if (reason)
+ {
+ *reason = _("Compositing not supported by this system, "
+ "please enable it in your Window Manager.");
+ }
+
+ return false;
+ }
+
+ return true;
+#else
+ if (reason)
+ {
+ *reason = _("This program was compiled with a too old version of GTK+, "
+ "please rebuild with GTK+ 2.12 or newer.");
+ }
+#endif // wxGTK_HAS_COMPOSITING_SUPPORT/!wxGTK_HAS_COMPOSITING_SUPPORT
+
+ return false;
+}
+
// ----------------------------------------------------------------------------
// Pop-up menu stuff
// ----------------------------------------------------------------------------
}
}
-void wxWindowGTK::SetWindowStyleFlag( long style )
-{
- // Updates the internal variable. NB: Now m_windowStyle bits carry the _new_ style values already
- wxWindowBase::SetWindowStyleFlag(style);
-}
-
// Find the wxWindow at the current mouse position, also returning the mouse
// position.
wxWindow* wxFindWindowAtPointer(wxPoint& pt)