[fix] resolve cross-platform build warnings

This commit is contained in:
dijunkun
2026-11-07 01:55:51 +08:00
parent 33bc5bf13b
commit e3ad683809
14 changed files with 58 additions and 39 deletions
+12 -12
View File
@@ -1,27 +1,27 @@
plugins { id 'com.android.application' } plugins { id 'com.android.application' }
android { android {
namespace 'cn.crossdesk.mobile' namespace = 'cn.crossdesk.mobile'
compileSdk 36 compileSdk = 36
ndkVersion '28.2.13676358' ndkVersion = '28.2.13676358'
defaultConfig { defaultConfig {
applicationId 'cn.crossdesk.mobile' applicationId = 'cn.crossdesk.mobile'
minSdk 26 minSdk = 26
targetSdk 36 targetSdk = 36
versionCode providers.gradleProperty('crossdeskVersionCode').get().toInteger() versionCode = providers.gradleProperty('crossdeskVersionCode').get().toInteger()
versionName providers.gradleProperty('crossdeskVersionName').get() versionName = providers.gradleProperty('crossdeskVersionName').get()
ndk { abiFilters 'arm64-v8a' } ndk { abiFilters 'arm64-v8a' }
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' testInstrumentationRunner = 'androidx.test.runner.AndroidJUnitRunner'
} }
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_17 sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17
} }
sourceSets.main.jniLibs.srcDirs = [layout.buildDirectory.dir('native')] sourceSets.main.jniLibs.srcDirs = [layout.buildDirectory.dir('native')]
sourceSets.main.assets.srcDirs += [layout.buildDirectory.dir('generated/notices')] sourceSets.main.assets.srcDirs += [layout.buildDirectory.dir('generated/notices')]
sourceSets.androidTest.java.srcDirs = ['../test/android/java'] sourceSets.androidTest.java.srcDirs = ['../test/android/java']
sourceSets.androidTest.assets.srcDirs = ['../test/android/assets'] sourceSets.androidTest.assets.srcDirs = ['../test/android/assets']
buildTypes.release { minifyEnabled false } buildTypes.release { minifyEnabled = false }
packaging.jniLibs.useLegacyPackaging = false packaging.jniLibs.useLegacyPackaging = false
} }
@@ -118,6 +118,9 @@ public final class MainActivity extends Activity implements NativeSession.Listen
private String serverKey(){return host+":"+port;} private String serverKey(){return host+":"+port;}
private void toast(String value){Toast.makeText(this,value,Toast.LENGTH_SHORT).show();} private void toast(String value){Toast.makeText(this,value,Toast.LENGTH_SHORT).show();}
private void hideKeyboard(){((InputMethodManager)getSystemService(INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(root.getWindowToken(),0);root.clearFocus();} private void hideKeyboard(){((InputMethodManager)getSystemService(INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(root.getWindowToken(),0);root.clearFocus();}
// Legacy inset handling also includes the IME on non-session pages. The
// decor-fitting call below is restricted to Android 11–14.
@SuppressWarnings("deprecation")
private void installRoot(String nextPage,boolean dark){ private void installRoot(String nextPage,boolean dark){
PageHost.Motion motion=PageHost.Motion.NONE; PageHost.Motion motion=PageHost.Motion.NONE;
if(canvas!=null&&foreground&&!page.equals(nextPage)){ if(canvas!=null&&foreground&&!page.equals(nextPage)){
@@ -147,6 +150,8 @@ public final class MainActivity extends Activity implements NativeSession.Listen
root.setFocusableInTouchMode(true);pageHost.show(canvas,motion); root.setFocusableInTouchMode(true);pageHost.show(canvas,motion);
applySystemBars(dark); applySystemBars(dark);
} }
// Android 8–10 require system UI flags instead of WindowInsetsController.
@SuppressWarnings("deprecation")
private void applySystemBars(boolean dark){ private void applySystemBars(boolean dark){
if(android.os.Build.VERSION.SDK_INT>=30){ if(android.os.Build.VERSION.SDK_INT>=30){
android.view.WindowInsetsController controller=getWindow().getInsetsController(); android.view.WindowInsetsController controller=getWindow().getInsetsController();
@@ -302,7 +307,9 @@ public final class MainActivity extends Activity implements NativeSession.Listen
rememberPassword=remember.isChecked();password.setText("");dialog.dismiss();begin(id,secret); rememberPassword=remember.isChecked();password.setText("");dialog.dismiss();begin(id,secret);
});connect.setContentDescription(L10n.tr("确认连接"));sheet.addView(connect,ui.size(-1,48)); });connect.setContentDescription(L10n.tr("确认连接"));sheet.addView(connect,ui.size(-1,48));
ScrollView scroll=new ScrollView(this);scroll.addView(sheet); ScrollView scroll=new ScrollView(this);scroll.addView(sheet);
dialog.setContentView(scroll);Window window=dialog.getWindow();if(window!=null){window.setBackgroundDrawableResource(android.R.color.transparent);window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);window.setDimAmount(.22f);}dialog.show();sizePasswordDialog();password.requestFocus();if(!error.isEmpty())password.setError(error); // This floating dialog uses window-managed IME resizing on all supported APIs.
@SuppressWarnings("deprecation") int resizeMode=WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
dialog.setContentView(scroll);Window window=dialog.getWindow();if(window!=null){window.setBackgroundDrawableResource(android.R.color.transparent);window.setSoftInputMode(resizeMode);window.setDimAmount(.22f);}dialog.show();sizePasswordDialog();password.requestFocus();if(!error.isEmpty())password.setError(error);
dialog.setOnDismissListener(d->{password.setText("");passwordDialog=null;}); dialog.setOnDismissListener(d->{password.setText("");passwordDialog=null;});
} }
private void sizePasswordDialog(){ private void sizePasswordDialog(){
@@ -715,6 +722,8 @@ public final class MainActivity extends Activity implements NativeSession.Listen
private void navigateBack(){if(backAction==null)return;navigatingBack=true;try{backAction.run();}finally{navigatingBack=false;}} private void navigateBack(){if(backAction==null)return;navigatingBack=true;try{backAction.run();}finally{navigatingBack=false;}}
private void back(){if(controls!=null&&controls.closeKeyboard())return;pageHost.finish();if(session!=null){if(ready)confirmDisconnect();else end("");}else if(backAction!=null)navigateBack();else finish();} private void back(){if(controls!=null&&controls.closeKeyboard())return;pageHost.finish();if(session!=null){if(ready)confirmDisconnect();else end("");}else if(backAction!=null)navigateBack();else finish();}
@Override public void onWindowFocusChanged(boolean focus){super.onWindowFocusChanged(focus);if(!focus)releaseKeys();else applySystemBars(ready);} @Override public void onWindowFocusChanged(boolean focus){super.onWindowFocusChanged(focus);if(!focus)releaseKeys();else applySystemBars(ready);}
// API 26–32 use this callback; API 33+ registers OnBackInvokedCallback in onCreate.
@SuppressWarnings("deprecation")
@android.annotation.SuppressLint("GestureBackNavigation") @Override public void onBackPressed(){back();} @android.annotation.SuppressLint("GestureBackNavigation") @Override public void onBackPressed(){back();}
@Override public void onConfigurationChanged(Configuration config){ @Override public void onConfigurationChanged(Configuration config){
super.onConfigurationChanged(config); super.onConfigurationChanged(config);
@@ -90,6 +90,8 @@ final class MobileUi {
} }
@Override public void setAlpha(int alpha) { bitmapPaint.setAlpha(alpha);invalidateSelf(); } @Override public void setAlpha(int alpha) { bitmapPaint.setAlpha(alpha);invalidateSelf(); }
@Override public void setColorFilter(ColorFilter filter) { bitmapPaint.setColorFilter(filter);invalidateSelf(); } @Override public void setColorFilter(ColorFilter filter) { bitmapPaint.setColorFilter(filter);invalidateSelf(); }
// Drawable still requires this abstract method, including on API 26.
@SuppressWarnings("deprecation")
@Override public int getOpacity() { return PixelFormat.TRANSLUCENT; } @Override public int getOpacity() { return PixelFormat.TRANSLUCENT; }
} }
@android.annotation.SuppressLint("ViewConstructor") // Programmatic icon primitive, not inflated from XML. @android.annotation.SuppressLint("ViewConstructor") // Programmatic icon primitive, not inflated from XML.
@@ -601,6 +601,9 @@ export component FileBrowserWindow inherits Window {
SurfaceSeparator { x: 0px; y: 0px; width: parent.width; } SurfaceSeparator { x: 0px; y: 0px; width: parent.width; }
focus := FocusScope { focus := FocusScope {
focus-on-click: true; focus-on-click: true;
// Window sizing is defined above. Keep its layout constraints separate
// from children whose dimensions adapt to the current window size.
x: 0px; y: 0px; width: root.width; height: root.height;
key-pressed(event) => { key-pressed(event) => {
if event.text == Key.Escape { root.cancel-drag(); return accept; } if event.text == Key.Escape { root.cancel-drag(); return accept; }
reject reject
@@ -141,7 +141,6 @@ export component TrustedDevicesDialog inherits Rectangle {
// Extend into the right margin to preserve the existing card width. // Extend into the right margin to preserve the existing card width.
width: parent.width - 56px + dialog.scrollbar-gutter; width: parent.width - 56px + dialog.scrollbar-gutter;
height: parent.height - 84px; height: parent.height - 84px;
min-width: 0px; min-height: 0px;
horizontal-scrollbar-policy: always-off; horizontal-scrollbar-policy: always-off;
vertical-scrollbar-policy: as-needed; vertical-scrollbar-policy: as-needed;
viewport-width: self.visible-width; viewport-width: self.visible-width;
@@ -102,7 +102,11 @@ void Launch(const fs::path& executable, const std::vector<std::string>& argument
} }
execv(executable.c_str(), argv.data()); execv(executable.c_str(), argv.data());
const int error = errno; const int error = errno;
(void)write(errors[1], &error, sizeof(error)); // This small blocking pipe write is atomic. Retry signal interruptions so
// the parent cannot mistake a failed exec for a successful launch.
ssize_t written;
do { written = write(errors[1], &error, sizeof(error)); }
while (written < 0 && errno == EINTR);
_exit(127); _exit(127);
} }
close(errors[1]); close(errors[1]);
@@ -17,16 +17,16 @@ namespace crossdesk {
class PlatformKeyboardCapturer final : public KeyboardCapturer { class PlatformKeyboardCapturer final : public KeyboardCapturer {
public: public:
PlatformKeyboardCapturer(); PlatformKeyboardCapturer();
virtual ~PlatformKeyboardCapturer(); ~PlatformKeyboardCapturer() override;
public: public:
virtual int Hook(OnKeyAction on_key_action, void* user_ptr); int Hook(OnKeyAction on_key_action, void* user_ptr) override;
virtual int Unhook(); int Unhook() override;
bool SupportsTextInput() const override { return true; } bool SupportsTextInput() const override { return true; }
int SendTextCommand(const std::string& text) override; int SendTextCommand(const std::string& text) override;
virtual int SendKeyboardCommand(int key_code, bool is_down, int SendKeyboardCommand(int key_code, bool is_down,
uint32_t scan_code = 0, uint32_t scan_code = 0,
bool extended = false); bool extended = false) override;
private: private:
CFMachPortRef event_tap_ = nullptr; CFMachPortRef event_tap_ = nullptr;
@@ -1,7 +1,7 @@
/* /*
* @Author: DI JUNKUN * @Author: DI JUNKUN
* @Date: 2023-12-14 * @Date: 2023-12-14
* Copyright (c) 2023 by DI JUNKUN, All Rights Reserved. * Copyright (c) 2026 by DI JUNKUN, All Rights Reserved.
*/ */
#ifndef _MOUSE_CONTROLLER_H_ #ifndef _MOUSE_CONTROLLER_H_
@@ -20,15 +20,15 @@ namespace crossdesk {
class PlatformMouseController final : public MouseController { class PlatformMouseController final : public MouseController {
public: public:
PlatformMouseController(); PlatformMouseController();
virtual ~PlatformMouseController(); ~PlatformMouseController() override;
public: public:
virtual int Init(std::vector<DisplayInfo> display_info_list); int Init(std::vector<DisplayInfo> display_info_list) override;
virtual int Destroy(); int Destroy() override;
virtual int SendMouseCommand(RemoteAction remote_action, int display_index); int SendMouseCommand(RemoteAction remote_action, int display_index) override;
unsigned ReleasePressedButtons(unsigned mask = 7) override; unsigned ReleasePressedButtons(unsigned mask = 7) override;
void UpdateDisplayInfoList( void UpdateDisplayInfoList(
const std::vector<DisplayInfo>& display_info_list); const std::vector<DisplayInfo>& display_info_list) override;
private: private:
struct ClickTracker { struct ClickTracker {
-3
View File
@@ -99,9 +99,6 @@ function setup_platform_settings()
add_cxflags("-Wno-unused-variable") add_cxflags("-Wno-unused-variable")
elseif is_os("macosx") then elseif is_os("macosx") then
if is_arch("x86_64") then
add_ldflags("-Wl,-ld_classic")
end
add_cxflags("-Wno-unused-variable") add_cxflags("-Wno-unused-variable")
add_frameworks("Cocoa", "CoreGraphics", "Metal", "QuartzCore", "IOKit", add_frameworks("Cocoa", "CoreGraphics", "Metal", "QuartzCore", "IOKit",
"IOSurface", "IOSurface",
-2
View File
@@ -1,6 +1,4 @@
function setup_targets() function setup_targets()
includes("deps/submodules", "deps/thirdparty")
local crossdesk_version = get_config("CROSSDESK_VERSION") or "0.0.0" local crossdesk_version = get_config("CROSSDESK_VERSION") or "0.0.0"
local version_define = "CROSSDESK_VERSION=\"" .. crossdesk_version .. "\"" local version_define = "CROSSDESK_VERSION=\"" .. crossdesk_version .. "\""
local windows_resource_defines = { local windows_resource_defines = {
+2 -1
View File
@@ -196,7 +196,8 @@ fi
# no second project definition to maintain. # no second project definition to maintain.
( (
cd "${WIRE_WORK_DIR}" cd "${WIRE_WORK_DIR}"
configure_xmake "${WIRE_WORK_DIR}" "${WIRE_BUILD_DIR}" configure_xmake "${WIRE_WORK_DIR}" "${WIRE_BUILD_DIR}" \
--CROSSDESK_BUILD_DESKTOP=false --CROSSDESK_BUILD_CLI=false
print "Building CrossDesk wire for ${SDK_NAME} (${MODE})" print "Building CrossDesk wire for ${SDK_NAME} (${MODE})"
run_xmake b -P "${WIRE_WORK_DIR}" "${XMAKE_LOG_FLAGS[@]}" crossdesk_wire run_xmake b -P "${WIRE_WORK_DIR}" "${XMAKE_LOG_FLAGS[@]}" crossdesk_wire
) )
+9 -5
View File
@@ -9,6 +9,7 @@
#include <fstream> #include <fstream>
#include <set> #include <set>
#include <stdexcept> #include <stdexcept>
#include <string_view>
namespace crossdesk { namespace crossdesk {
namespace { namespace {
@@ -16,6 +17,9 @@ using Json = FileBrowser::Json;
namespace fs = std::filesystem; namespace fs = std::filesystem;
constexpr size_t kPageEntries = 512; constexpr size_t kPageEntries = 512;
constexpr size_t kPageBytes = 45000; constexpr size_t kPageBytes = 45000;
fs::path PathFromUtf8(std::string_view value) {
return fs::path(std::u8string(value.begin(), value.end()));
}
std::string Utf8(const fs::path& path) { std::string Utf8(const fs::path& path) {
const auto value = path.u8string(); const auto value = path.u8string();
return {value.begin(), value.end()}; return {value.begin(), value.end()};
@@ -26,7 +30,7 @@ fs::path Home() {
#else #else
const auto* home = std::getenv("HOME"); const auto* home = std::getenv("HOME");
#endif #endif
return home ? std::filesystem::u8path(home) : fs::current_path(); return home ? PathFromUtf8(home) : fs::current_path();
} }
Json Failure(const std::string& reason) { return {{"ok", false}, {"error", reason}}; } Json Failure(const std::string& reason) { return {{"ok", false}, {"error", reason}}; }
template <typename FileTime> template <typename FileTime>
@@ -76,7 +80,7 @@ std::string Text(const Json& value, const char* key) {
} }
fs::path ExistingDirectory(const std::string& path) { fs::path ExistingDirectory(const std::string& path) {
if (path.empty()) throw std::runtime_error("invalid_path"); if (path.empty()) throw std::runtime_error("invalid_path");
auto input = std::filesystem::u8path(path); auto input = PathFromUtf8(path);
if (!input.is_absolute()) throw std::runtime_error("invalid_path"); if (!input.is_absolute()) throw std::runtime_error("invalid_path");
std::error_code ec; std::error_code ec;
auto result = fs::canonical(input, ec); auto result = fs::canonical(input, ec);
@@ -84,7 +88,7 @@ fs::path ExistingDirectory(const std::string& path) {
return result; return result;
} }
fs::path Destination(const fs::path& root, const std::string& relative) { fs::path Destination(const fs::path& root, const std::string& relative) {
auto path = std::filesystem::u8path(relative); auto path = PathFromUtf8(relative);
if (path.is_absolute() || path.has_root_name()) throw std::runtime_error("invalid_path"); if (path.is_absolute() || path.has_root_name()) throw std::runtime_error("invalid_path");
auto result = root; auto result = root;
for (const auto& component : path) { for (const auto& component : path) {
@@ -358,7 +362,7 @@ FileBrowser::Json FileBrowser::Directory(const std::string& value, const std::fu
for (char drive = 'A'; drive <= 'Z'; ++drive) { for (char drive = 'A'; drive <= 'Z'; ++drive) {
const std::string root = std::string(1, drive) + ":\\"; const std::string root = std::string(1, drive) + ":\\";
std::error_code ec; std::error_code ec;
if (fs::is_directory(std::filesystem::u8path(root), ec)) if (fs::is_directory(PathFromUtf8(root), ec))
entries.push_back({{"name", root}, {"path", root}, {"directory", true}, {"size", 0}, {"modified", ""}, {"link", false}}); entries.push_back({{"name", root}, {"path", root}, {"directory", true}, {"size", 0}, {"modified", ""}, {"link", false}});
} }
#else #else
@@ -514,7 +518,7 @@ void FileBrowser::Upload(const std::string& peer, const std::vector<std::string>
}; };
// Validate the entire selection before creating remote folders or sending. // Validate the entire selection before creating remote folders or sending.
for (const auto& source : paths) { for (const auto& source : paths) {
auto path = std::filesystem::u8path(source); auto path = PathFromUtf8(source);
if (!path.is_absolute() || path.filename().empty()) throw std::runtime_error("invalid_path"); if (!path.is_absolute() || path.filename().empty()) throw std::runtime_error("invalid_path");
add(path, path.filename()); add(path, path.filename());
if (fs::is_directory(fs::symlink_status(path))) { if (fs::is_directory(fs::symlink_status(path))) {
+2
View File
@@ -86,6 +86,8 @@ if os.isdir(path.join(wire_dir, "tests")) then
end end
if build_desktop then if build_desktop then
includes(path.join(source_dir, "deps/submodules"),
path.join(source_dir, "deps/thirdparty"))
setup_targets() setup_targets()
end end