mirror of
https://github.com/rustdesk/rustdesk.git
synced 2024-11-23 19:49:05 +08:00
refact: window frame border (#7946)
Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
parent
26adc557bf
commit
01322146c0
@ -3214,3 +3214,46 @@ Widget buildPresetPasswordWarning() {
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// https://github.com/leanflutter/window_manager/blob/87dd7a50b4cb47a375b9fc697f05e56eea0a2ab3/lib/src/widgets/virtual_window_frame.dart#L44
|
||||
Widget buildVirtualWindowFrame(BuildContext context, Widget child) {
|
||||
boxShadow() => isMainDesktopWindow
|
||||
? <BoxShadow>[
|
||||
if (stateGlobal.fullscreen.isFalse || stateGlobal.isMaximized.isFalse)
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
offset: Offset(
|
||||
0.0,
|
||||
stateGlobal.isFocused.isTrue
|
||||
? kFrameBoxShadowOffsetFocused
|
||||
: kFrameBoxShadowOffsetUnfocused),
|
||||
blurRadius: kFrameBoxShadowBlurRadius,
|
||||
),
|
||||
]
|
||||
: null;
|
||||
return Obx(
|
||||
() => Container(
|
||||
decoration: BoxDecoration(
|
||||
color: isMainDesktopWindow ? Colors.transparent : Theme.of(context).colorScheme.background,
|
||||
border: Border.all(
|
||||
color: Theme.of(context).dividerColor,
|
||||
width: stateGlobal.windowBorderWidth.value,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(
|
||||
(stateGlobal.fullscreen.isTrue || stateGlobal.isMaximized.isTrue)
|
||||
? 0
|
||||
: kFrameBorderRadius,
|
||||
),
|
||||
boxShadow: boxShadow(),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(
|
||||
(stateGlobal.fullscreen.isTrue || stateGlobal.isMaximized.isTrue)
|
||||
? 0
|
||||
: kFrameClipRRectBorderRadius,
|
||||
),
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -154,9 +154,14 @@ const kDefaultScrollDuration = Duration(milliseconds: 50);
|
||||
const kDefaultMouseWheelThrottleDuration = Duration(milliseconds: 50);
|
||||
const kFullScreenEdgeSize = 0.0;
|
||||
const kMaximizeEdgeSize = 0.0;
|
||||
var kWindowEdgeSize = isWindows ? 1.0 : 5.0;
|
||||
const kWindowBorderWidth = 1.0;
|
||||
final kWindowEdgeSize = isWindows ? 1.0 : 5.0;
|
||||
final kWindowBorderWidth = isLinux ? 1.0 : 0.0;
|
||||
const kDesktopMenuPadding = EdgeInsets.only(left: 12.0, right: 3.0);
|
||||
const kFrameBorderRadius = 12.0;
|
||||
const kFrameClipRRectBorderRadius = 12.0;
|
||||
const kFrameBoxShadowBlurRadius = 32.0;
|
||||
const kFrameBoxShadowOffsetFocused = 4.0;
|
||||
const kFrameBoxShadowOffsetUnfocused = 2.0;
|
||||
|
||||
const kInvalidValueStr = 'InvalidValueStr';
|
||||
|
||||
|
@ -91,18 +91,21 @@ class _FileManagerTabPageState extends State<FileManagerTabPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final tabWidget = Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: MyTheme.color(context).border!)),
|
||||
child: Scaffold(
|
||||
backgroundColor: Theme.of(context).cardColor,
|
||||
body: DesktopTab(
|
||||
controller: tabController,
|
||||
onWindowCloseButton: handleWindowCloseButton,
|
||||
tail: const AddButton(),
|
||||
labelGetter: DesktopTab.tablabelGetter,
|
||||
)),
|
||||
);
|
||||
final child = Scaffold(
|
||||
backgroundColor: Theme.of(context).cardColor,
|
||||
body: DesktopTab(
|
||||
controller: tabController,
|
||||
onWindowCloseButton: handleWindowCloseButton,
|
||||
tail: const AddButton(),
|
||||
labelGetter: DesktopTab.tablabelGetter,
|
||||
));
|
||||
final tabWidget = isLinux
|
||||
? buildVirtualWindowFrame(context, child)
|
||||
: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: MyTheme.color(context).border!)),
|
||||
child: child,
|
||||
);
|
||||
return isMacOS || kUseCompatibleUiMode
|
||||
? tabWidget
|
||||
: SubWindowDragToResizeArea(
|
||||
|
@ -97,21 +97,30 @@ class _PortForwardTabPageState extends State<PortForwardTabPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final tabWidget = Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: MyTheme.color(context).border!)),
|
||||
child: Scaffold(
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
body: DesktopTab(
|
||||
controller: tabController,
|
||||
onWindowCloseButton: () async {
|
||||
tabController.clear();
|
||||
return true;
|
||||
},
|
||||
tail: AddButton(),
|
||||
labelGetter: DesktopTab.tablabelGetter,
|
||||
)),
|
||||
final child = Scaffold(
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
body: DesktopTab(
|
||||
controller: tabController,
|
||||
onWindowCloseButton: () async {
|
||||
tabController.clear();
|
||||
return true;
|
||||
},
|
||||
tail: AddButton(),
|
||||
labelGetter: DesktopTab.tablabelGetter,
|
||||
),
|
||||
);
|
||||
final tabWidget = isLinux
|
||||
? buildVirtualWindowFrame(
|
||||
context,
|
||||
Scaffold(
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
body: child),
|
||||
)
|
||||
: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: MyTheme.color(context).border!)),
|
||||
child: child,
|
||||
);
|
||||
return isMacOS || kUseCompatibleUiMode
|
||||
? tabWidget
|
||||
: Obx(
|
||||
|
@ -7,6 +7,7 @@ import 'package:get/get.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wakelock_plus/wakelock_plus.dart';
|
||||
import 'package:flutter_improved_scrolling/flutter_improved_scrolling.dart';
|
||||
import 'package:flutter_hbb/models/state_model.dart';
|
||||
|
||||
import '../../consts.dart';
|
||||
import '../../common/widgets/overlay.dart';
|
||||
@ -165,6 +166,7 @@ class _RemotePageState extends State<RemotePage>
|
||||
// and let OS to handle events instead.
|
||||
_rawKeyFocusNode.unfocus();
|
||||
}
|
||||
stateGlobal.isFocused.value = false;
|
||||
}
|
||||
|
||||
@override
|
||||
@ -174,6 +176,7 @@ class _RemotePageState extends State<RemotePage>
|
||||
if (isWindows) {
|
||||
_isWindowBlur = false;
|
||||
}
|
||||
stateGlobal.isFocused.value = true;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -131,103 +131,103 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final tabWidget = Obx(
|
||||
() => Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: MyTheme.color(context).border!,
|
||||
width: stateGlobal.windowBorderWidth.value),
|
||||
),
|
||||
child: Scaffold(
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
body: DesktopTab(
|
||||
controller: tabController,
|
||||
onWindowCloseButton: handleWindowCloseButton,
|
||||
tail: const AddButton(),
|
||||
pageViewBuilder: (pageView) => pageView,
|
||||
labelGetter: DesktopTab.tablabelGetter,
|
||||
tabBuilder: (key, icon, label, themeConf) => Obx(() {
|
||||
final connectionType = ConnectionTypeState.find(key);
|
||||
if (!connectionType.isValid()) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
icon,
|
||||
label,
|
||||
],
|
||||
);
|
||||
} else {
|
||||
bool secure =
|
||||
connectionType.secure.value == ConnectionType.strSecure;
|
||||
bool direct =
|
||||
connectionType.direct.value == ConnectionType.strDirect;
|
||||
String msgConn;
|
||||
if (secure && direct) {
|
||||
msgConn = translate("Direct and encrypted connection");
|
||||
} else if (secure && !direct) {
|
||||
msgConn = translate("Relayed and encrypted connection");
|
||||
} else if (!secure && direct) {
|
||||
msgConn = translate("Direct and unencrypted connection");
|
||||
} else {
|
||||
msgConn = translate("Relayed and unencrypted connection");
|
||||
}
|
||||
var msgFingerprint = '${translate('Fingerprint')}:\n';
|
||||
var fingerprint = FingerprintState.find(key).value;
|
||||
if (fingerprint.isEmpty) {
|
||||
fingerprint = 'N/A';
|
||||
}
|
||||
if (fingerprint.length > 5 * 8) {
|
||||
var first = fingerprint.substring(0, 39);
|
||||
var second = fingerprint.substring(40);
|
||||
msgFingerprint += '$first\n$second';
|
||||
} else {
|
||||
msgFingerprint += fingerprint;
|
||||
}
|
||||
final child = Scaffold(
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
body: DesktopTab(
|
||||
controller: tabController,
|
||||
onWindowCloseButton: handleWindowCloseButton,
|
||||
tail: const AddButton(),
|
||||
pageViewBuilder: (pageView) => pageView,
|
||||
labelGetter: DesktopTab.tablabelGetter,
|
||||
tabBuilder: (key, icon, label, themeConf) => Obx(() {
|
||||
final connectionType = ConnectionTypeState.find(key);
|
||||
if (!connectionType.isValid()) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
icon,
|
||||
label,
|
||||
],
|
||||
);
|
||||
} else {
|
||||
bool secure =
|
||||
connectionType.secure.value == ConnectionType.strSecure;
|
||||
bool direct =
|
||||
connectionType.direct.value == ConnectionType.strDirect;
|
||||
String msgConn;
|
||||
if (secure && direct) {
|
||||
msgConn = translate("Direct and encrypted connection");
|
||||
} else if (secure && !direct) {
|
||||
msgConn = translate("Relayed and encrypted connection");
|
||||
} else if (!secure && direct) {
|
||||
msgConn = translate("Direct and unencrypted connection");
|
||||
} else {
|
||||
msgConn = translate("Relayed and unencrypted connection");
|
||||
}
|
||||
var msgFingerprint = '${translate('Fingerprint')}:\n';
|
||||
var fingerprint = FingerprintState.find(key).value;
|
||||
if (fingerprint.isEmpty) {
|
||||
fingerprint = 'N/A';
|
||||
}
|
||||
if (fingerprint.length > 5 * 8) {
|
||||
var first = fingerprint.substring(0, 39);
|
||||
var second = fingerprint.substring(40);
|
||||
msgFingerprint += '$first\n$second';
|
||||
} else {
|
||||
msgFingerprint += fingerprint;
|
||||
}
|
||||
|
||||
final tab = Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
icon,
|
||||
Tooltip(
|
||||
message: '$msgConn\n$msgFingerprint',
|
||||
child: SvgPicture.asset(
|
||||
'assets/${connectionType.secure.value}${connectionType.direct.value}.svg',
|
||||
width: themeConf.iconSize,
|
||||
height: themeConf.iconSize,
|
||||
).paddingOnly(right: 5),
|
||||
),
|
||||
label,
|
||||
unreadMessageCountBuilder(UnreadChatCountState.find(key))
|
||||
.marginOnly(left: 4),
|
||||
],
|
||||
);
|
||||
final tab = Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
icon,
|
||||
Tooltip(
|
||||
message: '$msgConn\n$msgFingerprint',
|
||||
child: SvgPicture.asset(
|
||||
'assets/${connectionType.secure.value}${connectionType.direct.value}.svg',
|
||||
width: themeConf.iconSize,
|
||||
height: themeConf.iconSize,
|
||||
).paddingOnly(right: 5),
|
||||
),
|
||||
label,
|
||||
unreadMessageCountBuilder(UnreadChatCountState.find(key))
|
||||
.marginOnly(left: 4),
|
||||
],
|
||||
);
|
||||
|
||||
return Listener(
|
||||
onPointerDown: (e) {
|
||||
if (e.kind != ui.PointerDeviceKind.mouse) {
|
||||
return;
|
||||
}
|
||||
final remotePage = tabController.state.value.tabs
|
||||
.firstWhere((tab) => tab.key == key)
|
||||
.page as RemotePage;
|
||||
if (remotePage.ffi.ffiModel.pi.isSet.isTrue &&
|
||||
e.buttons == 2) {
|
||||
showRightMenu(
|
||||
(CancelFunc cancelFunc) {
|
||||
return _tabMenuBuilder(key, cancelFunc);
|
||||
},
|
||||
target: e.position,
|
||||
);
|
||||
}
|
||||
},
|
||||
child: tab,
|
||||
);
|
||||
}
|
||||
}),
|
||||
),
|
||||
),
|
||||
return Listener(
|
||||
onPointerDown: (e) {
|
||||
if (e.kind != ui.PointerDeviceKind.mouse) {
|
||||
return;
|
||||
}
|
||||
final remotePage = tabController.state.value.tabs
|
||||
.firstWhere((tab) => tab.key == key)
|
||||
.page as RemotePage;
|
||||
if (remotePage.ffi.ffiModel.pi.isSet.isTrue && e.buttons == 2) {
|
||||
showRightMenu(
|
||||
(CancelFunc cancelFunc) {
|
||||
return _tabMenuBuilder(key, cancelFunc);
|
||||
},
|
||||
target: e.position,
|
||||
);
|
||||
}
|
||||
},
|
||||
child: tab,
|
||||
);
|
||||
}
|
||||
}),
|
||||
),
|
||||
);
|
||||
final tabWidget = isLinux
|
||||
? buildVirtualWindowFrame(context, child)
|
||||
: Obx(() => Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: MyTheme.color(context).border!,
|
||||
width: stateGlobal.windowBorderWidth.value),
|
||||
),
|
||||
child: child,
|
||||
));
|
||||
return isMacOS || kUseCompatibleUiMode
|
||||
? tabWidget
|
||||
: Obx(() => SubWindowDragToResizeArea(
|
||||
|
@ -77,14 +77,20 @@ class _DesktopServerPageState extends State<DesktopServerPage>
|
||||
ChangeNotifierProvider.value(value: gFFI.chatModel),
|
||||
],
|
||||
child: Consumer<ServerModel>(
|
||||
builder: (context, serverModel, child) => Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: MyTheme.color(context).border!)),
|
||||
child: Scaffold(
|
||||
builder: (context, serverModel, child) {
|
||||
final body = Scaffold(
|
||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
body: ConnectionManager(),
|
||||
),
|
||||
),
|
||||
);
|
||||
return isLinux
|
||||
? buildVirtualWindowFrame(context, body)
|
||||
: Container(
|
||||
decoration: BoxDecoration(
|
||||
border:
|
||||
Border.all(color: MyTheme.color(context).border!)),
|
||||
child: body,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ class DesktopFileTransferScreen extends StatelessWidget {
|
||||
ChangeNotifierProvider.value(value: gFFI.canvasModel),
|
||||
],
|
||||
child: Scaffold(
|
||||
backgroundColor: isLinux ? Colors.transparent : null,
|
||||
body: FileManagerTabPage(
|
||||
params: params,
|
||||
),
|
||||
|
@ -17,6 +17,7 @@ class DesktopPortForwardScreen extends StatelessWidget {
|
||||
ChangeNotifierProvider.value(value: gFFI.ffiModel),
|
||||
],
|
||||
child: Scaffold(
|
||||
backgroundColor: isLinux ? Colors.transparent : null,
|
||||
body: PortForwardTabPage(
|
||||
params: params,
|
||||
),
|
||||
|
@ -548,6 +548,16 @@ class WindowActionPanelState extends State<WindowActionPanel>
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
void onWindowFocus() {
|
||||
stateGlobal.isFocused.value = true;
|
||||
}
|
||||
|
||||
@override
|
||||
void onWindowBlur() {
|
||||
stateGlobal.isFocused.value = false;
|
||||
}
|
||||
|
||||
@override
|
||||
void onWindowMinimize() {
|
||||
stateGlobal.setMinimized(true);
|
||||
|
@ -440,6 +440,9 @@ class _AppState extends State<App> {
|
||||
if (isDesktop && desktopType == DesktopType.main) {
|
||||
child = keyListenerBuilder(context, child);
|
||||
}
|
||||
if (isLinux) {
|
||||
child = buildVirtualWindowFrame(context, child);
|
||||
}
|
||||
return child;
|
||||
},
|
||||
),
|
||||
|
@ -20,6 +20,7 @@ class StateGlobal {
|
||||
final svcStatus = SvcStatus.notReady.obs;
|
||||
// Only used for macOS
|
||||
bool? closeOnFullscreen;
|
||||
final RxBool isFocused = false.obs;
|
||||
|
||||
String _inputSource = '';
|
||||
|
||||
|
@ -21,7 +21,6 @@ static void my_application_activate(GApplication* application) {
|
||||
MyApplication* self = MY_APPLICATION(application);
|
||||
GtkWindow* window =
|
||||
GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
|
||||
// we have custom window frame
|
||||
gtk_window_set_decorated(window, FALSE);
|
||||
// try setting icon for rustdesk, which uses the system cache
|
||||
GtkIconTheme* theme = gtk_icon_theme_get_default();
|
||||
@ -75,12 +74,7 @@ static void my_application_activate(GApplication* application) {
|
||||
|
||||
FlView* view = fl_view_new(project);
|
||||
gtk_widget_show(GTK_WIDGET(view));
|
||||
|
||||
auto border_frame = gtk_frame_new(nullptr);
|
||||
gtk_frame_set_shadow_type(GTK_FRAME(border_frame), GTK_SHADOW_ETCHED_IN);
|
||||
gtk_container_add(GTK_CONTAINER(border_frame), GTK_WIDGET(view));
|
||||
gtk_widget_show(GTK_WIDGET(border_frame));
|
||||
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(border_frame));
|
||||
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
|
||||
|
||||
fl_register_plugins(FL_PLUGIN_REGISTRY(view));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user