[gedit] Implement compositing support for GeditOverlay
- From: Jesse van den Kieboom <jessevdk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gedit] Implement compositing support for GeditOverlay
- Date: Sat, 9 Apr 2011 12:11:04 +0000 (UTC)
commit 63f13103ea314499aa6f753dccb83bede2c9f1e9
Author: Jesse van den Kieboom <jessevdk gnome org>
Date: Sat Apr 9 14:08:48 2011 +0200
Implement compositing support for GeditOverlay
https://bugzilla.gnome.org/show_bug.cgi?id=642091
gedit/gedit-overlay-child.c | 37 +++++++-
gedit/gedit-overlay.c | 240 +++++++++++++++++++++++++++++++++++++++---
gedit/gedit-overlay.h | 3 +
gedit/gedit-rounded-frame.c | 2 +-
gedit/gedit-view-frame.c | 17 +++
5 files changed, 279 insertions(+), 20 deletions(-)
---
diff --git a/gedit/gedit-overlay-child.c b/gedit/gedit-overlay-child.c
index e30d6ed..a4b4769 100644
--- a/gedit/gedit-overlay-child.c
+++ b/gedit/gedit-overlay-child.c
@@ -97,19 +97,30 @@ gedit_overlay_child_realize (GtkWidget *widget)
GdkWindow *parent_window;
GdkWindow *window;
GtkStyleContext *context;
+ GdkScreen *screen;
+ GdkVisual *visual;
gtk_widget_set_realized (widget, TRUE);
parent_window = gtk_widget_get_parent_window (widget);
context = gtk_widget_get_style_context (widget);
+ screen = gtk_widget_get_screen (gtk_widget_get_parent (widget));
+ visual = gdk_screen_get_rgba_visual (screen);
+
+ if (visual == NULL)
+ {
+ visual = gdk_screen_get_system_visual (screen);
+ }
+
attributes.window_type = GDK_WINDOW_CHILD;
attributes.wclass = GDK_INPUT_OUTPUT;
attributes.event_mask = GDK_EXPOSURE_MASK;
attributes.width = 0;
attributes.height = 0;
+ attributes.visual = visual;
- window = gdk_window_new (parent_window, &attributes, 0);
+ window = gdk_window_new (parent_window, &attributes, GDK_WA_VISUAL);
gdk_window_set_user_data (window, widget);
gtk_widget_set_window (widget, window);
gtk_style_context_set_state (context, GTK_STATE_FLAG_NORMAL);
@@ -201,6 +212,29 @@ gedit_overlay_child_remove (GtkContainer *container,
}
static void
+gedit_overlay_child_screen_changed (GtkWidget *widget,
+ GdkScreen *prev)
+{
+ GdkScreen *screen;
+ GdkVisual *visual;
+
+ if (GTK_WIDGET_CLASS (gedit_overlay_child_parent_class)->screen_changed)
+ {
+ GTK_WIDGET_CLASS (gedit_overlay_child_parent_class)->screen_changed (widget, prev);
+ }
+
+ screen = gtk_widget_get_screen (widget);
+ visual = gdk_screen_get_rgba_visual (screen);
+
+ if (visual == NULL)
+ {
+ visual = gdk_screen_get_system_visual (screen);
+ }
+
+ gtk_widget_set_visual (widget, visual);
+}
+
+static void
gedit_overlay_child_class_init (GeditOverlayChildClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -214,6 +248,7 @@ gedit_overlay_child_class_init (GeditOverlayChildClass *klass)
widget_class->get_preferred_width = gedit_overlay_child_get_preferred_width;
widget_class->get_preferred_height = gedit_overlay_child_get_preferred_height;
widget_class->size_allocate = gedit_overlay_child_size_allocate;
+ widget_class->screen_changed = gedit_overlay_child_screen_changed;
container_class->add = gedit_overlay_child_add;
container_class->remove = gedit_overlay_child_remove;
diff --git a/gedit/gedit-overlay.c b/gedit/gedit-overlay.c
index 530e602..2a60f68 100644
--- a/gedit/gedit-overlay.c
+++ b/gedit/gedit-overlay.c
@@ -31,18 +31,45 @@ struct _GeditOverlayPrivate
GtkWidget *main_widget;
GtkWidget *relative_widget;
GSList *children;
+
+ guint composited : 1;
};
enum
{
PROP_0,
PROP_MAIN_WIDGET,
- PROP_RELATIVE_WIDGET
+ PROP_RELATIVE_WIDGET,
+ PROP_COMPOSITED
};
G_DEFINE_TYPE (GeditOverlay, gedit_overlay, GTK_TYPE_CONTAINER)
static void
+enable_compositing (GeditOverlay *overlay,
+ GtkWidget *child,
+ gboolean enable)
+{
+ GdkWindow *window;
+ GdkWindow *mywindow;
+
+ mywindow = gtk_widget_get_window (GTK_WIDGET (overlay));
+ window = gtk_widget_get_window (child);
+
+ if (window != NULL && window != mywindow)
+ {
+ gdk_window_set_composited (window, enable);
+ }
+}
+
+static void
+on_child_realized (GtkWidget *child,
+ GeditOverlay *overlay)
+{
+ enable_compositing (overlay, child, overlay->priv->composited);
+}
+
+static void
add_toplevel_widget (GeditOverlay *overlay,
GtkWidget *child)
{
@@ -50,6 +77,13 @@ add_toplevel_widget (GeditOverlay *overlay,
overlay->priv->children = g_slist_append (overlay->priv->children,
child);
+
+ enable_compositing (overlay, child, overlay->priv->composited);
+
+ g_signal_connect_after (child,
+ "realize",
+ G_CALLBACK (on_child_realized),
+ overlay);
}
static void
@@ -59,6 +93,30 @@ gedit_overlay_dispose (GObject *object)
}
static void
+set_enable_compositing (GeditOverlay *overlay,
+ gboolean enabled)
+{
+ GSList *item;
+
+ if (overlay->priv->composited == enabled)
+ {
+ return;
+ }
+
+ overlay->priv->composited = enabled;
+
+ /* Enable/disable compositing on all the children */
+ for (item = overlay->priv->children; item; item = g_slist_next (item))
+ {
+ GtkWidget *child = item->data;
+
+ enable_compositing (overlay, child, enabled);
+ }
+
+ g_object_notify (G_OBJECT (overlay), "composited");
+}
+
+static void
gedit_overlay_get_property (GObject *object,
guint prop_id,
GValue *value,
@@ -77,6 +135,10 @@ gedit_overlay_get_property (GObject *object,
g_value_set_object (value, priv->relative_widget);
break;
+ case PROP_COMPOSITED:
+ g_value_set_boolean (value, priv->composited);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -84,6 +146,51 @@ gedit_overlay_get_property (GObject *object,
}
static void
+set_transparent_background_color (GtkWidget *widget)
+{
+ GtkStyleContext *context;
+ GdkRGBA bg_color;
+
+ context = gtk_widget_get_style_context (widget);
+ gtk_style_context_get_background_color (context,
+ GTK_STATE_NORMAL,
+ &bg_color);
+
+ bg_color.alpha = 0;
+
+ gtk_widget_override_background_color (widget,
+ GTK_STATE_FLAG_NORMAL,
+ &bg_color);
+}
+
+static GtkWidget *
+wrap_child_if_needed (GtkWidget *widget,
+ gboolean make_transparent)
+{
+ GtkWidget *child;
+
+ if (GEDIT_IS_OVERLAY_CHILD (widget))
+ {
+ return widget;
+ }
+
+ child = GTK_WIDGET (gedit_overlay_child_new (widget));
+ gtk_widget_show (child);
+
+ if (make_transparent)
+ {
+ set_transparent_background_color (child);
+ }
+
+ g_signal_connect_swapped (widget,
+ "destroy",
+ G_CALLBACK (gtk_widget_destroy),
+ child);
+
+ return child;
+}
+
+static void
gedit_overlay_set_property (GObject *object,
guint prop_id,
const GValue *value,
@@ -95,14 +202,23 @@ gedit_overlay_set_property (GObject *object,
switch (prop_id)
{
case PROP_MAIN_WIDGET:
- priv->main_widget = g_value_get_object (value);
- add_toplevel_widget (overlay, priv->main_widget);
- break;
+ {
+ priv->main_widget = wrap_child_if_needed (g_value_get_object (value),
+ FALSE);
+ add_toplevel_widget (overlay,
+ priv->main_widget);
+ break;
+ }
case PROP_RELATIVE_WIDGET:
priv->relative_widget = g_value_get_object (value);
break;
+ case PROP_COMPOSITED:
+ set_enable_compositing (overlay,
+ g_value_get_boolean (value));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -300,20 +416,8 @@ overlay_add (GtkContainer *overlay,
if (child == NULL)
{
- if (GEDIT_IS_OVERLAY_CHILD (widget))
- {
- child = GEDIT_OVERLAY_CHILD (widget);
- }
- else
- {
- child = gedit_overlay_child_new (widget);
- gtk_widget_show (GTK_WIDGET (child));
-
- g_signal_connect_swapped (widget, "destroy",
- G_CALLBACK (gtk_widget_destroy), child);
- }
-
- add_toplevel_widget (GEDIT_OVERLAY (overlay), GTK_WIDGET (child));
+ add_toplevel_widget (GEDIT_OVERLAY (overlay),
+ wrap_child_if_needed (widget, TRUE));
}
}
@@ -330,6 +434,10 @@ gedit_overlay_remove (GtkContainer *overlay,
if (child == widget)
{
+ g_signal_handlers_disconnect_by_func (child,
+ on_child_realized,
+ overlay);
+
gtk_widget_unparent (widget);
priv->children = g_slist_remove_link (priv->children,
l);
@@ -365,6 +473,81 @@ gedit_overlay_child_type (GtkContainer *overlay)
return GTK_TYPE_WIDGET;
}
+static gboolean
+gedit_overlay_draw (GtkWidget *widget,
+ cairo_t *cr)
+{
+ GeditOverlay *overlay;
+ GSList *item;
+ GdkWindow *mywindow;
+ GdkRectangle cliprect;
+ gboolean isclipped;
+
+ GTK_WIDGET_CLASS (gedit_overlay_parent_class)->draw (widget, cr);
+
+ overlay = GEDIT_OVERLAY (widget);
+
+ /* Draw composited children if necessary */
+ if (!overlay->priv->composited ||
+ !gdk_display_supports_composite (gtk_widget_get_display (widget)))
+ {
+ return FALSE;
+ }
+
+ mywindow = gtk_widget_get_window (widget);
+ isclipped = gdk_cairo_get_clip_rectangle (cr, &cliprect);
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+
+ for (item = overlay->priv->children; item; item = g_slist_next (item))
+ {
+ GtkWidget *child = item->data;
+ GdkWindow *window;
+ GtkAllocation allocation;
+ GdkRectangle childrect;
+ GdkRectangle cliparea;
+
+ window = gtk_widget_get_window (child);
+
+ if (window == NULL || window == mywindow)
+ {
+ continue;
+ }
+
+ gtk_widget_get_allocation (child, &allocation);
+
+ childrect.x = allocation.x;
+ childrect.y = allocation.y;
+ childrect.width = allocation.width;
+ childrect.height = allocation.height;
+
+ if (isclipped)
+ {
+ gdk_rectangle_intersect (&cliprect,
+ &childrect,
+ &cliparea);
+ }
+ else
+ {
+ cliparea = childrect;
+ }
+
+ cairo_save (cr);
+
+ gdk_cairo_rectangle (cr, &cliparea);
+ cairo_clip (cr);
+
+ gdk_cairo_set_source_window (cr,
+ window,
+ allocation.x,
+ allocation.y);
+
+ cairo_paint (cr);
+ cairo_restore (cr);
+ }
+
+ return FALSE;
+}
static void
gedit_overlay_class_init (GeditOverlayClass *klass)
@@ -381,6 +564,7 @@ gedit_overlay_class_init (GeditOverlayClass *klass)
widget_class->get_preferred_width = gedit_overlay_get_preferred_width;
widget_class->get_preferred_height = gedit_overlay_get_preferred_height;
widget_class->size_allocate = gedit_overlay_size_allocate;
+ widget_class->draw = gedit_overlay_draw;
container_class->add = overlay_add;
container_class->remove = gedit_overlay_remove;
@@ -404,6 +588,15 @@ gedit_overlay_class_init (GeditOverlayClass *klass)
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (object_class,
+ PROP_COMPOSITED,
+ g_param_spec_boolean ("composited",
+ "Composited",
+ "Whether the overlay composites its children",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
g_type_class_add_private (object_class, sizeof (GeditOverlayPrivate));
}
@@ -411,6 +604,8 @@ static void
gedit_overlay_init (GeditOverlay *overlay)
{
overlay->priv = GEDIT_OVERLAY_GET_PRIVATE (overlay);
+
+ gtk_widget_set_app_paintable (GTK_WIDGET (overlay), TRUE);
}
/**
@@ -465,3 +660,12 @@ gedit_overlay_add (GeditOverlay *overlay,
gedit_overlay_child_set_position (child, position);
gedit_overlay_child_set_offset (child, offset);
}
+
+void
+gedit_overlay_set_composited (GeditOverlay *overlay,
+ gboolean enabled)
+{
+ g_return_if_fail (GEDIT_IS_OVERLAY (overlay));
+
+ set_enable_compositing (overlay, enabled);
+}
diff --git a/gedit/gedit-overlay.h b/gedit/gedit-overlay.h
index 9e1c769..224c3ee 100644
--- a/gedit/gedit-overlay.h
+++ b/gedit/gedit-overlay.h
@@ -62,6 +62,9 @@ void gedit_overlay_add (GeditOverlay *overlay,
GeditOverlayChildPosition position,
guint offset);
+void gedit_overlay_set_composited (GeditOverlay *overlay,
+ gboolean enabled);
+
G_END_DECLS
#endif /* __GEDIT_OVERLAY_H__ */
diff --git a/gedit/gedit-rounded-frame.c b/gedit/gedit-rounded-frame.c
index ae84593..5fa5479 100644
--- a/gedit/gedit-rounded-frame.c
+++ b/gedit/gedit-rounded-frame.c
@@ -242,7 +242,7 @@ gedit_rounded_frame_init (GeditRoundedFrame *frame)
frame->priv->frame_width = 3; /* Make it a prop */
gtk_widget_set_has_window (GTK_WIDGET (frame), FALSE);
- gtk_widget_set_app_paintable (GTK_WIDGET (frame), FALSE);
+ gtk_widget_set_app_paintable (GTK_WIDGET (frame), TRUE);
}
GtkWidget *
diff --git a/gedit/gedit-view-frame.c b/gedit/gedit-view-frame.c
index d881bc9..4a51609 100644
--- a/gedit/gedit-view-frame.c
+++ b/gedit/gedit-view-frame.c
@@ -1090,6 +1090,7 @@ create_search_widget (GeditViewFrame *frame)
hbox = gtk_hbox_new (FALSE, 3);
gtk_widget_show (hbox);
+
gtk_container_add (GTK_CONTAINER (search_widget), hbox);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 3);
@@ -1417,6 +1418,8 @@ gedit_view_frame_init (GeditViewFrame *frame)
GeditDocument *doc;
GtkWidget *sw;
GeditOverlayChildPosition position;
+ GtkStyleContext *context;
+ GdkRGBA bg_color;
frame->priv = GEDIT_VIEW_FRAME_GET_PRIVATE (frame);
@@ -1448,6 +1451,8 @@ gedit_view_frame_init (GeditViewFrame *frame)
gtk_widget_show (sw);
frame->priv->overlay = gedit_animated_overlay_new (sw, frame->priv->view);
+
+ gedit_overlay_set_composited (GEDIT_OVERLAY (frame->priv->overlay), TRUE);
gtk_widget_show (frame->priv->overlay);
gtk_box_pack_start (GTK_BOX (frame), frame->priv->overlay, TRUE, TRUE, 0);
@@ -1472,6 +1477,18 @@ gedit_view_frame_init (GeditViewFrame *frame)
"orientation", GTK_ORIENTATION_VERTICAL,
NULL);
+ /* Force search widget slider to be transparent */
+ context = gtk_widget_get_style_context (frame->priv->slider);
+ gtk_style_context_get_background_color (context,
+ GTK_STATE_NORMAL,
+ &bg_color);
+
+ bg_color.alpha = 0;
+
+ gtk_widget_override_background_color (frame->priv->slider,
+ GTK_STATE_NORMAL,
+ &bg_color);
+
gedit_animated_overlay_add (GEDIT_ANIMATED_OVERLAY (frame->priv->overlay),
GEDIT_ANIMATABLE (frame->priv->slider));
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]