Re: Cheese patches



On Thu, 2011-03-24 at 22:20 -0400, Matthias Clasen wrote:
> On Thu, Mar 24, 2011 at 8:07 PM, Bastien Nocera <hadess hadess net> wrote:
> > Heya,
> >
> > A couple of patches for cheese's GTK+ widget, as used in the
> > gnome-control-center "User Accounts" panel.
> >
> > The largest patch ("Don't crop the video preview") uses a renamed
> > MxAspectFrame (currently under review in upstream Clutter), which was
> > already used within an Intel internal project. It works well in my
> > testing.
> >
> > "Make the flash not hide the gnome-shell panel" follows advice by Dan
> > Winship (IIRC) not put the flash over the shell panel. The majority of
> > the code is a cut'n'paste of code that's been used in Totem, and
> > gnome-desktop. Works well in my testing as well.
> >
> > All patches are here:
> > https://bugzilla.gnome.org/show_bug.cgi?id=522199
> 
> Bugzilla still down :-( Can you make the patches available elsewhere ?

Attached. Some of that code should be familiar to you ;)
>From e7e67cc0fab32b1784fc9e400a83962fa9799241 Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess hadess net>
Date: Thu, 24 Mar 2011 17:36:40 +0000
Subject: [PATCH 1/2] lib: Don't crop the video preview

But resize it, preserving aspect-ratio instead.

https://bugzilla.gnome.org/show_bug.cgi?id=522199
---
 configure.ac                    |    1 +
 libcheese/Makefile.am           |    2 +
 libcheese/cheese-aspect-frame.c |  399 +++++++++++++++++++++++++++++++++++++++
 libcheese/cheese-aspect-frame.h |   91 +++++++++
 libcheese/cheese-widget.c       |   16 ++-
 5 files changed, 506 insertions(+), 3 deletions(-)
 create mode 100644 libcheese/cheese-aspect-frame.c
 create mode 100644 libcheese/cheese-aspect-frame.h

diff --git a/configure.ac b/configure.ac
index cb9383c..dc49787 100644
--- a/configure.ac
+++ b/configure.ac
@@ -145,6 +145,7 @@ PKG_CHECK_MODULES(CHEESE, \
   pangocairo >= $PANGOCAIRO_REQUIRED \
   clutter-1.0 >= $CLUTTER_REQUIRED \
   clutter-gst-1.0 >= $CLUTTERGST_REQUIRED \
+  mx-1.0 \
   $UDEV_PKG
   )
 AC_SUBST(CHEESE_CFLAGS)
diff --git a/libcheese/Makefile.am b/libcheese/Makefile.am
index a6a034b..37b125b 100644
--- a/libcheese/Makefile.am
+++ b/libcheese/Makefile.am
@@ -49,6 +49,8 @@ libcheese_la_SOURCES = \
 libcheese_gtk_la_SOURCES = \
 	cheese-avatar-chooser.c \
 	cheese-avatar-chooser.h \
+	cheese-aspect-frame.c \
+	cheese-aspect-frame.h \
 	um-crop-area.c \
 	um-crop-area.h \
 	cheese-widget.c \
diff --git a/libcheese/cheese-aspect-frame.c b/libcheese/cheese-aspect-frame.c
new file mode 100644
index 0000000..9a281e2
--- /dev/null
+++ b/libcheese/cheese-aspect-frame.c
@@ -0,0 +1,399 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * mx-aspect-frame.c: A container that respect the aspect ratio of its child
+ *
+ * Copyright 2010, 2011 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "cheese-aspect-frame.h"
+
+G_DEFINE_TYPE (CheeseAspectFrame, cheese_aspect_frame, MX_TYPE_BIN)
+
+#define ASPECT_FRAME_PRIVATE(o)                         \
+  (G_TYPE_INSTANCE_GET_PRIVATE ((o),                    \
+                                CHEESE_TYPE_ASPECT_FRAME,   \
+                                CheeseAspectFramePrivate))
+
+enum
+{
+  PROP_0,
+
+  PROP_EXPAND,
+  PROP_RATIO
+};
+
+struct _CheeseAspectFramePrivate
+{
+  guint expand : 1;
+
+  gfloat ratio;
+};
+
+
+static void
+cheese_aspect_frame_get_property (GObject    *object,
+                               guint       property_id,
+                               GValue     *value,
+                               GParamSpec *pspec)
+{
+  CheeseAspectFrame *frame = CHEESE_ASPECT_FRAME (object);
+
+  switch (property_id)
+    {
+    case PROP_EXPAND:
+      g_value_set_boolean (value, cheese_aspect_frame_get_expand (frame));
+      break;
+
+    case PROP_RATIO:
+      g_value_set_float (value, cheese_aspect_frame_get_ratio (frame));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+cheese_aspect_frame_set_property (GObject      *object,
+                               guint         property_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
+{
+  switch (property_id)
+    {
+    case PROP_EXPAND:
+      cheese_aspect_frame_set_expand (CHEESE_ASPECT_FRAME (object),
+                                   g_value_get_boolean (value));
+      break;
+
+    case PROP_RATIO:
+      cheese_aspect_frame_set_ratio (CHEESE_ASPECT_FRAME (object),
+                                  g_value_get_float (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+cheese_aspect_frame_dispose (GObject *object)
+{
+  G_OBJECT_CLASS (cheese_aspect_frame_parent_class)->dispose (object);
+}
+
+static void
+cheese_aspect_frame_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (cheese_aspect_frame_parent_class)->finalize (object);
+}
+
+static void
+cheese_aspect_frame_get_preferred_width (ClutterActor *actor,
+                                      gfloat        for_height,
+                                      gfloat       *min_width_p,
+                                      gfloat       *nat_width_p)
+{
+  gboolean override;
+  MxPadding padding;
+
+  mx_widget_get_padding (MX_WIDGET (actor), &padding);
+  if (for_height >= 0)
+    for_height = MAX (0, for_height - padding.top - padding.bottom);
+
+  if (for_height >= 0)
+    override = FALSE;
+  else
+    g_object_get (G_OBJECT (actor), "natural-height-set", &override, NULL);
+
+  if (override)
+    g_object_get (G_OBJECT (actor), "natural-height", &for_height, NULL);
+
+  CLUTTER_ACTOR_CLASS (cheese_aspect_frame_parent_class)->
+    get_preferred_width (actor, for_height, min_width_p, nat_width_p);
+
+  if (min_width_p)
+    *min_width_p += padding.left + padding.right;
+  if (nat_width_p)
+    *nat_width_p += padding.left + padding.right;
+}
+
+static void
+cheese_aspect_frame_get_preferred_height (ClutterActor *actor,
+                                       gfloat        for_width,
+                                       gfloat       *min_height_p,
+                                       gfloat       *nat_height_p)
+{
+  gboolean override;
+  MxPadding padding;
+
+  mx_widget_get_padding (MX_WIDGET (actor), &padding);
+  if (for_width >= 0)
+    for_width = MAX (0, for_width - padding.left - padding.right);
+
+  if (for_width >= 0)
+    override = FALSE;
+  else
+    g_object_get (G_OBJECT (actor), "natural-width-set", &override, NULL);
+
+  if (override)
+    g_object_get (G_OBJECT (actor), "natural-width", &for_width, NULL);
+
+  CLUTTER_ACTOR_CLASS (cheese_aspect_frame_parent_class)->
+    get_preferred_height (actor, for_width, min_height_p, nat_height_p);
+}
+
+static void
+cheese_aspect_frame_allocate (ClutterActor           *actor,
+                           const ClutterActorBox  *box,
+                           ClutterAllocationFlags  flags)
+{
+  MxPadding padding;
+  ClutterActor *child;
+  ClutterActorBox child_box;
+  gfloat aspect, child_aspect, width, height, box_width, box_height;
+
+  CheeseAspectFramePrivate *priv = CHEESE_ASPECT_FRAME (actor)->priv;
+
+  CLUTTER_ACTOR_CLASS (cheese_aspect_frame_parent_class)->
+    allocate (actor, box, flags);
+
+  child = mx_bin_get_child (MX_BIN (actor));
+  if (!child)
+    return;
+
+  mx_widget_get_padding (MX_WIDGET (actor), &padding);
+
+  box_width = box->x2 - box->x1 - padding.left - padding.right;
+  box_height = box->y2 - box->y1 - padding.top - padding.bottom;
+  clutter_actor_get_preferred_size (child, NULL, NULL, &width, &height);
+
+  aspect = box_width / box_height;
+  if (priv->ratio >= 0.f)
+    child_aspect = priv->ratio;
+  else
+    child_aspect = width / height;
+
+  if ((aspect < child_aspect) ^ priv->expand)
+    {
+      width = box_width;
+      height = box_width / child_aspect;
+    }
+  else
+    {
+      height = box_height;
+      width = box_height * child_aspect;
+    }
+
+  child_box.x1 = (box_width - width) / 2 + padding.left;
+  child_box.y1 = (box_height - height) / 2 + padding.top;
+  child_box.x2 = child_box.x1 + width;
+  child_box.y2 = child_box.y1 + height;
+
+  clutter_actor_allocate (child, &child_box, flags);
+}
+
+static void
+cheese_aspect_frame_paint (ClutterActor *actor)
+{
+  ClutterActor *child = mx_bin_get_child (MX_BIN (actor));
+  CheeseAspectFramePrivate *priv = CHEESE_ASPECT_FRAME (actor)->priv;
+
+  if (!child)
+    return;
+
+  if (priv->expand)
+    {
+      MxPadding padding;
+      gfloat width, height;
+
+      clutter_actor_get_size (actor, &width, &height);
+      mx_widget_get_padding (MX_WIDGET (actor), &padding);
+
+      /* Special-case textures and just munge their coordinates.
+       * This avoids clipping, which can break Clutter's batching.
+       */
+      if (CLUTTER_IS_TEXTURE (child))
+        {
+          guint8 opacity;
+          gfloat x, y, tx, ty;
+          CoglHandle material;
+
+          clutter_actor_get_position (child, &x, &y);
+
+          material =
+            clutter_texture_get_cogl_material (CLUTTER_TEXTURE (child));
+          opacity = clutter_actor_get_paint_opacity (child);
+          cogl_material_set_color4ub (material,
+                                      opacity, opacity, opacity, opacity);
+          cogl_set_source (material);
+
+          x -= padding.left;
+          y -= padding.top;
+          width -= padding.left + padding.right;
+          height -= padding.top + padding.bottom;
+
+          tx = (width / (width - (x * 2.f))) / 2.f;
+          ty = (height / (height - (y * 2.f))) / 2.f;
+
+          cogl_rectangle_with_texture_coords (padding.left, padding.top,
+                                              padding.left + width,
+                                              padding.top + height,
+                                              0.5f - tx, 0.5f - ty,
+                                              0.5f + tx, 0.5f + ty);
+        }
+      else
+        {
+          cogl_clip_push_rectangle (padding.left, padding.top,
+                                    padding.left + width, padding.top + height);
+          clutter_actor_paint (child);
+          cogl_clip_pop ();
+        }
+    }
+  else
+    clutter_actor_paint (child);
+}
+
+static void
+cheese_aspect_frame_pick (ClutterActor       *actor,
+                       const ClutterColor *color)
+{
+  ClutterActorBox box;
+
+  ClutterActor *child = mx_bin_get_child (MX_BIN (actor));
+  CheeseAspectFramePrivate *priv = CHEESE_ASPECT_FRAME (actor)->priv;
+
+  clutter_actor_get_allocation_box (actor, &box);
+
+  cogl_set_source_color4ub (color->red, color->green,
+                            color->blue, color->alpha);
+  cogl_rectangle (box.x1, box.y1, box.x2, box.y2);
+
+  if (!child)
+    return;
+
+  if (priv->expand)
+    {
+      MxPadding padding;
+      mx_widget_get_padding (MX_WIDGET (actor), &padding);
+
+      cogl_clip_push_rectangle (padding.left, padding.top,
+                                padding.left + (box.x2 - box.x1),
+                                padding.top + (box.y2 - box.y1));
+      clutter_actor_paint (child);
+      cogl_clip_pop ();
+    }
+  else
+    clutter_actor_paint (child);
+}
+
+static void
+cheese_aspect_frame_class_init (CheeseAspectFrameClass *klass)
+{
+  GParamSpec *pspec;
+
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (CheeseAspectFramePrivate));
+
+  object_class->get_property = cheese_aspect_frame_get_property;
+  object_class->set_property = cheese_aspect_frame_set_property;
+  object_class->dispose = cheese_aspect_frame_dispose;
+  object_class->finalize = cheese_aspect_frame_finalize;
+
+  actor_class->get_preferred_width = cheese_aspect_frame_get_preferred_width;
+  actor_class->get_preferred_height = cheese_aspect_frame_get_preferred_height;
+  actor_class->allocate = cheese_aspect_frame_allocate;
+  actor_class->paint = cheese_aspect_frame_paint;
+  actor_class->pick = cheese_aspect_frame_pick;
+
+  pspec = g_param_spec_boolean ("expand",
+                                "Expand",
+                                "Fill the allocated area with the child and "
+                                "clip off the excess.",
+                                FALSE,
+                                G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+  g_object_class_install_property (object_class, PROP_EXPAND, pspec);
+
+  pspec = g_param_spec_float ("ratio",
+                              "Ratio",
+                              "Override the child's aspect ratio "
+                              "(width/height).",
+                              -1.f, G_MAXFLOAT, -1.f,
+                              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+  g_object_class_install_property (object_class, PROP_RATIO, pspec);
+}
+
+static void
+cheese_aspect_frame_init (CheeseAspectFrame *self)
+{
+  CheeseAspectFramePrivate *priv = self->priv = ASPECT_FRAME_PRIVATE (self);
+  priv->ratio = -1.f;
+}
+
+ClutterActor *
+cheese_aspect_frame_new (void)
+{
+  return g_object_new (CHEESE_TYPE_ASPECT_FRAME, NULL);
+}
+
+void
+cheese_aspect_frame_set_expand (CheeseAspectFrame *frame, gboolean expand)
+{
+  CheeseAspectFramePrivate *priv;
+
+  g_return_if_fail (CHEESE_IS_ASPECT_FRAME (frame));
+
+  priv = frame->priv;
+  if (priv->expand != expand)
+    {
+      priv->expand = expand;
+      clutter_actor_queue_relayout (CLUTTER_ACTOR (frame));
+      g_object_notify (G_OBJECT (frame), "expand");
+    }
+}
+
+gboolean
+cheese_aspect_frame_get_expand (CheeseAspectFrame *frame)
+{
+  g_return_val_if_fail (CHEESE_IS_ASPECT_FRAME (frame), FALSE);
+  return frame->priv->expand;
+}
+
+void
+cheese_aspect_frame_set_ratio (CheeseAspectFrame *frame, gfloat ratio)
+{
+  CheeseAspectFramePrivate *priv;
+
+  g_return_if_fail (CHEESE_IS_ASPECT_FRAME (frame));
+
+  priv = frame->priv;
+  if (priv->ratio != ratio)
+    {
+      priv->ratio = ratio;
+      clutter_actor_queue_relayout (CLUTTER_ACTOR (frame));
+      g_object_notify (G_OBJECT (frame), "ratio");
+    }
+}
+
+gfloat
+cheese_aspect_frame_get_ratio (CheeseAspectFrame *frame)
+{
+  g_return_val_if_fail (CHEESE_IS_ASPECT_FRAME (frame), -1.f);
+  return frame->priv->ratio;
+}
diff --git a/libcheese/cheese-aspect-frame.h b/libcheese/cheese-aspect-frame.h
new file mode 100644
index 0000000..b2d8da2
--- /dev/null
+++ b/libcheese/cheese-aspect-frame.h
@@ -0,0 +1,91 @@
+
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * mx-aspect-frame.h: A container that respect the aspect ratio of its child
+ *
+ * Copyright 2010, 2011 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __CHEESE_ASPECT_FRAME_H__
+#define __CHEESE_ASPECT_FRAME_H__
+
+#include <glib-object.h>
+#include <mx/mx.h>
+
+G_BEGIN_DECLS
+
+#define CHEESE_TYPE_ASPECT_FRAME cheese_aspect_frame_get_type()
+
+#define CHEESE_ASPECT_FRAME(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+  CHEESE_TYPE_ASPECT_FRAME, CheeseAspectFrame))
+
+#define CHEESE_ASPECT_FRAME_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), \
+  CHEESE_TYPE_ASPECT_FRAME, CheeseAspectFrameClass))
+
+#define CHEESE_IS_ASPECT_FRAME(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+  CHEESE_TYPE_ASPECT_FRAME))
+
+#define CHEESE_IS_ASPECT_FRAME_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+  CHEESE_TYPE_ASPECT_FRAME))
+
+#define CHEESE_ASPECT_FRAME_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+  CHEESE_TYPE_ASPECT_FRAME, CheeseAspectFrameClass))
+
+typedef struct _CheeseAspectFrame CheeseAspectFrame;
+typedef struct _CheeseAspectFrameClass CheeseAspectFrameClass;
+typedef struct _CheeseAspectFramePrivate CheeseAspectFramePrivate;
+
+struct _CheeseAspectFrame
+{
+  MxBin parent;
+
+  CheeseAspectFramePrivate *priv;
+};
+
+struct _CheeseAspectFrameClass
+{
+  MxBinClass parent_class;
+
+  /* padding for future expansion */
+  void (*_padding_0) (void);
+  void (*_padding_1) (void);
+  void (*_padding_2) (void);
+  void (*_padding_3) (void);
+  void (*_padding_4) (void);
+};
+
+GType           cheese_aspect_frame_get_type    (void) G_GNUC_CONST;
+
+ClutterActor *  cheese_aspect_frame_new         (void);
+
+void            cheese_aspect_frame_set_expand  (CheeseAspectFrame *frame,
+                                             gboolean       expand);
+gboolean        cheese_aspect_frame_get_expand  (CheeseAspectFrame *frame);
+
+void            cheese_aspect_frame_set_ratio   (CheeseAspectFrame *frame,
+                                             gfloat         ratio);
+gfloat          cheese_aspect_frame_get_ratio   (CheeseAspectFrame *frame);
+
+G_END_DECLS
+
+#endif /* __CHEESE_ASPECT_FRAME_H__ */
diff --git a/libcheese/cheese-widget.c b/libcheese/cheese-widget.c
index 4f80350..a2bac26 100644
--- a/libcheese/cheese-widget.c
+++ b/libcheese/cheese-widget.c
@@ -21,10 +21,12 @@
 
 #include <glib/gi18n.h>
 #include <clutter-gst/clutter-gst.h>
+#include <mx/mx.h>
 
 #include "cheese-widget.h"
 #include "cheese-camera.h"
 #include "cheese-enum-types.h"
+#include "cheese-aspect-frame.h"
 
 enum
 {
@@ -182,7 +184,9 @@ cheese_widget_init (CheeseWidget *widget)
 {
   CheeseWidgetPrivate *priv = CHEESE_WIDGET_GET_PRIVATE (widget);
   GtkWidget           *box;
-  ClutterActor        *stage;
+  ClutterActor        *stage, *frame;
+  ClutterConstraint   *constraint;
+  ClutterColor black = { 0x00, 0x00, 0x00, 0xff };
 
   priv->state = CHEESE_WIDGET_STATE_NONE;
   priv->error = NULL;
@@ -205,10 +209,16 @@ cheese_widget_init (CheeseWidget *widget)
   /* Webcam page */
   priv->screen = gtk_clutter_embed_new ();
   stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED (priv->screen));
-  priv->texture = clutter_texture_new ();
+  clutter_stage_set_color (CLUTTER_STAGE (stage), &black);
+  frame = cheese_aspect_frame_new ();
 
+  priv->texture = clutter_texture_new ();
   clutter_actor_set_size (priv->texture, 400, 300);
-  clutter_container_add_actor (CLUTTER_CONTAINER (stage), priv->texture);
+  mx_bin_set_child (MX_BIN (frame), priv->texture);
+
+  clutter_container_add_actor (CLUTTER_CONTAINER (stage), frame);
+  constraint = clutter_bind_constraint_new (stage, CLUTTER_BIND_SIZE, 0.0);
+  clutter_actor_add_constraint_with_name (frame, "size", constraint);
 
   gtk_widget_show (priv->screen);
   clutter_actor_show (priv->texture);
-- 
1.7.4.1

>From 6f2697c08165a594cd2cd0af7aa97a02298089fe Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess hadess net>
Date: Thu, 24 Mar 2011 18:01:32 +0000
Subject: [PATCH 2/2] lib: Make the flash not hide the gnome-shell panel

By using the work area, rather than the fullscreen
when it's available (X11 only).

https://bugzilla.gnome.org/show_bug.cgi?id=522199
---
 libcheese/cheese-flash.c |  122 +++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 121 insertions(+), 1 deletions(-)

diff --git a/libcheese/cheese-flash.c b/libcheese/cheese-flash.c
index 091d134..7bff521 100644
--- a/libcheese/cheese-flash.c
+++ b/libcheese/cheese-flash.c
@@ -27,6 +27,14 @@
 #include <cheese-camera.h>
 #include "cheese-flash.h"
 
+#ifdef GDK_WINDOWING_X11
+#include <X11/Xproto.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <gdk/gdkx.h>
+#endif /* GDK_WINDOWING_X11 */
+
 enum
 {
   PROP_0,
@@ -57,6 +65,110 @@ typedef struct
   guint fade_timeout_tag;
 } CheeseFlashPrivate;
 
+/* Copy-pasted from totem/src/backend/video-utils.c
+ * Waiting on GTK+ bug:
+ * https://bugzilla.gnome.org/show_bug.cgi?id=523574 */
+#ifdef GDK_WINDOWING_X11
+static int
+get_current_desktop (GdkScreen *screen)
+{
+        Display *display;
+        Window win;
+        Atom current_desktop, type;
+        int format;
+        unsigned long n_items, bytes_after;
+        unsigned char *data_return = NULL;
+        int workspace = 0;
+
+        display = GDK_DISPLAY_XDISPLAY (gdk_screen_get_display (screen));
+        win = XRootWindow (display, GDK_SCREEN_XNUMBER (screen));
+
+        current_desktop = XInternAtom (display, "_NET_CURRENT_DESKTOP", True);
+
+        XGetWindowProperty (display,
+                            win,
+                            current_desktop,
+                            0, G_MAXLONG,
+                            False, XA_CARDINAL,
+                            &type, &format, &n_items, &bytes_after,
+                            &data_return);
+
+        if (type == XA_CARDINAL && format == 32 && n_items > 0)
+                workspace = (int) data_return[0];
+        if (data_return)
+                XFree (data_return);
+
+        return workspace;
+}
+
+static gboolean
+get_work_area (GdkScreen      *screen,
+	       GdkRectangle   *rect)
+{
+	Atom            workarea;
+	Atom            type;
+	Window          win;
+	int             format;
+	gulong          num;
+	gulong          leftovers;
+	gulong          max_len = 4 * 32;
+	guchar         *ret_workarea;
+	long           *workareas;
+	int             result;
+	int             disp_screen;
+	int             desktop;
+	Display        *display;
+
+	display = GDK_DISPLAY_XDISPLAY (gdk_screen_get_display (screen));
+	workarea = XInternAtom (display, "_NET_WORKAREA", True);
+
+	disp_screen = GDK_SCREEN_XNUMBER (screen);
+
+	/* Defaults in case of error */
+	rect->x = 0;
+	rect->y = 0;
+	rect->width = gdk_screen_get_width (screen);
+	rect->height = gdk_screen_get_height (screen);
+
+	if (workarea == None)
+		return FALSE;
+
+	win = XRootWindow (display, disp_screen);
+	result = XGetWindowProperty (display,
+				     win,
+				     workarea,
+				     0,
+				     max_len,
+				     False,
+				     AnyPropertyType,
+				     &type,
+				     &format,
+				     &num,
+				     &leftovers,
+				     &ret_workarea);
+
+	if (result != Success
+	    || type == None
+	    || format == 0
+	    || leftovers
+	    || num % 4) {
+		return FALSE;
+	}
+
+	desktop = get_current_desktop (screen);
+
+	workareas = (long *) ret_workarea;
+	rect->x = workareas[desktop * 4];
+	rect->y = workareas[desktop * 4 + 1];
+	rect->width = workareas[desktop * 4 + 2];
+	rect->height = workareas[desktop * 4 + 3];
+
+	XFree (ret_workarea);
+
+	return TRUE;
+}
+#endif /* GDK_WINDOWING_X11 */
+
 static gboolean
 cheese_flash_window_draw_event_cb (GtkWidget *widget, cairo_t *cr, gpointer user_data)
 {
@@ -227,8 +339,16 @@ cheese_flash_fire (CheeseFlash *flash)
   parent  = gtk_widget_get_toplevel (flash_priv->parent);
   screen  = gtk_widget_get_screen (parent);
   monitor = gdk_screen_get_monitor_at_window (screen,
-                                              gtk_widget_get_window (parent));
+					      gtk_widget_get_window (parent));
   gdk_screen_get_monitor_geometry (screen, monitor, &rect);
+#ifdef GDK_WINDOWING_X11
+  {
+    GdkRectangle area, dest;
+    get_work_area (screen, &area);
+    if (gdk_rectangle_intersect (&area, &rect, &dest))
+      rect = dest;
+  }
+#endif /* GDK_WINDOWING_X11 */
   gtk_window_set_transient_for (GTK_WINDOW (flash_window), GTK_WINDOW (parent));
   gtk_window_resize (flash_window, rect.width, rect.height);
   gtk_window_move (flash_window, rect.x, rect.y);
-- 
1.7.4.1



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]