Last Updated on 2024-08-20 by Clay
Recently, I started experimenting with Flutter to develop desktop applications. Since I’m using the Linux Gnome desktop, its default system window bar (the top strip) is completely black, which doesn't match the light and playful tone of the app I’m developing. So, I found a great tool: bitsdojo_window.
The strength of this package is that it supports Windows, MacOS, and Linux simultaneously. However, it’s a bit tricky as it requires some adjustments, not just a simple installation.
bitsdojo_window usage guide (mainly for Linux)
- Check the pub.dev page of bitsdojo_window to confirm the latest version and syntax
- Add the package to your pubspec.yaml file
- Modify linux/my_application.cc
- Test the sample code
Step 1. Check the pub.dev page of bitsdojo_window to confirm the latest version and syntax
On my end, the latest version of bitsdojo_window on pub.dev is 0.1.6, so I’ll be adding this version.
Step 2: Add the package to your pubspec.yaml file
dependencies:
flutter:
sdk: flutter
bitsdojo_window: ^0.1.6
Then, get the package:
flutter pub get
Step 3: Modify linux/my_application.cc
When using bitsdojo_window
on Linux, we need to modify the linux/my_application.cc
file. Locate the following code:
gtk_window_set_default_size(window, 1280, 720);
gtk_widget_show(GTK_WIDGET(window));
And change it to:
auto bdw = bitsdojo_window_from(window);
bdw->setCustomFrame(true);
// gtk_window_set_default_size(window, 1280, 720); // <-- Comment this line
gtk_widget_show(GTK_WIDGET(window));
This allows the application to use a custom window frame instead of the system’s title bar.
Additionally, make sure that at the beginning of the file, you have included bitsdojo_window_plugin.h
:
#include <bitsdojo_window_linux/bitsdojo_window_plugin.h>
Step 4: Test the sample code
Here, I’m running the official sample code directly:
import 'package:flutter/material.dart';
import 'package:bitsdojo_window/bitsdojo_window.dart';
void main() {
runApp(const MyApp());
doWhenWindowReady(() {
final win = appWindow;
const initialSize = Size(600, 450);
win.minSize = initialSize;
win.size = initialSize;
win.alignment = Alignment.center;
win.title = "Custom window with Flutter";
win.show();
});
}
const borderColor = Color(0xFF805306);
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: WindowBorder(
color: borderColor,
width: 1,
child: Row(
children: const [LeftSide(), RightSide()],
),
),
),
);
}
}
const sidebarColor = Color(0xFFF6A00C);
class LeftSide extends StatelessWidget {
const LeftSide({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return SizedBox(
width: 200,
child: Container(
color: sidebarColor,
child: Column(
children: [
WindowTitleBarBox(child: MoveWindow()),
Expanded(child: Container())
],
)));
}
}
const backgroundStartColor = Color(0xFFFFD500);
const backgroundEndColor = Color(0xFFF6A00C);
class RightSide extends StatelessWidget {
const RightSide({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Expanded(
child: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [backgroundStartColor, backgroundEndColor],
stops: [0.0, 1.0]),
),
child: Column(children: [
WindowTitleBarBox(
child: Row(
children: [Expanded(child: MoveWindow()), const WindowButtons()],
),
)
]),
),
);
}
}
final buttonColors = WindowButtonColors(
iconNormal: const Color(0xFF805306),
mouseOver: const Color(0xFFF6A00C),
mouseDown: const Color(0xFF805306),
iconMouseOver: const Color(0xFF805306),
iconMouseDown: const Color(0xFFFFD500));
final closeButtonColors = WindowButtonColors(
mouseOver: const Color(0xFFD32F2F),
mouseDown: const Color(0xFFB71C1C),
iconNormal: const Color(0xFF805306),
iconMouseOver: Colors.white);
class WindowButtons extends StatelessWidget {
const WindowButtons({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Row(
children: [
MinimizeWindowButton(colors: buttonColors),
MaximizeWindowButton(colors: buttonColors),
CloseWindowButton(colors: closeButtonColors),
],
);
}
}
Output:
As you can see, we’ve successfully applied the custom window title bar!
This will be crucial for the art style I’m aiming for in my next attempts.
References
- https://pub.dev/packages/bitsdojo_window
- How to Remove Title Bar from Flutter app built for windows?