diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 8544fc240..8c927e8a1 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -9,6 +9,7 @@ import 'package:desktop_multi_window/desktop_multi_window.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_hbb/desktop/widgets/refresh_wrapper.dart'; import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart'; import 'package:flutter_hbb/main.dart'; import 'package:flutter_hbb/models/peer_model.dart'; @@ -1338,3 +1339,30 @@ class SimpleWrapper { T get value => t; set value(T t) => this.t = t; } + +/// call this to reload current window. +/// +/// [Note] +/// Must have [RefreshWrapper] on the top of widget tree. +void reloadCurrentWindow() { + if (Get.context != null) { + // reload self window + RefreshWrapper.of(Get.context!)?.rebuild(); + } else { + debugPrint( + "reload current window failed, global BuildContext does not exist"); + } +} + +/// call this to reload all windows, including main + all sub windows. +Future reloadAllWindows() async { + reloadCurrentWindow(); + try { + final ids = await DesktopMultiWindow.getAllSubWindowIds(); + for (final id in ids) { + DesktopMultiWindow.invokeMethod(id, kWindowActionRebuild); + } + } on AssertionError { + // ignore + } +} diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index 726ae24be..66aef10c0 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -9,6 +9,8 @@ const String kAppTypeDesktopRemote = "remote"; const String kAppTypeDesktopFileTransfer = "file transfer"; const String kAppTypeDesktopPortForward = "port forward"; +const String kWindowActionRebuild = "rebuild"; + const String kUniLinksPrefix = "rustdesk://"; const String kActionNewConnection = "connection/new/"; diff --git a/flutter/lib/desktop/pages/desktop_home_page.dart b/flutter/lib/desktop/pages/desktop_home_page.dart index 7d2690626..b65525159 100644 --- a/flutter/lib/desktop/pages/desktop_home_page.dart +++ b/flutter/lib/desktop/pages/desktop_home_page.dart @@ -5,6 +5,7 @@ import 'dart:convert'; import 'package:flutter/material.dart' hide MenuItem; import 'package:flutter/services.dart'; import 'package:flutter_hbb/common.dart'; +import 'package:flutter_hbb/consts.dart'; import 'package:flutter_hbb/desktop/pages/connection_page.dart'; import 'package:flutter_hbb/desktop/pages/desktop_setting_page.dart'; import 'package:flutter_hbb/desktop/pages/desktop_tab_page.dart'; @@ -452,6 +453,8 @@ class _DesktopHomePageState extends State 'scaleFactor': screen.scaleFactor, }); } + } else if (call.method == kWindowActionRebuild) { + reloadCurrentWindow(); } }); Future.delayed(Duration.zero, () { diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index 22247c033..709d4deda 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -406,7 +406,7 @@ class _GeneralState extends State<_General> { initialKey: currentKey, onChanged: (key) async { await bind.mainSetLocalOption(key: "lang", value: key); - Get.forceAppUpdate(); + reloadAllWindows(); bind.mainChangeLanguage(lang: key); }, ).marginOnly(left: _kContentHMargin); diff --git a/flutter/lib/desktop/pages/file_manager_tab_page.dart b/flutter/lib/desktop/pages/file_manager_tab_page.dart index 85a2ab197..68ad2529c 100644 --- a/flutter/lib/desktop/pages/file_manager_tab_page.dart +++ b/flutter/lib/desktop/pages/file_manager_tab_page.dart @@ -47,7 +47,7 @@ class _FileManagerTabPageState extends State { rustDeskWinManager.setMethodHandler((call, fromWindowId) async { print( - "call ${call.method} with args ${call.arguments} from window ${fromWindowId} to ${windowId()}"); + "[FileTransfer] call ${call.method} with args ${call.arguments} from window ${fromWindowId} to ${windowId()}"); // for simplify, just replace connectionId if (call.method == "new_file_transfer") { final args = jsonDecode(call.arguments); @@ -62,6 +62,8 @@ class _FileManagerTabPageState extends State { page: FileManagerPage(key: ValueKey(id), id: id))); } else if (call.method == "onDestroy") { tabController.clear(); + } else if (call.method == kWindowActionRebuild) { + reloadCurrentWindow(); } }); Future.delayed(Duration.zero, () { diff --git a/flutter/lib/desktop/pages/port_forward_tab_page.dart b/flutter/lib/desktop/pages/port_forward_tab_page.dart index 64a67121b..6d7390493 100644 --- a/flutter/lib/desktop/pages/port_forward_tab_page.dart +++ b/flutter/lib/desktop/pages/port_forward_tab_page.dart @@ -70,6 +70,8 @@ class _PortForwardTabPageState extends State { page: PortForwardPage(id: id, isRDP: isRDP))); } else if (call.method == "onDestroy") { tabController.clear(); + } else if (call.method == kWindowActionRebuild) { + reloadCurrentWindow(); } }); Future.delayed(Duration.zero, () { diff --git a/flutter/lib/desktop/pages/remote_tab_page.dart b/flutter/lib/desktop/pages/remote_tab_page.dart index ea0658b6e..b73dacec2 100644 --- a/flutter/lib/desktop/pages/remote_tab_page.dart +++ b/flutter/lib/desktop/pages/remote_tab_page.dart @@ -89,6 +89,8 @@ class _ConnectionTabPageState extends State { )))); } else if (call.method == "onDestroy") { tabController.clear(); + } else if (call.method == kWindowActionRebuild) { + reloadCurrentWindow(); } _update_remote_count(); }); diff --git a/flutter/lib/desktop/screen/desktop_file_transfer_screen.dart b/flutter/lib/desktop/screen/desktop_file_transfer_screen.dart index 694f18ace..74764a803 100644 --- a/flutter/lib/desktop/screen/desktop_file_transfer_screen.dart +++ b/flutter/lib/desktop/screen/desktop_file_transfer_screen.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_hbb/common.dart'; import 'package:flutter_hbb/desktop/pages/file_manager_tab_page.dart'; +import 'package:flutter_hbb/desktop/widgets/refresh_wrapper.dart'; import 'package:provider/provider.dart'; /// multi-tab file transfer remote screen diff --git a/flutter/lib/desktop/screen/desktop_port_forward_screen.dart b/flutter/lib/desktop/screen/desktop_port_forward_screen.dart index c7c163a57..5cec10f86 100644 --- a/flutter/lib/desktop/screen/desktop_port_forward_screen.dart +++ b/flutter/lib/desktop/screen/desktop_port_forward_screen.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_hbb/common.dart'; import 'package:flutter_hbb/desktop/pages/port_forward_tab_page.dart'; +import 'package:flutter_hbb/desktop/widgets/refresh_wrapper.dart'; import 'package:provider/provider.dart'; /// multi-tab file port forward screen diff --git a/flutter/lib/desktop/screen/desktop_remote_screen.dart b/flutter/lib/desktop/screen/desktop_remote_screen.dart index 1dcb426df..4d045d02b 100644 --- a/flutter/lib/desktop/screen/desktop_remote_screen.dart +++ b/flutter/lib/desktop/screen/desktop_remote_screen.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_hbb/common.dart'; import 'package:flutter_hbb/desktop/pages/remote_tab_page.dart'; +import 'package:flutter_hbb/desktop/widgets/refresh_wrapper.dart'; import 'package:get/get.dart'; import 'package:provider/provider.dart'; diff --git a/flutter/lib/desktop/widgets/refresh_wrapper.dart b/flutter/lib/desktop/widgets/refresh_wrapper.dart new file mode 100644 index 000000000..4f2795d71 --- /dev/null +++ b/flutter/lib/desktop/widgets/refresh_wrapper.dart @@ -0,0 +1,41 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_hbb/main.dart'; +import 'package:get/get.dart'; + +class RefreshWrapper extends StatefulWidget { + final Widget Function(BuildContext context) builder; + const RefreshWrapper({super.key, required this.builder}); + + @override + State createState() => RefreshWrapperState(); + + static RefreshWrapperState? of(BuildContext context) { + final state = context.findAncestorStateOfType(); + if (state == null) { + debugPrint( + "RefreshWrapperState not exists in this context, perhaps RefreshWrapper is not exists?"); + } + return state; + } +} + +class RefreshWrapperState extends State { + @override + Widget build(BuildContext context) { + return widget.builder(context); + } + + rebuild() { + debugPrint("=====Global State Rebuild (win-${windowId ?? 'main'})====="); + if (Get.context != null) { + (context as Element).visitChildren(_rebuildElement); + } + setState(() {}); + } + + /// set root tree dirty to trigger global rebuild + void _rebuildElement(Element el) { + el.markNeedsBuild(); + el.visitChildren(_rebuildElement); + } +} diff --git a/flutter/lib/main.dart b/flutter/lib/main.dart index 1b896c781..b3f74f930 100644 --- a/flutter/lib/main.dart +++ b/flutter/lib/main.dart @@ -9,6 +9,7 @@ import 'package:flutter_hbb/desktop/pages/install_page.dart'; import 'package:flutter_hbb/desktop/screen/desktop_file_transfer_screen.dart'; import 'package:flutter_hbb/desktop/screen/desktop_port_forward_screen.dart'; import 'package:flutter_hbb/desktop/screen/desktop_remote_screen.dart'; +import 'package:flutter_hbb/desktop/widgets/refresh_wrapper.dart'; import 'package:flutter_hbb/utils/multi_window_manager.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:get/get.dart'; @@ -121,40 +122,17 @@ void runMobileApp() async { void runRemoteScreen(Map argument) async { await initEnv(kAppTypeDesktopRemote); - runApp(GetMaterialApp( - navigatorKey: globalKey, - debugShowCheckedModeBanner: false, - title: 'RustDesk - Remote Desktop', - theme: MyTheme.lightTheme, - darkTheme: MyTheme.darkTheme, - themeMode: MyTheme.currentThemeMode(), - home: DesktopRemoteScreen( - params: argument, - ), - localizationsDelegates: const [ - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - ], - supportedLocales: supportedLocales, - navigatorObservers: const [ - // FirebaseAnalyticsObserver(analytics: analytics), - ], - builder: _keepScaleBuilder(), - )); -} - -void runFileTransferScreen(Map argument) async { - await initEnv(kAppTypeDesktopFileTransfer); - runApp( - GetMaterialApp( + runApp(RefreshWrapper( + builder: (context) => GetMaterialApp( navigatorKey: globalKey, debugShowCheckedModeBanner: false, - title: 'RustDesk - File Transfer', + title: 'RustDesk - Remote Desktop', theme: MyTheme.lightTheme, darkTheme: MyTheme.darkTheme, themeMode: MyTheme.currentThemeMode(), - home: DesktopFileTransferScreen(params: argument), + home: DesktopRemoteScreen( + params: argument, + ), localizationsDelegates: const [ GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, @@ -166,31 +144,60 @@ void runFileTransferScreen(Map argument) async { ], builder: _keepScaleBuilder(), ), + )); +} + +void runFileTransferScreen(Map argument) async { + await initEnv(kAppTypeDesktopFileTransfer); + runApp( + RefreshWrapper( + builder: (context) => GetMaterialApp( + navigatorKey: globalKey, + debugShowCheckedModeBanner: false, + title: 'RustDesk - File Transfer', + theme: MyTheme.lightTheme, + darkTheme: MyTheme.darkTheme, + themeMode: MyTheme.currentThemeMode(), + home: DesktopFileTransferScreen(params: argument), + localizationsDelegates: const [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + ], + supportedLocales: supportedLocales, + navigatorObservers: const [ + // FirebaseAnalyticsObserver(analytics: analytics), + ], + builder: _keepScaleBuilder(), + ), + ), ); } void runPortForwardScreen(Map argument) async { await initEnv(kAppTypeDesktopPortForward); runApp( - GetMaterialApp( - navigatorKey: globalKey, - debugShowCheckedModeBanner: false, - title: 'RustDesk - Port Forward', - theme: MyTheme.lightTheme, - darkTheme: MyTheme.darkTheme, - themeMode: MyTheme.currentThemeMode(), - home: DesktopPortForwardScreen(params: argument), - localizationsDelegates: const [ - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - ], - supportedLocales: supportedLocales, - navigatorObservers: const [ - // FirebaseAnalyticsObserver(analytics: analytics), - ], - builder: _keepScaleBuilder(), - ), + RefreshWrapper(builder: (context) { + return GetMaterialApp( + navigatorKey: globalKey, + debugShowCheckedModeBanner: false, + title: 'RustDesk - Port Forward', + theme: MyTheme.lightTheme, + darkTheme: MyTheme.darkTheme, + themeMode: MyTheme.currentThemeMode(), + home: DesktopPortForwardScreen(params: argument), + localizationsDelegates: const [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + ], + supportedLocales: supportedLocales, + navigatorObservers: const [ + // FirebaseAnalyticsObserver(analytics: analytics), + ], + builder: _keepScaleBuilder(), + ); + }), ); } @@ -199,19 +206,21 @@ void runConnectionManagerScreen() async { // initialize window WindowOptions windowOptions = getHiddenTitleBarWindowOptions(size: kConnectionManagerWindowSize); - runApp(GetMaterialApp( - debugShowCheckedModeBanner: false, - theme: MyTheme.lightTheme, - darkTheme: MyTheme.darkTheme, - themeMode: MyTheme.currentThemeMode(), - localizationsDelegates: const [ - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - ], - supportedLocales: supportedLocales, - home: const DesktopServerPage(), - builder: _keepScaleBuilder())); + runApp(RefreshWrapper(builder: (context) { + return GetMaterialApp( + debugShowCheckedModeBanner: false, + theme: MyTheme.lightTheme, + darkTheme: MyTheme.darkTheme, + themeMode: MyTheme.currentThemeMode(), + localizationsDelegates: const [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + ], + supportedLocales: supportedLocales, + home: const DesktopServerPage(), + builder: _keepScaleBuilder()); + })); windowManager.waitUntilReadyToShow(windowOptions, () async { await windowManager.show(); // ensure initial window size to be changed @@ -229,18 +238,20 @@ void runConnectionManagerScreen() async { void runInstallPage() async { await windowManager.ensureInitialized(); await initEnv(kAppTypeMain); - runApp(GetMaterialApp( - debugShowCheckedModeBanner: false, - theme: MyTheme.lightTheme, - themeMode: ThemeMode.light, - localizationsDelegates: const [ - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - ], - supportedLocales: supportedLocales, - home: const InstallPage(), - builder: _keepScaleBuilder())); + runApp(RefreshWrapper( + builder: (context) => GetMaterialApp( + debugShowCheckedModeBanner: false, + theme: MyTheme.lightTheme, + themeMode: ThemeMode.light, + localizationsDelegates: const [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + ], + supportedLocales: supportedLocales, + home: const InstallPage(), + builder: _keepScaleBuilder()), + )); windowManager.waitUntilReadyToShow( WindowOptions(size: Size(800, 600), center: true), () async { windowManager.show(); @@ -292,48 +303,50 @@ class _AppState extends State { @override Widget build(BuildContext context) { // final analytics = FirebaseAnalytics.instance; - return MultiProvider( - providers: [ - // global configuration - // use session related FFI when in remote control or file transfer page - ChangeNotifierProvider.value(value: gFFI.ffiModel), - ChangeNotifierProvider.value(value: gFFI.imageModel), - ChangeNotifierProvider.value(value: gFFI.cursorModel), - ChangeNotifierProvider.value(value: gFFI.canvasModel), - ], - child: GetMaterialApp( - navigatorKey: globalKey, - debugShowCheckedModeBanner: false, - title: 'RustDesk', - theme: MyTheme.lightTheme, - darkTheme: MyTheme.darkTheme, - themeMode: MyTheme.currentThemeMode(), - home: isDesktop - ? const DesktopTabPage() - : !isAndroid - ? WebHomePage() - : HomePage(), - navigatorObservers: const [ - // FirebaseAnalyticsObserver(analytics: analytics), + return RefreshWrapper(builder: (context) { + return MultiProvider( + providers: [ + // global configuration + // use session related FFI when in remote control or file transfer page + ChangeNotifierProvider.value(value: gFFI.ffiModel), + ChangeNotifierProvider.value(value: gFFI.imageModel), + ChangeNotifierProvider.value(value: gFFI.cursorModel), + ChangeNotifierProvider.value(value: gFFI.canvasModel), ], - localizationsDelegates: const [ - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - ], - supportedLocales: supportedLocales, - builder: isAndroid - ? (context, child) => AccessibilityListener( - child: MediaQuery( - data: MediaQuery.of(context).copyWith( - textScaleFactor: 1.0, + child: GetMaterialApp( + navigatorKey: globalKey, + debugShowCheckedModeBanner: false, + title: 'RustDesk', + theme: MyTheme.lightTheme, + darkTheme: MyTheme.darkTheme, + themeMode: MyTheme.currentThemeMode(), + home: isDesktop + ? const DesktopTabPage() + : !isAndroid + ? WebHomePage() + : HomePage(), + navigatorObservers: const [ + // FirebaseAnalyticsObserver(analytics: analytics), + ], + localizationsDelegates: const [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + ], + supportedLocales: supportedLocales, + builder: isAndroid + ? (context, child) => AccessibilityListener( + child: MediaQuery( + data: MediaQuery.of(context).copyWith( + textScaleFactor: 1.0, + ), + child: child ?? Container(), ), - child: child ?? Container(), - ), - ) - : _keepScaleBuilder(), - ), - ); + ) + : _keepScaleBuilder(), + ), + ); + }); } } @@ -357,7 +370,7 @@ _registerEventHandler() { } }); platformFFI.registerEventHandler('language', 'language', (_) async { - Get.forceAppUpdate(); + reloadAllWindows(); }); } } diff --git a/flutter/lib/mobile/widgets/dialog.dart b/flutter/lib/mobile/widgets/dialog.dart index ca82cbed9..03b36ecf3 100644 --- a/flutter/lib/mobile/widgets/dialog.dart +++ b/flutter/lib/mobile/widgets/dialog.dart @@ -6,7 +6,8 @@ import '../../models/model.dart'; import '../../models/platform_model.dart'; void clientClose(OverlayDialogManager dialogManager) { - msgBox('', 'Close', 'Are you sure to close the connection?', '', dialogManager); + msgBox( + '', 'Close', 'Are you sure to close the connection?', '', dialogManager); } void showSuccess() { diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 5c89ebbef..b789c65cb 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -64,7 +64,7 @@ dependencies: desktop_multi_window: git: url: https://github.com/Kingtous/rustdesk_desktop_multi_window - ref: 33e79865ab290b9f1babfb349786424a14405241 + ref: 08672abfb665a6defab6cb7c1b3bd13a32c57431 freezed_annotation: ^2.0.3 tray_manager: git: diff --git a/flutter/windows/runner/main.cpp b/flutter/windows/runner/main.cpp index a6716990d..19556a1f1 100644 --- a/flutter/windows/runner/main.cpp +++ b/flutter/windows/runner/main.cpp @@ -11,6 +11,7 @@ typedef char** (*FUNC_RUSTDESK_CORE_MAIN)(int*); typedef void (*FUNC_RUSTDESK_FREE_ARGS)( char**, int); +const char* uniLinksPrefix = "rustdesk://"; // auto bdw = bitsdojo_window_configure(BDW_CUSTOM_FRAME | BDW_HIDE_ON_STARTUP); int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, @@ -36,6 +37,8 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, std::cout << "Failed to get free_c_args" << std::endl; return EXIT_FAILURE; } + std::vector command_line_arguments = + GetCommandLineArguments(); int args_len = 0; char** c_args = rustdesk_core_main(&args_len); @@ -49,7 +52,8 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, // uni links dispatch // only do uni links when dispatch a rustdesk links - if (!rust_args.empty() && rust_args.front().compare("rustdesk://") == 0) { + auto prefix = std::string(uniLinksPrefix); + if (!command_line_arguments.empty() && command_line_arguments.front().compare(0, prefix.size(), prefix.c_str()) == 0) { HWND hwnd = ::FindWindow(L"FLUTTER_RUNNER_WIN32_WINDOW", L"rustdesk"); if (hwnd != NULL) { DispatchToUniLinksDesktop(hwnd); @@ -71,17 +75,19 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); flutter::DartProject project(L"data"); - - std::vector command_line_arguments = - GetCommandLineArguments(); - + // connection manager hide icon from taskbar + bool showOnTaskBar = true; + auto cmParam = std::string("--cm"); + if (!command_line_arguments.empty() && command_line_arguments.front().compare(0, cmParam.size(), cmParam.c_str()) == 0) { + showOnTaskBar = false; + } command_line_arguments.insert(command_line_arguments.end(), rust_args.begin(), rust_args.end()); project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); FlutterWindow window(project); Win32Window::Point origin(10, 10); Win32Window::Size size(800, 600); - if (!window.CreateAndShow(L"RustDesk", origin, size)) + if (!window.CreateAndShow(L"RustDesk", origin, size, showOnTaskBar)) { return EXIT_FAILURE; } diff --git a/flutter/windows/runner/win32_window.cpp b/flutter/windows/runner/win32_window.cpp index 3273c2c08..9ada9ab2e 100644 --- a/flutter/windows/runner/win32_window.cpp +++ b/flutter/windows/runner/win32_window.cpp @@ -1,6 +1,7 @@ #include "win32_window.h" #include +#include #include "resource.h" @@ -104,7 +105,7 @@ Win32Window::~Win32Window() { bool Win32Window::CreateAndShow(const std::wstring& title, const Point& origin, - const Size& size) { + const Size& size, bool showOnTaskBar) { Destroy(); const wchar_t* window_class = @@ -115,7 +116,7 @@ bool Win32Window::CreateAndShow(const std::wstring& title, HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); double scale_factor = dpi / 96.0; - + HWND window = CreateWindow( window_class, title.c_str(), WS_OVERLAPPEDWINDOW, Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), @@ -126,6 +127,19 @@ bool Win32Window::CreateAndShow(const std::wstring& title, return false; } + if (!showOnTaskBar) { + // hide from taskbar + HRESULT hr; + ITaskbarList* pTaskbarList; + hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER,IID_ITaskbarList,(void**)&pTaskbarList); + if (FAILED(hr)) { + return false; + } + hr = pTaskbarList->HrInit(); + hr = pTaskbarList->DeleteTab(window); + hr = pTaskbarList->Release(); + } + return OnCreate(); } diff --git a/flutter/windows/runner/win32_window.h b/flutter/windows/runner/win32_window.h index 17ba43112..77e52ff01 100644 --- a/flutter/windows/runner/win32_window.h +++ b/flutter/windows/runner/win32_window.h @@ -36,7 +36,8 @@ class Win32Window { // true if the window was created successfully. bool CreateAndShow(const std::wstring& title, const Point& origin, - const Size& size); + const Size& size, + bool showOnTaskBar = true); // Release OS resources associated with window. void Destroy();