diff --git a/obs/data/locale/en-US.ini b/obs/data/locale/en-US.ini
index b02b75e502b4d18de6051fe470929a6453429b96..9ae037ae948474079334102fb7d6964634ecb6a8 100644
--- a/obs/data/locale/en-US.ini
+++ b/obs/data/locale/en-US.ini
@@ -87,6 +87,7 @@ Basic.SourceSelect.AddExisting="Add Existing"
 # properties window
 Basic.PropertiesWindow="Properties for '%1'"
 Basic.PropertiesWindow.AutoSelectFormat="%1 (unsupported; autoselect: %2)"
+Basic.PropertiesWindow.SelectColor="Select color"
 
 # status bar
 Basic.StatusBar.Reconnecting="Disconnected, reconnecting (attempt %1)"
diff --git a/obs/properties-view.cpp b/obs/properties-view.cpp
index 5133d92e86de114374e40b5648438f0ae05ac2cb..58c665986cb68c3be71ef7b41841fd459310063f 100644
--- a/obs/properties-view.cpp
+++ b/obs/properties-view.cpp
@@ -8,6 +8,7 @@
 #include <QPushButton>
 #include <QStandardItem>
 #include <QFileDialog>
+#include <QColorDialog>
 #include "qt-wrappers.hpp"
 #include "properties-view.hpp"
 #include "obs-app.hpp"
@@ -15,6 +16,27 @@
 
 using namespace std;
 
+static inline QColor color_from_int(long long val)
+{
+	return QColor( val        & 0xff,
+		      (val >>  8) & 0xff,
+		      (val >> 16) & 0xff,
+		      (val >> 24) & 0xff);
+}
+
+static inline long long color_to_int(QColor color)
+{
+	auto shift = [&](unsigned val, int shift)
+	{
+		return ((val & 0xff) << shift);
+	};
+
+	return  shift(color.red(),    0) |
+		shift(color.green(),  8) |
+		shift(color.blue(),  16) |
+		shift(color.alpha(), 24);
+}
+
 void OBSPropertiesView::RefreshProperties()
 {
 	children.clear();
@@ -293,6 +315,37 @@ QWidget *OBSPropertiesView::AddButton(obs_property_t prop)
 	return NewWidget(prop, button, SIGNAL(clicked()));
 }
 
+void OBSPropertiesView::AddColor(obs_property_t prop, QFormLayout *layout,
+		QLabel *&label)
+{
+	QPushButton *button     = new QPushButton;
+	QLabel      *colorLabel = new QLabel;
+	const char  *name       = obs_property_name(prop);
+	long long   val         = obs_data_getint(settings, name);
+	QColor      color       = color_from_int(val);
+
+	button->setText(QTStr("Basic.PropertiesWindow.SelectColor"));
+
+	colorLabel->setFrameStyle(QFrame::Sunken | QFrame::Panel);
+	colorLabel->setText(color.name(QColor::HexArgb));
+	colorLabel->setPalette(QPalette(color));
+	colorLabel->setAutoFillBackground(true);
+	colorLabel->setAlignment(Qt::AlignCenter);
+
+	QHBoxLayout *subLayout = new QHBoxLayout;
+	subLayout->setContentsMargins(0, 0, 0, 0);
+
+	subLayout->addWidget(colorLabel);
+	subLayout->addWidget(button);
+
+	WidgetInfo *info = new WidgetInfo(this, prop, colorLabel);
+	connect(button, SIGNAL(clicked()), info, SLOT(ControlChanged()));
+	children.emplace_back(info);
+
+	label = new QLabel(QT_UTF8(obs_property_description(prop)));
+	layout->addRow(label, subLayout);
+}
+
 void OBSPropertiesView::AddProperty(obs_property_t property,
 		QFormLayout *layout)
 {
@@ -328,7 +381,7 @@ void OBSPropertiesView::AddProperty(obs_property_t property,
 		widget = AddList(property, warning);
 		break;
 	case OBS_PROPERTY_COLOR:
-		/* TODO */
+		AddColor(property, layout, label);
 		break;
 	case OBS_PROPERTY_BUTTON:
 		widget = AddButton(property);
@@ -448,10 +501,35 @@ void WidgetInfo::ListChanged(const char *setting)
 	}
 }
 
-void WidgetInfo::ColorChanged(const char *setting)
+bool WidgetInfo::ColorChanged(const char *setting)
 {
-	/* TODO */
-	UNUSED_PARAMETER(setting);
+	const char *desc = obs_property_description(property);
+	long long  val   = obs_data_getint(view->settings, setting);
+	QColor     color = color_from_int(val);
+
+	QColorDialog::ColorDialogOptions options =
+		QColorDialog::ShowAlphaChannel;
+
+	/* The native dialog on OSX has all kinds of problems, like closing
+	 * other open QDialogs on exit, and
+	 * https://bugreports.qt-project.org/browse/QTBUG-34532
+	 */
+#ifdef __APPLE__
+	options |= QColorDialog::DontUseNativeDialog;
+#endif
+
+	color = QColorDialog::getColor(color, view, QT_UTF8(desc), options);
+
+	if (!color.isValid())
+		return false;
+
+	QLabel *label = static_cast<QLabel*>(widget);
+	label->setText(color.name(QColor::HexArgb));
+	label->setPalette(QPalette(color));
+
+	obs_data_setint(view->settings, setting, color_to_int(color));
+
+	return true;
 }
 
 void WidgetInfo::ButtonClicked()
@@ -471,8 +549,11 @@ void WidgetInfo::ControlChanged()
 	case OBS_PROPERTY_FLOAT:   FloatChanged(setting); break;
 	case OBS_PROPERTY_TEXT:    TextChanged(setting); break;
 	case OBS_PROPERTY_LIST:    ListChanged(setting); break;
-	case OBS_PROPERTY_COLOR:   ColorChanged(setting); break;
 	case OBS_PROPERTY_BUTTON:  ButtonClicked(); return;
+	case OBS_PROPERTY_COLOR:
+		if (!ColorChanged(setting))
+			return;
+		break;
 	case OBS_PROPERTY_PATH:
 		if (!PathChanged(setting))
 			return;
diff --git a/obs/properties-view.hpp b/obs/properties-view.hpp
index 3680076d73b289a9e601fa109b2ef83245e33c2f..eaa7e0f8fd3460700a10fdec6d6e17367bf28d3c 100644
--- a/obs/properties-view.hpp
+++ b/obs/properties-view.hpp
@@ -27,7 +27,7 @@ private:
 	void TextChanged(const char *setting);
 	bool PathChanged(const char *setting);
 	void ListChanged(const char *setting);
-	void ColorChanged(const char *setting);
+	bool ColorChanged(const char *setting);
 	void ButtonClicked();
 
 public:
@@ -68,6 +68,7 @@ private:
 	QWidget *AddFloat(obs_property_t prop);
 	QWidget *AddList(obs_property_t prop, bool &warning);
 	QWidget *AddButton(obs_property_t prop);
+	void AddColor(obs_property_t prop, QFormLayout *layout, QLabel *&label);
 
 	void AddProperty(obs_property_t property, QFormLayout *layout);