diff --git a/app/actions/filters-actions.c b/app/actions/filters-actions.c
index db6bd0c06e..a1ad0e8025 100644
--- a/app/actions/filters-actions.c
+++ b/app/actions/filters-actions.c
@@ -354,6 +354,11 @@ static const GimpStringActionEntry filters_interactive_actions[] =
"gegl:fattal02",
GIMP_HELP_FILTER_FATTAL_2002 },
+ { "filters-focus-blur", GIMP_ICON_GEGL,
+ NC_("filters-action", "_Focus Blur..."), NULL, NULL,
+ "gegl:focus-blur",
+ GIMP_HELP_FILTER_FOCUS_BLUR },
+
{ "filters-fractal-trace", GIMP_ICON_GEGL,
NC_("filters-action", "_Fractal Trace..."), NULL, NULL,
"gegl:fractal-trace",
@@ -928,6 +933,7 @@ filters_actions_update (GimpActionGroup *group,
SET_SENSITIVE ("filters-erode", writable);
SET_SENSITIVE ("filters-exposure", writable);
SET_SENSITIVE ("filters-fattal-2002", writable);
+ SET_SENSITIVE ("filters-focus-blur", writable);
SET_SENSITIVE ("filters-fractal-trace", writable);
SET_SENSITIVE ("filters-gaussian-blur", writable);
SET_SENSITIVE ("filters-gaussian-blur-selective", writable);
diff --git a/app/propgui/Makefile.am b/app/propgui/Makefile.am
index 9654f45ad2..0f64ee77f8 100644
--- a/app/propgui/Makefile.am
+++ b/app/propgui/Makefile.am
@@ -33,6 +33,8 @@ libapppropgui_a_SOURCES = \
gimppropgui-diffraction-patterns.h \
gimppropgui-eval.c \
gimppropgui-eval.h \
+ gimppropgui-focus-blur.c \
+ gimppropgui-focus-blur.h \
gimppropgui-generic.c \
gimppropgui-generic.h \
gimppropgui-hue-saturation.c \
diff --git a/app/propgui/gimppropgui-focus-blur.c b/app/propgui/gimppropgui-focus-blur.c
new file mode 100644
index 0000000000..fbe2eaa137
--- /dev/null
+++ b/app/propgui/gimppropgui-focus-blur.c
@@ -0,0 +1,163 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
+ *
+ * gimppropgui-focus-blur.c
+ * Copyright (C) 2020 Ell
+ *
+ * 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 3 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 .
+ */
+
+#include "config.h"
+
+#include
+#include
+
+#include "libgimpmath/gimpmath.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "propgui-types.h"
+
+#include "core/gimpcontext.h"
+
+#include "gimppropgui.h"
+#include "gimppropgui-generic.h"
+#include "gimppropgui-focus-blur.h"
+
+#include "gimp-intl.h"
+
+
+static void
+focus_callback (GObject *config,
+ GeglRectangle *area,
+ GimpLimitType type,
+ gdouble x,
+ gdouble y,
+ gdouble radius,
+ gdouble aspect_ratio,
+ gdouble angle,
+ gdouble inner_limit,
+ gdouble midpoint)
+{
+ g_object_set_data_full (G_OBJECT (config), "area",
+ g_memdup (area, sizeof (GeglRectangle)),
+ (GDestroyNotify) g_free);
+
+ g_object_set (config,
+ "shape", type,
+ "x", x / area->width,
+ "y", y / area->height,
+ "radius", 2.0 * radius / area->width,
+ "focus", inner_limit,
+ "midpoint", midpoint,
+ "aspect-ratio", aspect_ratio,
+ "rotation", fmod (
+ fmod (angle * 180.0 / G_PI + 180.0, 360.0) +
+ 360.0,
+ 360.0) - 180.0,
+ NULL);
+}
+
+static void
+config_notify (GObject *config,
+ const GParamSpec *pspec,
+ gpointer set_data)
+{
+ GimpControllerFocusCallback set_func;
+ GeglRectangle *area;
+ GimpLimitType shape;
+ gdouble radius;
+ gdouble focus;
+ gdouble midpoint;
+ gdouble x, y;
+ gdouble aspect_ratio;
+ gdouble rotation;
+
+ set_func = g_object_get_data (G_OBJECT (config), "set-func");
+ area = g_object_get_data (G_OBJECT (config), "area");
+
+ g_object_get (config,
+ "shape", &shape,
+ "radius", &radius,
+ "focus", &focus,
+ "midpoint", &midpoint,
+ "x", &x,
+ "y", &y,
+ "aspect-ratio", &aspect_ratio,
+ "rotation", &rotation,
+ NULL);
+
+ set_func (set_data, area,
+ shape,
+ x * area->width,
+ y * area->height,
+ radius * area->width / 2.0,
+ aspect_ratio,
+ rotation / 180.0 * G_PI,
+ focus,
+ midpoint);
+}
+
+GtkWidget *
+_gimp_prop_gui_new_focus_blur (GObject *config,
+ GParamSpec **param_specs,
+ guint n_param_specs,
+ GeglRectangle *area,
+ GimpContext *context,
+ GimpCreatePickerFunc create_picker_func,
+ GimpCreateControllerFunc create_controller_func,
+ gpointer creator)
+{
+ GtkWidget *vbox;
+
+ g_return_val_if_fail (G_IS_OBJECT (config), NULL);
+ g_return_val_if_fail (param_specs != NULL, NULL);
+ g_return_val_if_fail (n_param_specs > 0, NULL);
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+
+ vbox = _gimp_prop_gui_new_generic (config,
+ param_specs, n_param_specs,
+ area, context,
+ create_picker_func,
+ create_controller_func,
+ creator);
+
+
+ if (create_controller_func)
+ {
+ GCallback set_func;
+ gpointer set_data;
+
+ set_func = create_controller_func (creator,
+ GIMP_CONTROLLER_TYPE_FOCUS,
+ _("Focus Blur: "),
+ (GCallback) focus_callback,
+ config,
+ &set_data);
+
+ g_object_set_data (G_OBJECT (config), "set-func", set_func);
+
+ g_object_set_data_full (G_OBJECT (config), "area",
+ g_memdup (area, sizeof (GeglRectangle)),
+ (GDestroyNotify) g_free);
+
+ config_notify (config, NULL, set_data);
+
+ g_signal_connect (config, "notify",
+ G_CALLBACK (config_notify),
+ set_data);
+ }
+
+ return vbox;
+}
+
diff --git a/app/propgui/gimppropgui-focus-blur.h b/app/propgui/gimppropgui-focus-blur.h
new file mode 100644
index 0000000000..1c0c0c78a1
--- /dev/null
+++ b/app/propgui/gimppropgui-focus-blur.h
@@ -0,0 +1,36 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
+ *
+ * gimppropgui-focus-blur.h
+ * Copyright (C) 2020 Ell
+ *
+ * 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 3 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 __GIMP_PROP_GUI_FOCUS_BLUR_H__
+#define __GIMP_PROP_GUI_FOCUS_BLUR_H__
+
+
+GtkWidget *
+_gimp_prop_gui_new_focus_blur (GObject *config,
+ GParamSpec **param_specs,
+ guint n_param_specs,
+ GeglRectangle *area,
+ GimpContext *context,
+ GimpCreatePickerFunc create_picker_func,
+ GimpCreateControllerFunc create_controller_func,
+ gpointer creator);
+
+
+#endif /* __GIMP_PROP_GUI_FOCUS_BLUR_H__ */
diff --git a/app/propgui/gimppropgui.c b/app/propgui/gimppropgui.c
index 8236731456..b22018a17f 100644
--- a/app/propgui/gimppropgui.c
+++ b/app/propgui/gimppropgui.c
@@ -52,6 +52,7 @@
#include "gimppropgui-convolution-matrix.h"
#include "gimppropgui-diffraction-patterns.h"
#include "gimppropgui-eval.h"
+#include "gimppropgui-focus-blur.h"
#include "gimppropgui-generic.h"
#include "gimppropgui-hue-saturation.h"
#include "gimppropgui-motion-blur-circular.h"
@@ -470,6 +471,8 @@ gui_new_funcs[] =
_gimp_prop_gui_new_channel_mixer },
{ "GimpGegl-gegl-diffraction-patterns-config",
_gimp_prop_gui_new_diffraction_patterns },
+ { "GimpGegl-gegl-focus-blur-config",
+ _gimp_prop_gui_new_focus_blur },
{ "GimpGegl-gegl-motion-blur-circular-config",
_gimp_prop_gui_new_motion_blur_circular },
{ "GimpGegl-gegl-motion-blur-linear-config",
diff --git a/app/propgui/meson.build b/app/propgui/meson.build
index e4b28fa9ed..2e9cc30f5d 100644
--- a/app/propgui/meson.build
+++ b/app/propgui/meson.build
@@ -6,6 +6,7 @@ libapppropgui_sources = [
'gimppropgui-convolution-matrix.c',
'gimppropgui-diffraction-patterns.c',
'gimppropgui-eval.c',
+ 'gimppropgui-focus-blur.c',
'gimppropgui-generic.c',
'gimppropgui-hue-saturation.c',
'gimppropgui-motion-blur-circular.c',
diff --git a/app/sanity.c b/app/sanity.c
index c8f3ab6555..52c20c1959 100644
--- a/app/sanity.c
+++ b/app/sanity.c
@@ -640,6 +640,7 @@ sanity_check_gegl_ops (void)
"gegl:engrave",
"gegl:exposure",
"gegl:fattal02",
+ "gegl:focus-blur",
"gegl:fractal-trace",
"gegl:gaussian-blur",
"gegl:gaussian-blur-selective",
diff --git a/app/tools/gimpgegltool.c b/app/tools/gimpgegltool.c
index 2b5ea9ed8c..ac06797a36 100644
--- a/app/tools/gimpgegltool.c
+++ b/app/tools/gimpgegltool.c
@@ -180,6 +180,7 @@ gimp_gegl_tool_operation_blacklisted (const gchar *name,
"gegl:engrave",
"gegl:exposure",
"gegl:fattal02",
+ "gegl:focus-blur",
"gegl:fractal-trace",
"gegl:gaussian-blur",
"gegl:gaussian-blur-selective",
diff --git a/app/widgets/gimphelp-ids.h b/app/widgets/gimphelp-ids.h
index 065eaa7823..8905afc589 100644
--- a/app/widgets/gimphelp-ids.h
+++ b/app/widgets/gimphelp-ids.h
@@ -379,6 +379,7 @@
#define GIMP_HELP_FILTER_ERODE "gimp-filter-erode"
#define GIMP_HELP_FILTER_EXPOSURE "gimp-filter-exposure"
#define GIMP_HELP_FILTER_FATTAL_2002 "gimp-filter-fattal-2002"
+#define GIMP_HELP_FILTER_FOCUS_BLUR "gimp-filter-focus-blur"
#define GIMP_HELP_FILTER_FRACTAL_TRACE "gimp-filter-fractal-trace"
#define GIMP_HELP_FILTER_GAUSSIAN_BLUR "gimp-filter-gaussian-blur"
#define GIMP_HELP_FILTER_GAUSSIAN_BLUR_SELECTIVE "gimp-filter-gaussian-blur-selective"
diff --git a/menus/image-menu.xml.in b/menus/image-menu.xml.in
index b696bc0bf2..d9f6bbfa43 100644
--- a/menus/image-menu.xml.in
+++ b/menus/image-menu.xml.in
@@ -700,6 +700,7 @@