refact: window frame border (#7946)

Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
fufesou 2024-05-08 09:59:05 +08:00 committed by GitHub
parent 26adc557bf
commit 01322146c0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 213 additions and 134 deletions

View File

@ -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,
),
),
);
}

View File

@ -154,9 +154,14 @@ const kDefaultScrollDuration = Duration(milliseconds: 50);
const kDefaultMouseWheelThrottleDuration = Duration(milliseconds: 50); const kDefaultMouseWheelThrottleDuration = Duration(milliseconds: 50);
const kFullScreenEdgeSize = 0.0; const kFullScreenEdgeSize = 0.0;
const kMaximizeEdgeSize = 0.0; const kMaximizeEdgeSize = 0.0;
var kWindowEdgeSize = isWindows ? 1.0 : 5.0; final kWindowEdgeSize = isWindows ? 1.0 : 5.0;
const kWindowBorderWidth = 1.0; final kWindowBorderWidth = isLinux ? 1.0 : 0.0;
const kDesktopMenuPadding = EdgeInsets.only(left: 12.0, right: 3.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'; const kInvalidValueStr = 'InvalidValueStr';

View File

@ -91,17 +91,20 @@ class _FileManagerTabPageState extends State<FileManagerTabPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final tabWidget = Container( final child = Scaffold(
decoration: BoxDecoration(
border: Border.all(color: MyTheme.color(context).border!)),
child: Scaffold(
backgroundColor: Theme.of(context).cardColor, backgroundColor: Theme.of(context).cardColor,
body: DesktopTab( body: DesktopTab(
controller: tabController, controller: tabController,
onWindowCloseButton: handleWindowCloseButton, onWindowCloseButton: handleWindowCloseButton,
tail: const AddButton(), tail: const AddButton(),
labelGetter: DesktopTab.tablabelGetter, 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 return isMacOS || kUseCompatibleUiMode
? tabWidget ? tabWidget

View File

@ -97,10 +97,7 @@ class _PortForwardTabPageState extends State<PortForwardTabPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final tabWidget = Container( final child = Scaffold(
decoration: BoxDecoration(
border: Border.all(color: MyTheme.color(context).border!)),
child: Scaffold(
backgroundColor: Theme.of(context).colorScheme.background, backgroundColor: Theme.of(context).colorScheme.background,
body: DesktopTab( body: DesktopTab(
controller: tabController, controller: tabController,
@ -110,7 +107,19 @@ class _PortForwardTabPageState extends State<PortForwardTabPage> {
}, },
tail: AddButton(), tail: AddButton(),
labelGetter: DesktopTab.tablabelGetter, 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 return isMacOS || kUseCompatibleUiMode
? tabWidget ? tabWidget

View File

@ -7,6 +7,7 @@ import 'package:get/get.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:wakelock_plus/wakelock_plus.dart'; import 'package:wakelock_plus/wakelock_plus.dart';
import 'package:flutter_improved_scrolling/flutter_improved_scrolling.dart'; import 'package:flutter_improved_scrolling/flutter_improved_scrolling.dart';
import 'package:flutter_hbb/models/state_model.dart';
import '../../consts.dart'; import '../../consts.dart';
import '../../common/widgets/overlay.dart'; import '../../common/widgets/overlay.dart';
@ -165,6 +166,7 @@ class _RemotePageState extends State<RemotePage>
// and let OS to handle events instead. // and let OS to handle events instead.
_rawKeyFocusNode.unfocus(); _rawKeyFocusNode.unfocus();
} }
stateGlobal.isFocused.value = false;
} }
@override @override
@ -174,6 +176,7 @@ class _RemotePageState extends State<RemotePage>
if (isWindows) { if (isWindows) {
_isWindowBlur = false; _isWindowBlur = false;
} }
stateGlobal.isFocused.value = true;
} }
@override @override

View File

@ -131,14 +131,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final tabWidget = Obx( final child = Scaffold(
() => Container(
decoration: BoxDecoration(
border: Border.all(
color: MyTheme.color(context).border!,
width: stateGlobal.windowBorderWidth.value),
),
child: Scaffold(
backgroundColor: Theme.of(context).colorScheme.background, backgroundColor: Theme.of(context).colorScheme.background,
body: DesktopTab( body: DesktopTab(
controller: tabController, controller: tabController,
@ -210,8 +203,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
final remotePage = tabController.state.value.tabs final remotePage = tabController.state.value.tabs
.firstWhere((tab) => tab.key == key) .firstWhere((tab) => tab.key == key)
.page as RemotePage; .page as RemotePage;
if (remotePage.ffi.ffiModel.pi.isSet.isTrue && if (remotePage.ffi.ffiModel.pi.isSet.isTrue && e.buttons == 2) {
e.buttons == 2) {
showRightMenu( showRightMenu(
(CancelFunc cancelFunc) { (CancelFunc cancelFunc) {
return _tabMenuBuilder(key, cancelFunc); return _tabMenuBuilder(key, cancelFunc);
@ -225,9 +217,17 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
} }
}), }),
), ),
),
),
); );
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 return isMacOS || kUseCompatibleUiMode
? tabWidget ? tabWidget
: Obx(() => SubWindowDragToResizeArea( : Obx(() => SubWindowDragToResizeArea(

View File

@ -77,14 +77,20 @@ class _DesktopServerPageState extends State<DesktopServerPage>
ChangeNotifierProvider.value(value: gFFI.chatModel), ChangeNotifierProvider.value(value: gFFI.chatModel),
], ],
child: Consumer<ServerModel>( child: Consumer<ServerModel>(
builder: (context, serverModel, child) => Container( builder: (context, serverModel, child) {
decoration: BoxDecoration( final body = Scaffold(
border: Border.all(color: MyTheme.color(context).border!)),
child: Scaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor, backgroundColor: Theme.of(context).scaffoldBackgroundColor,
body: ConnectionManager(), body: ConnectionManager(),
), );
), return isLinux
? buildVirtualWindowFrame(context, body)
: Container(
decoration: BoxDecoration(
border:
Border.all(color: MyTheme.color(context).border!)),
child: body,
);
},
), ),
); );
} }

View File

@ -20,6 +20,7 @@ class DesktopFileTransferScreen extends StatelessWidget {
ChangeNotifierProvider.value(value: gFFI.canvasModel), ChangeNotifierProvider.value(value: gFFI.canvasModel),
], ],
child: Scaffold( child: Scaffold(
backgroundColor: isLinux ? Colors.transparent : null,
body: FileManagerTabPage( body: FileManagerTabPage(
params: params, params: params,
), ),

View File

@ -17,6 +17,7 @@ class DesktopPortForwardScreen extends StatelessWidget {
ChangeNotifierProvider.value(value: gFFI.ffiModel), ChangeNotifierProvider.value(value: gFFI.ffiModel),
], ],
child: Scaffold( child: Scaffold(
backgroundColor: isLinux ? Colors.transparent : null,
body: PortForwardTabPage( body: PortForwardTabPage(
params: params, params: params,
), ),

View File

@ -548,6 +548,16 @@ class WindowActionPanelState extends State<WindowActionPanel>
setState(() {}); setState(() {});
} }
@override
void onWindowFocus() {
stateGlobal.isFocused.value = true;
}
@override
void onWindowBlur() {
stateGlobal.isFocused.value = false;
}
@override @override
void onWindowMinimize() { void onWindowMinimize() {
stateGlobal.setMinimized(true); stateGlobal.setMinimized(true);

View File

@ -440,6 +440,9 @@ class _AppState extends State<App> {
if (isDesktop && desktopType == DesktopType.main) { if (isDesktop && desktopType == DesktopType.main) {
child = keyListenerBuilder(context, child); child = keyListenerBuilder(context, child);
} }
if (isLinux) {
child = buildVirtualWindowFrame(context, child);
}
return child; return child;
}, },
), ),

View File

@ -20,6 +20,7 @@ class StateGlobal {
final svcStatus = SvcStatus.notReady.obs; final svcStatus = SvcStatus.notReady.obs;
// Only used for macOS // Only used for macOS
bool? closeOnFullscreen; bool? closeOnFullscreen;
final RxBool isFocused = false.obs;
String _inputSource = ''; String _inputSource = '';

View File

@ -21,7 +21,6 @@ static void my_application_activate(GApplication* application) {
MyApplication* self = MY_APPLICATION(application); MyApplication* self = MY_APPLICATION(application);
GtkWindow* window = GtkWindow* window =
GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
// we have custom window frame
gtk_window_set_decorated(window, FALSE); gtk_window_set_decorated(window, FALSE);
// try setting icon for rustdesk, which uses the system cache // try setting icon for rustdesk, which uses the system cache
GtkIconTheme* theme = gtk_icon_theme_get_default(); GtkIconTheme* theme = gtk_icon_theme_get_default();
@ -75,12 +74,7 @@ static void my_application_activate(GApplication* application) {
FlView* view = fl_view_new(project); FlView* view = fl_view_new(project);
gtk_widget_show(GTK_WIDGET(view)); gtk_widget_show(GTK_WIDGET(view));
gtk_container_add(GTK_CONTAINER(window), 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));
fl_register_plugins(FL_PLUGIN_REGISTRY(view)); fl_register_plugins(FL_PLUGIN_REGISTRY(view));