Merge pull request #1824 from Kingtous/master

feat: replace forceAppUpdate with customed reloadWindow & fix a memory issue on windows
This commit is contained in:
RustDesk 2022-10-26 17:02:14 +08:00 committed by GitHub
commit abe9b66bba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 245 additions and 127 deletions

View File

@ -9,6 +9,7 @@ import 'package:desktop_multi_window/desktop_multi_window.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.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/desktop/widgets/tabbar_widget.dart';
import 'package:flutter_hbb/main.dart'; import 'package:flutter_hbb/main.dart';
import 'package:flutter_hbb/models/peer_model.dart'; import 'package:flutter_hbb/models/peer_model.dart';
@ -1338,3 +1339,30 @@ class SimpleWrapper<T> {
T get value => t; T get value => t;
set value(T t) => this.t = 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<void> reloadAllWindows() async {
reloadCurrentWindow();
try {
final ids = await DesktopMultiWindow.getAllSubWindowIds();
for (final id in ids) {
DesktopMultiWindow.invokeMethod(id, kWindowActionRebuild);
}
} on AssertionError {
// ignore
}
}

View File

@ -9,6 +9,8 @@ const String kAppTypeDesktopRemote = "remote";
const String kAppTypeDesktopFileTransfer = "file transfer"; const String kAppTypeDesktopFileTransfer = "file transfer";
const String kAppTypeDesktopPortForward = "port forward"; const String kAppTypeDesktopPortForward = "port forward";
const String kWindowActionRebuild = "rebuild";
const String kUniLinksPrefix = "rustdesk://"; const String kUniLinksPrefix = "rustdesk://";
const String kActionNewConnection = "connection/new/"; const String kActionNewConnection = "connection/new/";

View File

@ -5,6 +5,7 @@ import 'dart:convert';
import 'package:flutter/material.dart' hide MenuItem; import 'package:flutter/material.dart' hide MenuItem;
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_hbb/common.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/connection_page.dart';
import 'package:flutter_hbb/desktop/pages/desktop_setting_page.dart'; import 'package:flutter_hbb/desktop/pages/desktop_setting_page.dart';
import 'package:flutter_hbb/desktop/pages/desktop_tab_page.dart'; import 'package:flutter_hbb/desktop/pages/desktop_tab_page.dart';
@ -452,6 +453,8 @@ class _DesktopHomePageState extends State<DesktopHomePage>
'scaleFactor': screen.scaleFactor, 'scaleFactor': screen.scaleFactor,
}); });
} }
} else if (call.method == kWindowActionRebuild) {
reloadCurrentWindow();
} }
}); });
Future.delayed(Duration.zero, () { Future.delayed(Duration.zero, () {

View File

@ -406,7 +406,7 @@ class _GeneralState extends State<_General> {
initialKey: currentKey, initialKey: currentKey,
onChanged: (key) async { onChanged: (key) async {
await bind.mainSetLocalOption(key: "lang", value: key); await bind.mainSetLocalOption(key: "lang", value: key);
Get.forceAppUpdate(); reloadAllWindows();
bind.mainChangeLanguage(lang: key); bind.mainChangeLanguage(lang: key);
}, },
).marginOnly(left: _kContentHMargin); ).marginOnly(left: _kContentHMargin);

View File

@ -47,7 +47,7 @@ class _FileManagerTabPageState extends State<FileManagerTabPage> {
rustDeskWinManager.setMethodHandler((call, fromWindowId) async { rustDeskWinManager.setMethodHandler((call, fromWindowId) async {
print( 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 // for simplify, just replace connectionId
if (call.method == "new_file_transfer") { if (call.method == "new_file_transfer") {
final args = jsonDecode(call.arguments); final args = jsonDecode(call.arguments);
@ -62,6 +62,8 @@ class _FileManagerTabPageState extends State<FileManagerTabPage> {
page: FileManagerPage(key: ValueKey(id), id: id))); page: FileManagerPage(key: ValueKey(id), id: id)));
} else if (call.method == "onDestroy") { } else if (call.method == "onDestroy") {
tabController.clear(); tabController.clear();
} else if (call.method == kWindowActionRebuild) {
reloadCurrentWindow();
} }
}); });
Future.delayed(Duration.zero, () { Future.delayed(Duration.zero, () {

View File

@ -70,6 +70,8 @@ class _PortForwardTabPageState extends State<PortForwardTabPage> {
page: PortForwardPage(id: id, isRDP: isRDP))); page: PortForwardPage(id: id, isRDP: isRDP)));
} else if (call.method == "onDestroy") { } else if (call.method == "onDestroy") {
tabController.clear(); tabController.clear();
} else if (call.method == kWindowActionRebuild) {
reloadCurrentWindow();
} }
}); });
Future.delayed(Duration.zero, () { Future.delayed(Duration.zero, () {

View File

@ -89,6 +89,8 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
)))); ))));
} else if (call.method == "onDestroy") { } else if (call.method == "onDestroy") {
tabController.clear(); tabController.clear();
} else if (call.method == kWindowActionRebuild) {
reloadCurrentWindow();
} }
_update_remote_count(); _update_remote_count();
}); });

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hbb/common.dart'; import 'package:flutter_hbb/common.dart';
import 'package:flutter_hbb/desktop/pages/file_manager_tab_page.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'; import 'package:provider/provider.dart';
/// multi-tab file transfer remote screen /// multi-tab file transfer remote screen

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hbb/common.dart'; import 'package:flutter_hbb/common.dart';
import 'package:flutter_hbb/desktop/pages/port_forward_tab_page.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'; import 'package:provider/provider.dart';
/// multi-tab file port forward screen /// multi-tab file port forward screen

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hbb/common.dart'; import 'package:flutter_hbb/common.dart';
import 'package:flutter_hbb/desktop/pages/remote_tab_page.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:get/get.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';

View File

@ -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<RefreshWrapper> createState() => RefreshWrapperState();
static RefreshWrapperState? of(BuildContext context) {
final state = context.findAncestorStateOfType<RefreshWrapperState>();
if (state == null) {
debugPrint(
"RefreshWrapperState not exists in this context, perhaps RefreshWrapper is not exists?");
}
return state;
}
}
class RefreshWrapperState extends State<RefreshWrapper> {
@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);
}
}

View File

@ -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_file_transfer_screen.dart';
import 'package:flutter_hbb/desktop/screen/desktop_port_forward_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/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_hbb/utils/multi_window_manager.dart';
import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
@ -121,40 +122,17 @@ void runMobileApp() async {
void runRemoteScreen(Map<String, dynamic> argument) async { void runRemoteScreen(Map<String, dynamic> argument) async {
await initEnv(kAppTypeDesktopRemote); await initEnv(kAppTypeDesktopRemote);
runApp(GetMaterialApp( runApp(RefreshWrapper(
navigatorKey: globalKey, builder: (context) => GetMaterialApp(
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<String, dynamic> argument) async {
await initEnv(kAppTypeDesktopFileTransfer);
runApp(
GetMaterialApp(
navigatorKey: globalKey, navigatorKey: globalKey,
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
title: 'RustDesk - File Transfer', title: 'RustDesk - Remote Desktop',
theme: MyTheme.lightTheme, theme: MyTheme.lightTheme,
darkTheme: MyTheme.darkTheme, darkTheme: MyTheme.darkTheme,
themeMode: MyTheme.currentThemeMode(), themeMode: MyTheme.currentThemeMode(),
home: DesktopFileTransferScreen(params: argument), home: DesktopRemoteScreen(
params: argument,
),
localizationsDelegates: const [ localizationsDelegates: const [
GlobalMaterialLocalizations.delegate, GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate, GlobalWidgetsLocalizations.delegate,
@ -166,31 +144,60 @@ void runFileTransferScreen(Map<String, dynamic> argument) async {
], ],
builder: _keepScaleBuilder(), builder: _keepScaleBuilder(),
), ),
));
}
void runFileTransferScreen(Map<String, dynamic> 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<String, dynamic> argument) async { void runPortForwardScreen(Map<String, dynamic> argument) async {
await initEnv(kAppTypeDesktopPortForward); await initEnv(kAppTypeDesktopPortForward);
runApp( runApp(
GetMaterialApp( RefreshWrapper(builder: (context) {
navigatorKey: globalKey, return GetMaterialApp(
debugShowCheckedModeBanner: false, navigatorKey: globalKey,
title: 'RustDesk - Port Forward', debugShowCheckedModeBanner: false,
theme: MyTheme.lightTheme, title: 'RustDesk - Port Forward',
darkTheme: MyTheme.darkTheme, theme: MyTheme.lightTheme,
themeMode: MyTheme.currentThemeMode(), darkTheme: MyTheme.darkTheme,
home: DesktopPortForwardScreen(params: argument), themeMode: MyTheme.currentThemeMode(),
localizationsDelegates: const [ home: DesktopPortForwardScreen(params: argument),
GlobalMaterialLocalizations.delegate, localizationsDelegates: const [
GlobalWidgetsLocalizations.delegate, GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate, GlobalWidgetsLocalizations.delegate,
], GlobalCupertinoLocalizations.delegate,
supportedLocales: supportedLocales, ],
navigatorObservers: const [ supportedLocales: supportedLocales,
// FirebaseAnalyticsObserver(analytics: analytics), navigatorObservers: const [
], // FirebaseAnalyticsObserver(analytics: analytics),
builder: _keepScaleBuilder(), ],
), builder: _keepScaleBuilder(),
);
}),
); );
} }
@ -199,19 +206,21 @@ void runConnectionManagerScreen() async {
// initialize window // initialize window
WindowOptions windowOptions = WindowOptions windowOptions =
getHiddenTitleBarWindowOptions(size: kConnectionManagerWindowSize); getHiddenTitleBarWindowOptions(size: kConnectionManagerWindowSize);
runApp(GetMaterialApp( runApp(RefreshWrapper(builder: (context) {
debugShowCheckedModeBanner: false, return GetMaterialApp(
theme: MyTheme.lightTheme, debugShowCheckedModeBanner: false,
darkTheme: MyTheme.darkTheme, theme: MyTheme.lightTheme,
themeMode: MyTheme.currentThemeMode(), darkTheme: MyTheme.darkTheme,
localizationsDelegates: const [ themeMode: MyTheme.currentThemeMode(),
GlobalMaterialLocalizations.delegate, localizationsDelegates: const [
GlobalWidgetsLocalizations.delegate, GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate, GlobalWidgetsLocalizations.delegate,
], GlobalCupertinoLocalizations.delegate,
supportedLocales: supportedLocales, ],
home: const DesktopServerPage(), supportedLocales: supportedLocales,
builder: _keepScaleBuilder())); home: const DesktopServerPage(),
builder: _keepScaleBuilder());
}));
windowManager.waitUntilReadyToShow(windowOptions, () async { windowManager.waitUntilReadyToShow(windowOptions, () async {
await windowManager.show(); await windowManager.show();
// ensure initial window size to be changed // ensure initial window size to be changed
@ -229,18 +238,20 @@ void runConnectionManagerScreen() async {
void runInstallPage() async { void runInstallPage() async {
await windowManager.ensureInitialized(); await windowManager.ensureInitialized();
await initEnv(kAppTypeMain); await initEnv(kAppTypeMain);
runApp(GetMaterialApp( runApp(RefreshWrapper(
debugShowCheckedModeBanner: false, builder: (context) => GetMaterialApp(
theme: MyTheme.lightTheme, debugShowCheckedModeBanner: false,
themeMode: ThemeMode.light, theme: MyTheme.lightTheme,
localizationsDelegates: const [ themeMode: ThemeMode.light,
GlobalMaterialLocalizations.delegate, localizationsDelegates: const [
GlobalWidgetsLocalizations.delegate, GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate, GlobalWidgetsLocalizations.delegate,
], GlobalCupertinoLocalizations.delegate,
supportedLocales: supportedLocales, ],
home: const InstallPage(), supportedLocales: supportedLocales,
builder: _keepScaleBuilder())); home: const InstallPage(),
builder: _keepScaleBuilder()),
));
windowManager.waitUntilReadyToShow( windowManager.waitUntilReadyToShow(
WindowOptions(size: Size(800, 600), center: true), () async { WindowOptions(size: Size(800, 600), center: true), () async {
windowManager.show(); windowManager.show();
@ -292,48 +303,50 @@ class _AppState extends State<App> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// final analytics = FirebaseAnalytics.instance; // final analytics = FirebaseAnalytics.instance;
return MultiProvider( return RefreshWrapper(builder: (context) {
providers: [ return MultiProvider(
// global configuration providers: [
// use session related FFI when in remote control or file transfer page // global configuration
ChangeNotifierProvider.value(value: gFFI.ffiModel), // use session related FFI when in remote control or file transfer page
ChangeNotifierProvider.value(value: gFFI.imageModel), ChangeNotifierProvider.value(value: gFFI.ffiModel),
ChangeNotifierProvider.value(value: gFFI.cursorModel), ChangeNotifierProvider.value(value: gFFI.imageModel),
ChangeNotifierProvider.value(value: gFFI.canvasModel), 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),
], ],
localizationsDelegates: const [ child: GetMaterialApp(
GlobalMaterialLocalizations.delegate, navigatorKey: globalKey,
GlobalWidgetsLocalizations.delegate, debugShowCheckedModeBanner: false,
GlobalCupertinoLocalizations.delegate, title: 'RustDesk',
], theme: MyTheme.lightTheme,
supportedLocales: supportedLocales, darkTheme: MyTheme.darkTheme,
builder: isAndroid themeMode: MyTheme.currentThemeMode(),
? (context, child) => AccessibilityListener( home: isDesktop
child: MediaQuery( ? const DesktopTabPage()
data: MediaQuery.of(context).copyWith( : !isAndroid
textScaleFactor: 1.0, ? 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 { platformFFI.registerEventHandler('language', 'language', (_) async {
Get.forceAppUpdate(); reloadAllWindows();
}); });
} }
} }

View File

@ -6,7 +6,8 @@ import '../../models/model.dart';
import '../../models/platform_model.dart'; import '../../models/platform_model.dart';
void clientClose(OverlayDialogManager dialogManager) { 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() { void showSuccess() {

View File

@ -64,7 +64,7 @@ dependencies:
desktop_multi_window: desktop_multi_window:
git: git:
url: https://github.com/Kingtous/rustdesk_desktop_multi_window url: https://github.com/Kingtous/rustdesk_desktop_multi_window
ref: 33e79865ab290b9f1babfb349786424a14405241 ref: 08672abfb665a6defab6cb7c1b3bd13a32c57431
freezed_annotation: ^2.0.3 freezed_annotation: ^2.0.3
tray_manager: tray_manager:
git: git:

View File

@ -11,6 +11,7 @@
typedef char** (*FUNC_RUSTDESK_CORE_MAIN)(int*); typedef char** (*FUNC_RUSTDESK_CORE_MAIN)(int*);
typedef void (*FUNC_RUSTDESK_FREE_ARGS)( char**, 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); // auto bdw = bitsdojo_window_configure(BDW_CUSTOM_FRAME | BDW_HIDE_ON_STARTUP);
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, 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; std::cout << "Failed to get free_c_args" << std::endl;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
std::vector<std::string> command_line_arguments =
GetCommandLineArguments();
int args_len = 0; int args_len = 0;
char** c_args = rustdesk_core_main(&args_len); 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 // uni links dispatch
// only do uni links when dispatch a rustdesk links // 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"); HWND hwnd = ::FindWindow(L"FLUTTER_RUNNER_WIN32_WINDOW", L"rustdesk");
if (hwnd != NULL) { if (hwnd != NULL) {
DispatchToUniLinksDesktop(hwnd); DispatchToUniLinksDesktop(hwnd);
@ -71,17 +75,19 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
flutter::DartProject project(L"data"); flutter::DartProject project(L"data");
// connection manager hide icon from taskbar
std::vector<std::string> command_line_arguments = bool showOnTaskBar = true;
GetCommandLineArguments(); 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()); command_line_arguments.insert(command_line_arguments.end(), rust_args.begin(), rust_args.end());
project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
FlutterWindow window(project); FlutterWindow window(project);
Win32Window::Point origin(10, 10); Win32Window::Point origin(10, 10);
Win32Window::Size size(800, 600); Win32Window::Size size(800, 600);
if (!window.CreateAndShow(L"RustDesk", origin, size)) if (!window.CreateAndShow(L"RustDesk", origin, size, showOnTaskBar))
{ {
return EXIT_FAILURE; return EXIT_FAILURE;
} }

View File

@ -1,6 +1,7 @@
#include "win32_window.h" #include "win32_window.h"
#include <flutter_windows.h> #include <flutter_windows.h>
#include <shobjidl_core.h>
#include "resource.h" #include "resource.h"
@ -104,7 +105,7 @@ Win32Window::~Win32Window() {
bool Win32Window::CreateAndShow(const std::wstring& title, bool Win32Window::CreateAndShow(const std::wstring& title,
const Point& origin, const Point& origin,
const Size& size) { const Size& size, bool showOnTaskBar) {
Destroy(); Destroy();
const wchar_t* window_class = const wchar_t* window_class =
@ -115,7 +116,7 @@ bool Win32Window::CreateAndShow(const std::wstring& title,
HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST);
UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); UINT dpi = FlutterDesktopGetDpiForMonitor(monitor);
double scale_factor = dpi / 96.0; double scale_factor = dpi / 96.0;
HWND window = CreateWindow( HWND window = CreateWindow(
window_class, title.c_str(), WS_OVERLAPPEDWINDOW, window_class, title.c_str(), WS_OVERLAPPEDWINDOW,
Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), Scale(origin.x, scale_factor), Scale(origin.y, scale_factor),
@ -126,6 +127,19 @@ bool Win32Window::CreateAndShow(const std::wstring& title,
return false; 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(); return OnCreate();
} }

View File

@ -36,7 +36,8 @@ class Win32Window {
// true if the window was created successfully. // true if the window was created successfully.
bool CreateAndShow(const std::wstring& title, bool CreateAndShow(const std::wstring& title,
const Point& origin, const Point& origin,
const Size& size); const Size& size,
bool showOnTaskBar = true);
// Release OS resources associated with window. // Release OS resources associated with window.
void Destroy(); void Destroy();