diff --git a/gnome-control-center-crash-when-date-unavailable.patch b/gnome-control-center-crash-when-date-unavailable.patch new file mode 100644 index 0000000..303ebc6 --- /dev/null +++ b/gnome-control-center-crash-when-date-unavailable.patch @@ -0,0 +1,29 @@ +From 57aab756e9d67d6420bcb651537e45930a257aa2 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Mon, 20 Oct 2014 13:41:21 +0200 +Subject: background: Fix possible crash when date isn't available + +https://bugzilla.gnome.org/show_bug.cgi?id=736475 + +diff --git a/panels/background/bg-pictures-source.c b/panels/background/bg-pictures-source.c +index c165fa3..1dcce19 100644 +--- a/panels/background/bg-pictures-source.c ++++ b/panels/background/bg-pictures-source.c +@@ -571,7 +571,12 @@ add_single_file_from_media (BgPicturesSource *bg_source, + * plugin, GRL_METADATA_KEY_MODIFICATION_DATE is not + */ + mtime = grl_media_get_creation_date (media); +- mtime_unix = g_date_time_to_unix (mtime); ++ if (!mtime) ++ mtime = grl_media_get_modification_date (media); ++ if (mtime) ++ mtime_unix = g_date_time_to_unix (mtime); ++ else ++ mtime_unix = g_get_real_time () / G_USEC_PER_SEC; + + return add_single_file (bg_source, file, content_type, (guint64) mtime_unix, NULL); + } +-- +cgit v0.10.1 + + diff --git a/gnome-control-center-follow-polkit-permissions-for-tz.patch b/gnome-control-center-follow-polkit-permissions-for-tz.patch new file mode 100644 index 0000000..fd0748f --- /dev/null +++ b/gnome-control-center-follow-polkit-permissions-for-tz.patch @@ -0,0 +1,107 @@ +Index: gnome-control-center-3.14.1/panels/datetime/cc-datetime-panel.c +=================================================================== +--- gnome-control-center-3.14.1.orig/panels/datetime/cc-datetime-panel.c ++++ gnome-control-center-3.14.1/panels/datetime/cc-datetime-panel.c +@@ -59,6 +59,7 @@ enum { + #define W(x) (GtkWidget*) gtk_builder_get_object (priv->builder, x) + + #define DATETIME_PERMISSION "org.gnome.controlcenter.datetime.configure" ++#define DATETIME_TZ_PERMISSION "org.freedesktop.timedate1.set-timezone" + + #define CLOCK_SCHEMA "org.gnome.desktop.interface" + #define CLOCK_FORMAT_KEY "clock-format" +@@ -99,6 +100,7 @@ struct _CcDateTimePanelPrivate + GCancellable *cancellable; + + GPermission *permission; ++ GPermission *tz_permission; + }; + + static void update_time (CcDateTimePanel *self); +@@ -133,6 +135,7 @@ cc_date_time_panel_dispose (GObject *obj + g_clear_object (&priv->clock_tracker); + g_clear_object (&priv->dtm); + g_clear_object (&priv->permission); ++ g_clear_object (&priv->tz_permission); + g_clear_object (&priv->clock_settings); + g_clear_object (&priv->datetime_settings); + g_clear_object (&priv->filechooser_settings); +@@ -777,24 +780,24 @@ on_permission_changed (GPermission *perm + gpointer data) + { + CcDateTimePanelPrivate *priv = CC_DATE_TIME_PANEL (data)->priv; +- gboolean allowed, auto_timezone, using_ntp; ++ gboolean allowed, tz_allowed, auto_timezone, using_ntp; + + allowed = (priv->permission == NULL || g_permission_get_allowed (priv->permission)); ++ tz_allowed = (priv->tz_permission == NULL || g_permission_get_allowed (priv->tz_permission)); + using_ntp = gtk_switch_get_active (GTK_SWITCH (W("network_time_switch"))); + auto_timezone = gtk_switch_get_active (GTK_SWITCH (W("auto_timezone_switch"))); + + /* All the widgets but the lock button and the 24h setting */ + gtk_widget_set_sensitive (W("auto-datetime-row"), allowed); +- gtk_widget_set_sensitive (W("auto-timezone-row"), allowed); ++ gtk_widget_set_sensitive (W("auto-timezone-row"), allowed || tz_allowed); + gtk_widget_set_sensitive (W("datetime-button"), allowed && !using_ntp); +- gtk_widget_set_sensitive (W("timezone-button"), allowed && !auto_timezone); ++ gtk_widget_set_sensitive (W("timezone-button"), (allowed || tz_allowed) && !auto_timezone); + + /* Hide the subdialogs if we no longer have permissions */ + if (!allowed) +- { + gtk_widget_hide (GTK_WIDGET (W ("datetime-dialog"))); ++ if (!allowed && !tz_allowed) + gtk_widget_hide (GTK_WIDGET (W ("timezone-dialog"))); +- } + } + + static void +@@ -886,6 +889,25 @@ run_dialog (CcDateTimePanel *self, + } + + static gboolean ++tz_switch_to_row_transform_func (GBinding *binding, ++ const GValue *source_value, ++ GValue *target_value, ++ CcDateTimePanel *self) ++{ ++ CcDateTimePanelPrivate *priv = self->priv; ++ gboolean active; ++ gboolean allowed; ++ ++ active = g_value_get_boolean (source_value); ++ allowed = (priv->permission == NULL || g_permission_get_allowed (priv->permission)) || ++ (priv->tz_permission == NULL || g_permission_get_allowed (priv->tz_permission)); ++ ++ g_value_set_boolean (target_value, !active && allowed); ++ ++ return TRUE; ++} ++ ++static gboolean + switch_to_row_transform_func (GBinding *binding, + const GValue *source_value, + GValue *target_value, +@@ -1241,6 +1263,7 @@ cc_date_time_panel_init (CcDateTimePanel + + /* add the lock button */ + priv->permission = polkit_permission_new_sync (DATETIME_PERMISSION, NULL, NULL, NULL); ++ priv->tz_permission = polkit_permission_new_sync (DATETIME_TZ_PERMISSION, NULL, NULL, NULL); + if (priv->permission != NULL) + { + g_signal_connect (priv->permission, "notify", +@@ -1278,9 +1301,11 @@ cc_date_time_panel_init (CcDateTimePanel + gtk_widget_set_visible (W ("auto-datetime-row"), is_ntp_available (self)); + + /* Timezone settings */ +- bind_switch_to_row (self, +- W ("auto_timezone_switch"), +- W ("timezone-button")); ++ g_object_bind_property_full (W ("auto_timezone_switch"), "active", ++ W ("timezone-button"), "sensitive", ++ G_BINDING_SYNC_CREATE, ++ (GBindingTransformFunc) tz_switch_to_row_transform_func, ++ NULL, self, NULL); + + priv->datetime_settings = g_settings_new (DATETIME_SCHEMA); + g_settings_bind (priv->datetime_settings, AUTO_TIMEZONE_KEY, diff --git a/gnome-control-center-no-country-code-crash.patch b/gnome-control-center-no-country-code-crash.patch new file mode 100644 index 0000000..bda372f --- /dev/null +++ b/gnome-control-center-no-country-code-crash.patch @@ -0,0 +1,50 @@ +From 422166f3206740b98304528fb0974419ac0aeadb Mon Sep 17 00:00:00 2001 +From: Cosimo Cecchi +Date: Mon, 20 Oct 2014 14:52:47 -0700 +Subject: region: don't crash for locales with no country_code + +gnome_parse_locale() can return an empty country_code for some locales, +which we are not taking into account when building the simple_locale +string. + +https://bugzilla.gnome.org/show_bug.cgi?id=738963 + +diff --git a/panels/region/cc-input-chooser.c b/panels/region/cc-input-chooser.c +index bb620f8..26a30a2 100644 +--- a/panels/region/cc-input-chooser.c ++++ b/panels/region/cc-input-chooser.c +@@ -1022,7 +1022,11 @@ get_locale_infos (GtkWidget *chooser) + if (!gnome_parse_locale (*locale, &lang_code, &country_code, NULL, NULL)) + continue; + +- simple_locale = g_strdup_printf ("%s_%s.utf8", lang_code, country_code); ++ if (country_code != NULL) ++ simple_locale = g_strdup_printf ("%s_%s.utf8", lang_code, country_code); ++ else ++ simple_locale = g_strdup_printf ("%s.utf8", lang_code); ++ + if (g_hash_table_contains (priv->locales, simple_locale)) + { + g_free (simple_locale); +@@ -1060,10 +1064,13 @@ get_locale_infos (GtkWidget *chooser) + add_ids_to_set (layouts_with_locale, list); + g_list_free (list); + +- list = gnome_xkb_info_get_layouts_for_country (priv->xkb_info, country_code); +- add_rows_to_table (chooser, info, list, INPUT_SOURCE_TYPE_XKB, id); +- add_ids_to_set (layouts_with_locale, list); +- g_list_free (list); ++ if (country_code != NULL) ++ { ++ list = gnome_xkb_info_get_layouts_for_country (priv->xkb_info, country_code); ++ add_rows_to_table (chooser, info, list, INPUT_SOURCE_TYPE_XKB, id); ++ add_ids_to_set (layouts_with_locale, list); ++ g_list_free (list); ++ } + + g_free (lang_code); + g_free (country_code); +-- +cgit v0.10.1 + + diff --git a/gnome-control-center-user-account-cheese-crash.patch b/gnome-control-center-user-account-cheese-crash.patch new file mode 100644 index 0000000..dc4f9cb --- /dev/null +++ b/gnome-control-center-user-account-cheese-crash.patch @@ -0,0 +1,1858 @@ +From d3c93d92497ba796427245fab266658e6d330086 Mon Sep 17 00:00:00 2001 +From: David King +Date: Wed, 15 Oct 2014 13:40:08 +0100 +Subject: 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 + +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 . ++ * ++ * Written by: Matthias Clasen ++ */ ++ ++#include "config.h" ++ ++#include ++ ++#include ++#include ++#include ++ ++#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 ++ * ++ * 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 . ++ */ ++ ++#ifndef _CC_CROP_AREA_H_ ++#define _CC_CROP_AREA_H_ ++ ++#include ++#include ++ ++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 . +- * +- * Written by: Matthias Clasen +- */ +- +-#include "config.h" +- +-#include +- +-#include +-#include +-#include +- +-#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 +- * +- * 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 . +- */ +- +-#ifndef _UM_CROP_AREA_H_ +-#define _UM_CROP_AREA_H_ +- +-#include +-#include +- +-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); +-- +cgit v0.10.1 + + diff --git a/gnome-control-center.changes b/gnome-control-center.changes index ada9adf..125e277 100644 --- a/gnome-control-center.changes +++ b/gnome-control-center.changes @@ -1,3 +1,21 @@ +------------------------------------------------------------------- +Mon Nov 3 14:55:37 UTC 2014 - badshah400@gmail.com + +- Downgrade cups-pk-helper Requires to Recommends (boo#904047) +- Add gnome-control-center-follow-polkit-permissions-for-tz.patch + to allow timezone changes by user if permitted by polkit + permissions (boo#904058) +- Add patches from upstream for critical issues: + + gnome-control-center-no-country-code-crash.patch: fix + a crash for locales with no country codes (boo#904071, + bgo#738963) + + gnome-control-center-user-account-cheese-crash.patch: + user-account -- do not crash while taking a picture for user + avatar using cheese (boo#904070, bgo#697039) + + gnome-control-center-crash-when-date-unavailable.patch: + background -- do not crash when date is unavailable + (boo#904073, bgo#736475). + ------------------------------------------------------------------- Fri Oct 17 20:34:01 UTC 2014 - dimstar@opensuse.org diff --git a/gnome-control-center.spec b/gnome-control-center.spec index 24b09dd..41cc66c 100644 --- a/gnome-control-center.spec +++ b/gnome-control-center.spec @@ -45,6 +45,14 @@ Patch14: gnome-control-center-system-proxy-configuration.patch Patch15: gcc-private-connection.patch # PATCH-FIX-UPSTREAM gnome-control-center-probe-radius-server-cert.patch bnc#574266 glin@suse.com -- network: Probe the RADIUS server certificate Patch16: gnome-control-center-probe-radius-server-cert.patch +# PATCH-FEATURE-OPENSUSE gnome-control-center-follow-polkit-permissions-for-tz.patch boo#904058 badshah400@gmail.com -- Follow polkit permissions for allowing/locking timezone setting changes +Patch17: gnome-control-center-follow-polkit-permissions-for-tz.patch +# PATCH-FIX-UPSTREAM gnome-control-center-user-account-cheese-crash.patch boo#904070 bgo#697039 badshah400@gmail.com -- user-account: Do not crash while taking a picture for user avatar using cheese, patch taken from upstream git +Patch18: gnome-control-center-user-account-cheese-crash.patch +# PATCH-FIX-UPSTREAM gnome-control-center-crash-when-date-unavailable.patch boo#904073 bgo#736475 badshah400@gmail.com -- background: Do not crash when date is unavailable, patch taken from upstream git +Patch19: gnome-control-center-crash-when-date-unavailable.patch +# PATCH-FIX-UPSTREAM gnome-control-center-no-country-code-crash.patch boo#904071 bgo#738963 badshah400@gmail.com -- region: don't crash for locales with no country_code, patch taken from upstream git +Patch20: gnome-control-center-no-country-code-crash.patch BuildRequires: cups-devel BuildRequires: desktop-file-utils BuildRequires: fdupes @@ -105,7 +113,6 @@ BuildRequires: pkgconfig(xi) >= 1.2 # needed for glxinfo, used by System info panel Requires: Mesa-demo-x # needed for printers panel -Requires: cups-pk-helper Requires: gnome-menus Requires: gnome-settings-daemon # needed for universal access panel @@ -117,6 +124,8 @@ Requires: libgnomekbd Requires: nautilus Recommends: %{name}-lang Recommends: %{name}-user-faces +# cups-pk-helper should only be recommended, rather than a hard Requires, see boo#904047 +Recommends: cups-pk-helper Recommends: dbus(com.intel.dleyna-server) # the printers panel can use the dbus service Recommends: system-config-printer-dbus-service @@ -178,6 +187,10 @@ GNOME control center. %patch1 -p1 %patch15 -p1 %patch16 -p1 +%patch17 -p1 +%patch18 -p1 +%patch19 -p1 +%patch20 -p1 #NEEDS-REBASE #patch14 -p1