[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