[control-center] Fix a symbol collision with cheese

Kalev Lember kalev at fedoraproject.org
Wed Oct 15 14:12:50 UTC 2014


commit 6ba353865d97fb8cbe03f31a76c2cf6828e83228
Author: Kalev Lember <kalevlember at gmail.com>
Date:   Wed Oct 15 15:59:15 2014 +0200

    Fix a symbol collision with cheese

 ...-accounts-Rename-UmCropArea-to-CcCropArea.patch | 1869 ++++++++++++++++++++
 control-center.spec                                |   12 +-
 2 files changed, 1880 insertions(+), 1 deletions(-)
---
diff --git a/0001-user-accounts-Rename-UmCropArea-to-CcCropArea.patch b/0001-user-accounts-Rename-UmCropArea-to-CcCropArea.patch
new file mode 100644
index 0000000..3ce38fb
--- /dev/null
+++ b/0001-user-accounts-Rename-UmCropArea-to-CcCropArea.patch
@@ -0,0 +1,1869 @@
+From 5e7294acbf3360ebdb7ee4658e12984955a3ef64 Mon Sep 17 00:00:00 2001
+From: David King <amigadave at amigadave.com>
+Date: Wed, 15 Oct 2014 13:40:08 +0100
+Subject: [PATCH] user-accounts: Rename UmCropArea to CcCropArea
+
+Cheese has an internal copy of UmCropArea, and exports the corresponding
+um_crop_area_get_type() as part of libcheese-gtk. This leads to a crash
+when taking a photo in the avatar chooser, as the control center copy of
+the get_type() function is used. Renaming the function in Cheese would
+be an ABI break, so at this stage it is best to do the rename in the
+control center instead.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=697039
+---
+ panels/user-accounts/Makefile.am       |   4 +-
+ panels/user-accounts/cc-crop-area.c    | 817 +++++++++++++++++++++++++++++++++
+ panels/user-accounts/cc-crop-area.h    |  65 +++
+ panels/user-accounts/um-crop-area.c    | 817 ---------------------------------
+ panels/user-accounts/um-crop-area.h    |  65 ---
+ panels/user-accounts/um-photo-dialog.c |  12 +-
+ 6 files changed, 890 insertions(+), 890 deletions(-)
+ create mode 100644 panels/user-accounts/cc-crop-area.c
+ create mode 100644 panels/user-accounts/cc-crop-area.h
+ delete mode 100644 panels/user-accounts/um-crop-area.c
+ delete mode 100644 panels/user-accounts/um-crop-area.h
+
+diff --git a/panels/user-accounts/Makefile.am b/panels/user-accounts/Makefile.am
+index 5ef4c33..1de5719 100644
+--- a/panels/user-accounts/Makefile.am
++++ b/panels/user-accounts/Makefile.am
+@@ -37,8 +37,8 @@ libuser_accounts_la_SOURCES =		\
+ 	pw-utils.c			\
+ 	um-photo-dialog.h		\
+ 	um-photo-dialog.c		\
+-	um-crop-area.h			\
+-	um-crop-area.c			\
++	cc-crop-area.h			\
++	cc-crop-area.c			\
+ 	um-fingerprint-dialog.h		\
+ 	um-fingerprint-dialog.c		\
+ 	um-utils.h			\
+diff --git a/panels/user-accounts/cc-crop-area.c b/panels/user-accounts/cc-crop-area.c
+new file mode 100644
+index 0000000..1b6e407
+--- /dev/null
++++ b/panels/user-accounts/cc-crop-area.c
+@@ -0,0 +1,817 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
++ *
++ * Copyright 2009  Red Hat, Inc,
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ *
++ * Written by: Matthias Clasen <mclasen at redhat.com>
++ */
++
++#include "config.h"
++
++#include <stdlib.h>
++
++#include <glib.h>
++#include <glib/gi18n.h>
++#include <gtk/gtk.h>
++
++#include "cc-crop-area.h"
++
++struct _CcCropAreaPrivate {
++        GdkPixbuf *browse_pixbuf;
++        GdkPixbuf *pixbuf;
++        GdkPixbuf *color_shifted;
++        gdouble scale;
++        GdkRectangle image;
++        GdkCursorType current_cursor;
++        GdkRectangle crop;
++        gint active_region;
++        gint last_press_x;
++        gint last_press_y;
++        gint base_width;
++        gint base_height;
++        gdouble aspect;
++};
++
++G_DEFINE_TYPE (CcCropArea, cc_crop_area, GTK_TYPE_DRAWING_AREA);
++
++static inline guchar
++shift_color_byte (guchar b,
++                  int    shift)
++{
++        return CLAMP(b + shift, 0, 255);
++}
++
++static void
++shift_colors (GdkPixbuf *pixbuf,
++              gint       red,
++              gint       green,
++              gint       blue,
++              gint       alpha)
++{
++        gint x, y, offset, y_offset, rowstride, width, height;
++        guchar *pixels;
++        gint channels;
++
++        width = gdk_pixbuf_get_width (pixbuf);
++        height = gdk_pixbuf_get_height (pixbuf);
++        rowstride = gdk_pixbuf_get_rowstride (pixbuf);
++        pixels = gdk_pixbuf_get_pixels (pixbuf);
++        channels = gdk_pixbuf_get_n_channels (pixbuf);
++
++        for (y = 0; y < height; y++) {
++                y_offset = y * rowstride;
++                for (x = 0; x < width; x++) {
++                        offset = y_offset + x * channels;
++                        if (red != 0)
++                                pixels[offset] = shift_color_byte (pixels[offset], red);
++                        if (green != 0)
++                                pixels[offset + 1] = shift_color_byte (pixels[offset + 1], green);
++                        if (blue != 0)
++                                pixels[offset + 2] = shift_color_byte (pixels[offset + 2], blue);
++                        if (alpha != 0 && channels >= 4)
++                                pixels[offset + 3] = shift_color_byte (pixels[offset + 3], blue);
++                }
++        }
++}
++
++static void
++update_pixbufs (CcCropArea *area)
++{
++        gint width;
++        gint height;
++        GtkAllocation allocation;
++        gdouble scale;
++        GdkRGBA color;
++        guint32 pixel;
++        gint dest_x, dest_y, dest_width, dest_height;
++        GtkWidget *widget;
++        GtkStyleContext *context;
++
++        widget = GTK_WIDGET (area);
++        gtk_widget_get_allocation (widget, &allocation);
++        context = gtk_widget_get_style_context (widget);
++
++        if (area->priv->pixbuf == NULL ||
++            gdk_pixbuf_get_width (area->priv->pixbuf) != allocation.width ||
++            gdk_pixbuf_get_height (area->priv->pixbuf) != allocation.height) {
++                if (area->priv->pixbuf != NULL)
++                        g_object_unref (area->priv->pixbuf);
++                area->priv->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
++                                                     gdk_pixbuf_get_has_alpha (area->priv->browse_pixbuf),
++                                                     8,
++                                                     allocation.width, allocation.height);
++
++                gtk_style_context_get_background_color (context, gtk_style_context_get_state (context), &color);
++                pixel = (((gint)(color.red * 1.0)) << 16) |
++                        (((gint)(color.green * 1.0)) << 8) |
++                         ((gint)(color.blue * 1.0));
++                gdk_pixbuf_fill (area->priv->pixbuf, pixel);
++
++                width = gdk_pixbuf_get_width (area->priv->browse_pixbuf);
++                height = gdk_pixbuf_get_height (area->priv->browse_pixbuf);
++
++                scale = allocation.height / (gdouble)height;
++                if (scale * width > allocation.width)
++                    scale = allocation.width / (gdouble)width;
++
++                dest_width = width * scale;
++                dest_height = height * scale;
++                dest_x = (allocation.width - dest_width) / 2;
++                dest_y = (allocation.height - dest_height) / 2,
++
++                gdk_pixbuf_scale (area->priv->browse_pixbuf,
++                                  area->priv->pixbuf,
++                                  dest_x, dest_y,
++                                  dest_width, dest_height,
++                                  dest_x, dest_y,
++                                  scale, scale,
++                                  GDK_INTERP_BILINEAR);
++
++                if (area->priv->color_shifted)
++                        g_object_unref (area->priv->color_shifted);
++                area->priv->color_shifted = gdk_pixbuf_copy (area->priv->pixbuf);
++                shift_colors (area->priv->color_shifted, -32, -32, -32, 0);
++
++                if (area->priv->scale == 0.0) {
++                        area->priv->crop.width = 2 * area->priv->base_width / scale;
++                        area->priv->crop.height = 2 * area->priv->base_height / scale;
++                        area->priv->crop.x = (gdk_pixbuf_get_width (area->priv->browse_pixbuf) - area->priv->crop.width) / 2;
++                        area->priv->crop.y = (gdk_pixbuf_get_height (area->priv->browse_pixbuf) - area->priv->crop.height) / 2;
++                }
++
++                area->priv->scale = scale;
++                area->priv->image.x = dest_x;
++                area->priv->image.y = dest_y;
++                area->priv->image.width = dest_width;
++                area->priv->image.height = dest_height;
++        }
++}
++
++static void
++crop_to_widget (CcCropArea    *area,
++                GdkRectangle  *crop)
++{
++        crop->x = area->priv->image.x + area->priv->crop.x * area->priv->scale;
++        crop->y = area->priv->image.y + area->priv->crop.y * area->priv->scale;
++        crop->width = area->priv->crop.width * area->priv->scale;
++        crop->height = area->priv->crop.height * area->priv->scale;
++}
++
++typedef enum {
++        OUTSIDE,
++        INSIDE,
++        TOP,
++        TOP_LEFT,
++        TOP_RIGHT,
++        BOTTOM,
++        BOTTOM_LEFT,
++        BOTTOM_RIGHT,
++        LEFT,
++        RIGHT
++} Location;
++
++static gboolean
++cc_crop_area_draw (GtkWidget *widget,
++                   cairo_t   *cr)
++{
++        GdkRectangle crop;
++        gint width, height;
++        CcCropArea *uarea = CC_CROP_AREA (widget);
++
++        if (uarea->priv->browse_pixbuf == NULL)
++                return FALSE;
++
++        update_pixbufs (uarea);
++
++        width = gdk_pixbuf_get_width (uarea->priv->pixbuf);
++        height = gdk_pixbuf_get_height (uarea->priv->pixbuf);
++        crop_to_widget (uarea, &crop);
++
++        gdk_cairo_set_source_pixbuf (cr, uarea->priv->color_shifted, 0, 0);
++        cairo_rectangle (cr, 0, 0, width, crop.y);
++        cairo_rectangle (cr, 0, crop.y, crop.x, crop.height);
++        cairo_rectangle (cr, crop.x + crop.width, crop.y, width - crop.x - crop.width, crop.height);
++        cairo_rectangle (cr, 0, crop.y + crop.height, width, height - crop.y - crop.height);
++        cairo_fill (cr);
++
++        gdk_cairo_set_source_pixbuf (cr, uarea->priv->pixbuf, 0, 0);
++        cairo_rectangle (cr, crop.x, crop.y, crop.width, crop.height);
++        cairo_fill (cr);
++
++        if (uarea->priv->active_region != OUTSIDE) {
++                gint x1, x2, y1, y2;
++                cairo_set_source_rgb (cr, 1, 1, 1);
++                cairo_set_line_width (cr, 1.0);
++                x1 = crop.x + crop.width / 3.0;
++                x2 = crop.x + 2 * crop.width / 3.0;
++                y1 = crop.y + crop.height / 3.0;
++                y2 = crop.y + 2 * crop.height / 3.0;
++
++                cairo_move_to (cr, x1 + 0.5, crop.y);
++                cairo_line_to (cr, x1 + 0.5, crop.y + crop.height);
++
++                cairo_move_to (cr, x2 + 0.5, crop.y);
++                cairo_line_to (cr, x2 + 0.5, crop.y + crop.height);
++
++                cairo_move_to (cr, crop.x, y1 + 0.5);
++                cairo_line_to (cr, crop.x + crop.width, y1 + 0.5);
++
++                cairo_move_to (cr, crop.x, y2 + 0.5);
++                cairo_line_to (cr, crop.x + crop.width, y2 + 0.5);
++                cairo_stroke (cr);
++        }
++
++        cairo_set_source_rgb (cr,  0, 0, 0);
++        cairo_set_line_width (cr, 1.0);
++        cairo_rectangle (cr,
++                         crop.x + 0.5,
++                         crop.y + 0.5,
++                         crop.width - 1.0,
++                         crop.height - 1.0);
++        cairo_stroke (cr);
++
++        cairo_set_source_rgb (cr, 1, 1, 1);
++        cairo_set_line_width (cr, 2.0);
++        cairo_rectangle (cr,
++                         crop.x + 2.0,
++                         crop.y + 2.0,
++                         crop.width - 4.0,
++                         crop.height - 4.0);
++        cairo_stroke (cr);
++
++        return FALSE;
++}
++
++typedef enum {
++        BELOW,
++        LOWER,
++        BETWEEN,
++        UPPER,
++        ABOVE
++} Range;
++
++static Range
++find_range (gint x,
++            gint min,
++            gint max)
++{
++        gint tolerance = 12;
++
++        if (x < min - tolerance)
++                return BELOW;
++        if (x <= min + tolerance)
++                return LOWER;
++        if (x < max - tolerance)
++                return BETWEEN;
++        if (x <= max + tolerance)
++                return UPPER;
++        return ABOVE;
++}
++
++static Location
++find_location (GdkRectangle *rect,
++               gint          x,
++               gint          y)
++{
++        Range x_range, y_range;
++        Location location[5][5] = {
++                { OUTSIDE, OUTSIDE,     OUTSIDE, OUTSIDE,      OUTSIDE },
++                { OUTSIDE, TOP_LEFT,    TOP,     TOP_RIGHT,    OUTSIDE },
++                { OUTSIDE, LEFT,        INSIDE,  RIGHT,        OUTSIDE },
++                { OUTSIDE, BOTTOM_LEFT, BOTTOM,  BOTTOM_RIGHT, OUTSIDE },
++                { OUTSIDE, OUTSIDE,     OUTSIDE, OUTSIDE,      OUTSIDE }
++        };
++
++        x_range = find_range (x, rect->x, rect->x + rect->width);
++        y_range = find_range (y, rect->y, rect->y + rect->height);
++
++        return location[y_range][x_range];
++}
++
++static void
++update_cursor (CcCropArea *area,
++               gint           x,
++               gint           y)
++{
++        gint cursor_type;
++        GdkRectangle crop;
++        gint region;
++
++        region = area->priv->active_region;
++        if (region == OUTSIDE) {
++                crop_to_widget (area, &crop);
++                region = find_location (&crop, x, y);
++        }
++
++        switch (region) {
++        case OUTSIDE:
++                cursor_type = GDK_LEFT_PTR;
++                break;
++        case TOP_LEFT:
++                cursor_type = GDK_TOP_LEFT_CORNER;
++                break;
++        case TOP:
++                cursor_type = GDK_TOP_SIDE;
++                break;
++        case TOP_RIGHT:
++                cursor_type = GDK_TOP_RIGHT_CORNER;
++                break;
++        case LEFT:
++                cursor_type = GDK_LEFT_SIDE;
++                break;
++        case INSIDE:
++                cursor_type = GDK_FLEUR;
++                break;
++        case RIGHT:
++                cursor_type = GDK_RIGHT_SIDE;
++                break;
++        case BOTTOM_LEFT:
++                cursor_type = GDK_BOTTOM_LEFT_CORNER;
++                break;
++        case BOTTOM:
++                cursor_type = GDK_BOTTOM_SIDE;
++                break;
++        case BOTTOM_RIGHT:
++                cursor_type = GDK_BOTTOM_RIGHT_CORNER;
++                break;
++	default:
++		g_assert_not_reached ();
++        }
++
++        if (cursor_type != area->priv->current_cursor) {
++                GdkCursor *cursor = gdk_cursor_new (cursor_type);
++                gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (area)), cursor);
++                g_object_unref (cursor);
++                area->priv->current_cursor = cursor_type;
++        }
++}
++
++static int
++eval_radial_line (gdouble center_x, gdouble center_y,
++                  gdouble bounds_x, gdouble bounds_y,
++                  gdouble user_x)
++{
++        gdouble decision_slope;
++        gdouble decision_intercept;
++
++        decision_slope = (bounds_y - center_y) / (bounds_x - center_x);
++        decision_intercept = -(decision_slope * bounds_x);
++
++        return (int) (decision_slope * user_x + decision_intercept);
++}
++
++static gboolean
++cc_crop_area_motion_notify_event (GtkWidget      *widget,
++                                  GdkEventMotion *event)
++{
++        CcCropArea *area = CC_CROP_AREA (widget);
++        gint x, y;
++        gint delta_x, delta_y;
++        gint width, height;
++        gint adj_width, adj_height;
++        gint pb_width, pb_height;
++        GdkRectangle damage;
++        gint left, right, top, bottom;
++        gdouble new_width, new_height;
++        gdouble center_x, center_y;
++        gint min_width, min_height;
++
++        if (area->priv->browse_pixbuf == NULL)
++                return FALSE;
++
++        update_cursor (area, event->x, event->y);
++
++        crop_to_widget (area, &damage);
++        gtk_widget_queue_draw_area (widget,
++                                    damage.x - 1, damage.y - 1,
++                                    damage.width + 2, damage.height + 2);
++
++        pb_width = gdk_pixbuf_get_width (area->priv->browse_pixbuf);
++        pb_height = gdk_pixbuf_get_height (area->priv->browse_pixbuf);
++
++        x = (event->x - area->priv->image.x) / area->priv->scale;
++        y = (event->y - area->priv->image.y) / area->priv->scale;
++
++        delta_x = x - area->priv->last_press_x;
++        delta_y = y - area->priv->last_press_y;
++        area->priv->last_press_x = x;
++        area->priv->last_press_y = y;
++
++        left = area->priv->crop.x;
++        right = area->priv->crop.x + area->priv->crop.width - 1;
++        top = area->priv->crop.y;
++        bottom = area->priv->crop.y + area->priv->crop.height - 1;
++
++        center_x = (left + right) / 2.0;
++        center_y = (top + bottom) / 2.0;
++
++        switch (area->priv->active_region) {
++        case INSIDE:
++                width = right - left + 1;
++                height = bottom - top + 1;
++
++                left += delta_x;
++                right += delta_x;
++                top += delta_y;
++                bottom += delta_y;
++
++                if (left < 0)
++                        left = 0;
++                if (top < 0)
++                        top = 0;
++                if (right > pb_width)
++                        right = pb_width;
++                if (bottom > pb_height)
++                        bottom = pb_height;
++
++                adj_width = right - left + 1;
++                adj_height = bottom - top + 1;
++                if (adj_width != width) {
++                        if (delta_x < 0)
++                                right = left + width - 1;
++                        else
++                                left = right - width + 1;
++                }
++                if (adj_height != height) {
++                        if (delta_y < 0)
++                                bottom = top + height - 1;
++                        else
++                                top = bottom - height + 1;
++                }
++
++                break;
++
++        case TOP_LEFT:
++                if (area->priv->aspect < 0) {
++                        top = y;
++                        left = x;
++                }
++                else if (y < eval_radial_line (center_x, center_y, left, top, x)) {
++                        top = y;
++                        new_width = (bottom - top) * area->priv->aspect;
++                        left = right - new_width;
++                }
++                else {
++                        left = x;
++                        new_height = (right - left) / area->priv->aspect;
++                        top = bottom - new_height;
++                }
++                break;
++
++        case TOP:
++                top = y;
++                if (area->priv->aspect > 0) {
++                        new_width = (bottom - top) * area->priv->aspect;
++                        right = left + new_width;
++                }
++                break;
++
++        case TOP_RIGHT:
++                if (area->priv->aspect < 0) {
++                        top = y;
++                        right = x;
++                }
++                else if (y < eval_radial_line (center_x, center_y, right, top, x)) {
++                        top = y;
++                        new_width = (bottom - top) * area->priv->aspect;
++                        right = left + new_width;
++                }
++                else {
++                        right = x;
++                        new_height = (right - left) / area->priv->aspect;
++                        top = bottom - new_height;
++                }
++                break;
++
++        case LEFT:
++                left = x;
++                if (area->priv->aspect > 0) {
++                        new_height = (right - left) / area->priv->aspect;
++                        bottom = top + new_height;
++                }
++                break;
++
++        case BOTTOM_LEFT:
++                if (area->priv->aspect < 0) {
++                        bottom = y;
++                        left = x;
++                }
++                else if (y < eval_radial_line (center_x, center_y, left, bottom, x)) {
++                        left = x;
++                        new_height = (right - left) / area->priv->aspect;
++                        bottom = top + new_height;
++                }
++                else {
++                        bottom = y;
++                        new_width = (bottom - top) * area->priv->aspect;
++                        left = right - new_width;
++                }
++                break;
++
++        case RIGHT:
++                right = x;
++                if (area->priv->aspect > 0) {
++                        new_height = (right - left) / area->priv->aspect;
++                        bottom = top + new_height;
++                }
++                break;
++
++        case BOTTOM_RIGHT:
++                if (area->priv->aspect < 0) {
++                        bottom = y;
++                        right = x;
++                }
++                else if (y < eval_radial_line (center_x, center_y, right, bottom, x)) {
++                        right = x;
++                        new_height = (right - left) / area->priv->aspect;
++                        bottom = top + new_height;
++                }
++                else {
++                        bottom = y;
++                        new_width = (bottom - top) * area->priv->aspect;
++                        right = left + new_width;
++                }
++                break;
++
++        case BOTTOM:
++                bottom = y;
++                if (area->priv->aspect > 0) {
++                        new_width = (bottom - top) * area->priv->aspect;
++                        right= left + new_width;
++                }
++                break;
++
++        default:
++                return FALSE;
++        }
++
++        min_width = area->priv->base_width / area->priv->scale;
++        min_height = area->priv->base_height / area->priv->scale;
++
++        width = right - left + 1;
++        height = bottom - top + 1;
++        if (area->priv->aspect < 0) {
++                if (left < 0)
++                        left = 0;
++                if (top < 0)
++                        top = 0;
++                if (right > pb_width)
++                        right = pb_width;
++                if (bottom > pb_height)
++                        bottom = pb_height;
++
++                width = right - left + 1;
++                height = bottom - top + 1;
++
++                switch (area->priv->active_region) {
++                case LEFT:
++                case TOP_LEFT:
++                case BOTTOM_LEFT:
++                        if (width < min_width)
++                                left = right - min_width;
++                        break;
++                case RIGHT:
++                case TOP_RIGHT:
++                case BOTTOM_RIGHT:
++                        if (width < min_width)
++                                right = left + min_width;
++                        break;
++
++                default: ;
++                }
++
++                switch (area->priv->active_region) {
++                case TOP:
++                case TOP_LEFT:
++                case TOP_RIGHT:
++                        if (height < min_height)
++                                top = bottom - min_height;
++                        break;
++                case BOTTOM:
++                case BOTTOM_LEFT:
++                case BOTTOM_RIGHT:
++                        if (height < min_height)
++                                bottom = top + min_height;
++                        break;
++
++                default: ;
++                }
++        }
++        else {
++                if (left < 0 || top < 0 ||
++                    right > pb_width || bottom > pb_height ||
++                    width < min_width || height < min_height) {
++                        left = area->priv->crop.x;
++                        right = area->priv->crop.x + area->priv->crop.width - 1;
++                        top = area->priv->crop.y;
++                        bottom = area->priv->crop.y + area->priv->crop.height - 1;
++                }
++        }
++
++        area->priv->crop.x = left;
++        area->priv->crop.y = top;
++        area->priv->crop.width = right - left + 1;
++        area->priv->crop.height = bottom - top + 1;
++
++        crop_to_widget (area, &damage);
++        gtk_widget_queue_draw_area (widget,
++                                    damage.x - 1, damage.y - 1,
++                                    damage.width + 2, damage.height + 2);
++
++        return FALSE;
++}
++
++static gboolean
++cc_crop_area_button_press_event (GtkWidget      *widget,
++                                 GdkEventButton *event)
++{
++        CcCropArea *area = CC_CROP_AREA (widget);
++        GdkRectangle crop;
++
++        if (area->priv->browse_pixbuf == NULL)
++                return FALSE;
++
++        crop_to_widget (area, &crop);
++
++        area->priv->last_press_x = (event->x - area->priv->image.x) / area->priv->scale;
++        area->priv->last_press_y = (event->y - area->priv->image.y) / area->priv->scale;
++        area->priv->active_region = find_location (&crop, event->x, event->y);
++
++        gtk_widget_queue_draw_area (widget,
++                                    crop.x - 1, crop.y - 1,
++                                    crop.width + 2, crop.height + 2);
++
++        return FALSE;
++}
++
++static gboolean
++cc_crop_area_button_release_event (GtkWidget      *widget,
++                                   GdkEventButton *event)
++{
++        CcCropArea *area = CC_CROP_AREA (widget);
++        GdkRectangle crop;
++
++        if (area->priv->browse_pixbuf == NULL)
++                return FALSE;
++
++        crop_to_widget (area, &crop);
++
++        area->priv->last_press_x = -1;
++        area->priv->last_press_y = -1;
++        area->priv->active_region = OUTSIDE;
++
++        gtk_widget_queue_draw_area (widget,
++                                    crop.x - 1, crop.y - 1,
++                                    crop.width + 2, crop.height + 2);
++
++        return FALSE;
++}
++
++static void
++cc_crop_area_finalize (GObject *object)
++{
++        CcCropArea *area = CC_CROP_AREA (object);
++
++        if (area->priv->browse_pixbuf) {
++                g_object_unref (area->priv->browse_pixbuf);
++                area->priv->browse_pixbuf = NULL;
++        }
++        if (area->priv->pixbuf) {
++                g_object_unref (area->priv->pixbuf);
++                area->priv->pixbuf = NULL;
++        }
++        if (area->priv->color_shifted) {
++                g_object_unref (area->priv->color_shifted);
++                area->priv->color_shifted = NULL;
++        }
++}
++
++static void
++cc_crop_area_class_init (CcCropAreaClass *klass)
++{
++        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
++        GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
++
++        object_class->finalize = cc_crop_area_finalize;
++        widget_class->draw = cc_crop_area_draw;
++        widget_class->button_press_event = cc_crop_area_button_press_event;
++        widget_class->button_release_event = cc_crop_area_button_release_event;
++        widget_class->motion_notify_event = cc_crop_area_motion_notify_event;
++
++        g_type_class_add_private (klass, sizeof (CcCropAreaPrivate));
++}
++
++static void
++cc_crop_area_init (CcCropArea *area)
++{
++        area->priv = (G_TYPE_INSTANCE_GET_PRIVATE ((area), CC_TYPE_CROP_AREA,
++                                                   CcCropAreaPrivate));
++
++        gtk_widget_add_events (GTK_WIDGET (area), GDK_POINTER_MOTION_MASK |
++                               GDK_BUTTON_PRESS_MASK |
++                               GDK_BUTTON_RELEASE_MASK);
++
++        area->priv->scale = 0.0;
++        area->priv->image.x = 0;
++        area->priv->image.y = 0;
++        area->priv->image.width = 0;
++        area->priv->image.height = 0;
++        area->priv->active_region = OUTSIDE;
++        area->priv->base_width = 48;
++        area->priv->base_height = 48;
++        area->priv->aspect = 1;
++}
++
++GtkWidget *
++cc_crop_area_new (void)
++{
++        return g_object_new (CC_TYPE_CROP_AREA, NULL);
++}
++
++GdkPixbuf *
++cc_crop_area_get_picture (CcCropArea *area)
++{
++        gint width, height;
++
++        width = gdk_pixbuf_get_width (area->priv->browse_pixbuf);
++        height = gdk_pixbuf_get_height (area->priv->browse_pixbuf);
++        width = MIN (area->priv->crop.width, width - area->priv->crop.x);
++        height = MIN (area->priv->crop.height, height - area->priv->crop.y);
++
++        return gdk_pixbuf_new_subpixbuf (area->priv->browse_pixbuf,
++                                         area->priv->crop.x,
++                                         area->priv->crop.y,
++                                         width, height);
++}
++
++void
++cc_crop_area_set_picture (CcCropArea *area,
++                          GdkPixbuf  *pixbuf)
++{
++        int width;
++        int height;
++
++        if (area->priv->browse_pixbuf) {
++                g_object_unref (area->priv->browse_pixbuf);
++                area->priv->browse_pixbuf = NULL;
++        }
++        if (pixbuf) {
++                area->priv->browse_pixbuf = g_object_ref (pixbuf);
++                width = gdk_pixbuf_get_width (pixbuf);
++                height = gdk_pixbuf_get_height (pixbuf);
++        } else {
++                width = 0;
++                height = 0;
++        }
++
++        area->priv->crop.width = 2 * area->priv->base_width;
++        area->priv->crop.height = 2 * area->priv->base_height;
++        area->priv->crop.x = (width - area->priv->crop.width) / 2;
++        area->priv->crop.y = (height - area->priv->crop.height) / 2;
++
++        area->priv->scale = 0.0;
++        area->priv->image.x = 0;
++        area->priv->image.y = 0;
++        area->priv->image.width = 0;
++        area->priv->image.height = 0;
++
++        gtk_widget_queue_draw (GTK_WIDGET (area));
++}
++
++void
++cc_crop_area_set_min_size (CcCropArea *area,
++                           gint        width,
++                           gint        height)
++{
++        area->priv->base_width = width;
++        area->priv->base_height = height;
++
++        if (area->priv->aspect > 0) {
++                area->priv->aspect = area->priv->base_width / (gdouble)area->priv->base_height;
++        }
++}
++
++void
++cc_crop_area_set_constrain_aspect (CcCropArea *area,
++                                   gboolean    constrain)
++{
++        if (constrain) {
++                area->priv->aspect = area->priv->base_width / (gdouble)area->priv->base_height;
++        }
++        else {
++                area->priv->aspect = -1;
++        }
++}
++
+diff --git a/panels/user-accounts/cc-crop-area.h b/panels/user-accounts/cc-crop-area.h
+new file mode 100644
+index 0000000..38657c6
+--- /dev/null
++++ b/panels/user-accounts/cc-crop-area.h
+@@ -0,0 +1,65 @@
++/*
++ * Copyright © 2009 Bastien Nocera <hadess at hadess.net>
++ *
++ * Licensed under the GNU General Public License Version 2
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef _CC_CROP_AREA_H_
++#define _CC_CROP_AREA_H_
++
++#include <glib-object.h>
++#include <gtk/gtk.h>
++
++G_BEGIN_DECLS
++
++#define CC_TYPE_CROP_AREA (cc_crop_area_get_type ())
++#define CC_CROP_AREA(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), CC_TYPE_CROP_AREA, \
++                                                                           CcCropArea))
++#define CC_CROP_AREA_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), CC_TYPE_CROP_AREA, \
++                                                                        CcCropAreaClass))
++#define CC_IS_CROP_AREA(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CC_TYPE_CROP_AREA))
++#define CC_IS_CROP_AREA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CC_TYPE_CROP_AREA))
++#define CC_CROP_AREA_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), CC_TYPE_CROP_AREA, \
++                                                                          CcCropAreaClass))
++
++typedef struct _CcCropAreaClass CcCropAreaClass;
++typedef struct _CcCropArea CcCropArea;
++typedef struct _CcCropAreaPrivate CcCropAreaPrivate;
++
++struct _CcCropAreaClass {
++        GtkDrawingAreaClass parent_class;
++};
++
++struct _CcCropArea {
++        GtkDrawingArea parent_instance;
++        CcCropAreaPrivate *priv;
++};
++
++GType      cc_crop_area_get_type             (void) G_GNUC_CONST;
++
++GtkWidget *cc_crop_area_new                  (void);
++GdkPixbuf *cc_crop_area_get_picture          (CcCropArea *area);
++void       cc_crop_area_set_picture          (CcCropArea *area,
++                                              GdkPixbuf  *pixbuf);
++void       cc_crop_area_set_min_size         (CcCropArea *area,
++                                              gint        width,
++                                              gint        height);
++void       cc_crop_area_set_constrain_aspect (CcCropArea *area,
++                                              gboolean    constrain);
++
++G_END_DECLS
++
++#endif /* _CC_CROP_AREA_H_ */
+diff --git a/panels/user-accounts/um-crop-area.c b/panels/user-accounts/um-crop-area.c
+deleted file mode 100644
+index 2f2461c..0000000
+--- a/panels/user-accounts/um-crop-area.c
++++ /dev/null
+@@ -1,817 +0,0 @@
+-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+- *
+- * Copyright 2009  Red Hat, Inc,
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+- *
+- * Written by: Matthias Clasen <mclasen at redhat.com>
+- */
+-
+-#include "config.h"
+-
+-#include <stdlib.h>
+-
+-#include <glib.h>
+-#include <glib/gi18n.h>
+-#include <gtk/gtk.h>
+-
+-#include "um-crop-area.h"
+-
+-struct _UmCropAreaPrivate {
+-        GdkPixbuf *browse_pixbuf;
+-        GdkPixbuf *pixbuf;
+-        GdkPixbuf *color_shifted;
+-        gdouble scale;
+-        GdkRectangle image;
+-        GdkCursorType current_cursor;
+-        GdkRectangle crop;
+-        gint active_region;
+-        gint last_press_x;
+-        gint last_press_y;
+-        gint base_width;
+-        gint base_height;
+-        gdouble aspect;
+-};
+-
+-G_DEFINE_TYPE (UmCropArea, um_crop_area, GTK_TYPE_DRAWING_AREA);
+-
+-static inline guchar
+-shift_color_byte (guchar b,
+-                  int    shift)
+-{
+-        return CLAMP(b + shift, 0, 255);
+-}
+-
+-static void
+-shift_colors (GdkPixbuf *pixbuf,
+-              gint       red,
+-              gint       green,
+-              gint       blue,
+-              gint       alpha)
+-{
+-        gint x, y, offset, y_offset, rowstride, width, height;
+-        guchar *pixels;
+-        gint channels;
+-
+-        width = gdk_pixbuf_get_width (pixbuf);
+-        height = gdk_pixbuf_get_height (pixbuf);
+-        rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+-        pixels = gdk_pixbuf_get_pixels (pixbuf);
+-        channels = gdk_pixbuf_get_n_channels (pixbuf);
+-
+-        for (y = 0; y < height; y++) {
+-                y_offset = y * rowstride;
+-                for (x = 0; x < width; x++) {
+-                        offset = y_offset + x * channels;
+-                        if (red != 0)
+-                                pixels[offset] = shift_color_byte (pixels[offset], red);
+-                        if (green != 0)
+-                                pixels[offset + 1] = shift_color_byte (pixels[offset + 1], green);
+-                        if (blue != 0)
+-                                pixels[offset + 2] = shift_color_byte (pixels[offset + 2], blue);
+-                        if (alpha != 0 && channels >= 4)
+-                                pixels[offset + 3] = shift_color_byte (pixels[offset + 3], blue);
+-                }
+-        }
+-}
+-
+-static void
+-update_pixbufs (UmCropArea *area)
+-{
+-        gint width;
+-        gint height;
+-        GtkAllocation allocation;
+-        gdouble scale;
+-        GdkRGBA color;
+-        guint32 pixel;
+-        gint dest_x, dest_y, dest_width, dest_height;
+-        GtkWidget *widget;
+-        GtkStyleContext *context;
+-
+-        widget = GTK_WIDGET (area);
+-        gtk_widget_get_allocation (widget, &allocation);
+-        context = gtk_widget_get_style_context (widget);
+-
+-        if (area->priv->pixbuf == NULL ||
+-            gdk_pixbuf_get_width (area->priv->pixbuf) != allocation.width ||
+-            gdk_pixbuf_get_height (area->priv->pixbuf) != allocation.height) {
+-                if (area->priv->pixbuf != NULL)
+-                        g_object_unref (area->priv->pixbuf);
+-                area->priv->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
+-                                                     gdk_pixbuf_get_has_alpha (area->priv->browse_pixbuf),
+-                                                     8,
+-                                                     allocation.width, allocation.height);
+-
+-                gtk_style_context_get_background_color (context, gtk_style_context_get_state (context), &color);
+-                pixel = (((gint)(color.red * 1.0)) << 16) |
+-                        (((gint)(color.green * 1.0)) << 8) |
+-                         ((gint)(color.blue * 1.0));
+-                gdk_pixbuf_fill (area->priv->pixbuf, pixel);
+-
+-                width = gdk_pixbuf_get_width (area->priv->browse_pixbuf);
+-                height = gdk_pixbuf_get_height (area->priv->browse_pixbuf);
+-
+-                scale = allocation.height / (gdouble)height;
+-                if (scale * width > allocation.width)
+-                    scale = allocation.width / (gdouble)width;
+-
+-                dest_width = width * scale;
+-                dest_height = height * scale;
+-                dest_x = (allocation.width - dest_width) / 2;
+-                dest_y = (allocation.height - dest_height) / 2,
+-
+-                gdk_pixbuf_scale (area->priv->browse_pixbuf,
+-                                  area->priv->pixbuf,
+-                                  dest_x, dest_y,
+-                                  dest_width, dest_height,
+-                                  dest_x, dest_y,
+-                                  scale, scale,
+-                                  GDK_INTERP_BILINEAR);
+-
+-                if (area->priv->color_shifted)
+-                        g_object_unref (area->priv->color_shifted);
+-                area->priv->color_shifted = gdk_pixbuf_copy (area->priv->pixbuf);
+-                shift_colors (area->priv->color_shifted, -32, -32, -32, 0);
+-
+-                if (area->priv->scale == 0.0) {
+-                        area->priv->crop.width = 2 * area->priv->base_width / scale;
+-                        area->priv->crop.height = 2 * area->priv->base_height / scale;
+-                        area->priv->crop.x = (gdk_pixbuf_get_width (area->priv->browse_pixbuf) - area->priv->crop.width) / 2;
+-                        area->priv->crop.y = (gdk_pixbuf_get_height (area->priv->browse_pixbuf) - area->priv->crop.height) / 2;
+-                }
+-
+-                area->priv->scale = scale;
+-                area->priv->image.x = dest_x;
+-                area->priv->image.y = dest_y;
+-                area->priv->image.width = dest_width;
+-                area->priv->image.height = dest_height;
+-        }
+-}
+-
+-static void
+-crop_to_widget (UmCropArea    *area,
+-                GdkRectangle  *crop)
+-{
+-        crop->x = area->priv->image.x + area->priv->crop.x * area->priv->scale;
+-        crop->y = area->priv->image.y + area->priv->crop.y * area->priv->scale;
+-        crop->width = area->priv->crop.width * area->priv->scale;
+-        crop->height = area->priv->crop.height * area->priv->scale;
+-}
+-
+-typedef enum {
+-        OUTSIDE,
+-        INSIDE,
+-        TOP,
+-        TOP_LEFT,
+-        TOP_RIGHT,
+-        BOTTOM,
+-        BOTTOM_LEFT,
+-        BOTTOM_RIGHT,
+-        LEFT,
+-        RIGHT
+-} Location;
+-
+-static gboolean
+-um_crop_area_draw (GtkWidget *widget,
+-                   cairo_t   *cr)
+-{
+-        GdkRectangle crop;
+-        gint width, height;
+-        UmCropArea *uarea = UM_CROP_AREA (widget);
+-
+-        if (uarea->priv->browse_pixbuf == NULL)
+-                return FALSE;
+-
+-        update_pixbufs (uarea);
+-
+-        width = gdk_pixbuf_get_width (uarea->priv->pixbuf);
+-        height = gdk_pixbuf_get_height (uarea->priv->pixbuf);
+-        crop_to_widget (uarea, &crop);
+-
+-        gdk_cairo_set_source_pixbuf (cr, uarea->priv->color_shifted, 0, 0);
+-        cairo_rectangle (cr, 0, 0, width, crop.y);
+-        cairo_rectangle (cr, 0, crop.y, crop.x, crop.height);
+-        cairo_rectangle (cr, crop.x + crop.width, crop.y, width - crop.x - crop.width, crop.height);
+-        cairo_rectangle (cr, 0, crop.y + crop.height, width, height - crop.y - crop.height);
+-        cairo_fill (cr);
+-
+-        gdk_cairo_set_source_pixbuf (cr, uarea->priv->pixbuf, 0, 0);
+-        cairo_rectangle (cr, crop.x, crop.y, crop.width, crop.height);
+-        cairo_fill (cr);
+-
+-        if (uarea->priv->active_region != OUTSIDE) {
+-                gint x1, x2, y1, y2;
+-                cairo_set_source_rgb (cr, 1, 1, 1);
+-                cairo_set_line_width (cr, 1.0);
+-                x1 = crop.x + crop.width / 3.0;
+-                x2 = crop.x + 2 * crop.width / 3.0;
+-                y1 = crop.y + crop.height / 3.0;
+-                y2 = crop.y + 2 * crop.height / 3.0;
+-
+-                cairo_move_to (cr, x1 + 0.5, crop.y);
+-                cairo_line_to (cr, x1 + 0.5, crop.y + crop.height);
+-
+-                cairo_move_to (cr, x2 + 0.5, crop.y);
+-                cairo_line_to (cr, x2 + 0.5, crop.y + crop.height);
+-
+-                cairo_move_to (cr, crop.x, y1 + 0.5);
+-                cairo_line_to (cr, crop.x + crop.width, y1 + 0.5);
+-
+-                cairo_move_to (cr, crop.x, y2 + 0.5);
+-                cairo_line_to (cr, crop.x + crop.width, y2 + 0.5);
+-                cairo_stroke (cr);
+-        }
+-
+-        cairo_set_source_rgb (cr,  0, 0, 0);
+-        cairo_set_line_width (cr, 1.0);
+-        cairo_rectangle (cr,
+-                         crop.x + 0.5,
+-                         crop.y + 0.5,
+-                         crop.width - 1.0,
+-                         crop.height - 1.0);
+-        cairo_stroke (cr);
+-
+-        cairo_set_source_rgb (cr, 1, 1, 1);
+-        cairo_set_line_width (cr, 2.0);
+-        cairo_rectangle (cr,
+-                         crop.x + 2.0,
+-                         crop.y + 2.0,
+-                         crop.width - 4.0,
+-                         crop.height - 4.0);
+-        cairo_stroke (cr);
+-
+-        return FALSE;
+-}
+-
+-typedef enum {
+-        BELOW,
+-        LOWER,
+-        BETWEEN,
+-        UPPER,
+-        ABOVE
+-} Range;
+-
+-static Range
+-find_range (gint x,
+-            gint min,
+-            gint max)
+-{
+-        gint tolerance = 12;
+-
+-        if (x < min - tolerance)
+-                return BELOW;
+-        if (x <= min + tolerance)
+-                return LOWER;
+-        if (x < max - tolerance)
+-                return BETWEEN;
+-        if (x <= max + tolerance)
+-                return UPPER;
+-        return ABOVE;
+-}
+-
+-static Location
+-find_location (GdkRectangle *rect,
+-               gint          x,
+-               gint          y)
+-{
+-        Range x_range, y_range;
+-        Location location[5][5] = {
+-                { OUTSIDE, OUTSIDE,     OUTSIDE, OUTSIDE,      OUTSIDE },
+-                { OUTSIDE, TOP_LEFT,    TOP,     TOP_RIGHT,    OUTSIDE },
+-                { OUTSIDE, LEFT,        INSIDE,  RIGHT,        OUTSIDE },
+-                { OUTSIDE, BOTTOM_LEFT, BOTTOM,  BOTTOM_RIGHT, OUTSIDE },
+-                { OUTSIDE, OUTSIDE,     OUTSIDE, OUTSIDE,      OUTSIDE }
+-        };
+-
+-        x_range = find_range (x, rect->x, rect->x + rect->width);
+-        y_range = find_range (y, rect->y, rect->y + rect->height);
+-
+-        return location[y_range][x_range];
+-}
+-
+-static void
+-update_cursor (UmCropArea *area,
+-               gint           x,
+-               gint           y)
+-{
+-        gint cursor_type;
+-        GdkRectangle crop;
+-        gint region;
+-
+-        region = area->priv->active_region;
+-        if (region == OUTSIDE) {
+-                crop_to_widget (area, &crop);
+-                region = find_location (&crop, x, y);
+-        }
+-
+-        switch (region) {
+-        case OUTSIDE:
+-                cursor_type = GDK_LEFT_PTR;
+-                break;
+-        case TOP_LEFT:
+-                cursor_type = GDK_TOP_LEFT_CORNER;
+-                break;
+-        case TOP:
+-                cursor_type = GDK_TOP_SIDE;
+-                break;
+-        case TOP_RIGHT:
+-                cursor_type = GDK_TOP_RIGHT_CORNER;
+-                break;
+-        case LEFT:
+-                cursor_type = GDK_LEFT_SIDE;
+-                break;
+-        case INSIDE:
+-                cursor_type = GDK_FLEUR;
+-                break;
+-        case RIGHT:
+-                cursor_type = GDK_RIGHT_SIDE;
+-                break;
+-        case BOTTOM_LEFT:
+-                cursor_type = GDK_BOTTOM_LEFT_CORNER;
+-                break;
+-        case BOTTOM:
+-                cursor_type = GDK_BOTTOM_SIDE;
+-                break;
+-        case BOTTOM_RIGHT:
+-                cursor_type = GDK_BOTTOM_RIGHT_CORNER;
+-                break;
+-	default:
+-		g_assert_not_reached ();
+-        }
+-
+-        if (cursor_type != area->priv->current_cursor) {
+-                GdkCursor *cursor = gdk_cursor_new (cursor_type);
+-                gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (area)), cursor);
+-                g_object_unref (cursor);
+-                area->priv->current_cursor = cursor_type;
+-        }
+-}
+-
+-static int
+-eval_radial_line (gdouble center_x, gdouble center_y,
+-                  gdouble bounds_x, gdouble bounds_y,
+-                  gdouble user_x)
+-{
+-        gdouble decision_slope;
+-        gdouble decision_intercept;
+-
+-        decision_slope = (bounds_y - center_y) / (bounds_x - center_x);
+-        decision_intercept = -(decision_slope * bounds_x);
+-
+-        return (int) (decision_slope * user_x + decision_intercept);
+-}
+-
+-static gboolean
+-um_crop_area_motion_notify_event (GtkWidget      *widget,
+-                                  GdkEventMotion *event)
+-{
+-        UmCropArea *area = UM_CROP_AREA (widget);
+-        gint x, y;
+-        gint delta_x, delta_y;
+-        gint width, height;
+-        gint adj_width, adj_height;
+-        gint pb_width, pb_height;
+-        GdkRectangle damage;
+-        gint left, right, top, bottom;
+-        gdouble new_width, new_height;
+-        gdouble center_x, center_y;
+-        gint min_width, min_height;
+-
+-        if (area->priv->browse_pixbuf == NULL)
+-                return FALSE;
+-
+-        update_cursor (area, event->x, event->y);
+-
+-        crop_to_widget (area, &damage);
+-        gtk_widget_queue_draw_area (widget,
+-                                    damage.x - 1, damage.y - 1,
+-                                    damage.width + 2, damage.height + 2);
+-
+-        pb_width = gdk_pixbuf_get_width (area->priv->browse_pixbuf);
+-        pb_height = gdk_pixbuf_get_height (area->priv->browse_pixbuf);
+-
+-        x = (event->x - area->priv->image.x) / area->priv->scale;
+-        y = (event->y - area->priv->image.y) / area->priv->scale;
+-
+-        delta_x = x - area->priv->last_press_x;
+-        delta_y = y - area->priv->last_press_y;
+-        area->priv->last_press_x = x;
+-        area->priv->last_press_y = y;
+-
+-        left = area->priv->crop.x;
+-        right = area->priv->crop.x + area->priv->crop.width - 1;
+-        top = area->priv->crop.y;
+-        bottom = area->priv->crop.y + area->priv->crop.height - 1;
+-
+-        center_x = (left + right) / 2.0;
+-        center_y = (top + bottom) / 2.0;
+-
+-        switch (area->priv->active_region) {
+-        case INSIDE:
+-                width = right - left + 1;
+-                height = bottom - top + 1;
+-
+-                left += delta_x;
+-                right += delta_x;
+-                top += delta_y;
+-                bottom += delta_y;
+-
+-                if (left < 0)
+-                        left = 0;
+-                if (top < 0)
+-                        top = 0;
+-                if (right > pb_width)
+-                        right = pb_width;
+-                if (bottom > pb_height)
+-                        bottom = pb_height;
+-
+-                adj_width = right - left + 1;
+-                adj_height = bottom - top + 1;
+-                if (adj_width != width) {
+-                        if (delta_x < 0)
+-                                right = left + width - 1;
+-                        else
+-                                left = right - width + 1;
+-                }
+-                if (adj_height != height) {
+-                        if (delta_y < 0)
+-                                bottom = top + height - 1;
+-                        else
+-                                top = bottom - height + 1;
+-                }
+-
+-                break;
+-
+-        case TOP_LEFT:
+-                if (area->priv->aspect < 0) {
+-                        top = y;
+-                        left = x;
+-                }
+-                else if (y < eval_radial_line (center_x, center_y, left, top, x)) {
+-                        top = y;
+-                        new_width = (bottom - top) * area->priv->aspect;
+-                        left = right - new_width;
+-                }
+-                else {
+-                        left = x;
+-                        new_height = (right - left) / area->priv->aspect;
+-                        top = bottom - new_height;
+-                }
+-                break;
+-
+-        case TOP:
+-                top = y;
+-                if (area->priv->aspect > 0) {
+-                        new_width = (bottom - top) * area->priv->aspect;
+-                        right = left + new_width;
+-                }
+-                break;
+-
+-        case TOP_RIGHT:
+-                if (area->priv->aspect < 0) {
+-                        top = y;
+-                        right = x;
+-                }
+-                else if (y < eval_radial_line (center_x, center_y, right, top, x)) {
+-                        top = y;
+-                        new_width = (bottom - top) * area->priv->aspect;
+-                        right = left + new_width;
+-                }
+-                else {
+-                        right = x;
+-                        new_height = (right - left) / area->priv->aspect;
+-                        top = bottom - new_height;
+-                }
+-                break;
+-
+-        case LEFT:
+-                left = x;
+-                if (area->priv->aspect > 0) {
+-                        new_height = (right - left) / area->priv->aspect;
+-                        bottom = top + new_height;
+-                }
+-                break;
+-
+-        case BOTTOM_LEFT:
+-                if (area->priv->aspect < 0) {
+-                        bottom = y;
+-                        left = x;
+-                }
+-                else if (y < eval_radial_line (center_x, center_y, left, bottom, x)) {
+-                        left = x;
+-                        new_height = (right - left) / area->priv->aspect;
+-                        bottom = top + new_height;
+-                }
+-                else {
+-                        bottom = y;
+-                        new_width = (bottom - top) * area->priv->aspect;
+-                        left = right - new_width;
+-                }
+-                break;
+-
+-        case RIGHT:
+-                right = x;
+-                if (area->priv->aspect > 0) {
+-                        new_height = (right - left) / area->priv->aspect;
+-                        bottom = top + new_height;
+-                }
+-                break;
+-
+-        case BOTTOM_RIGHT:
+-                if (area->priv->aspect < 0) {
+-                        bottom = y;
+-                        right = x;
+-                }
+-                else if (y < eval_radial_line (center_x, center_y, right, bottom, x)) {
+-                        right = x;
+-                        new_height = (right - left) / area->priv->aspect;
+-                        bottom = top + new_height;
+-                }
+-                else {
+-                        bottom = y;
+-                        new_width = (bottom - top) * area->priv->aspect;
+-                        right = left + new_width;
+-                }
+-                break;
+-
+-        case BOTTOM:
+-                bottom = y;
+-                if (area->priv->aspect > 0) {
+-                        new_width = (bottom - top) * area->priv->aspect;
+-                        right= left + new_width;
+-                }
+-                break;
+-
+-        default:
+-                return FALSE;
+-        }
+-
+-        min_width = area->priv->base_width / area->priv->scale;
+-        min_height = area->priv->base_height / area->priv->scale;
+-
+-        width = right - left + 1;
+-        height = bottom - top + 1;
+-        if (area->priv->aspect < 0) {
+-                if (left < 0)
+-                        left = 0;
+-                if (top < 0)
+-                        top = 0;
+-                if (right > pb_width)
+-                        right = pb_width;
+-                if (bottom > pb_height)
+-                        bottom = pb_height;
+-
+-                width = right - left + 1;
+-                height = bottom - top + 1;
+-
+-                switch (area->priv->active_region) {
+-                case LEFT:
+-                case TOP_LEFT:
+-                case BOTTOM_LEFT:
+-                        if (width < min_width)
+-                                left = right - min_width;
+-                        break;
+-                case RIGHT:
+-                case TOP_RIGHT:
+-                case BOTTOM_RIGHT:
+-                        if (width < min_width)
+-                                right = left + min_width;
+-                        break;
+-
+-                default: ;
+-                }
+-
+-                switch (area->priv->active_region) {
+-                case TOP:
+-                case TOP_LEFT:
+-                case TOP_RIGHT:
+-                        if (height < min_height)
+-                                top = bottom - min_height;
+-                        break;
+-                case BOTTOM:
+-                case BOTTOM_LEFT:
+-                case BOTTOM_RIGHT:
+-                        if (height < min_height)
+-                                bottom = top + min_height;
+-                        break;
+-
+-                default: ;
+-                }
+-        }
+-        else {
+-                if (left < 0 || top < 0 ||
+-                    right > pb_width || bottom > pb_height ||
+-                    width < min_width || height < min_height) {
+-                        left = area->priv->crop.x;
+-                        right = area->priv->crop.x + area->priv->crop.width - 1;
+-                        top = area->priv->crop.y;
+-                        bottom = area->priv->crop.y + area->priv->crop.height - 1;
+-                }
+-        }
+-
+-        area->priv->crop.x = left;
+-        area->priv->crop.y = top;
+-        area->priv->crop.width = right - left + 1;
+-        area->priv->crop.height = bottom - top + 1;
+-
+-        crop_to_widget (area, &damage);
+-        gtk_widget_queue_draw_area (widget,
+-                                    damage.x - 1, damage.y - 1,
+-                                    damage.width + 2, damage.height + 2);
+-
+-        return FALSE;
+-}
+-
+-static gboolean
+-um_crop_area_button_press_event (GtkWidget      *widget,
+-                                 GdkEventButton *event)
+-{
+-        UmCropArea *area = UM_CROP_AREA (widget);
+-        GdkRectangle crop;
+-
+-        if (area->priv->browse_pixbuf == NULL)
+-                return FALSE;
+-
+-        crop_to_widget (area, &crop);
+-
+-        area->priv->last_press_x = (event->x - area->priv->image.x) / area->priv->scale;
+-        area->priv->last_press_y = (event->y - area->priv->image.y) / area->priv->scale;
+-        area->priv->active_region = find_location (&crop, event->x, event->y);
+-
+-        gtk_widget_queue_draw_area (widget,
+-                                    crop.x - 1, crop.y - 1,
+-                                    crop.width + 2, crop.height + 2);
+-
+-        return FALSE;
+-}
+-
+-static gboolean
+-um_crop_area_button_release_event (GtkWidget      *widget,
+-                                   GdkEventButton *event)
+-{
+-        UmCropArea *area = UM_CROP_AREA (widget);
+-        GdkRectangle crop;
+-
+-        if (area->priv->browse_pixbuf == NULL)
+-                return FALSE;
+-
+-        crop_to_widget (area, &crop);
+-
+-        area->priv->last_press_x = -1;
+-        area->priv->last_press_y = -1;
+-        area->priv->active_region = OUTSIDE;
+-
+-        gtk_widget_queue_draw_area (widget,
+-                                    crop.x - 1, crop.y - 1,
+-                                    crop.width + 2, crop.height + 2);
+-
+-        return FALSE;
+-}
+-
+-static void
+-um_crop_area_finalize (GObject *object)
+-{
+-        UmCropArea *area = UM_CROP_AREA (object);
+-
+-        if (area->priv->browse_pixbuf) {
+-                g_object_unref (area->priv->browse_pixbuf);
+-                area->priv->browse_pixbuf = NULL;
+-        }
+-        if (area->priv->pixbuf) {
+-                g_object_unref (area->priv->pixbuf);
+-                area->priv->pixbuf = NULL;
+-        }
+-        if (area->priv->color_shifted) {
+-                g_object_unref (area->priv->color_shifted);
+-                area->priv->color_shifted = NULL;
+-        }
+-}
+-
+-static void
+-um_crop_area_class_init (UmCropAreaClass *klass)
+-{
+-        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
+-        GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+-
+-        object_class->finalize = um_crop_area_finalize;
+-        widget_class->draw = um_crop_area_draw;
+-        widget_class->button_press_event = um_crop_area_button_press_event;
+-        widget_class->button_release_event = um_crop_area_button_release_event;
+-        widget_class->motion_notify_event = um_crop_area_motion_notify_event;
+-
+-        g_type_class_add_private (klass, sizeof (UmCropAreaPrivate));
+-}
+-
+-static void
+-um_crop_area_init (UmCropArea *area)
+-{
+-        area->priv = (G_TYPE_INSTANCE_GET_PRIVATE ((area), UM_TYPE_CROP_AREA,
+-                                                   UmCropAreaPrivate));
+-
+-        gtk_widget_add_events (GTK_WIDGET (area), GDK_POINTER_MOTION_MASK |
+-                               GDK_BUTTON_PRESS_MASK |
+-                               GDK_BUTTON_RELEASE_MASK);
+-
+-        area->priv->scale = 0.0;
+-        area->priv->image.x = 0;
+-        area->priv->image.y = 0;
+-        area->priv->image.width = 0;
+-        area->priv->image.height = 0;
+-        area->priv->active_region = OUTSIDE;
+-        area->priv->base_width = 48;
+-        area->priv->base_height = 48;
+-        area->priv->aspect = 1;
+-}
+-
+-GtkWidget *
+-um_crop_area_new (void)
+-{
+-        return g_object_new (UM_TYPE_CROP_AREA, NULL);
+-}
+-
+-GdkPixbuf *
+-um_crop_area_get_picture (UmCropArea *area)
+-{
+-        gint width, height;
+-
+-        width = gdk_pixbuf_get_width (area->priv->browse_pixbuf);
+-        height = gdk_pixbuf_get_height (area->priv->browse_pixbuf);
+-        width = MIN (area->priv->crop.width, width - area->priv->crop.x);
+-        height = MIN (area->priv->crop.height, height - area->priv->crop.y);
+-
+-        return gdk_pixbuf_new_subpixbuf (area->priv->browse_pixbuf,
+-                                         area->priv->crop.x,
+-                                         area->priv->crop.y,
+-                                         width, height);
+-}
+-
+-void
+-um_crop_area_set_picture (UmCropArea *area,
+-                          GdkPixbuf  *pixbuf)
+-{
+-        int width;
+-        int height;
+-
+-        if (area->priv->browse_pixbuf) {
+-                g_object_unref (area->priv->browse_pixbuf);
+-                area->priv->browse_pixbuf = NULL;
+-        }
+-        if (pixbuf) {
+-                area->priv->browse_pixbuf = g_object_ref (pixbuf);
+-                width = gdk_pixbuf_get_width (pixbuf);
+-                height = gdk_pixbuf_get_height (pixbuf);
+-        } else {
+-                width = 0;
+-                height = 0;
+-        }
+-
+-        area->priv->crop.width = 2 * area->priv->base_width;
+-        area->priv->crop.height = 2 * area->priv->base_height;
+-        area->priv->crop.x = (width - area->priv->crop.width) / 2;
+-        area->priv->crop.y = (height - area->priv->crop.height) / 2;
+-
+-        area->priv->scale = 0.0;
+-        area->priv->image.x = 0;
+-        area->priv->image.y = 0;
+-        area->priv->image.width = 0;
+-        area->priv->image.height = 0;
+-
+-        gtk_widget_queue_draw (GTK_WIDGET (area));
+-}
+-
+-void
+-um_crop_area_set_min_size (UmCropArea *area,
+-                           gint        width,
+-                           gint        height)
+-{
+-        area->priv->base_width = width;
+-        area->priv->base_height = height;
+-
+-        if (area->priv->aspect > 0) {
+-                area->priv->aspect = area->priv->base_width / (gdouble)area->priv->base_height;
+-        }
+-}
+-
+-void
+-um_crop_area_set_constrain_aspect (UmCropArea *area,
+-                                   gboolean    constrain)
+-{
+-        if (constrain) {
+-                area->priv->aspect = area->priv->base_width / (gdouble)area->priv->base_height;
+-        }
+-        else {
+-                area->priv->aspect = -1;
+-        }
+-}
+-
+diff --git a/panels/user-accounts/um-crop-area.h b/panels/user-accounts/um-crop-area.h
+deleted file mode 100644
+index 8992957..0000000
+--- a/panels/user-accounts/um-crop-area.h
++++ /dev/null
+@@ -1,65 +0,0 @@
+-/*
+- * Copyright © 2009 Bastien Nocera <hadess at hadess.net>
+- *
+- * Licensed under the GNU General Public License Version 2
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+- */
+-
+-#ifndef _UM_CROP_AREA_H_
+-#define _UM_CROP_AREA_H_
+-
+-#include <glib-object.h>
+-#include <gtk/gtk.h>
+-
+-G_BEGIN_DECLS
+-
+-#define UM_TYPE_CROP_AREA (um_crop_area_get_type ())
+-#define UM_CROP_AREA(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), UM_TYPE_CROP_AREA, \
+-                                                                           UmCropArea))
+-#define UM_CROP_AREA_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), UM_TYPE_CROP_AREA, \
+-                                                                        UmCropAreaClass))
+-#define UM_IS_CROP_AREA(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UM_TYPE_CROP_AREA))
+-#define UM_IS_CROP_AREA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UM_TYPE_CROP_AREA))
+-#define UM_CROP_AREA_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), UM_TYPE_CROP_AREA, \
+-                                                                          UmCropAreaClass))
+-
+-typedef struct _UmCropAreaClass UmCropAreaClass;
+-typedef struct _UmCropArea UmCropArea;
+-typedef struct _UmCropAreaPrivate UmCropAreaPrivate;
+-
+-struct _UmCropAreaClass {
+-        GtkDrawingAreaClass parent_class;
+-};
+-
+-struct _UmCropArea {
+-        GtkDrawingArea parent_instance;
+-        UmCropAreaPrivate *priv;
+-};
+-
+-GType      um_crop_area_get_type             (void) G_GNUC_CONST;
+-
+-GtkWidget *um_crop_area_new                  (void);
+-GdkPixbuf *um_crop_area_get_picture          (UmCropArea *area);
+-void       um_crop_area_set_picture          (UmCropArea *area,
+-                                              GdkPixbuf  *pixbuf);
+-void       um_crop_area_set_min_size         (UmCropArea *area,
+-                                              gint        width,
+-                                              gint        height);
+-void       um_crop_area_set_constrain_aspect (UmCropArea *area,
+-                                              gboolean    constrain);
+-
+-G_END_DECLS
+-
+-#endif /* _UM_CROP_AREA_H_ */
+diff --git a/panels/user-accounts/um-photo-dialog.c b/panels/user-accounts/um-photo-dialog.c
+index 13fa8e7..31205c8 100644
+--- a/panels/user-accounts/um-photo-dialog.c
++++ b/panels/user-accounts/um-photo-dialog.c
+@@ -36,7 +36,7 @@
+ #endif /* HAVE_CHEESE */
+ 
+ #include "um-photo-dialog.h"
+-#include "um-crop-area.h"
++#include "cc-crop-area.h"
+ #include "um-utils.h"
+ 
+ #define ROW_SPAN 6
+@@ -70,7 +70,7 @@ crop_dialog_response (GtkWidget     *dialog,
+                 return;
+         }
+ 
+-        pb = um_crop_area_get_picture (UM_CROP_AREA (um->crop_area));
++        pb = cc_crop_area_get_picture (CC_CROP_AREA (um->crop_area));
+         pb2 = gdk_pixbuf_scale_simple (pb, 96, 96, GDK_INTERP_BILINEAR);
+ 
+         set_user_icon_data (um->user, pb2);
+@@ -105,10 +105,10 @@ um_photo_dialog_crop (UmPhotoDialog *um,
+                           G_CALLBACK (crop_dialog_response), um);
+ 
+         /* Content */
+-        um->crop_area           = um_crop_area_new ();
+-        um_crop_area_set_min_size (UM_CROP_AREA (um->crop_area), 48, 48);
+-        um_crop_area_set_constrain_aspect (UM_CROP_AREA (um->crop_area), TRUE);
+-        um_crop_area_set_picture (UM_CROP_AREA (um->crop_area), pixbuf);
++        um->crop_area           = cc_crop_area_new ();
++        cc_crop_area_set_min_size (CC_CROP_AREA (um->crop_area), 48, 48);
++        cc_crop_area_set_constrain_aspect (CC_CROP_AREA (um->crop_area), TRUE);
++        cc_crop_area_set_picture (CC_CROP_AREA (um->crop_area), pixbuf);
+         frame                   = gtk_frame_new (NULL);
+         gtk_container_add (GTK_CONTAINER (frame), um->crop_area);
+         gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
+-- 
+2.1.0
+
diff --git a/control-center.spec b/control-center.spec
index 273120f..ef1822e 100644
--- a/control-center.spec
+++ b/control-center.spec
@@ -10,7 +10,7 @@
 Summary: Utilities to configure the GNOME desktop
 Name: control-center
 Version: 3.14.1
-Release: 1%{?dist}
+Release: 2%{?dist}
 Epoch: 1
 License: GPLv2+ and GFDL
 #VCS: git:git://git.gnome.org/gnome-control-center
@@ -19,6 +19,9 @@ URL: http://www.gnome.org
 
 # https://bugzilla.gnome.org/show_bug.cgi?id=695691
 Patch0: distro-logo.patch
+# Fix symbol collision with cheese,
+# https://bugzilla.gnome.org/show_bug.cgi?id=697039#c13
+Patch1: 0001-user-accounts-Rename-UmCropArea-to-CcCropArea.patch
 
 Requires: gnome-settings-daemon >= %{gsd_version}
 Requires: alsa-lib
@@ -90,6 +93,8 @@ BuildRequires: grilo-devel
 BuildRequires: gnome-bluetooth-devel >= 3.9.3
 BuildRequires: libwacom-devel
 %endif
+# For patch1
+BuildRequires: autoconf automake libtool
 
 Provides: control-center-extra = %{epoch}:%{version}-%{release}
 Obsoletes: control-center-extra < 1:2.30.3-3
@@ -121,8 +126,10 @@ utilities.
 %prep
 %setup -q -n gnome-control-center-%{version}
 %patch0 -p1 -b .distro-logo
+%patch1 -p1
 
 %build
+autoreconf -fi
 %configure \
         --disable-static \
         --disable-update-mimedb \
@@ -204,6 +211,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
 
 
 %changelog
+* Wed Oct 15 2014 Kalev Lember <kalevlember at gmail.com> - 1:3.14.1-2
+- Fix a symbol collision with cheese
+
 * Tue Oct 14 2014 Kalev Lember <kalevlember at gmail.com> - 1:3.14.1-1
 - Update to 3.14.1
 


More information about the scm-commits mailing list