diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp
index 8a0540efc2efdfa6a399f2a458161ceaf751f29b..e82e30df8088084ee5c717c83f2afd38681f06e6 100644
--- a/src/gui/kernel/qplatformintegration.cpp
+++ b/src/gui/kernel/qplatformintegration.cpp
@@ -313,6 +313,8 @@ QVariant QPlatformIntegration::styleHint(StyleHint hint) const
         return false;
     case PasswordMaskDelay:
         return QPlatformTheme::defaultThemeHint(QPlatformTheme::PasswordMaskDelay);
+    case PasswordMaskCharacter:
+        return QPlatformTheme::defaultThemeHint(QPlatformTheme::PasswordMaskCharacter);
     case FontSmoothingGamma:
         return qreal(1.7);
     case StartDragVelocity:
diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h
index bee2ba0caf1c033fe06f0305610c486cecde3c80..b7a44b13de2a96001eea8f17b376e39ee4b8074e 100644
--- a/src/gui/kernel/qplatformintegration.h
+++ b/src/gui/kernel/qplatformintegration.h
@@ -140,7 +140,8 @@ public:
         FontSmoothingGamma,
         StartDragVelocity,
         UseRtlExtensions,
-        SynthesizeMouseFromTouchEvents
+        SynthesizeMouseFromTouchEvents,
+        PasswordMaskCharacter
     };
 
     virtual QVariant styleHint(StyleHint hint) const;
diff --git a/src/gui/kernel/qplatformtheme.cpp b/src/gui/kernel/qplatformtheme.cpp
index b8bc72cf735209f162b553c78fde6771e723e86d..02b69bcb4d0f4a3fc14e2dd63edba99c54024528 100644
--- a/src/gui/kernel/qplatformtheme.cpp
+++ b/src/gui/kernel/qplatformtheme.cpp
@@ -238,6 +238,8 @@ QVariant QPlatformTheme::defaultThemeHint(ThemeHint hint)
         return QVariant(500);
     case QPlatformTheme::PasswordMaskDelay:
         return QVariant(int(0));
+    case QPlatformTheme::PasswordMaskCharacter:
+        return QVariant(QChar(0x25CF));
     case QPlatformTheme::StartDragVelocity:
         return QVariant(int(0)); // no limit
     case QPlatformTheme::UseFullScreenForPopupMenu:
diff --git a/src/gui/kernel/qplatformtheme.h b/src/gui/kernel/qplatformtheme.h
index ee12792547151587053b61cf995508c45689f54c..80ba29a028142e3b8e09c2a7d1a1a1414c741ae9 100644
--- a/src/gui/kernel/qplatformtheme.h
+++ b/src/gui/kernel/qplatformtheme.h
@@ -103,7 +103,8 @@ public:
         UiEffects,
         SpellCheckUnderlineStyle,
         TabAllWidgets,
-        IconPixmapSizes
+        IconPixmapSizes,
+        PasswordMaskCharacter
     };
 
     enum DialogType {
diff --git a/src/gui/kernel/qstylehints.cpp b/src/gui/kernel/qstylehints.cpp
index 23bc165edd50964b0bc4de61ba471f30ece856fb..30b12835f712a5667c54a755c7523ca398250e1b 100644
--- a/src/gui/kernel/qstylehints.cpp
+++ b/src/gui/kernel/qstylehints.cpp
@@ -192,6 +192,15 @@ int QStyleHints::passwordMaskDelay() const
     return themeableHint(QPlatformTheme::PasswordMaskDelay, QPlatformIntegration::PasswordMaskDelay).toInt();
 }
 
+/*!
+    Returns the character used to mask the characters typed into text input
+    fields in password mode.
+*/
+QChar QStyleHints::passwordMaskCharacter() const
+{
+    return themeableHint(QPlatformTheme::PasswordMaskCharacter, QPlatformIntegration::PasswordMaskCharacter).toChar();
+}
+
 /*!
     Returns the gamma value used in font smoothing.
 */
diff --git a/src/gui/kernel/qstylehints.h b/src/gui/kernel/qstylehints.h
index 7a447aae677c2b91ad512b388e5a788a86b97b0f..64ef182aabb97374075a0712192c864b763dcb2a 100644
--- a/src/gui/kernel/qstylehints.h
+++ b/src/gui/kernel/qstylehints.h
@@ -62,6 +62,7 @@ public:
     int cursorFlashTime() const;
     bool showIsFullScreen() const;
     int passwordMaskDelay() const;
+    QChar passwordMaskCharacter() const;
     qreal fontSmoothingGamma() const;
     bool useRtlExtensions() const;
 
diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
index 4fc542c39aec5d0d1c4ec4123988f780be4619ff..cabddcc8155f177c0f1163d9f1e3c3cbc1e8a208 100644
--- a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
+++ b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
@@ -448,6 +448,8 @@ QVariant QGnomeTheme::themeHint(QPlatformTheme::ThemeHint hint) const
     }
     case QPlatformTheme::KeyboardScheme:
         return QVariant(int(GnomeKeyboardScheme));
+    case QPlatformTheme::PasswordMaskCharacter:
+        return QVariant(QChar(0x2022));
     default:
         break;
     }
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm
index f8eed0ebf1765cb7039c35a9e3a26edb647600b7..8337e00eb6dc7db30c72679abd421c6ef395b5a4 100644
--- a/src/plugins/platforms/cocoa/qcocoatheme.mm
+++ b/src/plugins/platforms/cocoa/qcocoatheme.mm
@@ -290,6 +290,8 @@ QVariant QCocoaTheme::themeHint(ThemeHint hint) const
         sizes << 16 << 32 << 64 << 128;
         return QVariant::fromValue(sizes);
     }
+    case QPlatformTheme::PasswordMaskDelay:
+        return QVariant(QChar(kBulletUnicode));
     default:
         break;
     }
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp
index f7ae667a8254e26ffdd1f0ae0d5948c2ec9a60bd..c6edbee67d060035ac2741f8be771498a2976e1c 100644
--- a/src/widgets/styles/qcommonstyle.cpp
+++ b/src/widgets/styles/qcommonstyle.cpp
@@ -4905,20 +4905,12 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget
             ret = -1;
         break;
     case SH_LineEdit_PasswordCharacter: {
-        const QFontMetrics &fm = opt ? opt->fontMetrics
-                                     : (widget ? widget->fontMetrics() : QFontMetrics(QFont()));
-        ret = 0;
-        if (fm.inFont(QChar(0x25CF))) {
-            ret = 0x25CF;
-        } else if (fm.inFont(QChar(0x2022))) {
-            ret = 0x2022;
-        } else {
-            ret = '*';
-        }
+        const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
+        const QPlatformTheme::ThemeHint hintType = QPlatformTheme::PasswordMaskCharacter;
+        const QVariant hint = theme ? theme->themeHint(hintType) : QPlatformTheme::defaultThemeHint(hintType);
+        ret = hint.toChar().unicode();
         break;
     }
-
-
     case SH_ToolBox_SelectedPageTitleBold:
         ret = 1;
         break;
diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm
index ed721e06c41af849f282ef5f8a8e12dff7ff7e81..b2bf2c5565663f1e70e88700a2a4eedd6b8cf0e0 100644
--- a/src/widgets/styles/qmacstyle_mac.mm
+++ b/src/widgets/styles/qmacstyle_mac.mm
@@ -2466,9 +2466,6 @@ int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w
     case SH_TabBar_PreferNoArrows:
         ret = true;
         break;
-    case SH_LineEdit_PasswordCharacter:
-        ret = kBulletUnicode;
-        break;
         /*
     case SH_DialogButtons_DefaultButton:
         ret = QDialogButtons::Reject;
diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp
index 86fccabcbcb607373a641c2f105fd66563827d26..0acd6052c8d3e07035d779be3e183f0a65f80231 100644
--- a/src/widgets/styles/qwindowsstyle.cpp
+++ b/src/widgets/styles/qwindowsstyle.cpp
@@ -602,21 +602,6 @@ int QWindowsStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QWid
         }
         break;
 #endif // QT_NO_RUBBERBAND
-    case SH_LineEdit_PasswordCharacter:
-        {
-#ifdef Q_OS_WIN
-            if (widget && (QSysInfo::WindowsVersion >= QSysInfo::WV_XP && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based))) {
-                const QFontMetrics &fm = widget->fontMetrics();
-                if (fm.inFont(QChar(0x25CF)))
-                    ret = 0x25CF;
-                else if (fm.inFont(QChar(0x2022)))
-                    ret = 0x2022;
-            }
-#endif
-            if (!ret)
-                ret = '*';
-        }
-        break;
 #ifndef QT_NO_WIZARD
     case SH_WizardStyle:
         ret = QWizard::ModernStyle;
diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp
index ea58ec1429cbfe5f6101a0580d1a9c68376d50f5..abef6e8832159703c089993fd6170e7d62fea4bf 100644
--- a/src/widgets/widgets/qlineedit.cpp
+++ b/src/widgets/widgets/qlineedit.cpp
@@ -360,9 +360,9 @@ void QLineEdit::setPlaceholderText(const QString& placeholderText)
     \brief the displayed text
 
     If \l echoMode is \l Normal this returns the same as text(); if
-    \l EchoMode is \l Password or \l PasswordEchoOnEdit it returns a string of asterisks
-    text().length() characters long, e.g. "******"; if \l EchoMode is
-    \l NoEcho returns an empty string, "".
+    \l EchoMode is \l Password or \l PasswordEchoOnEdit it returns a string of
+    platform-dependent password mask characters text().length() in size,
+    e.g. "******"; if \l EchoMode is \l NoEcho returns an empty string, "".
 
     By default, this property contains an empty string.
 
@@ -440,10 +440,11 @@ void QLineEdit::setFrame(bool enable)
     \value NoEcho   Do not display anything. This may be appropriate
                     for passwords where even the length of the
                     password should be kept secret.
-    \value Password  Display asterisks instead of the characters
-                    actually entered.
+    \value Password  Display platform-dependent password mask characters instead
+                    of the characters actually entered.
     \value PasswordEchoOnEdit Display characters as they are entered
-                    while editing otherwise display asterisks.
+                    while editing otherwise display characters as with
+                    \c Password.
 
     \sa setEchoMode(), echoMode()
 */