diff --git a/flutter/lib/desktop/pages/connection_page.dart b/flutter/lib/desktop/pages/connection_page.dart
index 83e57dba8..a1e87b418 100644
--- a/flutter/lib/desktop/pages/connection_page.dart
+++ b/flutter/lib/desktop/pages/connection_page.dart
@@ -42,7 +42,7 @@ class _ConnectionPageState extends State<ConnectionPage>
   final RxBool _idInputFocused = false.obs;
   final FocusNode _idFocusNode = FocusNode();
 
-  var svcStopped = false.obs;
+  var svcStopped = Get.find<RxBool>(tag: 'stop-service');
   var svcStatusCode = 0.obs;
   var svcIsUsingPublicServer = true.obs;
 
@@ -67,7 +67,6 @@ class _ConnectionPageState extends State<ConnectionPage>
     _idFocusNode.addListener(() {
       _idInputFocused.value = _idFocusNode.hasFocus;
     });
-    Get.put<RxBool>(svcStopped, tag: 'service-stop');
     windowManager.addListener(this);
   }
 
@@ -75,7 +74,6 @@ class _ConnectionPageState extends State<ConnectionPage>
   void dispose() {
     _idController.dispose();
     _updateTimer?.cancel();
-    Get.delete<RxBool>(tag: 'service-stop');
     windowManager.removeListener(this);
     super.dispose();
   }
@@ -296,7 +294,7 @@ class _ConnectionPageState extends State<ConnectionPage>
               // stop
               Offstage(
                 offstage: !svcStopped.value,
-                child: GestureDetector(
+                child: InkWell(
                         onTap: () async {
                           bool checked = !bind.mainIsInstalled() ||
                               await bind.mainCheckSuperUserPermission();
@@ -357,7 +355,6 @@ class _ConnectionPageState extends State<ConnectionPage>
   }
 
   updateStatus() async {
-    svcStopped.value = await bind.mainGetOption(key: "stop-service") == "Y";
     final status =
         jsonDecode(await bind.mainGetConnectStatus()) as Map<String, dynamic>;
     svcStatusCode.value = status["status_num"];
diff --git a/flutter/lib/desktop/pages/desktop_home_page.dart b/flutter/lib/desktop/pages/desktop_home_page.dart
index 4be64eee0..a6d4691ce 100644
--- a/flutter/lib/desktop/pages/desktop_home_page.dart
+++ b/flutter/lib/desktop/pages/desktop_home_page.dart
@@ -40,7 +40,12 @@ class _DesktopHomePageState extends State<DesktopHomePage>
   @override
   bool get wantKeepAlive => true;
   var updateUrl = '';
+  var systemError = '';
   StreamSubscription? _uniLinksSubscription;
+  var svcStopped = false.obs;
+  var watchIsCanScreenRecording = false;
+  var watchIsProcessTrust = false;
+  Timer? _updateTimer;
 
   @override
   Widget build(BuildContext context) {
@@ -317,13 +322,37 @@ class _DesktopHomePageState extends State<DesktopHomePage>
         await launchUrl(url);
       });
     }
-    if (Platform.isMacOS) {}
+    if (systemError.isNotEmpty) {
+      return buildInstallCard("", systemError, "", () {});
+    }
+    if (Platform.isMacOS) {
+      if (!bind.mainIsCanScreenRecording(prompt: false)) {
+        return buildInstallCard("Permissions", "config_screen", "Configure",
+            () async {
+          bind.mainIsCanScreenRecording(prompt: true);
+          watchIsCanScreenRecording = true;
+        }, help: 'Help', link: translate("doc_mac_permission"));
+      } else if (!bind.mainIsProcessTrusted(prompt: false)) {
+        return buildInstallCard("Permissions", "config_acc", "Configure",
+            () async {
+          bind.mainIsProcessTrusted(prompt: true);
+          watchIsProcessTrust = true;
+        }, help: 'Help', link: translate("doc_mac_permission"));
+      } else if (!svcStopped.value &&
+          bind.mainIsInstalled() &&
+          !bind.mainIsInstalledDaemon(prompt: false)) {
+        return buildInstallCard("", "install_daemon_tip", "Install", () async {
+          bind.mainIsInstalledDaemon(prompt: true);
+        });
+      }
+    }
     if (bind.mainIsInstalledLowerVersion()) {}
     return Container();
   }
 
   Widget buildInstallCard(String title, String content, String btnText,
-      GestureTapCallback onPressed) {
+      GestureTapCallback onPressed,
+      {String? help, String? link}) {
     return Container(
       margin: EdgeInsets.only(top: 20),
       child: Container(
@@ -338,44 +367,64 @@ class _DesktopHomePageState extends State<DesktopHomePage>
           )),
           padding: EdgeInsets.all(20),
           child: Column(
-            mainAxisAlignment: MainAxisAlignment.start,
-            crossAxisAlignment: CrossAxisAlignment.start,
-            children: (title.isNotEmpty
-                    ? <Widget>[
-                        Center(
-                            child: Text(
-                          translate(title),
-                          style: TextStyle(
-                              color: Colors.white,
-                              fontWeight: FontWeight.bold,
-                              fontSize: 15),
-                        ).marginOnly(bottom: 6)),
-                      ]
-                    : <Widget>[]) +
-                <Widget>[
-                  Text(
-                    translate(content),
-                    style: TextStyle(
-                        height: 1.5,
-                        color: Colors.white,
-                        fontWeight: FontWeight.normal,
-                        fontSize: 13),
-                  ).marginOnly(bottom: 20),
-                  Row(mainAxisAlignment: MainAxisAlignment.center, children: [
-                    FixedWidthButton(
-                      width: 150,
-                      padding: 8,
-                      isOutline: true,
-                      text: translate(btnText),
-                      textColor: Colors.white,
-                      borderColor: Colors.white,
-                      textSize: 20,
-                      radius: 10,
-                      onTap: onPressed,
-                    )
-                  ]),
-                ],
-          )),
+              mainAxisAlignment: MainAxisAlignment.start,
+              crossAxisAlignment: CrossAxisAlignment.start,
+              children: (title.isNotEmpty
+                      ? <Widget>[
+                          Center(
+                              child: Text(
+                            translate(title),
+                            style: TextStyle(
+                                color: Colors.white,
+                                fontWeight: FontWeight.bold,
+                                fontSize: 15),
+                          ).marginOnly(bottom: 6)),
+                        ]
+                      : <Widget>[]) +
+                  <Widget>[
+                    Text(
+                      translate(content),
+                      style: TextStyle(
+                          height: 1.5,
+                          color: Colors.white,
+                          fontWeight: FontWeight.normal,
+                          fontSize: 13),
+                    ).marginOnly(bottom: 20)
+                  ] +
+                  (btnText.isNotEmpty
+                      ? <Widget>[
+                          Row(
+                              mainAxisAlignment: MainAxisAlignment.center,
+                              children: [
+                                FixedWidthButton(
+                                  width: 150,
+                                  padding: 8,
+                                  isOutline: true,
+                                  text: translate(btnText),
+                                  textColor: Colors.white,
+                                  borderColor: Colors.white,
+                                  textSize: 20,
+                                  radius: 10,
+                                  onTap: onPressed,
+                                )
+                              ])
+                        ]
+                      : <Widget>[]) +
+                  (help != null
+                      ? <Widget>[
+                          Center(
+                              child: InkWell(
+                                  onTap: () async =>
+                                      await launchUrl(Uri.parse(link!)),
+                                  child: Text(
+                                    translate(help),
+                                    style: TextStyle(
+                                        decoration: TextDecoration.underline,
+                                        color: Colors.white,
+                                        fontSize: 12),
+                                  )).marginOnly(top: 6)),
+                        ]
+                      : <Widget>[]))),
     );
   }
 
@@ -412,16 +461,42 @@ class _DesktopHomePageState extends State<DesktopHomePage>
   void initState() {
     super.initState();
     bind.mainStartGrabKeyboard();
-    Timer(const Duration(seconds: 5), () async {
-      updateUrl = await bind.mainGetSoftwareUpdateUrl();
-      if (updateUrl.isNotEmpty) setState(() {});
+    _updateTimer = Timer.periodic(const Duration(seconds: 1), (timer) async {
+      final url = await bind.mainGetSoftwareUpdateUrl();
+      if (updateUrl != url) {
+        updateUrl = url;
+        setState(() {});
+      }
+      final error = await bind.mainGetError();
+      if (systemError != error) {
+        systemError = error;
+        setState(() {});
+      }
+      final v = await bind.mainGetOption(key: "stop-service") == "Y";
+      if (v != svcStopped.value) {
+        svcStopped.value = v;
+        setState(() {});
+      }
+      if (watchIsCanScreenRecording) {
+        if (bind.mainIsCanScreenRecording(prompt: false)) {
+          watchIsCanScreenRecording = false;
+          setState(() {});
+        }
+      }
+      if (watchIsProcessTrust) {
+        if (bind.mainIsProcessTrusted(prompt: false)) {
+          watchIsProcessTrust = false;
+          setState(() {});
+        }
+      }
     });
+    Get.put<RxBool>(svcStopped, tag: 'stop-service');
     // disable this tray because we use tray function provided by rust now
     // initTray();
     trayManager.addListener(this);
     rustDeskWinManager.registerActiveWindowListener(onActiveWindowChanged);
     // main window may be hidden because of the initial uni link or arguments.
-    // note that we must wrap this active window registration in future because 
+    // note that we must wrap this active window registration in future because
     // we must ensure the execution is after `windowManager.hide/show()`.
     Future.delayed(Duration.zero, () {
       windowManager.isVisible().then((visibility) {
@@ -475,6 +550,8 @@ class _DesktopHomePageState extends State<DesktopHomePage>
     // rustDeskWinManager.unregisterActiveWindowListener(onActiveWindowChanged);
     trayManager.removeListener(this);
     _uniLinksSubscription?.cancel();
+    Get.delete<RxBool>(tag: 'stop-service');
+    _updateTimer?.cancel();
     super.dispose();
   }
 }
diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart
index 056b1028b..a51b4d035 100644
--- a/flutter/lib/desktop/pages/desktop_setting_page.dart
+++ b/flutter/lib/desktop/pages/desktop_setting_page.dart
@@ -434,7 +434,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
   bool get wantKeepAlive => true;
   bool locked = bind.mainIsInstalled();
   final scrollController = ScrollController();
-  final RxBool serviceStop = Get.find<RxBool>(tag: 'service-stop');
+  final RxBool serviceStop = Get.find<RxBool>(tag: 'stop-service');
 
   @override
   Widget build(BuildContext context) {
diff --git a/flutter/macos/Runner.xcodeproj/project.pbxproj b/flutter/macos/Runner.xcodeproj/project.pbxproj
index 5f369ea9e..ec4baf141 100644
--- a/flutter/macos/Runner.xcodeproj/project.pbxproj
+++ b/flutter/macos/Runner.xcodeproj/project.pbxproj
@@ -439,7 +439,7 @@
 					"$(inherited)",
 					../../target/profile,
 				);
-				MACOSX_DEPLOYMENT_TARGET = 10.15;
+				MACOSX_DEPLOYMENT_TARGET = 10.14;
 				PRODUCT_BUNDLE_IDENTIFIER = com.carriez.rustdesk;
 				PROVISIONING_PROFILE_SPECIFIER = "";
 				SWIFT_VERSION = 5.0;
@@ -499,7 +499,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				MACOSX_DEPLOYMENT_TARGET = 10.15;
+				MACOSX_DEPLOYMENT_TARGET = 10.14;
 				MTL_ENABLE_DEBUG_INFO = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				SDKROOT = macosx;
@@ -547,7 +547,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				MACOSX_DEPLOYMENT_TARGET = 10.15;
+				MACOSX_DEPLOYMENT_TARGET = 10.14;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				ONLY_ACTIVE_ARCH = YES;
 				SDKROOT = macosx;
@@ -574,7 +574,7 @@
 					"$(inherited)",
 					../../target/debug,
 				);
-				MACOSX_DEPLOYMENT_TARGET = 10.15;
+				MACOSX_DEPLOYMENT_TARGET = 10.14;
 				PRODUCT_BUNDLE_IDENTIFIER = com.carriez.rustdesk;
 				PROVISIONING_PROFILE_SPECIFIER = "";
 				"SWIFT_OBJC_BRIDGING_HEADER[arch=*]" = Runner/bridge_generated.h;
@@ -601,7 +601,7 @@
 					"$(inherited)",
 					../../target/release,
 				);
-				MACOSX_DEPLOYMENT_TARGET = 10.15;
+				MACOSX_DEPLOYMENT_TARGET = 10.14;
 				PRODUCT_BUNDLE_IDENTIFIER = com.carriez.rustdesk;
 				PROVISIONING_PROFILE_SPECIFIER = "";
 				"SWIFT_OBJC_BRIDGING_HEADER[arch=*]" = Runner/bridge_generated.h;
diff --git a/flutter/windows/runner/main.cpp b/flutter/windows/runner/main.cpp
index 5680ab5d3..9b75aa086 100644
--- a/flutter/windows/runner/main.cpp
+++ b/flutter/windows/runner/main.cpp
@@ -25,7 +25,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
     return EXIT_FAILURE;
   }
   FUNC_RUSTDESK_CORE_MAIN rustdesk_core_main =
-      (FUNC_RUSTDESK_CORE_MAIN)GetProcAddress(hInstance, "rustdesk_core_main");
+      (FUNC_RUSTDESK_CORE_MAIN)GetProcAddress(hInstance, "rustdesk_core_main_args");
   if (!rustdesk_core_main)
   {
     std::cout << "Failed to get rustdesk_core_main" << std::endl;
diff --git a/src/flutter.rs b/src/flutter.rs
index 9c4208625..27d12860b 100644
--- a/src/flutter.rs
+++ b/src/flutter.rs
@@ -40,7 +40,7 @@ pub extern "C" fn rustdesk_core_main() -> bool {
 
 #[cfg(windows)]
 #[no_mangle]
-pub extern "C" fn rustdesk_core_main(args_len: *mut c_int) -> *mut *mut c_char {
+pub extern "C" fn rustdesk_core_main_args(args_len: *mut c_int) -> *mut *mut c_char {
     unsafe { std::ptr::write(args_len, 0) };
     #[cfg(not(any(target_os = "android", target_os = "ios")))]
     {
diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs
index 00f9b51e6..0f3fb5ef6 100644
--- a/src/flutter_ffi.rs
+++ b/src/flutter_ffi.rs
@@ -483,6 +483,10 @@ pub fn main_get_option(key: String) -> String {
     get_option(key)
 }
 
+pub fn main_get_error() -> String {
+    get_error()
+}
+
 pub fn main_set_option(key: String, value: String) {
     if key.eq("custom-rendezvous-server") {
         set_option(key, value);
diff --git a/src/lang.rs b/src/lang.rs
index de0fed0b8..6254e988a 100644
--- a/src/lang.rs
+++ b/src/lang.rs
@@ -110,7 +110,7 @@ pub fn translate_locale(name: String, locale: &str) -> String {
         "fa" => fa::T.deref(),
         "ca" => ca::T.deref(),
         "gr" => gr::T.deref(),
-        "gr" => sv::T.deref(),
+        "sv" => sv::T.deref(),
         _ => en::T.deref(),
     };
     if let Some(v) = m.get(&name as &str) {