Fix feed tag search and prepare 2.0.1+22
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
# This file should be version controlled and should not be manually edited.
|
# This file should be version controlled and should not be manually edited.
|
||||||
|
|
||||||
version:
|
version:
|
||||||
revision: "ff37bef603469fb030f2b72995ab929ccfc227f0"
|
revision: "559ffa3f75e7402d65a8def9c28389a9b2e6fe42"
|
||||||
channel: "stable"
|
channel: "stable"
|
||||||
|
|
||||||
project_type: app
|
project_type: app
|
||||||
@@ -13,17 +13,11 @@ project_type: app
|
|||||||
migration:
|
migration:
|
||||||
platforms:
|
platforms:
|
||||||
- platform: root
|
- platform: root
|
||||||
create_revision: ff37bef603469fb030f2b72995ab929ccfc227f0
|
create_revision: 559ffa3f75e7402d65a8def9c28389a9b2e6fe42
|
||||||
base_revision: ff37bef603469fb030f2b72995ab929ccfc227f0
|
base_revision: 559ffa3f75e7402d65a8def9c28389a9b2e6fe42
|
||||||
- platform: android
|
|
||||||
create_revision: ff37bef603469fb030f2b72995ab929ccfc227f0
|
|
||||||
base_revision: ff37bef603469fb030f2b72995ab929ccfc227f0
|
|
||||||
- platform: linux
|
- platform: linux
|
||||||
create_revision: ff37bef603469fb030f2b72995ab929ccfc227f0
|
create_revision: 559ffa3f75e7402d65a8def9c28389a9b2e6fe42
|
||||||
base_revision: ff37bef603469fb030f2b72995ab929ccfc227f0
|
base_revision: 559ffa3f75e7402d65a8def9c28389a9b2e6fe42
|
||||||
- platform: windows
|
|
||||||
create_revision: ff37bef603469fb030f2b72995ab929ccfc227f0
|
|
||||||
base_revision: ff37bef603469fb030f2b72995ab929ccfc227f0
|
|
||||||
|
|
||||||
# User provided section
|
# User provided section
|
||||||
|
|
||||||
|
|||||||
@@ -101,4 +101,4 @@ ISCC.exe installer\Lunaris.iss
|
|||||||
- Приложение уважает API и rate limits сайтов.
|
- Приложение уважает API и rate limits сайтов.
|
||||||
- NSFW/blur/blacklist настраиваются локально.
|
- NSFW/blur/blacklist настраиваются локально.
|
||||||
- API keys/custom headers хранятся локально и экспортируются только через явный export settings.
|
- API keys/custom headers хранятся локально и экспортируются только через явный export settings.
|
||||||
- Локальные пути скачанных файлов не попадают в JSON export/import.
|
- Локальные пути скачанных файлов не попадают в JSON export/import.
|
||||||
|
|||||||
+8
-8
@@ -1,11 +1,11 @@
|
|||||||
/.gradle
|
/.gradle
|
||||||
/captures/
|
/captures/
|
||||||
/local.properties
|
/local.properties
|
||||||
GeneratedPluginRegistrant.java
|
GeneratedPluginRegistrant.java
|
||||||
.cxx/
|
.cxx/
|
||||||
|
|
||||||
# Remember to never publicly share your keystore.
|
# Remember to never publicly share your keystore.
|
||||||
# See https://flutter.dev/to/reference-keystore
|
# See https://flutter.dev/to/reference-keystore
|
||||||
key.properties
|
key.properties
|
||||||
**/*.keystore
|
**/*.keystore
|
||||||
**/*.jks
|
**/*.jks
|
||||||
|
|||||||
@@ -1,44 +1,44 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("com.android.application")
|
id("com.android.application")
|
||||||
id("kotlin-android")
|
id("kotlin-android")
|
||||||
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
|
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
|
||||||
id("dev.flutter.flutter-gradle-plugin")
|
id("dev.flutter.flutter-gradle-plugin")
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "com.example.gel_rule_app"
|
namespace = "com.example.gel_rule_app"
|
||||||
compileSdk = flutter.compileSdkVersion
|
compileSdk = flutter.compileSdkVersion
|
||||||
ndkVersion = flutter.ndkVersion
|
ndkVersion = flutter.ndkVersion
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
targetCompatibility = JavaVersion.VERSION_17
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = JavaVersion.VERSION_17.toString()
|
jvmTarget = JavaVersion.VERSION_17.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||||
applicationId = "com.example.gel_rule_app"
|
applicationId = "com.example.gel_rule_app"
|
||||||
// You can update the following values to match your application needs.
|
// You can update the following values to match your application needs.
|
||||||
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
||||||
minSdk = flutter.minSdkVersion
|
minSdk = flutter.minSdkVersion
|
||||||
targetSdk = flutter.targetSdkVersion
|
targetSdk = flutter.targetSdkVersion
|
||||||
versionCode = flutter.versionCode
|
versionCode = flutter.versionCode
|
||||||
versionName = flutter.versionName
|
versionName = flutter.versionName
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
// TODO: Add your own signing config for the release build.
|
// TODO: Add your own signing config for the release build.
|
||||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||||
signingConfig = signingConfigs.getByName("debug")
|
signingConfig = signingConfigs.getByName("debug")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flutter {
|
flutter {
|
||||||
source = "../.."
|
source = "../.."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<!-- The INTERNET permission is required for development. Specifically,
|
<!-- The INTERNET permission is required for development. Specifically,
|
||||||
the Flutter tool needs it to communicate with the running application
|
the Flutter tool needs it to communicate with the running application
|
||||||
to allow setting breakpoints, to provide hot reload, etc.
|
to allow setting breakpoints, to provide hot reload, etc.
|
||||||
-->
|
-->
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -4,32 +4,32 @@
|
|||||||
|
|
||||||
<application
|
<application
|
||||||
android:label="Lunaris"
|
android:label="Lunaris"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
android:icon="@mipmap/ic_launcher">
|
android:icon="@mipmap/ic_launcher">
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:taskAffinity=""
|
android:taskAffinity=""
|
||||||
android:theme="@style/LaunchTheme"
|
android:theme="@style/LaunchTheme"
|
||||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="true"
|
||||||
android:windowSoftInputMode="adjustResize">
|
android:windowSoftInputMode="adjustResize">
|
||||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||||
the Android process has started. This theme is visible to the user
|
the Android process has started. This theme is visible to the user
|
||||||
while the Flutter UI initializes. After that, this theme continues
|
while the Flutter UI initializes. After that, this theme continues
|
||||||
to determine the Window background behind the Flutter UI. -->
|
to determine the Window background behind the Flutter UI. -->
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="io.flutter.embedding.android.NormalTheme"
|
android:name="io.flutter.embedding.android.NormalTheme"
|
||||||
android:resource="@style/NormalTheme"
|
android:resource="@style/NormalTheme"
|
||||||
/>
|
/>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<!-- Don't delete the meta-data below.
|
<!-- Don't delete the meta-data below.
|
||||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="flutterEmbedding"
|
android:name="flutterEmbedding"
|
||||||
android:value="2" />
|
android:value="2" />
|
||||||
@@ -43,15 +43,15 @@
|
|||||||
android:resource="@xml/file_paths" />
|
android:resource="@xml/file_paths" />
|
||||||
</provider>
|
</provider>
|
||||||
</application>
|
</application>
|
||||||
<!-- Required to query activities that can process text, see:
|
<!-- Required to query activities that can process text, see:
|
||||||
https://developer.android.com/training/package-visibility and
|
https://developer.android.com/training/package-visibility and
|
||||||
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
|
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
|
||||||
|
|
||||||
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
||||||
<queries>
|
<queries>
|
||||||
<intent>
|
<intent>
|
||||||
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
||||||
<data android:mimeType="text/plain"/>
|
<data android:mimeType="text/plain"/>
|
||||||
</intent>
|
</intent>
|
||||||
</queries>
|
</queries>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!-- Modify this file to customize your launch splash screen -->
|
<!-- Modify this file to customize your launch splash screen -->
|
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<item android:drawable="@color/launch_background" />
|
<item android:drawable="@color/launch_background" />
|
||||||
|
|
||||||
<!-- You can insert your own image assets here -->
|
<!-- You can insert your own image assets here -->
|
||||||
<!-- <item>
|
<!-- <item>
|
||||||
<bitmap
|
<bitmap
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:src="@mipmap/launch_image" />
|
android:src="@mipmap/launch_image" />
|
||||||
</item> -->
|
</item> -->
|
||||||
</layer-list>
|
</layer-list>
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!-- Modify this file to customize your launch splash screen -->
|
<!-- Modify this file to customize your launch splash screen -->
|
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<item android:drawable="@color/launch_background" />
|
<item android:drawable="@color/launch_background" />
|
||||||
|
|
||||||
<!-- You can insert your own image assets here -->
|
<!-- You can insert your own image assets here -->
|
||||||
<!-- <item>
|
<!-- <item>
|
||||||
<bitmap
|
<bitmap
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:src="@mipmap/launch_image" />
|
android:src="@mipmap/launch_image" />
|
||||||
</item> -->
|
</item> -->
|
||||||
</layer-list>
|
</layer-list>
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
|
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
|
||||||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||||
<!-- Show a splash screen on the activity. Automatically removed when
|
<!-- Show a splash screen on the activity. Automatically removed when
|
||||||
the Flutter engine draws its first frame -->
|
the Flutter engine draws its first frame -->
|
||||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||||
</style>
|
</style>
|
||||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||||
This theme determines the color of the Android Window while your
|
This theme determines the color of the Android Window while your
|
||||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||||
running.
|
running.
|
||||||
|
|
||||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||||
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||||
<item name="android:windowBackground">?android:colorBackground</item>
|
<item name="android:windowBackground">?android:colorBackground</item>
|
||||||
</style>
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||||
<style name="LaunchTheme" parent="@android:style/Theme.NoTitleBar">
|
<style name="LaunchTheme" parent="@android:style/Theme.NoTitleBar">
|
||||||
<!-- Show a splash screen on the activity. Automatically removed when
|
<!-- Show a splash screen on the activity. Automatically removed when
|
||||||
the Flutter engine draws its first frame -->
|
the Flutter engine draws its first frame -->
|
||||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||||
</style>
|
</style>
|
||||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||||
This theme determines the color of the Android Window while your
|
This theme determines the color of the Android Window while your
|
||||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||||
running.
|
running.
|
||||||
|
|
||||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||||
<style name="NormalTheme" parent="@android:style/Theme.NoTitleBar">
|
<style name="NormalTheme" parent="@android:style/Theme.NoTitleBar">
|
||||||
<item name="android:windowBackground">#101114</item>
|
<item name="android:windowBackground">#101114</item>
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<!-- The INTERNET permission is required for development. Specifically,
|
<!-- The INTERNET permission is required for development. Specifically,
|
||||||
the Flutter tool needs it to communicate with the running application
|
the Flutter tool needs it to communicate with the running application
|
||||||
to allow setting breakpoints, to provide hot reload, etc.
|
to allow setting breakpoints, to provide hot reload, etc.
|
||||||
-->
|
-->
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
+13
-13
@@ -4,19 +4,19 @@ allprojects {
|
|||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val newBuildDir: Directory =
|
val newBuildDir: Directory =
|
||||||
rootProject.layout.buildDirectory
|
rootProject.layout.buildDirectory
|
||||||
.dir("../../build")
|
.dir("../../build")
|
||||||
.get()
|
.get()
|
||||||
rootProject.layout.buildDirectory.value(newBuildDir)
|
rootProject.layout.buildDirectory.value(newBuildDir)
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
|
val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
|
||||||
project.layout.buildDirectory.value(newSubprojectBuildDir)
|
project.layout.buildDirectory.value(newSubprojectBuildDir)
|
||||||
}
|
}
|
||||||
subprojects {
|
subprojects {
|
||||||
project.evaluationDependsOn(":app")
|
project.evaluationDependsOn(":app")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +1,6 @@
|
|||||||
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
|
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
|
# This builtInKotlin flag was added automatically by Flutter migrator
|
||||||
|
android.builtInKotlin=false
|
||||||
|
# This newDsl flag was added automatically by Flutter migrator
|
||||||
|
android.newDsl=false
|
||||||
|
|||||||
+5
-5
@@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip
|
||||||
|
|||||||
Vendored
+90
-90
@@ -1,90 +1,90 @@
|
|||||||
@if "%DEBUG%" == "" @echo off
|
@if "%DEBUG%" == "" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@rem
|
@rem
|
||||||
@rem Gradle startup script for Windows
|
@rem Gradle startup script for Windows
|
||||||
@rem
|
@rem
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
|
|
||||||
@rem Set local scope for the variables with windows NT shell
|
@rem Set local scope for the variables with windows NT shell
|
||||||
if "%OS%"=="Windows_NT" setlocal
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
set DEFAULT_JVM_OPTS=
|
set DEFAULT_JVM_OPTS=
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%" == "" set DIRNAME=.
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
@rem Find java.exe
|
@rem Find java.exe
|
||||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
set JAVA_EXE=java.exe
|
set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if "%ERRORLEVEL%" == "0" goto init
|
if "%ERRORLEVEL%" == "0" goto init
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
echo.
|
echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation.
|
echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:findJavaFromJavaHome
|
:findJavaFromJavaHome
|
||||||
set JAVA_HOME=%JAVA_HOME:"=%
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
if exist "%JAVA_EXE%" goto init
|
if exist "%JAVA_EXE%" goto init
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
echo.
|
echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation.
|
echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:init
|
:init
|
||||||
@rem Get command-line arguments, handling Windowz variants
|
@rem Get command-line arguments, handling Windowz variants
|
||||||
|
|
||||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||||
|
|
||||||
:win9xME_args
|
:win9xME_args
|
||||||
@rem Slurp the command line arguments.
|
@rem Slurp the command line arguments.
|
||||||
set CMD_LINE_ARGS=
|
set CMD_LINE_ARGS=
|
||||||
set _SKIP=2
|
set _SKIP=2
|
||||||
|
|
||||||
:win9xME_args_slurp
|
:win9xME_args_slurp
|
||||||
if "x%~1" == "x" goto execute
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
set CMD_LINE_ARGS=%*
|
set CMD_LINE_ARGS=%*
|
||||||
goto execute
|
goto execute
|
||||||
|
|
||||||
:4NT_args
|
:4NT_args
|
||||||
@rem Get arguments from the 4NT Shell from JP Software
|
@rem Get arguments from the 4NT Shell from JP Software
|
||||||
set CMD_LINE_ARGS=%$
|
set CMD_LINE_ARGS=%$
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
@rem Execute Gradle
|
@rem Execute Gradle
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
rem the _cmd.exe /c_ return code!
|
rem the _cmd.exe /c_ return code!
|
||||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
exit /b 1
|
exit /b 1
|
||||||
|
|
||||||
:mainEnd
|
:mainEnd
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
:omega
|
:omega
|
||||||
|
|||||||
+26
-26
@@ -1,26 +1,26 @@
|
|||||||
pluginManagement {
|
pluginManagement {
|
||||||
val flutterSdkPath =
|
val flutterSdkPath =
|
||||||
run {
|
run {
|
||||||
val properties = java.util.Properties()
|
val properties = java.util.Properties()
|
||||||
file("local.properties").inputStream().use { properties.load(it) }
|
file("local.properties").inputStream().use { properties.load(it) }
|
||||||
val flutterSdkPath = properties.getProperty("flutter.sdk")
|
val flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||||
require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
|
require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
|
||||||
flutterSdkPath
|
flutterSdkPath
|
||||||
}
|
}
|
||||||
|
|
||||||
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
|
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
|
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
|
||||||
id("com.android.application") version "8.11.1" apply false
|
id("com.android.application") version "8.11.1" apply false
|
||||||
id("org.jetbrains.kotlin.android") version "2.2.20" apply false
|
id("org.jetbrains.kotlin.android") version "2.2.20" apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
include(":app")
|
include(":app")
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
const appDisplayVersion = '2.0.1';
|
const appDisplayVersion = '2.0.1';
|
||||||
const appBuildNumber = 21;
|
const appBuildNumber = 22;
|
||||||
const appReleaseChannel = 'Stable';
|
const appReleaseChannel = 'Stable';
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class _FeedScreenState extends ConsumerState<FeedScreen> {
|
|||||||
final _scrollController = ScrollController();
|
final _scrollController = ScrollController();
|
||||||
final Set<String> _selectedKeys = {};
|
final Set<String> _selectedKeys = {};
|
||||||
bool _selectionMode = false;
|
bool _selectionMode = false;
|
||||||
bool _usedInitialQuery = false;
|
String? _appliedInitialQuery;
|
||||||
Timer? _scrollSaveDebounce;
|
Timer? _scrollSaveDebounce;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -70,10 +70,10 @@ class _FeedScreenState extends ConsumerState<FeedScreen> {
|
|||||||
if (nextQuery != null &&
|
if (nextQuery != null &&
|
||||||
nextQuery.isNotEmpty &&
|
nextQuery.isNotEmpty &&
|
||||||
nextQuery != oldWidget.initialQuery) {
|
nextQuery != oldWidget.initialQuery) {
|
||||||
_usedInitialQuery = true;
|
_appliedInitialQuery = nextQuery;
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
ref.read(feedControllerProvider.notifier).search(nextQuery);
|
_applySearchQuery(nextQuery);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,10 +93,16 @@ class _FeedScreenState extends ConsumerState<FeedScreen> {
|
|||||||
final favoriteKeys = ref.watch(favoriteKeysProvider).value ?? <String>{};
|
final favoriteKeys = ref.watch(favoriteKeysProvider).value ?? <String>{};
|
||||||
final viewedKeys = ref.watch(viewedKeysProvider).value ?? <String>{};
|
final viewedKeys = ref.watch(viewedKeysProvider).value ?? <String>{};
|
||||||
|
|
||||||
if (!_usedInitialQuery && (widget.initialQuery?.isNotEmpty ?? false)) {
|
final initialQuery = widget.initialQuery?.trim();
|
||||||
_usedInitialQuery = true;
|
final currentTags = feed.value?.selectedTags.join(' ');
|
||||||
|
if (initialQuery != null &&
|
||||||
|
initialQuery.isNotEmpty &&
|
||||||
|
_appliedInitialQuery != initialQuery &&
|
||||||
|
currentTags != initialQuery) {
|
||||||
|
_appliedInitialQuery = initialQuery;
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
ref.read(feedControllerProvider.notifier).search(widget.initialQuery!);
|
if (!mounted) return;
|
||||||
|
_applySearchQuery(initialQuery);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,17 +165,14 @@ class _FeedScreenState extends ConsumerState<FeedScreen> {
|
|||||||
onSearchChanged: (query) => ref
|
onSearchChanged: (query) => ref
|
||||||
.read(feedControllerProvider.notifier)
|
.read(feedControllerProvider.notifier)
|
||||||
.updateTagSuggestions(query),
|
.updateTagSuggestions(query),
|
||||||
onSuggestionTap: (query) =>
|
onSuggestionTap: _submitSearch,
|
||||||
ref.read(feedControllerProvider.notifier).search(query),
|
|
||||||
onTopPeriodChanged: (period) => ref
|
onTopPeriodChanged: (period) => ref
|
||||||
.read(feedControllerProvider.notifier)
|
.read(feedControllerProvider.notifier)
|
||||||
.setTopPeriod(period),
|
.setTopPeriod(period),
|
||||||
onSearch: (query) =>
|
onSearch: _submitSearch,
|
||||||
ref.read(feedControllerProvider.notifier).search(query),
|
|
||||||
onRefresh: () =>
|
onRefresh: () =>
|
||||||
ref.read(feedControllerProvider.notifier).refresh(),
|
ref.read(feedControllerProvider.notifier).refresh(),
|
||||||
onClearFilters: () =>
|
onClearFilters: _clearFilters,
|
||||||
ref.read(feedControllerProvider.notifier).clearFilters(),
|
|
||||||
selectionMode: _selectionMode,
|
selectionMode: _selectionMode,
|
||||||
onToggleSelectionMode: () {
|
onToggleSelectionMode: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
@@ -279,6 +282,35 @@ class _FeedScreenState extends ConsumerState<FeedScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _submitSearch(String query) {
|
||||||
|
final trimmed = query.trim();
|
||||||
|
if (trimmed.isEmpty) {
|
||||||
|
_clearFilters();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final location = '/?q=${Uri.encodeQueryComponent(trimmed)}';
|
||||||
|
if (widget.initialQuery?.trim() == trimmed) {
|
||||||
|
_applySearchQuery(trimmed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
context.go(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _applySearchQuery(String query) async {
|
||||||
|
await ref.read(feedControllerProvider.notifier).search(query);
|
||||||
|
if (_scrollController.hasClients) {
|
||||||
|
_scrollController.jumpTo(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _clearFilters() async {
|
||||||
|
_appliedInitialQuery = null;
|
||||||
|
await ref.read(feedControllerProvider.notifier).clearFilters();
|
||||||
|
if (mounted && widget.initialQuery != null) {
|
||||||
|
context.go('/');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _toggleSelected(Post post) {
|
void _toggleSelected(Post post) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectionMode = true;
|
_selectionMode = true;
|
||||||
|
|||||||
@@ -3,33 +3,57 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||||||
import '../../../backend/backend.dart';
|
import '../../../backend/backend.dart';
|
||||||
import '../../../core/utils/result.dart';
|
import '../../../core/utils/result.dart';
|
||||||
|
|
||||||
|
// Меняем FutureProvider на StreamProvider
|
||||||
final postDetailsControllerProvider =
|
final postDetailsControllerProvider =
|
||||||
FutureProvider.family<Post?, PostDetailsArgs>((ref, args) async {
|
StreamProvider.family<Post?, PostDetailsArgs>((ref, args) async* {
|
||||||
|
// Правильно собираем зависимости на самом верхнем уровне (фиксим антипаттерн)
|
||||||
|
final providerManager = ref.watch(providerManagerProvider);
|
||||||
|
final cacheService = ref.watch(cacheServiceProvider);
|
||||||
|
final postRepository = ref.watch(postRepositoryProvider);
|
||||||
|
|
||||||
|
// Вспомогательная функция для загрузки тегов
|
||||||
Future<Post?> enrich(Post? post) async {
|
Future<Post?> enrich(Post? post) async {
|
||||||
if (post == null) return null;
|
if (post == null) return null;
|
||||||
final shouldEnrich = post.tagGroups.isEmpty ||
|
final shouldEnrich = post.tagGroups.isEmpty ||
|
||||||
(post.tagGroups.length == 1 && post.tagGroups.containsKey('general'));
|
(post.tagGroups.length == 1 && post.tagGroups.containsKey('general'));
|
||||||
if (!shouldEnrich) return post;
|
if (!shouldEnrich) return post;
|
||||||
final enriched =
|
|
||||||
await ref.watch(providerManagerProvider).enrichPostTags(post);
|
final enriched = await providerManager.enrichPostTags(post);
|
||||||
if (enriched is Success<Post>) {
|
if (enriched is Success<Post>) {
|
||||||
await ref.watch(cacheServiceProvider).cachePosts([enriched.data]);
|
await cacheService.cachePosts([enriched.data]);
|
||||||
return enriched.data;
|
return enriched.data;
|
||||||
}
|
}
|
||||||
return post;
|
return post;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.initialPost != null) return enrich(args.initialPost);
|
// СЦЕНАРИЙ 1: Пост уже передан из ленты (Самый частый случай)
|
||||||
final cached = await ref
|
if (args.initialPost != null) {
|
||||||
.watch(postRepositoryProvider)
|
yield args
|
||||||
.getCachedPost(args.postId, args.providerId);
|
.initialPost; // МГНОВЕННО отдаем пост в UI, экран сразу рендерится!
|
||||||
|
final enriched = await enrich(args.initialPost);
|
||||||
|
yield enriched; // Чуть позже отдаем версию с загруженными тегами
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// СЦЕНАРИЙ 2: Прямой переход (например, по ссылке), проверяем локальный кэш
|
||||||
|
final cached =
|
||||||
|
await postRepository.getCachedPost(args.postId, args.providerId);
|
||||||
if (cached is Success<Post?> && cached.data != null) {
|
if (cached is Success<Post?> && cached.data != null) {
|
||||||
return enrich(cached.data);
|
yield cached.data; // Нашли в кэше — сразу показываем контент
|
||||||
|
final enriched = await enrich(cached.data);
|
||||||
|
yield enriched; // Догружаем теги на фоне
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// СЦЕНАРИЙ 3: Полный фоллбэк, если вообще ничего нет — идем в сеть за самим постом
|
||||||
|
final remote = await providerManager.getPost(args.providerId, args.postId);
|
||||||
|
if (remote is Success<Post?> && remote.data != null) {
|
||||||
|
yield remote.data;
|
||||||
|
final enriched = await enrich(remote.data);
|
||||||
|
yield enriched;
|
||||||
|
} else {
|
||||||
|
yield null;
|
||||||
}
|
}
|
||||||
final remote = await ref
|
|
||||||
.watch(providerManagerProvider)
|
|
||||||
.getPost(args.providerId, args.postId);
|
|
||||||
return remote is Success<Post?> ? enrich(remote.data) : null;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
class PostDetailsArgs {
|
class PostDetailsArgs {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -1 +1 @@
|
|||||||
flutter/ephemeral
|
flutter/ephemeral
|
||||||
|
|||||||
+128
-128
@@ -1,128 +1,128 @@
|
|||||||
# Project-level configuration.
|
# Project-level configuration.
|
||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
project(runner LANGUAGES CXX)
|
project(runner LANGUAGES CXX)
|
||||||
|
|
||||||
# The name of the executable created for the application. Change this to change
|
# The name of the executable created for the application. Change this to change
|
||||||
# the on-disk name of your application.
|
# the on-disk name of your application.
|
||||||
set(BINARY_NAME "gel_rule_app")
|
set(BINARY_NAME "gel_rule_app")
|
||||||
# The unique GTK application identifier for this application. See:
|
# The unique GTK application identifier for this application. See:
|
||||||
# https://wiki.gnome.org/HowDoI/ChooseApplicationID
|
# https://wiki.gnome.org/HowDoI/ChooseApplicationID
|
||||||
set(APPLICATION_ID "com.example.gel_rule_app")
|
set(APPLICATION_ID "com.example.gel_rule_app")
|
||||||
|
|
||||||
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
|
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
|
||||||
# versions of CMake.
|
# versions of CMake.
|
||||||
cmake_policy(SET CMP0063 NEW)
|
cmake_policy(SET CMP0063 NEW)
|
||||||
|
|
||||||
# Load bundled libraries from the lib/ directory relative to the binary.
|
# Load bundled libraries from the lib/ directory relative to the binary.
|
||||||
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
|
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
|
||||||
|
|
||||||
# Root filesystem for cross-building.
|
# Root filesystem for cross-building.
|
||||||
if(FLUTTER_TARGET_PLATFORM_SYSROOT)
|
if(FLUTTER_TARGET_PLATFORM_SYSROOT)
|
||||||
set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
|
set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
|
||||||
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
|
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
|
||||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Define build configuration options.
|
# Define build configuration options.
|
||||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||||
set(CMAKE_BUILD_TYPE "Debug" CACHE
|
set(CMAKE_BUILD_TYPE "Debug" CACHE
|
||||||
STRING "Flutter build mode" FORCE)
|
STRING "Flutter build mode" FORCE)
|
||||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
|
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
|
||||||
"Debug" "Profile" "Release")
|
"Debug" "Profile" "Release")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Compilation settings that should be applied to most targets.
|
# Compilation settings that should be applied to most targets.
|
||||||
#
|
#
|
||||||
# Be cautious about adding new options here, as plugins use this function by
|
# Be cautious about adding new options here, as plugins use this function by
|
||||||
# default. In most cases, you should add new options to specific targets instead
|
# default. In most cases, you should add new options to specific targets instead
|
||||||
# of modifying this function.
|
# of modifying this function.
|
||||||
function(APPLY_STANDARD_SETTINGS TARGET)
|
function(APPLY_STANDARD_SETTINGS TARGET)
|
||||||
target_compile_features(${TARGET} PUBLIC cxx_std_14)
|
target_compile_features(${TARGET} PUBLIC cxx_std_14)
|
||||||
target_compile_options(${TARGET} PRIVATE -Wall -Werror)
|
target_compile_options(${TARGET} PRIVATE -Wall -Werror)
|
||||||
target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
|
target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
|
||||||
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
|
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
# Flutter library and tool build rules.
|
# Flutter library and tool build rules.
|
||||||
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
|
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
|
||||||
add_subdirectory(${FLUTTER_MANAGED_DIR})
|
add_subdirectory(${FLUTTER_MANAGED_DIR})
|
||||||
|
|
||||||
# System-level dependencies.
|
# System-level dependencies.
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
|
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
|
||||||
|
|
||||||
# Application build; see runner/CMakeLists.txt.
|
# Application build; see runner/CMakeLists.txt.
|
||||||
add_subdirectory("runner")
|
add_subdirectory("runner")
|
||||||
|
|
||||||
# Run the Flutter tool portions of the build. This must not be removed.
|
# Run the Flutter tool portions of the build. This must not be removed.
|
||||||
add_dependencies(${BINARY_NAME} flutter_assemble)
|
add_dependencies(${BINARY_NAME} flutter_assemble)
|
||||||
|
|
||||||
# Only the install-generated bundle's copy of the executable will launch
|
# Only the install-generated bundle's copy of the executable will launch
|
||||||
# correctly, since the resources must in the right relative locations. To avoid
|
# correctly, since the resources must in the right relative locations. To avoid
|
||||||
# people trying to run the unbundled copy, put it in a subdirectory instead of
|
# people trying to run the unbundled copy, put it in a subdirectory instead of
|
||||||
# the default top-level location.
|
# the default top-level location.
|
||||||
set_target_properties(${BINARY_NAME}
|
set_target_properties(${BINARY_NAME}
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
|
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# Generated plugin build rules, which manage building the plugins and adding
|
# Generated plugin build rules, which manage building the plugins and adding
|
||||||
# them to the application.
|
# them to the application.
|
||||||
include(flutter/generated_plugins.cmake)
|
include(flutter/generated_plugins.cmake)
|
||||||
|
|
||||||
|
|
||||||
# === Installation ===
|
# === Installation ===
|
||||||
# By default, "installing" just makes a relocatable bundle in the build
|
# By default, "installing" just makes a relocatable bundle in the build
|
||||||
# directory.
|
# directory.
|
||||||
set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
|
set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
|
||||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||||
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
|
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Start with a clean build bundle directory every time.
|
# Start with a clean build bundle directory every time.
|
||||||
install(CODE "
|
install(CODE "
|
||||||
file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
|
file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
|
||||||
" COMPONENT Runtime)
|
" COMPONENT Runtime)
|
||||||
|
|
||||||
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
|
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
|
||||||
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
|
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
|
||||||
|
|
||||||
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
|
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
|
||||||
COMPONENT Runtime)
|
COMPONENT Runtime)
|
||||||
|
|
||||||
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
|
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
|
||||||
COMPONENT Runtime)
|
COMPONENT Runtime)
|
||||||
|
|
||||||
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||||
COMPONENT Runtime)
|
COMPONENT Runtime)
|
||||||
|
|
||||||
foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
|
foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
|
||||||
install(FILES "${bundled_library}"
|
install(FILES "${bundled_library}"
|
||||||
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||||
COMPONENT Runtime)
|
COMPONENT Runtime)
|
||||||
endforeach(bundled_library)
|
endforeach(bundled_library)
|
||||||
|
|
||||||
# Copy the native assets provided by the build.dart from all packages.
|
# Copy the native assets provided by the build.dart from all packages.
|
||||||
set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/")
|
set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/")
|
||||||
install(DIRECTORY "${NATIVE_ASSETS_DIR}"
|
install(DIRECTORY "${NATIVE_ASSETS_DIR}"
|
||||||
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||||
COMPONENT Runtime)
|
COMPONENT Runtime)
|
||||||
|
|
||||||
# Fully re-copy the assets directory on each build to avoid having stale files
|
# Fully re-copy the assets directory on each build to avoid having stale files
|
||||||
# from a previous install.
|
# from a previous install.
|
||||||
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
|
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
|
||||||
install(CODE "
|
install(CODE "
|
||||||
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
|
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
|
||||||
" COMPONENT Runtime)
|
" COMPONENT Runtime)
|
||||||
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
|
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
|
||||||
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
|
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
|
||||||
|
|
||||||
# Install the AOT library on non-Debug builds only.
|
# Install the AOT library on non-Debug builds only.
|
||||||
if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
|
if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||||
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||||
COMPONENT Runtime)
|
COMPONENT Runtime)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -1,88 +1,88 @@
|
|||||||
# This file controls Flutter-level build steps. It should not be edited.
|
# This file controls Flutter-level build steps. It should not be edited.
|
||||||
cmake_minimum_required(VERSION 3.10)
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
|
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
|
||||||
|
|
||||||
# Configuration provided via flutter tool.
|
# Configuration provided via flutter tool.
|
||||||
include(${EPHEMERAL_DIR}/generated_config.cmake)
|
include(${EPHEMERAL_DIR}/generated_config.cmake)
|
||||||
|
|
||||||
# TODO: Move the rest of this into files in ephemeral. See
|
# TODO: Move the rest of this into files in ephemeral. See
|
||||||
# https://github.com/flutter/flutter/issues/57146.
|
# https://github.com/flutter/flutter/issues/57146.
|
||||||
|
|
||||||
# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
|
# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
|
||||||
# which isn't available in 3.10.
|
# which isn't available in 3.10.
|
||||||
function(list_prepend LIST_NAME PREFIX)
|
function(list_prepend LIST_NAME PREFIX)
|
||||||
set(NEW_LIST "")
|
set(NEW_LIST "")
|
||||||
foreach(element ${${LIST_NAME}})
|
foreach(element ${${LIST_NAME}})
|
||||||
list(APPEND NEW_LIST "${PREFIX}${element}")
|
list(APPEND NEW_LIST "${PREFIX}${element}")
|
||||||
endforeach(element)
|
endforeach(element)
|
||||||
set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
|
set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
# === Flutter Library ===
|
# === Flutter Library ===
|
||||||
# System-level dependencies.
|
# System-level dependencies.
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
|
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
|
||||||
pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
|
pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
|
||||||
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
|
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
|
||||||
|
|
||||||
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
|
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
|
||||||
|
|
||||||
# Published to parent scope for install step.
|
# Published to parent scope for install step.
|
||||||
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
|
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
|
||||||
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
|
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
|
||||||
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
|
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
|
||||||
set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
|
set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
|
||||||
|
|
||||||
list(APPEND FLUTTER_LIBRARY_HEADERS
|
list(APPEND FLUTTER_LIBRARY_HEADERS
|
||||||
"fl_basic_message_channel.h"
|
"fl_basic_message_channel.h"
|
||||||
"fl_binary_codec.h"
|
"fl_binary_codec.h"
|
||||||
"fl_binary_messenger.h"
|
"fl_binary_messenger.h"
|
||||||
"fl_dart_project.h"
|
"fl_dart_project.h"
|
||||||
"fl_engine.h"
|
"fl_engine.h"
|
||||||
"fl_json_message_codec.h"
|
"fl_json_message_codec.h"
|
||||||
"fl_json_method_codec.h"
|
"fl_json_method_codec.h"
|
||||||
"fl_message_codec.h"
|
"fl_message_codec.h"
|
||||||
"fl_method_call.h"
|
"fl_method_call.h"
|
||||||
"fl_method_channel.h"
|
"fl_method_channel.h"
|
||||||
"fl_method_codec.h"
|
"fl_method_codec.h"
|
||||||
"fl_method_response.h"
|
"fl_method_response.h"
|
||||||
"fl_plugin_registrar.h"
|
"fl_plugin_registrar.h"
|
||||||
"fl_plugin_registry.h"
|
"fl_plugin_registry.h"
|
||||||
"fl_standard_message_codec.h"
|
"fl_standard_message_codec.h"
|
||||||
"fl_standard_method_codec.h"
|
"fl_standard_method_codec.h"
|
||||||
"fl_string_codec.h"
|
"fl_string_codec.h"
|
||||||
"fl_value.h"
|
"fl_value.h"
|
||||||
"fl_view.h"
|
"fl_view.h"
|
||||||
"flutter_linux.h"
|
"flutter_linux.h"
|
||||||
)
|
)
|
||||||
list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
|
list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
|
||||||
add_library(flutter INTERFACE)
|
add_library(flutter INTERFACE)
|
||||||
target_include_directories(flutter INTERFACE
|
target_include_directories(flutter INTERFACE
|
||||||
"${EPHEMERAL_DIR}"
|
"${EPHEMERAL_DIR}"
|
||||||
)
|
)
|
||||||
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
|
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
|
||||||
target_link_libraries(flutter INTERFACE
|
target_link_libraries(flutter INTERFACE
|
||||||
PkgConfig::GTK
|
PkgConfig::GTK
|
||||||
PkgConfig::GLIB
|
PkgConfig::GLIB
|
||||||
PkgConfig::GIO
|
PkgConfig::GIO
|
||||||
)
|
)
|
||||||
add_dependencies(flutter flutter_assemble)
|
add_dependencies(flutter flutter_assemble)
|
||||||
|
|
||||||
# === Flutter tool backend ===
|
# === Flutter tool backend ===
|
||||||
# _phony_ is a non-existent file to force this command to run every time,
|
# _phony_ is a non-existent file to force this command to run every time,
|
||||||
# since currently there's no way to get a full input/output list from the
|
# since currently there's no way to get a full input/output list from the
|
||||||
# flutter tool.
|
# flutter tool.
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
|
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/_phony_
|
${CMAKE_CURRENT_BINARY_DIR}/_phony_
|
||||||
COMMAND ${CMAKE_COMMAND} -E env
|
COMMAND ${CMAKE_COMMAND} -E env
|
||||||
${FLUTTER_TOOL_ENVIRONMENT}
|
${FLUTTER_TOOL_ENVIRONMENT}
|
||||||
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
|
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
|
||||||
${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
|
${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
|
||||||
VERBATIM
|
VERBATIM
|
||||||
)
|
)
|
||||||
add_custom_target(flutter_assemble DEPENDS
|
add_custom_target(flutter_assemble DEPENDS
|
||||||
"${FLUTTER_LIBRARY}"
|
"${FLUTTER_LIBRARY}"
|
||||||
${FLUTTER_LIBRARY_HEADERS}
|
${FLUTTER_LIBRARY_HEADERS}
|
||||||
)
|
)
|
||||||
|
|||||||
+26
-26
@@ -1,26 +1,26 @@
|
|||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
project(runner LANGUAGES CXX)
|
project(runner LANGUAGES CXX)
|
||||||
|
|
||||||
# Define the application target. To change its name, change BINARY_NAME in the
|
# Define the application target. To change its name, change BINARY_NAME in the
|
||||||
# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
|
# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
|
||||||
# work.
|
# work.
|
||||||
#
|
#
|
||||||
# Any new source files that you add to the application should be added here.
|
# Any new source files that you add to the application should be added here.
|
||||||
add_executable(${BINARY_NAME}
|
add_executable(${BINARY_NAME}
|
||||||
"main.cc"
|
"main.cc"
|
||||||
"my_application.cc"
|
"my_application.cc"
|
||||||
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
|
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Apply the standard set of build settings. This can be removed for applications
|
# Apply the standard set of build settings. This can be removed for applications
|
||||||
# that need different build settings.
|
# that need different build settings.
|
||||||
apply_standard_settings(${BINARY_NAME})
|
apply_standard_settings(${BINARY_NAME})
|
||||||
|
|
||||||
# Add preprocessor definitions for the application ID.
|
# Add preprocessor definitions for the application ID.
|
||||||
add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
|
add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
|
||||||
|
|
||||||
# Add dependency libraries. Add any application-specific dependencies here.
|
# Add dependency libraries. Add any application-specific dependencies here.
|
||||||
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
|
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
|
||||||
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
|
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
|
||||||
|
|
||||||
target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
|
target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "my_application.h"
|
#include "my_application.h"
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
g_autoptr(MyApplication) app = my_application_new();
|
g_autoptr(MyApplication) app = my_application_new();
|
||||||
return g_application_run(G_APPLICATION(app), argc, argv);
|
return g_application_run(G_APPLICATION(app), argc, argv);
|
||||||
}
|
}
|
||||||
|
|||||||
+146
-146
@@ -1,148 +1,148 @@
|
|||||||
#include "my_application.h"
|
#include "my_application.h"
|
||||||
|
|
||||||
#include <flutter_linux/flutter_linux.h>
|
#include <flutter_linux/flutter_linux.h>
|
||||||
#ifdef GDK_WINDOWING_X11
|
#ifdef GDK_WINDOWING_X11
|
||||||
#include <gdk/gdkx.h>
|
#include <gdk/gdkx.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "flutter/generated_plugin_registrant.h"
|
#include "flutter/generated_plugin_registrant.h"
|
||||||
|
|
||||||
struct _MyApplication {
|
struct _MyApplication {
|
||||||
GtkApplication parent_instance;
|
GtkApplication parent_instance;
|
||||||
char** dart_entrypoint_arguments;
|
char** dart_entrypoint_arguments;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
|
G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
|
||||||
|
|
||||||
// Called when first Flutter frame received.
|
// Called when first Flutter frame received.
|
||||||
static void first_frame_cb(MyApplication* self, FlView* view) {
|
static void first_frame_cb(MyApplication* self, FlView* view) {
|
||||||
gtk_widget_show(gtk_widget_get_toplevel(GTK_WIDGET(view)));
|
gtk_widget_show(gtk_widget_get_toplevel(GTK_WIDGET(view)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements GApplication::activate.
|
// Implements GApplication::activate.
|
||||||
static void my_application_activate(GApplication* application) {
|
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)));
|
||||||
|
|
||||||
// Use a header bar when running in GNOME as this is the common style used
|
// Use a header bar when running in GNOME as this is the common style used
|
||||||
// by applications and is the setup most users will be using (e.g. Ubuntu
|
// by applications and is the setup most users will be using (e.g. Ubuntu
|
||||||
// desktop).
|
// desktop).
|
||||||
// If running on X and not using GNOME then just use a traditional title bar
|
// If running on X and not using GNOME then just use a traditional title bar
|
||||||
// in case the window manager does more exotic layout, e.g. tiling.
|
// in case the window manager does more exotic layout, e.g. tiling.
|
||||||
// If running on Wayland assume the header bar will work (may need changing
|
// If running on Wayland assume the header bar will work (may need changing
|
||||||
// if future cases occur).
|
// if future cases occur).
|
||||||
gboolean use_header_bar = TRUE;
|
gboolean use_header_bar = TRUE;
|
||||||
#ifdef GDK_WINDOWING_X11
|
#ifdef GDK_WINDOWING_X11
|
||||||
GdkScreen* screen = gtk_window_get_screen(window);
|
GdkScreen* screen = gtk_window_get_screen(window);
|
||||||
if (GDK_IS_X11_SCREEN(screen)) {
|
if (GDK_IS_X11_SCREEN(screen)) {
|
||||||
const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
|
const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
|
||||||
if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
|
if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
|
||||||
use_header_bar = FALSE;
|
use_header_bar = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (use_header_bar) {
|
if (use_header_bar) {
|
||||||
GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
|
GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
|
||||||
gtk_widget_show(GTK_WIDGET(header_bar));
|
gtk_widget_show(GTK_WIDGET(header_bar));
|
||||||
gtk_header_bar_set_title(header_bar, "Lunaris");
|
gtk_header_bar_set_title(header_bar, "Lunaris");
|
||||||
gtk_header_bar_set_show_close_button(header_bar, TRUE);
|
gtk_header_bar_set_show_close_button(header_bar, TRUE);
|
||||||
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
|
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
|
||||||
} else {
|
} else {
|
||||||
gtk_window_set_title(window, "Lunaris");
|
gtk_window_set_title(window, "Lunaris");
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_window_set_default_size(window, 1280, 720);
|
gtk_window_set_default_size(window, 1280, 720);
|
||||||
|
|
||||||
g_autoptr(FlDartProject) project = fl_dart_project_new();
|
g_autoptr(FlDartProject) project = fl_dart_project_new();
|
||||||
fl_dart_project_set_dart_entrypoint_arguments(
|
fl_dart_project_set_dart_entrypoint_arguments(
|
||||||
project, self->dart_entrypoint_arguments);
|
project, self->dart_entrypoint_arguments);
|
||||||
|
|
||||||
FlView* view = fl_view_new(project);
|
FlView* view = fl_view_new(project);
|
||||||
GdkRGBA background_color;
|
GdkRGBA background_color;
|
||||||
// Background defaults to black, override it here if necessary, e.g. #00000000
|
// Background defaults to black, override it here if necessary, e.g. #00000000
|
||||||
// for transparent.
|
// for transparent.
|
||||||
gdk_rgba_parse(&background_color, "#000000");
|
gdk_rgba_parse(&background_color, "#000000");
|
||||||
fl_view_set_background_color(view, &background_color);
|
fl_view_set_background_color(view, &background_color);
|
||||||
gtk_widget_show(GTK_WIDGET(view));
|
gtk_widget_show(GTK_WIDGET(view));
|
||||||
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
|
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
|
||||||
|
|
||||||
// Show the window when Flutter renders.
|
// Show the window when Flutter renders.
|
||||||
// Requires the view to be realized so we can start rendering.
|
// Requires the view to be realized so we can start rendering.
|
||||||
g_signal_connect_swapped(view, "first-frame", G_CALLBACK(first_frame_cb),
|
g_signal_connect_swapped(view, "first-frame", G_CALLBACK(first_frame_cb),
|
||||||
self);
|
self);
|
||||||
gtk_widget_realize(GTK_WIDGET(view));
|
gtk_widget_realize(GTK_WIDGET(view));
|
||||||
|
|
||||||
fl_register_plugins(FL_PLUGIN_REGISTRY(view));
|
fl_register_plugins(FL_PLUGIN_REGISTRY(view));
|
||||||
|
|
||||||
gtk_widget_grab_focus(GTK_WIDGET(view));
|
gtk_widget_grab_focus(GTK_WIDGET(view));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements GApplication::local_command_line.
|
// Implements GApplication::local_command_line.
|
||||||
static gboolean my_application_local_command_line(GApplication* application,
|
static gboolean my_application_local_command_line(GApplication* application,
|
||||||
gchar*** arguments,
|
gchar*** arguments,
|
||||||
int* exit_status) {
|
int* exit_status) {
|
||||||
MyApplication* self = MY_APPLICATION(application);
|
MyApplication* self = MY_APPLICATION(application);
|
||||||
// Strip out the first argument as it is the binary name.
|
// Strip out the first argument as it is the binary name.
|
||||||
self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
|
self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
|
||||||
|
|
||||||
g_autoptr(GError) error = nullptr;
|
g_autoptr(GError) error = nullptr;
|
||||||
if (!g_application_register(application, nullptr, &error)) {
|
if (!g_application_register(application, nullptr, &error)) {
|
||||||
g_warning("Failed to register: %s", error->message);
|
g_warning("Failed to register: %s", error->message);
|
||||||
*exit_status = 1;
|
*exit_status = 1;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_application_activate(application);
|
g_application_activate(application);
|
||||||
*exit_status = 0;
|
*exit_status = 0;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements GApplication::startup.
|
// Implements GApplication::startup.
|
||||||
static void my_application_startup(GApplication* application) {
|
static void my_application_startup(GApplication* application) {
|
||||||
// MyApplication* self = MY_APPLICATION(object);
|
// MyApplication* self = MY_APPLICATION(object);
|
||||||
|
|
||||||
// Perform any actions required at application startup.
|
// Perform any actions required at application startup.
|
||||||
|
|
||||||
G_APPLICATION_CLASS(my_application_parent_class)->startup(application);
|
G_APPLICATION_CLASS(my_application_parent_class)->startup(application);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements GApplication::shutdown.
|
// Implements GApplication::shutdown.
|
||||||
static void my_application_shutdown(GApplication* application) {
|
static void my_application_shutdown(GApplication* application) {
|
||||||
// MyApplication* self = MY_APPLICATION(object);
|
// MyApplication* self = MY_APPLICATION(object);
|
||||||
|
|
||||||
// Perform any actions required at application shutdown.
|
// Perform any actions required at application shutdown.
|
||||||
|
|
||||||
G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application);
|
G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements GObject::dispose.
|
// Implements GObject::dispose.
|
||||||
static void my_application_dispose(GObject* object) {
|
static void my_application_dispose(GObject* object) {
|
||||||
MyApplication* self = MY_APPLICATION(object);
|
MyApplication* self = MY_APPLICATION(object);
|
||||||
g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
|
g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
|
||||||
G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
|
G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void my_application_class_init(MyApplicationClass* klass) {
|
static void my_application_class_init(MyApplicationClass* klass) {
|
||||||
G_APPLICATION_CLASS(klass)->activate = my_application_activate;
|
G_APPLICATION_CLASS(klass)->activate = my_application_activate;
|
||||||
G_APPLICATION_CLASS(klass)->local_command_line =
|
G_APPLICATION_CLASS(klass)->local_command_line =
|
||||||
my_application_local_command_line;
|
my_application_local_command_line;
|
||||||
G_APPLICATION_CLASS(klass)->startup = my_application_startup;
|
G_APPLICATION_CLASS(klass)->startup = my_application_startup;
|
||||||
G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown;
|
G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown;
|
||||||
G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
|
G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void my_application_init(MyApplication* self) {}
|
static void my_application_init(MyApplication* self) {}
|
||||||
|
|
||||||
MyApplication* my_application_new() {
|
MyApplication* my_application_new() {
|
||||||
// Set the program name to the application ID, which helps various systems
|
// Set the program name to the application ID, which helps various systems
|
||||||
// like GTK and desktop environments map this running application to its
|
// like GTK and desktop environments map this running application to its
|
||||||
// corresponding .desktop file. This ensures better integration by allowing
|
// corresponding .desktop file. This ensures better integration by allowing
|
||||||
// the application to be recognized beyond its binary name.
|
// the application to be recognized beyond its binary name.
|
||||||
g_set_prgname(APPLICATION_ID);
|
g_set_prgname(APPLICATION_ID);
|
||||||
|
|
||||||
return MY_APPLICATION(g_object_new(my_application_get_type(),
|
return MY_APPLICATION(g_object_new(my_application_get_type(),
|
||||||
"application-id", APPLICATION_ID, "flags",
|
"application-id", APPLICATION_ID, "flags",
|
||||||
G_APPLICATION_NON_UNIQUE, nullptr));
|
G_APPLICATION_NON_UNIQUE, nullptr));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
#ifndef FLUTTER_MY_APPLICATION_H_
|
#ifndef FLUTTER_MY_APPLICATION_H_
|
||||||
#define FLUTTER_MY_APPLICATION_H_
|
#define FLUTTER_MY_APPLICATION_H_
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
G_DECLARE_FINAL_TYPE(MyApplication,
|
G_DECLARE_FINAL_TYPE(MyApplication,
|
||||||
my_application,
|
my_application,
|
||||||
MY,
|
MY,
|
||||||
APPLICATION,
|
APPLICATION,
|
||||||
GtkApplication)
|
GtkApplication)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* my_application_new:
|
* my_application_new:
|
||||||
*
|
*
|
||||||
* Creates a new Flutter-based application.
|
* Creates a new Flutter-based application.
|
||||||
*
|
*
|
||||||
* Returns: a new #MyApplication.
|
* Returns: a new #MyApplication.
|
||||||
*/
|
*/
|
||||||
MyApplication* my_application_new();
|
MyApplication* my_application_new();
|
||||||
|
|
||||||
#endif // FLUTTER_MY_APPLICATION_H_
|
#endif // FLUTTER_MY_APPLICATION_H_
|
||||||
|
|||||||
+22
-14
@@ -165,10 +165,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: code_assets
|
name: code_assets
|
||||||
sha256: dad6bf6b9f4f378b0a69edbf42584d336efd1a9ce15deb1ba591cbb1b5ff440f
|
sha256: "67cf6d84013f9c601e42a6f8a6b74c4c0d9dc1a1619d775f2b28b732d3551b85"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.2.0"
|
||||||
code_builder:
|
code_builder:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -289,6 +289,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.0"
|
version: "2.2.0"
|
||||||
|
ffi_leak_tracker:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: ffi_leak_tracker
|
||||||
|
sha256: "4093d4ef9ca06ffe2786e73bfb25e22aa92112b9bb4ec941f11e3e6b61489a97"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.2"
|
||||||
file:
|
file:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -675,10 +683,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: meta
|
name: meta
|
||||||
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
|
sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.17.0"
|
version: "1.18.0"
|
||||||
mime:
|
mime:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -731,18 +739,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: package_info_plus
|
name: package_info_plus
|
||||||
sha256: "468c26b4254ab01979fa5e4a98cb343ea3631b9acee6f21028997419a80e1a20"
|
sha256: "4bf625947f6c7713ee242296a682e23e44823c09cf9d79e4f1238923c92db852"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "9.0.1"
|
version: "10.1.0"
|
||||||
package_info_plus_platform_interface:
|
package_info_plus_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: package_info_plus_platform_interface
|
name: package_info_plus_platform_interface
|
||||||
sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086"
|
sha256: db762cb2f4f25ee60fb6359773861b0f199e00b90d237bd85a76a1e806b46ef4
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.2.1"
|
version: "4.1.0"
|
||||||
path:
|
path:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -1056,10 +1064,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a"
|
sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.10"
|
version: "0.7.11"
|
||||||
time:
|
time:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1200,10 +1208,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: wakelock_plus
|
name: wakelock_plus
|
||||||
sha256: ddf3db70eaa10c37558ff817519b85d527dbd21034fd5d8e1c2e85f31588f1c1
|
sha256: "824c5bba0f800e86d32e57d3d1843c531f090005cc89d9a837933e6601093d53"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.5.2"
|
version: "1.6.1"
|
||||||
wakelock_plus_platform_interface:
|
wakelock_plus_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1256,10 +1264,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: win32
|
name: win32
|
||||||
sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e
|
sha256: ba6f4bba816c8d7e3c1580e170f3786d216951cc6b94babc3b814c08d2cb2738
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.15.0"
|
version: "6.3.0"
|
||||||
xdg_directories:
|
xdg_directories:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
name: gel_rule_app
|
name: gel_rule_app
|
||||||
description: Local backend/core layer for a Flutter booru browser app.
|
description: Local backend/core layer for a Flutter booru browser app.
|
||||||
publish_to: "none"
|
publish_to: "none"
|
||||||
version: 2.0.1+21
|
version: 2.0.1+22
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.3.0 <4.0.0"
|
sdk: ">=3.3.0 <4.0.0"
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'dart:ffi' show Abi;
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
@@ -15,6 +16,7 @@ import 'package:gel_rule_app/core/cache/cache_service.dart';
|
|||||||
import 'package:gel_rule_app/core/database/app_database.dart';
|
import 'package:gel_rule_app/core/database/app_database.dart';
|
||||||
import 'package:gel_rule_app/core/database/database_service.dart';
|
import 'package:gel_rule_app/core/database/database_service.dart';
|
||||||
import 'package:gel_rule_app/core/utils/result.dart';
|
import 'package:gel_rule_app/core/utils/result.dart';
|
||||||
|
import 'package:isar/isar.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
late Directory directory;
|
late Directory directory;
|
||||||
@@ -24,6 +26,14 @@ void main() {
|
|||||||
late File copiedIsarDll;
|
late File copiedIsarDll;
|
||||||
|
|
||||||
setUpAll(() async {
|
setUpAll(() async {
|
||||||
|
if (Platform.isLinux) {
|
||||||
|
await Isar.initializeIsarCore(
|
||||||
|
libraries: {
|
||||||
|
Abi.linuxX64:
|
||||||
|
'${Directory.current.path}/third_party/isar_flutter_libs/linux/libisar.so',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
copiedIsarDll =
|
copiedIsarDll =
|
||||||
File('${Directory.current.path}${Platform.pathSeparator}isar.dll');
|
File('${Directory.current.path}${Platform.pathSeparator}isar.dll');
|
||||||
if (Platform.isWindows && !copiedIsarDll.existsSync()) {
|
if (Platform.isWindows && !copiedIsarDll.existsSync()) {
|
||||||
|
|||||||
@@ -57,6 +57,48 @@ void main() {
|
|||||||
expect(changed, 'video');
|
expect(changed, 'video');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('clear button removes all committed tags', (tester) async {
|
||||||
|
String? changed;
|
||||||
|
await tester.pumpWidget(_Harness(
|
||||||
|
child: TagInputSearchBar(
|
||||||
|
initialValue: 'touhou video',
|
||||||
|
onSubmitted: (_) {},
|
||||||
|
onChanged: (value) {
|
||||||
|
changed = value;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
await tester.tap(find.byTooltip('Clear'));
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
expect(find.text('touhou'), findsNothing);
|
||||||
|
expect(find.text('video'), findsNothing);
|
||||||
|
expect(changed, '');
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('external initial value replaces committed tags', (tester) async {
|
||||||
|
await tester.pumpWidget(_Harness(
|
||||||
|
child: TagInputSearchBar(
|
||||||
|
initialValue: 'old_tag',
|
||||||
|
onSubmitted: (_) {},
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
expect(find.text('old_tag'), findsOneWidget);
|
||||||
|
|
||||||
|
await tester.pumpWidget(_Harness(
|
||||||
|
child: TagInputSearchBar(
|
||||||
|
initialValue: 'new_tag',
|
||||||
|
onSubmitted: (_) {},
|
||||||
|
),
|
||||||
|
));
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
expect(find.text('old_tag'), findsNothing);
|
||||||
|
expect(find.text('new_tag'), findsOneWidget);
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('suggestion appends active tag as a chip', (tester) async {
|
testWidgets('suggestion appends active tag as a chip', (tester) async {
|
||||||
String? applied;
|
String? applied;
|
||||||
await tester.pumpWidget(_Harness(
|
await tester.pumpWidget(_Harness(
|
||||||
|
|||||||
+17
-17
@@ -1,17 +1,17 @@
|
|||||||
flutter/ephemeral/
|
flutter/ephemeral/
|
||||||
|
|
||||||
# Visual Studio user-specific files.
|
# Visual Studio user-specific files.
|
||||||
*.suo
|
*.suo
|
||||||
*.user
|
*.user
|
||||||
*.userosscache
|
*.userosscache
|
||||||
*.sln.docstates
|
*.sln.docstates
|
||||||
|
|
||||||
# Visual Studio build-related files.
|
# Visual Studio build-related files.
|
||||||
x64/
|
x64/
|
||||||
x86/
|
x86/
|
||||||
|
|
||||||
# Visual Studio cache files
|
# Visual Studio cache files
|
||||||
# files ending in .cache can be ignored
|
# files ending in .cache can be ignored
|
||||||
*.[Cc]ache
|
*.[Cc]ache
|
||||||
# but keep track of directories ending in .cache
|
# but keep track of directories ending in .cache
|
||||||
!*.[Cc]ache/
|
!*.[Cc]ache/
|
||||||
|
|||||||
+103
-103
@@ -1,109 +1,109 @@
|
|||||||
# Project-level configuration.
|
# Project-level configuration.
|
||||||
cmake_minimum_required(VERSION 3.14)
|
cmake_minimum_required(VERSION 3.14)
|
||||||
project(gel_rule_app LANGUAGES CXX)
|
project(gel_rule_app LANGUAGES CXX)
|
||||||
|
|
||||||
# The name of the executable created for the application. Change this to change
|
# The name of the executable created for the application. Change this to change
|
||||||
# the on-disk name of your application.
|
# the on-disk name of your application.
|
||||||
set(BINARY_NAME "gel_rule_app")
|
set(BINARY_NAME "gel_rule_app")
|
||||||
|
|
||||||
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
|
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
|
||||||
# versions of CMake.
|
# versions of CMake.
|
||||||
cmake_policy(VERSION 3.14...3.25)
|
cmake_policy(VERSION 3.14...3.25)
|
||||||
|
|
||||||
# Define build configuration option.
|
# Define build configuration option.
|
||||||
get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||||
if(IS_MULTICONFIG)
|
if(IS_MULTICONFIG)
|
||||||
set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release"
|
set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release"
|
||||||
CACHE STRING "" FORCE)
|
CACHE STRING "" FORCE)
|
||||||
else()
|
else()
|
||||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||||
set(CMAKE_BUILD_TYPE "Debug" CACHE
|
set(CMAKE_BUILD_TYPE "Debug" CACHE
|
||||||
STRING "Flutter build mode" FORCE)
|
STRING "Flutter build mode" FORCE)
|
||||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
|
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
|
||||||
"Debug" "Profile" "Release")
|
"Debug" "Profile" "Release")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
# Define settings for the Profile build mode.
|
# Define settings for the Profile build mode.
|
||||||
set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
|
set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
|
set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
|
||||||
set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}")
|
set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}")
|
||||||
set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}")
|
set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}")
|
||||||
|
|
||||||
# Use Unicode for all projects.
|
# Use Unicode for all projects.
|
||||||
add_definitions(-DUNICODE -D_UNICODE)
|
add_definitions(-DUNICODE -D_UNICODE)
|
||||||
add_definitions(-D_SILENCE_EXPERIMENTAL_COROUTINE_DEPRECATION_WARNINGS)
|
add_definitions(-D_SILENCE_EXPERIMENTAL_COROUTINE_DEPRECATION_WARNINGS)
|
||||||
|
|
||||||
# Compilation settings that should be applied to most targets.
|
# Compilation settings that should be applied to most targets.
|
||||||
#
|
#
|
||||||
# Be cautious about adding new options here, as plugins use this function by
|
# Be cautious about adding new options here, as plugins use this function by
|
||||||
# default. In most cases, you should add new options to specific targets instead
|
# default. In most cases, you should add new options to specific targets instead
|
||||||
# of modifying this function.
|
# of modifying this function.
|
||||||
function(APPLY_STANDARD_SETTINGS TARGET)
|
function(APPLY_STANDARD_SETTINGS TARGET)
|
||||||
target_compile_features(${TARGET} PUBLIC cxx_std_17)
|
target_compile_features(${TARGET} PUBLIC cxx_std_17)
|
||||||
target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100")
|
target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100")
|
||||||
target_compile_options(${TARGET} PRIVATE /EHsc)
|
target_compile_options(${TARGET} PRIVATE /EHsc)
|
||||||
target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0")
|
target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0")
|
||||||
target_compile_definitions(${TARGET} PRIVATE "$<$<CONFIG:Debug>:_DEBUG>")
|
target_compile_definitions(${TARGET} PRIVATE "$<$<CONFIG:Debug>:_DEBUG>")
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
# Flutter library and tool build rules.
|
# Flutter library and tool build rules.
|
||||||
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
|
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
|
||||||
add_subdirectory(${FLUTTER_MANAGED_DIR})
|
add_subdirectory(${FLUTTER_MANAGED_DIR})
|
||||||
|
|
||||||
# Application build; see runner/CMakeLists.txt.
|
# Application build; see runner/CMakeLists.txt.
|
||||||
add_subdirectory("runner")
|
add_subdirectory("runner")
|
||||||
|
|
||||||
|
|
||||||
# Generated plugin build rules, which manage building the plugins and adding
|
# Generated plugin build rules, which manage building the plugins and adding
|
||||||
# them to the application.
|
# them to the application.
|
||||||
include(flutter/generated_plugins.cmake)
|
include(flutter/generated_plugins.cmake)
|
||||||
|
|
||||||
|
|
||||||
# === Installation ===
|
# === Installation ===
|
||||||
# Support files are copied into place next to the executable, so that it can
|
# Support files are copied into place next to the executable, so that it can
|
||||||
# run in place. This is done instead of making a separate bundle (as on Linux)
|
# run in place. This is done instead of making a separate bundle (as on Linux)
|
||||||
# so that building and running from within Visual Studio will work.
|
# so that building and running from within Visual Studio will work.
|
||||||
set(BUILD_BUNDLE_DIR "$<TARGET_FILE_DIR:${BINARY_NAME}>")
|
set(BUILD_BUNDLE_DIR "$<TARGET_FILE_DIR:${BINARY_NAME}>")
|
||||||
# Make the "install" step default, as it's required to run.
|
# Make the "install" step default, as it's required to run.
|
||||||
set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1)
|
set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1)
|
||||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT OR CMAKE_INSTALL_PREFIX MATCHES "Program Files")
|
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT OR CMAKE_INSTALL_PREFIX MATCHES "Program Files")
|
||||||
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
|
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
|
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
|
||||||
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}")
|
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}")
|
||||||
|
|
||||||
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
|
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
|
||||||
COMPONENT Runtime)
|
COMPONENT Runtime)
|
||||||
|
|
||||||
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
|
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
|
||||||
COMPONENT Runtime)
|
COMPONENT Runtime)
|
||||||
|
|
||||||
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||||
COMPONENT Runtime)
|
COMPONENT Runtime)
|
||||||
|
|
||||||
if(PLUGIN_BUNDLED_LIBRARIES)
|
if(PLUGIN_BUNDLED_LIBRARIES)
|
||||||
install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
|
install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
|
||||||
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||||
COMPONENT Runtime)
|
COMPONENT Runtime)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Copy the native assets provided by the build.dart from all packages.
|
# Copy the native assets provided by the build.dart from all packages.
|
||||||
set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/")
|
set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/")
|
||||||
install(DIRECTORY "${NATIVE_ASSETS_DIR}"
|
install(DIRECTORY "${NATIVE_ASSETS_DIR}"
|
||||||
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||||
COMPONENT Runtime)
|
COMPONENT Runtime)
|
||||||
|
|
||||||
# Fully re-copy the assets directory on each build to avoid having stale files
|
# Fully re-copy the assets directory on each build to avoid having stale files
|
||||||
# from a previous install.
|
# from a previous install.
|
||||||
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
|
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
|
||||||
install(CODE "
|
install(CODE "
|
||||||
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
|
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
|
||||||
" COMPONENT Runtime)
|
" COMPONENT Runtime)
|
||||||
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
|
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
|
||||||
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
|
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
|
||||||
|
|
||||||
# Install the AOT library on non-Debug builds only.
|
# Install the AOT library on non-Debug builds only.
|
||||||
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
|
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
|
||||||
CONFIGURATIONS Profile;Release
|
CONFIGURATIONS Profile;Release
|
||||||
COMPONENT Runtime)
|
COMPONENT Runtime)
|
||||||
|
|||||||
+109
-109
@@ -1,109 +1,109 @@
|
|||||||
# This file controls Flutter-level build steps. It should not be edited.
|
# This file controls Flutter-level build steps. It should not be edited.
|
||||||
cmake_minimum_required(VERSION 3.14)
|
cmake_minimum_required(VERSION 3.14)
|
||||||
|
|
||||||
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
|
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
|
||||||
|
|
||||||
# Configuration provided via flutter tool.
|
# Configuration provided via flutter tool.
|
||||||
include(${EPHEMERAL_DIR}/generated_config.cmake)
|
include(${EPHEMERAL_DIR}/generated_config.cmake)
|
||||||
|
|
||||||
# TODO: Move the rest of this into files in ephemeral. See
|
# TODO: Move the rest of this into files in ephemeral. See
|
||||||
# https://github.com/flutter/flutter/issues/57146.
|
# https://github.com/flutter/flutter/issues/57146.
|
||||||
set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper")
|
set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper")
|
||||||
|
|
||||||
# Set fallback configurations for older versions of the flutter tool.
|
# Set fallback configurations for older versions of the flutter tool.
|
||||||
if (NOT DEFINED FLUTTER_TARGET_PLATFORM)
|
if (NOT DEFINED FLUTTER_TARGET_PLATFORM)
|
||||||
set(FLUTTER_TARGET_PLATFORM "windows-x64")
|
set(FLUTTER_TARGET_PLATFORM "windows-x64")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# === Flutter Library ===
|
# === Flutter Library ===
|
||||||
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll")
|
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll")
|
||||||
|
|
||||||
# Published to parent scope for install step.
|
# Published to parent scope for install step.
|
||||||
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
|
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
|
||||||
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
|
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
|
||||||
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
|
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
|
||||||
set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE)
|
set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE)
|
||||||
|
|
||||||
list(APPEND FLUTTER_LIBRARY_HEADERS
|
list(APPEND FLUTTER_LIBRARY_HEADERS
|
||||||
"flutter_export.h"
|
"flutter_export.h"
|
||||||
"flutter_windows.h"
|
"flutter_windows.h"
|
||||||
"flutter_messenger.h"
|
"flutter_messenger.h"
|
||||||
"flutter_plugin_registrar.h"
|
"flutter_plugin_registrar.h"
|
||||||
"flutter_texture_registrar.h"
|
"flutter_texture_registrar.h"
|
||||||
)
|
)
|
||||||
list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/")
|
list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/")
|
||||||
add_library(flutter INTERFACE)
|
add_library(flutter INTERFACE)
|
||||||
target_include_directories(flutter INTERFACE
|
target_include_directories(flutter INTERFACE
|
||||||
"${EPHEMERAL_DIR}"
|
"${EPHEMERAL_DIR}"
|
||||||
)
|
)
|
||||||
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib")
|
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib")
|
||||||
add_dependencies(flutter flutter_assemble)
|
add_dependencies(flutter flutter_assemble)
|
||||||
|
|
||||||
# === Wrapper ===
|
# === Wrapper ===
|
||||||
list(APPEND CPP_WRAPPER_SOURCES_CORE
|
list(APPEND CPP_WRAPPER_SOURCES_CORE
|
||||||
"core_implementations.cc"
|
"core_implementations.cc"
|
||||||
"standard_codec.cc"
|
"standard_codec.cc"
|
||||||
)
|
)
|
||||||
list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/")
|
list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/")
|
||||||
list(APPEND CPP_WRAPPER_SOURCES_PLUGIN
|
list(APPEND CPP_WRAPPER_SOURCES_PLUGIN
|
||||||
"plugin_registrar.cc"
|
"plugin_registrar.cc"
|
||||||
)
|
)
|
||||||
list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/")
|
list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/")
|
||||||
list(APPEND CPP_WRAPPER_SOURCES_APP
|
list(APPEND CPP_WRAPPER_SOURCES_APP
|
||||||
"flutter_engine.cc"
|
"flutter_engine.cc"
|
||||||
"flutter_view_controller.cc"
|
"flutter_view_controller.cc"
|
||||||
)
|
)
|
||||||
list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/")
|
list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/")
|
||||||
|
|
||||||
# Wrapper sources needed for a plugin.
|
# Wrapper sources needed for a plugin.
|
||||||
add_library(flutter_wrapper_plugin STATIC
|
add_library(flutter_wrapper_plugin STATIC
|
||||||
${CPP_WRAPPER_SOURCES_CORE}
|
${CPP_WRAPPER_SOURCES_CORE}
|
||||||
${CPP_WRAPPER_SOURCES_PLUGIN}
|
${CPP_WRAPPER_SOURCES_PLUGIN}
|
||||||
)
|
)
|
||||||
apply_standard_settings(flutter_wrapper_plugin)
|
apply_standard_settings(flutter_wrapper_plugin)
|
||||||
set_target_properties(flutter_wrapper_plugin PROPERTIES
|
set_target_properties(flutter_wrapper_plugin PROPERTIES
|
||||||
POSITION_INDEPENDENT_CODE ON)
|
POSITION_INDEPENDENT_CODE ON)
|
||||||
set_target_properties(flutter_wrapper_plugin PROPERTIES
|
set_target_properties(flutter_wrapper_plugin PROPERTIES
|
||||||
CXX_VISIBILITY_PRESET hidden)
|
CXX_VISIBILITY_PRESET hidden)
|
||||||
target_link_libraries(flutter_wrapper_plugin PUBLIC flutter)
|
target_link_libraries(flutter_wrapper_plugin PUBLIC flutter)
|
||||||
target_include_directories(flutter_wrapper_plugin PUBLIC
|
target_include_directories(flutter_wrapper_plugin PUBLIC
|
||||||
"${WRAPPER_ROOT}/include"
|
"${WRAPPER_ROOT}/include"
|
||||||
)
|
)
|
||||||
add_dependencies(flutter_wrapper_plugin flutter_assemble)
|
add_dependencies(flutter_wrapper_plugin flutter_assemble)
|
||||||
|
|
||||||
# Wrapper sources needed for the runner.
|
# Wrapper sources needed for the runner.
|
||||||
add_library(flutter_wrapper_app STATIC
|
add_library(flutter_wrapper_app STATIC
|
||||||
${CPP_WRAPPER_SOURCES_CORE}
|
${CPP_WRAPPER_SOURCES_CORE}
|
||||||
${CPP_WRAPPER_SOURCES_APP}
|
${CPP_WRAPPER_SOURCES_APP}
|
||||||
)
|
)
|
||||||
apply_standard_settings(flutter_wrapper_app)
|
apply_standard_settings(flutter_wrapper_app)
|
||||||
target_link_libraries(flutter_wrapper_app PUBLIC flutter)
|
target_link_libraries(flutter_wrapper_app PUBLIC flutter)
|
||||||
target_include_directories(flutter_wrapper_app PUBLIC
|
target_include_directories(flutter_wrapper_app PUBLIC
|
||||||
"${WRAPPER_ROOT}/include"
|
"${WRAPPER_ROOT}/include"
|
||||||
)
|
)
|
||||||
add_dependencies(flutter_wrapper_app flutter_assemble)
|
add_dependencies(flutter_wrapper_app flutter_assemble)
|
||||||
|
|
||||||
# === Flutter tool backend ===
|
# === Flutter tool backend ===
|
||||||
# _phony_ is a non-existent file to force this command to run every time,
|
# _phony_ is a non-existent file to force this command to run every time,
|
||||||
# since currently there's no way to get a full input/output list from the
|
# since currently there's no way to get a full input/output list from the
|
||||||
# flutter tool.
|
# flutter tool.
|
||||||
set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_")
|
set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_")
|
||||||
set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE)
|
set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE)
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
|
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
|
||||||
${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN}
|
${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN}
|
||||||
${CPP_WRAPPER_SOURCES_APP}
|
${CPP_WRAPPER_SOURCES_APP}
|
||||||
${PHONY_OUTPUT}
|
${PHONY_OUTPUT}
|
||||||
COMMAND ${CMAKE_COMMAND} -E env
|
COMMAND ${CMAKE_COMMAND} -E env
|
||||||
${FLUTTER_TOOL_ENVIRONMENT}
|
${FLUTTER_TOOL_ENVIRONMENT}
|
||||||
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat"
|
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat"
|
||||||
${FLUTTER_TARGET_PLATFORM} $<CONFIG>
|
${FLUTTER_TARGET_PLATFORM} $<CONFIG>
|
||||||
VERBATIM
|
VERBATIM
|
||||||
)
|
)
|
||||||
add_custom_target(flutter_assemble DEPENDS
|
add_custom_target(flutter_assemble DEPENDS
|
||||||
"${FLUTTER_LIBRARY}"
|
"${FLUTTER_LIBRARY}"
|
||||||
${FLUTTER_LIBRARY_HEADERS}
|
${FLUTTER_LIBRARY_HEADERS}
|
||||||
${CPP_WRAPPER_SOURCES_CORE}
|
${CPP_WRAPPER_SOURCES_CORE}
|
||||||
${CPP_WRAPPER_SOURCES_PLUGIN}
|
${CPP_WRAPPER_SOURCES_PLUGIN}
|
||||||
${CPP_WRAPPER_SOURCES_APP}
|
${CPP_WRAPPER_SOURCES_APP}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,40 +1,40 @@
|
|||||||
cmake_minimum_required(VERSION 3.14)
|
cmake_minimum_required(VERSION 3.14)
|
||||||
project(runner LANGUAGES CXX)
|
project(runner LANGUAGES CXX)
|
||||||
|
|
||||||
# Define the application target. To change its name, change BINARY_NAME in the
|
# Define the application target. To change its name, change BINARY_NAME in the
|
||||||
# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
|
# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
|
||||||
# work.
|
# work.
|
||||||
#
|
#
|
||||||
# Any new source files that you add to the application should be added here.
|
# Any new source files that you add to the application should be added here.
|
||||||
add_executable(${BINARY_NAME} WIN32
|
add_executable(${BINARY_NAME} WIN32
|
||||||
"flutter_window.cpp"
|
"flutter_window.cpp"
|
||||||
"main.cpp"
|
"main.cpp"
|
||||||
"utils.cpp"
|
"utils.cpp"
|
||||||
"win32_window.cpp"
|
"win32_window.cpp"
|
||||||
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
|
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
|
||||||
"Runner.rc"
|
"Runner.rc"
|
||||||
"runner.exe.manifest"
|
"runner.exe.manifest"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Apply the standard set of build settings. This can be removed for applications
|
# Apply the standard set of build settings. This can be removed for applications
|
||||||
# that need different build settings.
|
# that need different build settings.
|
||||||
apply_standard_settings(${BINARY_NAME})
|
apply_standard_settings(${BINARY_NAME})
|
||||||
|
|
||||||
# Add preprocessor definitions for the build version.
|
# Add preprocessor definitions for the build version.
|
||||||
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"")
|
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"")
|
||||||
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}")
|
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}")
|
||||||
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}")
|
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}")
|
||||||
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}")
|
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}")
|
||||||
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}")
|
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}")
|
||||||
|
|
||||||
# Disable Windows macros that collide with C++ standard library functions.
|
# Disable Windows macros that collide with C++ standard library functions.
|
||||||
target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX")
|
target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX")
|
||||||
|
|
||||||
# Add dependency libraries and include directories. Add any application-specific
|
# Add dependency libraries and include directories. Add any application-specific
|
||||||
# dependencies here.
|
# dependencies here.
|
||||||
target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app)
|
target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app)
|
||||||
target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib")
|
target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib")
|
||||||
target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
|
target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
|
||||||
|
|
||||||
# Run the Flutter tool portions of the build. This must not be removed.
|
# Run the Flutter tool portions of the build. This must not be removed.
|
||||||
add_dependencies(${BINARY_NAME} flutter_assemble)
|
add_dependencies(${BINARY_NAME} flutter_assemble)
|
||||||
|
|||||||
+118
-118
@@ -1,121 +1,121 @@
|
|||||||
// Microsoft Visual C++ generated resource script.
|
// Microsoft Visual C++ generated resource script.
|
||||||
//
|
//
|
||||||
#pragma code_page(65001)
|
#pragma code_page(65001)
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
|
||||||
#define APSTUDIO_READONLY_SYMBOLS
|
#define APSTUDIO_READONLY_SYMBOLS
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Generated from the TEXTINCLUDE 2 resource.
|
// Generated from the TEXTINCLUDE 2 resource.
|
||||||
//
|
//
|
||||||
#include "winres.h"
|
#include "winres.h"
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
#undef APSTUDIO_READONLY_SYMBOLS
|
#undef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
// English (United States) resources
|
// English (United States) resources
|
||||||
|
|
||||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||||
|
|
||||||
#ifdef APSTUDIO_INVOKED
|
#ifdef APSTUDIO_INVOKED
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// TEXTINCLUDE
|
// TEXTINCLUDE
|
||||||
//
|
//
|
||||||
|
|
||||||
1 TEXTINCLUDE
|
1 TEXTINCLUDE
|
||||||
BEGIN
|
BEGIN
|
||||||
"resource.h\0"
|
"resource.h\0"
|
||||||
END
|
END
|
||||||
|
|
||||||
2 TEXTINCLUDE
|
2 TEXTINCLUDE
|
||||||
BEGIN
|
BEGIN
|
||||||
"#include ""winres.h""\r\n"
|
"#include ""winres.h""\r\n"
|
||||||
"\0"
|
"\0"
|
||||||
END
|
END
|
||||||
|
|
||||||
3 TEXTINCLUDE
|
3 TEXTINCLUDE
|
||||||
BEGIN
|
BEGIN
|
||||||
"\r\n"
|
"\r\n"
|
||||||
"\0"
|
"\0"
|
||||||
END
|
END
|
||||||
|
|
||||||
#endif // APSTUDIO_INVOKED
|
#endif // APSTUDIO_INVOKED
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Icon
|
// Icon
|
||||||
//
|
//
|
||||||
|
|
||||||
// Icon with lowest ID value placed first to ensure application icon
|
// Icon with lowest ID value placed first to ensure application icon
|
||||||
// remains consistent on all systems.
|
// remains consistent on all systems.
|
||||||
IDI_APP_ICON ICON "resources\\app_icon.ico"
|
IDI_APP_ICON ICON "resources\\app_icon.ico"
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Version
|
// Version
|
||||||
//
|
//
|
||||||
|
|
||||||
#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD)
|
#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD)
|
||||||
#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD
|
#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD
|
||||||
#else
|
#else
|
||||||
#define VERSION_AS_NUMBER 1,0,0,0
|
#define VERSION_AS_NUMBER 1,0,0,0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(FLUTTER_VERSION)
|
#if defined(FLUTTER_VERSION)
|
||||||
#define VERSION_AS_STRING FLUTTER_VERSION
|
#define VERSION_AS_STRING FLUTTER_VERSION
|
||||||
#else
|
#else
|
||||||
#define VERSION_AS_STRING "1.0.0"
|
#define VERSION_AS_STRING "1.0.0"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION VERSION_AS_NUMBER
|
FILEVERSION VERSION_AS_NUMBER
|
||||||
PRODUCTVERSION VERSION_AS_NUMBER
|
PRODUCTVERSION VERSION_AS_NUMBER
|
||||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS VS_FF_DEBUG
|
FILEFLAGS VS_FF_DEBUG
|
||||||
#else
|
#else
|
||||||
FILEFLAGS 0x0L
|
FILEFLAGS 0x0L
|
||||||
#endif
|
#endif
|
||||||
FILEOS VOS__WINDOWS32
|
FILEOS VOS__WINDOWS32
|
||||||
FILETYPE VFT_APP
|
FILETYPE VFT_APP
|
||||||
FILESUBTYPE 0x0L
|
FILESUBTYPE 0x0L
|
||||||
BEGIN
|
BEGIN
|
||||||
BLOCK "StringFileInfo"
|
BLOCK "StringFileInfo"
|
||||||
BEGIN
|
BEGIN
|
||||||
BLOCK "040904e4"
|
BLOCK "040904e4"
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "com.example" "\0"
|
VALUE "CompanyName", "com.example" "\0"
|
||||||
VALUE "FileDescription", "Lunaris" "\0"
|
VALUE "FileDescription", "Lunaris" "\0"
|
||||||
VALUE "FileVersion", VERSION_AS_STRING "\0"
|
VALUE "FileVersion", VERSION_AS_STRING "\0"
|
||||||
VALUE "InternalName", "Lunaris" "\0"
|
VALUE "InternalName", "Lunaris" "\0"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2026 com.example. All rights reserved." "\0"
|
VALUE "LegalCopyright", "Copyright (C) 2026 com.example. All rights reserved." "\0"
|
||||||
VALUE "OriginalFilename", "gel_rule_app.exe" "\0"
|
VALUE "OriginalFilename", "gel_rule_app.exe" "\0"
|
||||||
VALUE "ProductName", "Lunaris" "\0"
|
VALUE "ProductName", "Lunaris" "\0"
|
||||||
VALUE "ProductVersion", VERSION_AS_STRING "\0"
|
VALUE "ProductVersion", VERSION_AS_STRING "\0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "Translation", 0x409, 1252
|
VALUE "Translation", 0x409, 1252
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
|
|
||||||
#endif // English (United States) resources
|
#endif // English (United States) resources
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef APSTUDIO_INVOKED
|
#ifndef APSTUDIO_INVOKED
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Generated from the TEXTINCLUDE 3 resource.
|
// Generated from the TEXTINCLUDE 3 resource.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
#endif // not APSTUDIO_INVOKED
|
#endif // not APSTUDIO_INVOKED
|
||||||
|
|||||||
@@ -1,71 +1,71 @@
|
|||||||
#include "flutter_window.h"
|
#include "flutter_window.h"
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
#include "flutter/generated_plugin_registrant.h"
|
#include "flutter/generated_plugin_registrant.h"
|
||||||
|
|
||||||
FlutterWindow::FlutterWindow(const flutter::DartProject& project)
|
FlutterWindow::FlutterWindow(const flutter::DartProject& project)
|
||||||
: project_(project) {}
|
: project_(project) {}
|
||||||
|
|
||||||
FlutterWindow::~FlutterWindow() {}
|
FlutterWindow::~FlutterWindow() {}
|
||||||
|
|
||||||
bool FlutterWindow::OnCreate() {
|
bool FlutterWindow::OnCreate() {
|
||||||
if (!Win32Window::OnCreate()) {
|
if (!Win32Window::OnCreate()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
RECT frame = GetClientArea();
|
RECT frame = GetClientArea();
|
||||||
|
|
||||||
// The size here must match the window dimensions to avoid unnecessary surface
|
// The size here must match the window dimensions to avoid unnecessary surface
|
||||||
// creation / destruction in the startup path.
|
// creation / destruction in the startup path.
|
||||||
flutter_controller_ = std::make_unique<flutter::FlutterViewController>(
|
flutter_controller_ = std::make_unique<flutter::FlutterViewController>(
|
||||||
frame.right - frame.left, frame.bottom - frame.top, project_);
|
frame.right - frame.left, frame.bottom - frame.top, project_);
|
||||||
// Ensure that basic setup of the controller was successful.
|
// Ensure that basic setup of the controller was successful.
|
||||||
if (!flutter_controller_->engine() || !flutter_controller_->view()) {
|
if (!flutter_controller_->engine() || !flutter_controller_->view()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
RegisterPlugins(flutter_controller_->engine());
|
RegisterPlugins(flutter_controller_->engine());
|
||||||
SetChildContent(flutter_controller_->view()->GetNativeWindow());
|
SetChildContent(flutter_controller_->view()->GetNativeWindow());
|
||||||
|
|
||||||
flutter_controller_->engine()->SetNextFrameCallback([&]() {
|
flutter_controller_->engine()->SetNextFrameCallback([&]() {
|
||||||
this->Show();
|
this->Show();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Flutter can complete the first frame before the "show window" callback is
|
// Flutter can complete the first frame before the "show window" callback is
|
||||||
// registered. The following call ensures a frame is pending to ensure the
|
// registered. The following call ensures a frame is pending to ensure the
|
||||||
// window is shown. It is a no-op if the first frame hasn't completed yet.
|
// window is shown. It is a no-op if the first frame hasn't completed yet.
|
||||||
flutter_controller_->ForceRedraw();
|
flutter_controller_->ForceRedraw();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlutterWindow::OnDestroy() {
|
void FlutterWindow::OnDestroy() {
|
||||||
if (flutter_controller_) {
|
if (flutter_controller_) {
|
||||||
flutter_controller_ = nullptr;
|
flutter_controller_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Win32Window::OnDestroy();
|
Win32Window::OnDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
LRESULT
|
LRESULT
|
||||||
FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
|
FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
|
||||||
WPARAM const wparam,
|
WPARAM const wparam,
|
||||||
LPARAM const lparam) noexcept {
|
LPARAM const lparam) noexcept {
|
||||||
// Give Flutter, including plugins, an opportunity to handle window messages.
|
// Give Flutter, including plugins, an opportunity to handle window messages.
|
||||||
if (flutter_controller_) {
|
if (flutter_controller_) {
|
||||||
std::optional<LRESULT> result =
|
std::optional<LRESULT> result =
|
||||||
flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
|
flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
|
||||||
lparam);
|
lparam);
|
||||||
if (result) {
|
if (result) {
|
||||||
return *result;
|
return *result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (message) {
|
switch (message) {
|
||||||
case WM_FONTCHANGE:
|
case WM_FONTCHANGE:
|
||||||
flutter_controller_->engine()->ReloadSystemFonts();
|
flutter_controller_->engine()->ReloadSystemFonts();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
|
return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +1,33 @@
|
|||||||
#ifndef RUNNER_FLUTTER_WINDOW_H_
|
#ifndef RUNNER_FLUTTER_WINDOW_H_
|
||||||
#define RUNNER_FLUTTER_WINDOW_H_
|
#define RUNNER_FLUTTER_WINDOW_H_
|
||||||
|
|
||||||
#include <flutter/dart_project.h>
|
#include <flutter/dart_project.h>
|
||||||
#include <flutter/flutter_view_controller.h>
|
#include <flutter/flutter_view_controller.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "win32_window.h"
|
#include "win32_window.h"
|
||||||
|
|
||||||
// A window that does nothing but host a Flutter view.
|
// A window that does nothing but host a Flutter view.
|
||||||
class FlutterWindow : public Win32Window {
|
class FlutterWindow : public Win32Window {
|
||||||
public:
|
public:
|
||||||
// Creates a new FlutterWindow hosting a Flutter view running |project|.
|
// Creates a new FlutterWindow hosting a Flutter view running |project|.
|
||||||
explicit FlutterWindow(const flutter::DartProject& project);
|
explicit FlutterWindow(const flutter::DartProject& project);
|
||||||
virtual ~FlutterWindow();
|
virtual ~FlutterWindow();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Win32Window:
|
// Win32Window:
|
||||||
bool OnCreate() override;
|
bool OnCreate() override;
|
||||||
void OnDestroy() override;
|
void OnDestroy() override;
|
||||||
LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam,
|
LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam,
|
||||||
LPARAM const lparam) noexcept override;
|
LPARAM const lparam) noexcept override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The project to run.
|
// The project to run.
|
||||||
flutter::DartProject project_;
|
flutter::DartProject project_;
|
||||||
|
|
||||||
// The Flutter instance hosted by this window.
|
// The Flutter instance hosted by this window.
|
||||||
std::unique_ptr<flutter::FlutterViewController> flutter_controller_;
|
std::unique_ptr<flutter::FlutterViewController> flutter_controller_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // RUNNER_FLUTTER_WINDOW_H_
|
#endif // RUNNER_FLUTTER_WINDOW_H_
|
||||||
|
|||||||
+42
-42
@@ -1,43 +1,43 @@
|
|||||||
#include <flutter/dart_project.h>
|
#include <flutter/dart_project.h>
|
||||||
#include <flutter/flutter_view_controller.h>
|
#include <flutter/flutter_view_controller.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#include "flutter_window.h"
|
#include "flutter_window.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
||||||
_In_ wchar_t *command_line, _In_ int show_command) {
|
_In_ wchar_t *command_line, _In_ int show_command) {
|
||||||
// Attach to console when present (e.g., 'flutter run') or create a
|
// Attach to console when present (e.g., 'flutter run') or create a
|
||||||
// new console when running with a debugger.
|
// new console when running with a debugger.
|
||||||
if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
|
if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
|
||||||
CreateAndAttachConsole();
|
CreateAndAttachConsole();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize COM, so that it is available for use in the library and/or
|
// Initialize COM, so that it is available for use in the library and/or
|
||||||
// plugins.
|
// plugins.
|
||||||
::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
|
::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
|
||||||
|
|
||||||
flutter::DartProject project(L"data");
|
flutter::DartProject project(L"data");
|
||||||
|
|
||||||
std::vector<std::string> command_line_arguments =
|
std::vector<std::string> command_line_arguments =
|
||||||
GetCommandLineArguments();
|
GetCommandLineArguments();
|
||||||
|
|
||||||
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(1280, 720);
|
Win32Window::Size size(1280, 720);
|
||||||
if (!window.Create(L"Lunaris", origin, size)) {
|
if (!window.Create(L"Lunaris", origin, size)) {
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
window.SetQuitOnClose(true);
|
window.SetQuitOnClose(true);
|
||||||
|
|
||||||
::MSG msg;
|
::MSG msg;
|
||||||
while (::GetMessage(&msg, nullptr, 0, 0)) {
|
while (::GetMessage(&msg, nullptr, 0, 0)) {
|
||||||
::TranslateMessage(&msg);
|
::TranslateMessage(&msg);
|
||||||
::DispatchMessage(&msg);
|
::DispatchMessage(&msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
::CoUninitialize();
|
::CoUninitialize();
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-16
@@ -1,16 +1,16 @@
|
|||||||
//{{NO_DEPENDENCIES}}
|
//{{NO_DEPENDENCIES}}
|
||||||
// Microsoft Visual C++ generated include file.
|
// Microsoft Visual C++ generated include file.
|
||||||
// Used by Runner.rc
|
// Used by Runner.rc
|
||||||
//
|
//
|
||||||
#define IDI_APP_ICON 101
|
#define IDI_APP_ICON 101
|
||||||
|
|
||||||
// Next default values for new objects
|
// Next default values for new objects
|
||||||
//
|
//
|
||||||
#ifdef APSTUDIO_INVOKED
|
#ifdef APSTUDIO_INVOKED
|
||||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||||
#define _APS_NEXT_SYMED_VALUE 101
|
#define _APS_NEXT_SYMED_VALUE 101
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
<windowsSettings>
|
<windowsSettings>
|
||||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
||||||
</windowsSettings>
|
</windowsSettings>
|
||||||
</application>
|
</application>
|
||||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
<application>
|
<application>
|
||||||
<!-- Windows 10 and Windows 11 -->
|
<!-- Windows 10 and Windows 11 -->
|
||||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||||
</application>
|
</application>
|
||||||
</compatibility>
|
</compatibility>
|
||||||
</assembly>
|
</assembly>
|
||||||
|
|||||||
+65
-65
@@ -1,65 +1,65 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#include <flutter_windows.h>
|
#include <flutter_windows.h>
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
void CreateAndAttachConsole() {
|
void CreateAndAttachConsole() {
|
||||||
if (::AllocConsole()) {
|
if (::AllocConsole()) {
|
||||||
FILE *unused;
|
FILE *unused;
|
||||||
if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
|
if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
|
||||||
_dup2(_fileno(stdout), 1);
|
_dup2(_fileno(stdout), 1);
|
||||||
}
|
}
|
||||||
if (freopen_s(&unused, "CONOUT$", "w", stderr)) {
|
if (freopen_s(&unused, "CONOUT$", "w", stderr)) {
|
||||||
_dup2(_fileno(stdout), 2);
|
_dup2(_fileno(stdout), 2);
|
||||||
}
|
}
|
||||||
std::ios::sync_with_stdio();
|
std::ios::sync_with_stdio();
|
||||||
FlutterDesktopResyncOutputStreams();
|
FlutterDesktopResyncOutputStreams();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> GetCommandLineArguments() {
|
std::vector<std::string> GetCommandLineArguments() {
|
||||||
// Convert the UTF-16 command line arguments to UTF-8 for the Engine to use.
|
// Convert the UTF-16 command line arguments to UTF-8 for the Engine to use.
|
||||||
int argc;
|
int argc;
|
||||||
wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
|
wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
|
||||||
if (argv == nullptr) {
|
if (argv == nullptr) {
|
||||||
return std::vector<std::string>();
|
return std::vector<std::string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> command_line_arguments;
|
std::vector<std::string> command_line_arguments;
|
||||||
|
|
||||||
// Skip the first argument as it's the binary name.
|
// Skip the first argument as it's the binary name.
|
||||||
for (int i = 1; i < argc; i++) {
|
for (int i = 1; i < argc; i++) {
|
||||||
command_line_arguments.push_back(Utf8FromUtf16(argv[i]));
|
command_line_arguments.push_back(Utf8FromUtf16(argv[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
::LocalFree(argv);
|
::LocalFree(argv);
|
||||||
|
|
||||||
return command_line_arguments;
|
return command_line_arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Utf8FromUtf16(const wchar_t* utf16_string) {
|
std::string Utf8FromUtf16(const wchar_t* utf16_string) {
|
||||||
if (utf16_string == nullptr) {
|
if (utf16_string == nullptr) {
|
||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
unsigned int target_length = ::WideCharToMultiByte(
|
unsigned int target_length = ::WideCharToMultiByte(
|
||||||
CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
|
CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
|
||||||
-1, nullptr, 0, nullptr, nullptr)
|
-1, nullptr, 0, nullptr, nullptr)
|
||||||
-1; // remove the trailing null character
|
-1; // remove the trailing null character
|
||||||
int input_length = (int)wcslen(utf16_string);
|
int input_length = (int)wcslen(utf16_string);
|
||||||
std::string utf8_string;
|
std::string utf8_string;
|
||||||
if (target_length == 0 || target_length > utf8_string.max_size()) {
|
if (target_length == 0 || target_length > utf8_string.max_size()) {
|
||||||
return utf8_string;
|
return utf8_string;
|
||||||
}
|
}
|
||||||
utf8_string.resize(target_length);
|
utf8_string.resize(target_length);
|
||||||
int converted_length = ::WideCharToMultiByte(
|
int converted_length = ::WideCharToMultiByte(
|
||||||
CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
|
CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
|
||||||
input_length, utf8_string.data(), target_length, nullptr, nullptr);
|
input_length, utf8_string.data(), target_length, nullptr, nullptr);
|
||||||
if (converted_length == 0) {
|
if (converted_length == 0) {
|
||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
return utf8_string;
|
return utf8_string;
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-19
@@ -1,19 +1,19 @@
|
|||||||
#ifndef RUNNER_UTILS_H_
|
#ifndef RUNNER_UTILS_H_
|
||||||
#define RUNNER_UTILS_H_
|
#define RUNNER_UTILS_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
// Creates a console for the process, and redirects stdout and stderr to
|
// Creates a console for the process, and redirects stdout and stderr to
|
||||||
// it for both the runner and the Flutter library.
|
// it for both the runner and the Flutter library.
|
||||||
void CreateAndAttachConsole();
|
void CreateAndAttachConsole();
|
||||||
|
|
||||||
// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string
|
// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string
|
||||||
// encoded in UTF-8. Returns an empty std::string on failure.
|
// encoded in UTF-8. Returns an empty std::string on failure.
|
||||||
std::string Utf8FromUtf16(const wchar_t* utf16_string);
|
std::string Utf8FromUtf16(const wchar_t* utf16_string);
|
||||||
|
|
||||||
// Gets the command line arguments passed in as a std::vector<std::string>,
|
// Gets the command line arguments passed in as a std::vector<std::string>,
|
||||||
// encoded in UTF-8. Returns an empty std::vector<std::string> on failure.
|
// encoded in UTF-8. Returns an empty std::vector<std::string> on failure.
|
||||||
std::vector<std::string> GetCommandLineArguments();
|
std::vector<std::string> GetCommandLineArguments();
|
||||||
|
|
||||||
#endif // RUNNER_UTILS_H_
|
#endif // RUNNER_UTILS_H_
|
||||||
|
|||||||
+288
-288
@@ -1,288 +1,288 @@
|
|||||||
#include "win32_window.h"
|
#include "win32_window.h"
|
||||||
|
|
||||||
#include <dwmapi.h>
|
#include <dwmapi.h>
|
||||||
#include <flutter_windows.h>
|
#include <flutter_windows.h>
|
||||||
|
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/// Window attribute that enables dark mode window decorations.
|
/// Window attribute that enables dark mode window decorations.
|
||||||
///
|
///
|
||||||
/// Redefined in case the developer's machine has a Windows SDK older than
|
/// Redefined in case the developer's machine has a Windows SDK older than
|
||||||
/// version 10.0.22000.0.
|
/// version 10.0.22000.0.
|
||||||
/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute
|
/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute
|
||||||
#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
|
#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
|
||||||
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
|
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW";
|
constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW";
|
||||||
|
|
||||||
/// Registry key for app theme preference.
|
/// Registry key for app theme preference.
|
||||||
///
|
///
|
||||||
/// A value of 0 indicates apps should use dark mode. A non-zero or missing
|
/// A value of 0 indicates apps should use dark mode. A non-zero or missing
|
||||||
/// value indicates apps should use light mode.
|
/// value indicates apps should use light mode.
|
||||||
constexpr const wchar_t kGetPreferredBrightnessRegKey[] =
|
constexpr const wchar_t kGetPreferredBrightnessRegKey[] =
|
||||||
L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize";
|
L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize";
|
||||||
constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme";
|
constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme";
|
||||||
|
|
||||||
// The number of Win32Window objects that currently exist.
|
// The number of Win32Window objects that currently exist.
|
||||||
static int g_active_window_count = 0;
|
static int g_active_window_count = 0;
|
||||||
|
|
||||||
using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd);
|
using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd);
|
||||||
|
|
||||||
// Scale helper to convert logical scaler values to physical using passed in
|
// Scale helper to convert logical scaler values to physical using passed in
|
||||||
// scale factor
|
// scale factor
|
||||||
int Scale(int source, double scale_factor) {
|
int Scale(int source, double scale_factor) {
|
||||||
return static_cast<int>(source * scale_factor);
|
return static_cast<int>(source * scale_factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module.
|
// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module.
|
||||||
// This API is only needed for PerMonitor V1 awareness mode.
|
// This API is only needed for PerMonitor V1 awareness mode.
|
||||||
void EnableFullDpiSupportIfAvailable(HWND hwnd) {
|
void EnableFullDpiSupportIfAvailable(HWND hwnd) {
|
||||||
HMODULE user32_module = LoadLibraryA("User32.dll");
|
HMODULE user32_module = LoadLibraryA("User32.dll");
|
||||||
if (!user32_module) {
|
if (!user32_module) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto enable_non_client_dpi_scaling =
|
auto enable_non_client_dpi_scaling =
|
||||||
reinterpret_cast<EnableNonClientDpiScaling*>(
|
reinterpret_cast<EnableNonClientDpiScaling*>(
|
||||||
GetProcAddress(user32_module, "EnableNonClientDpiScaling"));
|
GetProcAddress(user32_module, "EnableNonClientDpiScaling"));
|
||||||
if (enable_non_client_dpi_scaling != nullptr) {
|
if (enable_non_client_dpi_scaling != nullptr) {
|
||||||
enable_non_client_dpi_scaling(hwnd);
|
enable_non_client_dpi_scaling(hwnd);
|
||||||
}
|
}
|
||||||
FreeLibrary(user32_module);
|
FreeLibrary(user32_module);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// Manages the Win32Window's window class registration.
|
// Manages the Win32Window's window class registration.
|
||||||
class WindowClassRegistrar {
|
class WindowClassRegistrar {
|
||||||
public:
|
public:
|
||||||
~WindowClassRegistrar() = default;
|
~WindowClassRegistrar() = default;
|
||||||
|
|
||||||
// Returns the singleton registrar instance.
|
// Returns the singleton registrar instance.
|
||||||
static WindowClassRegistrar* GetInstance() {
|
static WindowClassRegistrar* GetInstance() {
|
||||||
if (!instance_) {
|
if (!instance_) {
|
||||||
instance_ = new WindowClassRegistrar();
|
instance_ = new WindowClassRegistrar();
|
||||||
}
|
}
|
||||||
return instance_;
|
return instance_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the name of the window class, registering the class if it hasn't
|
// Returns the name of the window class, registering the class if it hasn't
|
||||||
// previously been registered.
|
// previously been registered.
|
||||||
const wchar_t* GetWindowClass();
|
const wchar_t* GetWindowClass();
|
||||||
|
|
||||||
// Unregisters the window class. Should only be called if there are no
|
// Unregisters the window class. Should only be called if there are no
|
||||||
// instances of the window.
|
// instances of the window.
|
||||||
void UnregisterWindowClass();
|
void UnregisterWindowClass();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WindowClassRegistrar() = default;
|
WindowClassRegistrar() = default;
|
||||||
|
|
||||||
static WindowClassRegistrar* instance_;
|
static WindowClassRegistrar* instance_;
|
||||||
|
|
||||||
bool class_registered_ = false;
|
bool class_registered_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr;
|
WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr;
|
||||||
|
|
||||||
const wchar_t* WindowClassRegistrar::GetWindowClass() {
|
const wchar_t* WindowClassRegistrar::GetWindowClass() {
|
||||||
if (!class_registered_) {
|
if (!class_registered_) {
|
||||||
WNDCLASS window_class{};
|
WNDCLASS window_class{};
|
||||||
window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||||
window_class.lpszClassName = kWindowClassName;
|
window_class.lpszClassName = kWindowClassName;
|
||||||
window_class.style = CS_HREDRAW | CS_VREDRAW;
|
window_class.style = CS_HREDRAW | CS_VREDRAW;
|
||||||
window_class.cbClsExtra = 0;
|
window_class.cbClsExtra = 0;
|
||||||
window_class.cbWndExtra = 0;
|
window_class.cbWndExtra = 0;
|
||||||
window_class.hInstance = GetModuleHandle(nullptr);
|
window_class.hInstance = GetModuleHandle(nullptr);
|
||||||
window_class.hIcon =
|
window_class.hIcon =
|
||||||
LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON));
|
LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON));
|
||||||
window_class.hbrBackground = 0;
|
window_class.hbrBackground = 0;
|
||||||
window_class.lpszMenuName = nullptr;
|
window_class.lpszMenuName = nullptr;
|
||||||
window_class.lpfnWndProc = Win32Window::WndProc;
|
window_class.lpfnWndProc = Win32Window::WndProc;
|
||||||
RegisterClass(&window_class);
|
RegisterClass(&window_class);
|
||||||
class_registered_ = true;
|
class_registered_ = true;
|
||||||
}
|
}
|
||||||
return kWindowClassName;
|
return kWindowClassName;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowClassRegistrar::UnregisterWindowClass() {
|
void WindowClassRegistrar::UnregisterWindowClass() {
|
||||||
UnregisterClass(kWindowClassName, nullptr);
|
UnregisterClass(kWindowClassName, nullptr);
|
||||||
class_registered_ = false;
|
class_registered_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Win32Window::Win32Window() {
|
Win32Window::Win32Window() {
|
||||||
++g_active_window_count;
|
++g_active_window_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
Win32Window::~Win32Window() {
|
Win32Window::~Win32Window() {
|
||||||
--g_active_window_count;
|
--g_active_window_count;
|
||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Win32Window::Create(const std::wstring& title,
|
bool Win32Window::Create(const std::wstring& title,
|
||||||
const Point& origin,
|
const Point& origin,
|
||||||
const Size& size) {
|
const Size& size) {
|
||||||
Destroy();
|
Destroy();
|
||||||
|
|
||||||
const wchar_t* window_class =
|
const wchar_t* window_class =
|
||||||
WindowClassRegistrar::GetInstance()->GetWindowClass();
|
WindowClassRegistrar::GetInstance()->GetWindowClass();
|
||||||
|
|
||||||
const POINT target_point = {static_cast<LONG>(origin.x),
|
const POINT target_point = {static_cast<LONG>(origin.x),
|
||||||
static_cast<LONG>(origin.y)};
|
static_cast<LONG>(origin.y)};
|
||||||
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),
|
||||||
Scale(size.width, scale_factor), Scale(size.height, scale_factor),
|
Scale(size.width, scale_factor), Scale(size.height, scale_factor),
|
||||||
nullptr, nullptr, GetModuleHandle(nullptr), this);
|
nullptr, nullptr, GetModuleHandle(nullptr), this);
|
||||||
|
|
||||||
if (!window) {
|
if (!window) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateTheme(window);
|
UpdateTheme(window);
|
||||||
|
|
||||||
return OnCreate();
|
return OnCreate();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Win32Window::Show() {
|
bool Win32Window::Show() {
|
||||||
return ShowWindow(window_handle_, SW_SHOWNORMAL);
|
return ShowWindow(window_handle_, SW_SHOWNORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
LRESULT CALLBACK Win32Window::WndProc(HWND const window,
|
LRESULT CALLBACK Win32Window::WndProc(HWND const window,
|
||||||
UINT const message,
|
UINT const message,
|
||||||
WPARAM const wparam,
|
WPARAM const wparam,
|
||||||
LPARAM const lparam) noexcept {
|
LPARAM const lparam) noexcept {
|
||||||
if (message == WM_NCCREATE) {
|
if (message == WM_NCCREATE) {
|
||||||
auto window_struct = reinterpret_cast<CREATESTRUCT*>(lparam);
|
auto window_struct = reinterpret_cast<CREATESTRUCT*>(lparam);
|
||||||
SetWindowLongPtr(window, GWLP_USERDATA,
|
SetWindowLongPtr(window, GWLP_USERDATA,
|
||||||
reinterpret_cast<LONG_PTR>(window_struct->lpCreateParams));
|
reinterpret_cast<LONG_PTR>(window_struct->lpCreateParams));
|
||||||
|
|
||||||
auto that = static_cast<Win32Window*>(window_struct->lpCreateParams);
|
auto that = static_cast<Win32Window*>(window_struct->lpCreateParams);
|
||||||
EnableFullDpiSupportIfAvailable(window);
|
EnableFullDpiSupportIfAvailable(window);
|
||||||
that->window_handle_ = window;
|
that->window_handle_ = window;
|
||||||
} else if (Win32Window* that = GetThisFromHandle(window)) {
|
} else if (Win32Window* that = GetThisFromHandle(window)) {
|
||||||
return that->MessageHandler(window, message, wparam, lparam);
|
return that->MessageHandler(window, message, wparam, lparam);
|
||||||
}
|
}
|
||||||
|
|
||||||
return DefWindowProc(window, message, wparam, lparam);
|
return DefWindowProc(window, message, wparam, lparam);
|
||||||
}
|
}
|
||||||
|
|
||||||
LRESULT
|
LRESULT
|
||||||
Win32Window::MessageHandler(HWND hwnd,
|
Win32Window::MessageHandler(HWND hwnd,
|
||||||
UINT const message,
|
UINT const message,
|
||||||
WPARAM const wparam,
|
WPARAM const wparam,
|
||||||
LPARAM const lparam) noexcept {
|
LPARAM const lparam) noexcept {
|
||||||
switch (message) {
|
switch (message) {
|
||||||
case WM_DESTROY:
|
case WM_DESTROY:
|
||||||
window_handle_ = nullptr;
|
window_handle_ = nullptr;
|
||||||
Destroy();
|
Destroy();
|
||||||
if (quit_on_close_) {
|
if (quit_on_close_) {
|
||||||
PostQuitMessage(0);
|
PostQuitMessage(0);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case WM_DPICHANGED: {
|
case WM_DPICHANGED: {
|
||||||
auto newRectSize = reinterpret_cast<RECT*>(lparam);
|
auto newRectSize = reinterpret_cast<RECT*>(lparam);
|
||||||
LONG newWidth = newRectSize->right - newRectSize->left;
|
LONG newWidth = newRectSize->right - newRectSize->left;
|
||||||
LONG newHeight = newRectSize->bottom - newRectSize->top;
|
LONG newHeight = newRectSize->bottom - newRectSize->top;
|
||||||
|
|
||||||
SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth,
|
SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth,
|
||||||
newHeight, SWP_NOZORDER | SWP_NOACTIVATE);
|
newHeight, SWP_NOZORDER | SWP_NOACTIVATE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case WM_SIZE: {
|
case WM_SIZE: {
|
||||||
RECT rect = GetClientArea();
|
RECT rect = GetClientArea();
|
||||||
if (child_content_ != nullptr) {
|
if (child_content_ != nullptr) {
|
||||||
// Size and position the child window.
|
// Size and position the child window.
|
||||||
MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left,
|
MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left,
|
||||||
rect.bottom - rect.top, TRUE);
|
rect.bottom - rect.top, TRUE);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
case WM_ACTIVATE:
|
case WM_ACTIVATE:
|
||||||
if (child_content_ != nullptr) {
|
if (child_content_ != nullptr) {
|
||||||
SetFocus(child_content_);
|
SetFocus(child_content_);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case WM_DWMCOLORIZATIONCOLORCHANGED:
|
case WM_DWMCOLORIZATIONCOLORCHANGED:
|
||||||
UpdateTheme(hwnd);
|
UpdateTheme(hwnd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DefWindowProc(window_handle_, message, wparam, lparam);
|
return DefWindowProc(window_handle_, message, wparam, lparam);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Win32Window::Destroy() {
|
void Win32Window::Destroy() {
|
||||||
OnDestroy();
|
OnDestroy();
|
||||||
|
|
||||||
if (window_handle_) {
|
if (window_handle_) {
|
||||||
DestroyWindow(window_handle_);
|
DestroyWindow(window_handle_);
|
||||||
window_handle_ = nullptr;
|
window_handle_ = nullptr;
|
||||||
}
|
}
|
||||||
if (g_active_window_count == 0) {
|
if (g_active_window_count == 0) {
|
||||||
WindowClassRegistrar::GetInstance()->UnregisterWindowClass();
|
WindowClassRegistrar::GetInstance()->UnregisterWindowClass();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept {
|
Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept {
|
||||||
return reinterpret_cast<Win32Window*>(
|
return reinterpret_cast<Win32Window*>(
|
||||||
GetWindowLongPtr(window, GWLP_USERDATA));
|
GetWindowLongPtr(window, GWLP_USERDATA));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Win32Window::SetChildContent(HWND content) {
|
void Win32Window::SetChildContent(HWND content) {
|
||||||
child_content_ = content;
|
child_content_ = content;
|
||||||
SetParent(content, window_handle_);
|
SetParent(content, window_handle_);
|
||||||
RECT frame = GetClientArea();
|
RECT frame = GetClientArea();
|
||||||
|
|
||||||
MoveWindow(content, frame.left, frame.top, frame.right - frame.left,
|
MoveWindow(content, frame.left, frame.top, frame.right - frame.left,
|
||||||
frame.bottom - frame.top, true);
|
frame.bottom - frame.top, true);
|
||||||
|
|
||||||
SetFocus(child_content_);
|
SetFocus(child_content_);
|
||||||
}
|
}
|
||||||
|
|
||||||
RECT Win32Window::GetClientArea() {
|
RECT Win32Window::GetClientArea() {
|
||||||
RECT frame;
|
RECT frame;
|
||||||
GetClientRect(window_handle_, &frame);
|
GetClientRect(window_handle_, &frame);
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
HWND Win32Window::GetHandle() {
|
HWND Win32Window::GetHandle() {
|
||||||
return window_handle_;
|
return window_handle_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Win32Window::SetQuitOnClose(bool quit_on_close) {
|
void Win32Window::SetQuitOnClose(bool quit_on_close) {
|
||||||
quit_on_close_ = quit_on_close;
|
quit_on_close_ = quit_on_close;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Win32Window::OnCreate() {
|
bool Win32Window::OnCreate() {
|
||||||
// No-op; provided for subclasses.
|
// No-op; provided for subclasses.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Win32Window::OnDestroy() {
|
void Win32Window::OnDestroy() {
|
||||||
// No-op; provided for subclasses.
|
// No-op; provided for subclasses.
|
||||||
}
|
}
|
||||||
|
|
||||||
void Win32Window::UpdateTheme(HWND const window) {
|
void Win32Window::UpdateTheme(HWND const window) {
|
||||||
DWORD light_mode;
|
DWORD light_mode;
|
||||||
DWORD light_mode_size = sizeof(light_mode);
|
DWORD light_mode_size = sizeof(light_mode);
|
||||||
LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey,
|
LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey,
|
||||||
kGetPreferredBrightnessRegValue,
|
kGetPreferredBrightnessRegValue,
|
||||||
RRF_RT_REG_DWORD, nullptr, &light_mode,
|
RRF_RT_REG_DWORD, nullptr, &light_mode,
|
||||||
&light_mode_size);
|
&light_mode_size);
|
||||||
|
|
||||||
if (result == ERROR_SUCCESS) {
|
if (result == ERROR_SUCCESS) {
|
||||||
BOOL enable_dark_mode = light_mode == 0;
|
BOOL enable_dark_mode = light_mode == 0;
|
||||||
DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE,
|
DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE,
|
||||||
&enable_dark_mode, sizeof(enable_dark_mode));
|
&enable_dark_mode, sizeof(enable_dark_mode));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+102
-102
@@ -1,102 +1,102 @@
|
|||||||
#ifndef RUNNER_WIN32_WINDOW_H_
|
#ifndef RUNNER_WIN32_WINDOW_H_
|
||||||
#define RUNNER_WIN32_WINDOW_H_
|
#define RUNNER_WIN32_WINDOW_H_
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
// A class abstraction for a high DPI-aware Win32 Window. Intended to be
|
// A class abstraction for a high DPI-aware Win32 Window. Intended to be
|
||||||
// inherited from by classes that wish to specialize with custom
|
// inherited from by classes that wish to specialize with custom
|
||||||
// rendering and input handling
|
// rendering and input handling
|
||||||
class Win32Window {
|
class Win32Window {
|
||||||
public:
|
public:
|
||||||
struct Point {
|
struct Point {
|
||||||
unsigned int x;
|
unsigned int x;
|
||||||
unsigned int y;
|
unsigned int y;
|
||||||
Point(unsigned int x, unsigned int y) : x(x), y(y) {}
|
Point(unsigned int x, unsigned int y) : x(x), y(y) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Size {
|
struct Size {
|
||||||
unsigned int width;
|
unsigned int width;
|
||||||
unsigned int height;
|
unsigned int height;
|
||||||
Size(unsigned int width, unsigned int height)
|
Size(unsigned int width, unsigned int height)
|
||||||
: width(width), height(height) {}
|
: width(width), height(height) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
Win32Window();
|
Win32Window();
|
||||||
virtual ~Win32Window();
|
virtual ~Win32Window();
|
||||||
|
|
||||||
// Creates a win32 window with |title| that is positioned and sized using
|
// Creates a win32 window with |title| that is positioned and sized using
|
||||||
// |origin| and |size|. New windows are created on the default monitor. Window
|
// |origin| and |size|. New windows are created on the default monitor. Window
|
||||||
// sizes are specified to the OS in physical pixels, hence to ensure a
|
// sizes are specified to the OS in physical pixels, hence to ensure a
|
||||||
// consistent size this function will scale the inputted width and height as
|
// consistent size this function will scale the inputted width and height as
|
||||||
// as appropriate for the default monitor. The window is invisible until
|
// as appropriate for the default monitor. The window is invisible until
|
||||||
// |Show| is called. Returns true if the window was created successfully.
|
// |Show| is called. Returns true if the window was created successfully.
|
||||||
bool Create(const std::wstring& title, const Point& origin, const Size& size);
|
bool Create(const std::wstring& title, const Point& origin, const Size& size);
|
||||||
|
|
||||||
// Show the current window. Returns true if the window was successfully shown.
|
// Show the current window. Returns true if the window was successfully shown.
|
||||||
bool Show();
|
bool Show();
|
||||||
|
|
||||||
// Release OS resources associated with window.
|
// Release OS resources associated with window.
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
// Inserts |content| into the window tree.
|
// Inserts |content| into the window tree.
|
||||||
void SetChildContent(HWND content);
|
void SetChildContent(HWND content);
|
||||||
|
|
||||||
// Returns the backing Window handle to enable clients to set icon and other
|
// Returns the backing Window handle to enable clients to set icon and other
|
||||||
// window properties. Returns nullptr if the window has been destroyed.
|
// window properties. Returns nullptr if the window has been destroyed.
|
||||||
HWND GetHandle();
|
HWND GetHandle();
|
||||||
|
|
||||||
// If true, closing this window will quit the application.
|
// If true, closing this window will quit the application.
|
||||||
void SetQuitOnClose(bool quit_on_close);
|
void SetQuitOnClose(bool quit_on_close);
|
||||||
|
|
||||||
// Return a RECT representing the bounds of the current client area.
|
// Return a RECT representing the bounds of the current client area.
|
||||||
RECT GetClientArea();
|
RECT GetClientArea();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Processes and route salient window messages for mouse handling,
|
// Processes and route salient window messages for mouse handling,
|
||||||
// size change and DPI. Delegates handling of these to member overloads that
|
// size change and DPI. Delegates handling of these to member overloads that
|
||||||
// inheriting classes can handle.
|
// inheriting classes can handle.
|
||||||
virtual LRESULT MessageHandler(HWND window,
|
virtual LRESULT MessageHandler(HWND window,
|
||||||
UINT const message,
|
UINT const message,
|
||||||
WPARAM const wparam,
|
WPARAM const wparam,
|
||||||
LPARAM const lparam) noexcept;
|
LPARAM const lparam) noexcept;
|
||||||
|
|
||||||
// Called when CreateAndShow is called, allowing subclass window-related
|
// Called when CreateAndShow is called, allowing subclass window-related
|
||||||
// setup. Subclasses should return false if setup fails.
|
// setup. Subclasses should return false if setup fails.
|
||||||
virtual bool OnCreate();
|
virtual bool OnCreate();
|
||||||
|
|
||||||
// Called when Destroy is called.
|
// Called when Destroy is called.
|
||||||
virtual void OnDestroy();
|
virtual void OnDestroy();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class WindowClassRegistrar;
|
friend class WindowClassRegistrar;
|
||||||
|
|
||||||
// OS callback called by message pump. Handles the WM_NCCREATE message which
|
// OS callback called by message pump. Handles the WM_NCCREATE message which
|
||||||
// is passed when the non-client area is being created and enables automatic
|
// is passed when the non-client area is being created and enables automatic
|
||||||
// non-client DPI scaling so that the non-client area automatically
|
// non-client DPI scaling so that the non-client area automatically
|
||||||
// responds to changes in DPI. All other messages are handled by
|
// responds to changes in DPI. All other messages are handled by
|
||||||
// MessageHandler.
|
// MessageHandler.
|
||||||
static LRESULT CALLBACK WndProc(HWND const window,
|
static LRESULT CALLBACK WndProc(HWND const window,
|
||||||
UINT const message,
|
UINT const message,
|
||||||
WPARAM const wparam,
|
WPARAM const wparam,
|
||||||
LPARAM const lparam) noexcept;
|
LPARAM const lparam) noexcept;
|
||||||
|
|
||||||
// Retrieves a class instance pointer for |window|
|
// Retrieves a class instance pointer for |window|
|
||||||
static Win32Window* GetThisFromHandle(HWND const window) noexcept;
|
static Win32Window* GetThisFromHandle(HWND const window) noexcept;
|
||||||
|
|
||||||
// Update the window frame's theme to match the system theme.
|
// Update the window frame's theme to match the system theme.
|
||||||
static void UpdateTheme(HWND const window);
|
static void UpdateTheme(HWND const window);
|
||||||
|
|
||||||
bool quit_on_close_ = false;
|
bool quit_on_close_ = false;
|
||||||
|
|
||||||
// window handle for top level window.
|
// window handle for top level window.
|
||||||
HWND window_handle_ = nullptr;
|
HWND window_handle_ = nullptr;
|
||||||
|
|
||||||
// window handle for hosted content.
|
// window handle for hosted content.
|
||||||
HWND child_content_ = nullptr;
|
HWND child_content_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // RUNNER_WIN32_WINDOW_H_
|
#endif // RUNNER_WIN32_WINDOW_H_
|
||||||
|
|||||||
Reference in New Issue
Block a user