adapt linux.

This commit is contained in:
amass 2024-09-05 22:05:05 +08:00
parent 7b40c42407
commit 578a764ec0
9 changed files with 1552 additions and 1189 deletions

View File

@ -2,8 +2,33 @@ cmake_minimum_required(VERSION 3.15)
project(Kylin) project(Kylin)
option(INDEPENDENT_BUILD "build self." OFF)
option(UNIT_TEST "do unit test" OFF) option(UNIT_TEST "do unit test" OFF)
if(INDEPENDENT_BUILD)
set(KYLIN_WITH_FLUENT ON)
if(WIN32)
set(Projects_ROOT E:/Projects)
set(Libraries_ROOT ${Projects_ROOT}/Libraries)
set(BOOST_ROOT ${Libraries_ROOT}/boost_1_86_0_msvc2022_64bit)
set(Boost_INCLUDE_DIR ${BOOST_ROOT}/include/boost-1_86)
add_compile_definitions(
BOOST_USE_WINAPI_VERSION=BOOST_WINAPI_VERSION_WIN10
)
else()
execute_process(
COMMAND sh -c "echo $HOME"
OUTPUT_VARIABLE USER_HOME
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(Projects_ROOT ${USER_HOME}/Projects)
set(Libraries_ROOT /opt/Libraries)
set(BOOST_ROOT ${Libraries_ROOT}/boost_1_86_0)
set(Boost_INCLUDE_DIR ${BOOST_ROOT}/include)
endif()
add_subdirectory(Examples)
endif()
find_package(Boost REQUIRED COMPONENTS log serialization) find_package(Boost REQUIRED COMPONENTS log serialization)
set(OpenSSL_LIBRARY ssl crypto) set(OpenSSL_LIBRARY ssl crypto)

View File

@ -1,11 +1,26 @@
import QtQuick import QtQuick
import Fluent as Fluent import Fluent as Fluent
Fluent.Window { Fluent.ApplicationWindow {
width: 640 width: 640
height: 480 height: 480
visible: true visible: true
title: qsTr("FluentWindow") title: qsTr("FluentWindow")
appBar {
height: 30
showDark: true
darkClickListener:(button)=>handleDarkChanged(button)
closeClickListener: ()=>{dialog_close.open()}
z:7
}
Fluent.Button {
text: "成功"
property int dd: 0
onClicked: {
showSuccess("This is a success message %1".arg(dd++),2000)
}
}
Fluent.Rectangle { Fluent.Rectangle {
x:100 x:100
@ -15,4 +30,59 @@ Fluent.Window {
color:"red" color:"red"
radius:[10,0,10,0] radius:[10,0,10,0]
} }
Fluent.ContentDialog{
id: dialog_close
title: qsTr("Quit")
message: qsTr("Are you sure you want to exit the program?")
negativeText: qsTr("Minimize")
buttonFlags: Fluent.ContentDialogType.NegativeButton | Fluent.ContentDialogType.NeutralButton | Fluent.ContentDialogType.PositiveButton
onNegativeClicked: {
system_tray.showMessage(qsTr("Friendly Reminder"),qsTr("FluentUI is hidden from the tray, click on the tray to activate the window again"));
timer_window_hide_delay.restart()
}
positiveText: qsTr("Quit")
neutralText: qsTr("Cancel")
onPositiveClicked:{
Fluent.Router.exit(0)
}
}
function changeDark(){
if(Fluent.Theme.dark){
Fluent.Theme.darkMode = Fluent.ThemeType.Light
}else{
Fluent.Theme.darkMode = Fluent.ThemeType.Dark
}
}
function handleDarkChanged(button){
if(Fluent.Utilities.isMacos() || !Fluent.Theme.animationEnabled || !fitsAppBarWindows){
changeDark()
}else{
loader_reveal.sourceComponent = com_reveal
var target = window.containerItem()
var pos = button.mapToItem(target,0,0)
var mouseX = pos.x + button.width / 2
var mouseY = pos.y + button.height / 2
var radius = Math.max(distance(mouseX,mouseY,0,0),distance(mouseX,mouseY,target.width,0),distance(mouseX,mouseY,0,target.height),distance(mouseX,mouseY,target.width,target.height))
var reveal = loader_reveal.item
reveal.start(reveal.width*Screen.devicePixelRatio,reveal.height*Screen.devicePixelRatio,Qt.point(mouseX,mouseY),radius)
}
}
Fluent.FpsItem {
id:fps_item
}
Fluent.Text{
text: "fps %1".arg(fps_item.fps)
opacity: 0.3
anchors{
bottom: parent.bottom
right: parent.right
bottomMargin: 5
rightMargin: 5
}
}
} }

View File

@ -1,4 +1,5 @@
#include "Colors.h" #include "Colors.h"
#include <QJSEngine>
Colors *Colors::instance() { Colors *Colors::instance() {
static Colors *self = nullptr; static Colors *self = nullptr;

File diff suppressed because it is too large Load Diff

View File

@ -1,91 +1,180 @@
#ifndef FRAMELESS_H #ifndef __FRAMELESS_H__
#define FRAMELESS_H #define __FRAMELESS_H__
#include "Utilities.h" #include "Utilities.h"
#include <QAbstractNativeEventFilter> #include <QAbstractNativeEventFilter>
#include <QQuickItem> #include <QObject>
#include <QQmlProperty>
class Frameless : public QQuickItem, QAbstractNativeEventFilter { #include <QQuickItem>
Q_OBJECT
QML_ELEMENT #ifdef Q_OS_WIN
Q_PROPERTY_AUTO(QString, effect)
Q_PROPERTY_READONLY_AUTO(bool, effective) #pragma comment (lib, "user32.lib")
Q_PROPERTY_READONLY_AUTO(QStringList, availableEffects) #pragma comment (lib, "dwmapi.lib")
Q_PROPERTY(QQuickItem *appBar READ appBar WRITE setAppBar NOTIFY appBarChanged)
Q_PROPERTY(QQuickItem *maximizeButton READ maximizeButton WRITE setMaximizeButton NOTIFY maximizeButtonChanged) #include <windows.h>
Q_PROPERTY(QQuickItem *minimizedButton READ minimizedButton WRITE setMinimizedButton NOTIFY minimizedButtonChanged) #include <windowsx.h>
Q_PROPERTY(QQuickItem *closeButton READ closeButton WRITE setCloseButton NOTIFY closeButtonChanged) #include <dwmapi.h>
enum _DWM_SYSTEMBACKDROP_TYPE {
Q_PROPERTY(bool fixSize READ fixSize WRITE setFixSize NOTIFY fixSizeChanged) _DWMSBT_AUTO, // [Default] Let DWM automatically decide the system-drawn backdrop for this
Q_PROPERTY(bool topmost READ topmost WRITE setTopmost NOTIFY topmostChanged) // window.
Q_PROPERTY(bool disabled READ disabled WRITE setDisabled NOTIFY disabledChanged) _DWMSBT_NONE, // [Disable] Do not draw any system backdrop.
_DWMSBT_MAINWINDOW, // [Mica] Draw the backdrop material effect corresponding to a
public: // long-lived window.
Frameless(QQuickItem *parent = nullptr); _DWMSBT_TRANSIENTWINDOW, // [Acrylic] Draw the backdrop material effect corresponding to a
QQuickItem *appBar() const; // transient window.
void setAppBar(QQuickItem *appBar); _DWMSBT_TABBEDWINDOW, // [Mica Alt] Draw the backdrop material effect corresponding to a
// window with a tabbed title bar.
QQuickItem *maximizeButton() const; };
void setMaximizeButton(QQuickItem *button); enum WINDOWCOMPOSITIONATTRIB {
WCA_UNDEFINED = 0,
QQuickItem *minimizedButton() const; WCA_NCRENDERING_ENABLED = 1,
void setMinimizedButton(QQuickItem *button); WCA_NCRENDERING_POLICY = 2,
WCA_TRANSITIONS_FORCEDISABLED = 3,
QQuickItem *closeButton() const; WCA_ALLOW_NCPAINT = 4,
void setCloseButton(QQuickItem *button); WCA_CAPTION_BUTTON_BOUNDS = 5,
WCA_NONCLIENT_RTL_LAYOUT = 6,
bool fixSize() const; WCA_FORCE_ICONIC_REPRESENTATION = 7,
void setFixSize(bool fix); WCA_EXTENDED_FRAME_BOUNDS = 8,
WCA_HAS_ICONIC_BITMAP = 9,
bool topmost() const; WCA_THEME_ATTRIBUTES = 10,
void setTopmost(bool topmost); WCA_NCRENDERING_EXILED = 11,
WCA_NCADORNMENTINFO = 12,
bool disabled() const; WCA_EXCLUDED_FROM_LIVEPREVIEW = 13,
void setDisabled(bool disabled); WCA_VIDEO_OVERLAY_ACTIVE = 14,
WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 15,
Q_INVOKABLE void showMaximized(); WCA_DISALLOW_PEEK = 16,
Q_INVOKABLE void showMinimized(); WCA_CLOAK = 17,
Q_INVOKABLE void showNormal(); WCA_CLOAKED = 18,
WCA_ACCENT_POLICY = 19,
Q_INVOKABLE void setHitTestVisible(QQuickItem *item); WCA_FREEZE_REPRESENTATION = 20,
Q_INVOKABLE void onDestruction(); WCA_EVER_UNCLOAKED = 21,
void componentComplete() final; WCA_VISUAL_OWNER = 22,
WCA_HOLOGRAPHIC = 23,
bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) final; WCA_EXCLUDED_FROM_DDA = 24,
WCA_PASSIVEUPDATEMODE = 25,
signals: WCA_USEDARKMODECOLORS = 26,
void appBarChanged(); WCA_CORNER_STYLE = 27,
void maximizeButtonChanged(); WCA_PART_COLOR = 28,
void minimizedButtonChanged(); WCA_DISABLE_MOVESIZE_FEEDBACK = 29,
void closeButtonChanged(); WCA_LAST = 30
void fixSizeChanged(); };
void topmostChanged();
void disabledChanged(); enum ACCENT_STATE {
ACCENT_DISABLED = 0,
protected: ACCENT_ENABLE_GRADIENT = 1,
bool isFullScreen(); ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
bool isMaximized(); ACCENT_ENABLE_BLURBEHIND = 3, // Traditional DWM blur
void setMaximizeHovered(bool val); ACCENT_ENABLE_ACRYLICBLURBEHIND = 4, // RS4 1803
void setMaximizePressed(bool val); ACCENT_ENABLE_HOST_BACKDROP = 5, // RS5 1809
void setWindowTopmost(bool topmost); ACCENT_INVALID_STATE = 6 // Using this value will remove the window background
bool hitMaximizeButton(); };
bool hitAppBar();
void showSystemMenu(QPoint point); enum ACCENT_FLAG {
bool eventFilter(QObject *obj, QEvent *event) final; ACCENT_NONE = 0,
ACCENT_ENABLE_ACRYLIC = 1,
private: ACCENT_ENABLE_ACRYLIC_WITH_LUMINOSITY = 482
quint64 m_current = 0; };
QQuickItem *m_appBar = nullptr;
QQuickItem *m_maximizeButton = nullptr; struct ACCENT_POLICY {
QQuickItem *m_minimizedButton = nullptr; DWORD dwAccentState;
QQuickItem *m_closeButton = nullptr; DWORD dwAccentFlags;
bool m_fixSize = false; DWORD dwGradientColor; // #AABBGGRR
bool m_topmost = false; DWORD dwAnimationId;
bool m_disabled = false; };
int m_margins = 8; using PACCENT_POLICY = ACCENT_POLICY *;
QList<QPointer<QQuickItem>> m_hitTestList; struct WINDOWCOMPOSITIONATTRIBDATA {
bool m_isWindows11OrGreater = false; WINDOWCOMPOSITIONATTRIB Attrib;
QString m_currentEffect; PVOID pvData;
}; SIZE_T cbData;
};
#endif // FRAMELESS_H using PWINDOWCOMPOSITIONATTRIBDATA = WINDOWCOMPOSITIONATTRIBDATA *;
typedef HRESULT (WINAPI *DwmSetWindowAttributeFunc)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute);
typedef HRESULT (WINAPI *DwmExtendFrameIntoClientAreaFunc)(HWND hwnd, const MARGINS *pMarInset);
typedef HRESULT (WINAPI *DwmIsCompositionEnabledFunc)(BOOL *pfEnabled);
typedef HRESULT (WINAPI *DwmEnableBlurBehindWindowFunc)(HWND hWnd, const DWM_BLURBEHIND *pBlurBehind);
typedef BOOL (WINAPI *SetWindowCompositionAttributeFunc)(HWND hwnd, const WINDOWCOMPOSITIONATTRIBDATA *);
#endif
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
using QT_NATIVE_EVENT_RESULT_TYPE = qintptr;
using QT_ENTER_EVENT_TYPE = QEnterEvent;
#else
using QT_NATIVE_EVENT_RESULT_TYPE = long;
using QT_ENTER_EVENT_TYPE = QEvent;
#endif
class Frameless : public QQuickItem, QAbstractNativeEventFilter {
Q_OBJECT
QML_ELEMENT
Q_PROPERTY_AUTO_P(QQuickItem *, appBar)
Q_PROPERTY_AUTO_P(QQuickItem *, maximizeButton)
Q_PROPERTY_AUTO_P(QQuickItem *, minimizedButton)
Q_PROPERTY_AUTO_P(QQuickItem *, closeButton)
Q_PROPERTY_AUTO(bool, topmost)
Q_PROPERTY_AUTO(bool, disabled)
Q_PROPERTY_AUTO(bool, fixSize)
Q_PROPERTY_AUTO(QString, effect)
Q_PROPERTY_READONLY_AUTO(bool, effective)
Q_PROPERTY_READONLY_AUTO(QStringList, availableEffects)
Q_PROPERTY_AUTO(bool, isDarkMode)
Q_PROPERTY_AUTO(bool, useSystemEffect)
public:
explicit Frameless(QQuickItem *parent = nullptr);
~Frameless() override;
void componentComplete() override;
[[maybe_unused]] bool nativeEventFilter(const QByteArray &eventType, void *message,
QT_NATIVE_EVENT_RESULT_TYPE *result) override;
[[maybe_unused]] Q_INVOKABLE void showFullScreen();
Q_INVOKABLE void showMaximized();
[[maybe_unused]] Q_INVOKABLE void showMinimized();
Q_INVOKABLE void showNormal();
Q_INVOKABLE void setHitTestVisible(QQuickItem *);
[[maybe_unused]] Q_INVOKABLE void onDestruction();
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
private:
bool _isFullScreen();
bool _isMaximized();
void _updateCursor(int edges);
void _setWindowTopmost(bool topmost);
void _showSystemMenu(QPoint point);
bool _hitAppBar();
bool _hitMaximizeButton();
void _setMaximizePressed(bool val);
void _setMaximizeHovered(bool val);
private:
quint64 m_current = 0;
int m_edges = 0;
int m_margins = 8;
quint64 m_clickTimer = 0;
bool m_isWindows11OrGreater = false;
QList<QPointer<QQuickItem>> m_hitTestList;
QString m_currentEffect;
};
#endif // __FRAMELESS_H__

View File

@ -1,7 +1,9 @@
add_library(QHotkey add_library(QHotkey
qhotkey.h qhotkey.cpp qhotkey.h qhotkey.cpp
qhotkey_p.h qhotkey_win.cpp qhotkey_p.h
$<$<PLATFORM_ID:Windows>:qhotkey_win.cpp>
$<$<PLATFORM_ID:Linux>:qhotkey_x11.cpp>
) )
target_include_directories(QHotkey target_include_directories(QHotkey
@ -10,4 +12,5 @@ target_include_directories(QHotkey
target_link_libraries(QHotkey target_link_libraries(QHotkey
PUBLIC Qt${QT_VERSION_MAJOR}::Gui PUBLIC Qt${QT_VERSION_MAJOR}::Gui
$<$<PLATFORM_ID:Linux>:X11>
) )

View File

@ -1,133 +1,335 @@
#include "Utilities.h" #include "Utilities.h"
#include <QSettings> #include <QClipboard>
#include <qt_windows.h> #include <QColor>
#include <QCryptographicHash>
Utilities *Utilities::instance() { #include <QCursor>
static Utilities *self = nullptr; #include <QDateTime>
if (self == nullptr) { #include <QDir>
self = new Utilities(); #include <QFileInfo>
} #include <QGuiApplication>
return self; #include <QJSEngine>
} #include <QOpenGLContext>
#include <QProcess>
Utilities *Utilities::create(QQmlEngine *, QJSEngine *) { #include <QQuickWindow>
auto ret = instance(); #include <QScreen>
QJSEngine::setObjectOwnership(ret, QJSEngine::CppOwnership); #include <QSettings>
return ret; #include <QTextDocument>
} #include <QUuid>
Utilities::Utilities(QObject *parent) : QObject{parent} { #ifdef Q_OS_WIN
} # pragma comment(lib, "user32.lib")
bool Utilities::isSoftware() { # include <windows.h>
return QQuickWindow::sceneGraphBackend() == "software"; # include <windowsx.h>
}
#endif
void Utilities::deleteLater(QObject *p) {
if (p) { Utilities *Utilities::instance() {
p->deleteLater(); static Utilities *self = nullptr;
} if (self == nullptr) {
} self = new Utilities();
}
QColor Utilities::withOpacity(const QColor &color, qreal opacity) { return self;
int alpha = qRound(opacity * 255) & 0xff; }
return QColor::fromRgba((alpha << 24) | (color.rgba() & 0xffffff));
} Utilities *Utilities::create(QQmlEngine *, QJSEngine *) {
auto ret = instance();
QRect Utilities::desktopAvailableGeometry(QQuickWindow *window) { QJSEngine::setObjectOwnership(ret, QJSEngine::CppOwnership);
return window->screen()->availableGeometry(); return ret;
} }
QString Utilities::getWallpaperFilePath() { Utilities::Utilities(QObject *parent) : QObject{parent} {
#if defined(Q_OS_WIN) }
wchar_t path[MAX_PATH] = {};
if (::SystemParametersInfoW(SPI_GETDESKWALLPAPER, MAX_PATH, path, FALSE) == FALSE) { void Utilities::clipText(const QString &text) {
return {}; QGuiApplication::clipboard()->setText(text);
} }
return QString::fromWCharArray(path);
#elif defined(Q_OS_LINUX) QString Utilities::uuid() {
auto type = QSysInfo::productType(); return QUuid::createUuid().toString().remove('-').remove('{').remove('}');
if (type == "uos") { }
QProcess process;
QStringList args; QString Utilities::readFile(const QString &fileName) {
args << "--session"; QString content;
args << "--type=method_call"; QFile file(fileName);
args << "--print-reply"; if (file.open(QIODevice::ReadOnly)) {
args << "--dest=com.deepin.wm"; QTextStream stream(&file);
args << "/com/deepin/wm"; content = stream.readAll();
args << "com.deepin.wm.GetCurrentWorkspaceBackgroundForMonitor"; }
args << QString("string:'%1'").arg(currentTimestamp()); return content;
process.start("dbus-send", args); }
process.waitForFinished();
QByteArray result = process.readAllStandardOutput().trimmed(); bool Utilities::isMacos() {
int startIndex = result.indexOf("file:///"); #if defined(Q_OS_MACOS)
if (startIndex != -1) { return true;
auto path = result.mid(startIndex + 7, result.length() - startIndex - 8); #else
return path; return false;
} #endif
} }
#elif defined(Q_OS_MACOS)
QProcess process; bool Utilities::isLinux() {
QStringList args; #if defined(Q_OS_LINUX)
args << "-e"; return true;
args << R"(tell application "Finder" to get POSIX path of (desktop picture as alias))"; #else
process.start("osascript", args); return false;
process.waitForFinished(); #endif
QByteArray result = process.readAllStandardOutput().trimmed(); }
if (result.isEmpty()) {
return "/System/Library/CoreServices/DefaultDesktop.heic"; bool Utilities::isWin() {
} #if defined(Q_OS_WIN)
return result; return true;
#else #else
return {}; return false;
#endif #endif
} }
QUrl Utilities::getUrlByFilePath(const QString &path) { int Utilities::qtMajor() {
return QUrl::fromLocalFile(path); const QString qtVersion = QString::fromLatin1(qVersion());
} const QStringList versionParts = qtVersion.split('.');
return versionParts[0].toInt();
bool Utilities::isMacos() { }
#if defined(Q_OS_MACOS)
return true; int Utilities::qtMinor() {
#else const QString qtVersion = QString::fromLatin1(qVersion());
return false; const QStringList versionParts = qtVersion.split('.');
#endif return versionParts[1].toInt();
} }
bool Utilities::isWin() { void Utilities::setQuitOnLastWindowClosed(bool val) {
#if defined(Q_OS_WIN) QGuiApplication::setQuitOnLastWindowClosed(val);
return true; }
#else
return false; void Utilities::setOverrideCursor(Qt::CursorShape shape) {
#endif QGuiApplication::setOverrideCursor(QCursor(shape));
} }
int Utilities::windowBuildNumber() { void Utilities::restoreOverrideCursor() {
#if defined(Q_OS_WIN) QGuiApplication::restoreOverrideCursor();
QSettings regKey{QString::fromUtf8(R"(HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion)"), }
QSettings::NativeFormat};
if (regKey.contains(QString::fromUtf8("CurrentBuildNumber"))) { void Utilities::deleteLater(QObject *p) {
auto buildNumber = regKey.value(QString::fromUtf8("CurrentBuildNumber")).toInt(); if (p) {
return buildNumber; p->deleteLater();
} }
#endif }
return -1;
} QString Utilities::toLocalPath(const QUrl &url) {
return url.toLocalFile();
bool Utilities::isWindows11OrGreater() { }
static QVariant var;
if (var.isNull()) { QString Utilities::getFileNameByUrl(const QUrl &url) {
#if defined(Q_OS_WIN) return QFileInfo(url.toLocalFile()).fileName();
auto buildNumber = windowBuildNumber(); }
if (buildNumber >= 22000) {
var = QVariant::fromValue(true); QString Utilities::html2PlantText(const QString &html) {
return true; QTextDocument textDocument;
} textDocument.setHtml(html);
#endif return textDocument.toPlainText();
var = QVariant::fromValue(false); }
return false;
} else { QRect Utilities::getVirtualGeometry() {
return var.toBool(); return QGuiApplication::primaryScreen()->virtualGeometry();
} }
}
QString Utilities::getApplicationDirPath() {
return QGuiApplication::applicationDirPath();
}
QUrl Utilities::getUrlByFilePath(const QString &path) {
return QUrl::fromLocalFile(path);
}
QColor Utilities::withOpacity(const QColor &color, qreal opacity) {
int alpha = qRound(opacity * 255) & 0xff;
return QColor::fromRgba((alpha << 24) | (color.rgba() & 0xffffff));
}
QString Utilities::md5(const QString &text) {
return QCryptographicHash::hash(text.toUtf8(), QCryptographicHash::Md5).toHex();
}
QString Utilities::toBase64(const QString &text) {
return text.toUtf8().toBase64();
}
QString Utilities::fromBase64(const QString &text) {
return QByteArray::fromBase64(text.toUtf8());
}
bool Utilities::removeDir(const QString &dirPath) {
QDir qDir(dirPath);
return qDir.removeRecursively();
}
bool Utilities::removeFile(const QString &filePath) {
QFile file(filePath);
return file.remove();
}
QString Utilities::sha256(const QString &text) {
return QCryptographicHash::hash(text.toUtf8(), QCryptographicHash::Sha256).toHex();
}
void Utilities::showFileInFolder(const QString &path) {
#if defined(Q_OS_WIN)
QProcess::startDetached("explorer.exe", {"/select,", QDir::toNativeSeparators(path)});
#endif
#if defined(Q_OS_LINUX)
QFileInfo fileInfo(path);
auto process = "xdg-open";
auto arguments = {fileInfo.absoluteDir().absolutePath()};
QProcess::startDetached(process, arguments);
#endif
#if defined(Q_OS_MACOS)
QProcess::execute("/usr/bin/osascript",
{"-e", "tell application \"Finder\" to reveal POSIX file \"" + path + "\""});
QProcess::execute("/usr/bin/osascript", {"-e", "tell application \"Finder\" to activate"});
#endif
}
bool Utilities::isSoftware() {
return QQuickWindow::sceneGraphBackend() == "software";
}
QPoint Utilities::cursorPos() {
return QCursor::pos();
}
qint64 Utilities::currentTimestamp() {
return QDateTime::currentMSecsSinceEpoch();
}
QIcon Utilities::windowIcon() {
return QGuiApplication::windowIcon();
}
int Utilities::cursorScreenIndex() {
int screenIndex = 0;
int screenCount = QGuiApplication::screens().count();
if (screenCount > 1) {
QPoint pos = QCursor::pos();
for (int i = 0; i <= screenCount - 1; ++i) {
if (QGuiApplication::screens().at(i)->geometry().contains(pos)) {
screenIndex = i;
break;
}
}
}
return screenIndex;
}
int Utilities::windowBuildNumber() {
#if defined(Q_OS_WIN)
QSettings regKey{
QString::fromUtf8(R"(HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion)"),
QSettings::NativeFormat};
if (regKey.contains(QString::fromUtf8("CurrentBuildNumber"))) {
auto buildNumber = regKey.value(QString::fromUtf8("CurrentBuildNumber")).toInt();
return buildNumber;
}
#endif
return -1;
}
bool Utilities::isWindows11OrGreater() {
static QVariant var;
if (var.isNull()) {
#if defined(Q_OS_WIN)
auto buildNumber = windowBuildNumber();
if (buildNumber >= 22000) {
var = QVariant::fromValue(true);
return true;
}
#endif
var = QVariant::fromValue(false);
return false;
} else {
return var.toBool();
}
}
bool Utilities::isWindows10OrGreater() {
static QVariant var;
if (var.isNull()) {
#if defined(Q_OS_WIN)
auto buildNumber = windowBuildNumber();
if (buildNumber >= 10240) {
var = QVariant::fromValue(true);
return true;
}
#endif
var = QVariant::fromValue(false);
return false;
} else {
return var.toBool();
}
}
QRect Utilities::desktopAvailableGeometry(QQuickWindow *window) {
return window->screen()->availableGeometry();
}
QString Utilities::getWallpaperFilePath() {
#if defined(Q_OS_WIN)
wchar_t path[MAX_PATH] = {};
if (::SystemParametersInfoW(SPI_GETDESKWALLPAPER, MAX_PATH, path, FALSE) == FALSE) {
return {};
}
return QString::fromWCharArray(path);
#elif defined(Q_OS_LINUX)
auto type = QSysInfo::productType();
if (type == "uos") {
QProcess process;
QStringList args;
args << "--session";
args << "--type=method_call";
args << "--print-reply";
args << "--dest=com.deepin.wm";
args << "/com/deepin/wm";
args << "com.deepin.wm.GetCurrentWorkspaceBackgroundForMonitor";
args << QString("string:'%1'").arg(currentTimestamp());
process.start("dbus-send", args);
process.waitForFinished();
QByteArray result = process.readAllStandardOutput().trimmed();
int startIndex = result.indexOf("file:///");
if (startIndex != -1) {
auto path = result.mid(startIndex + 7, result.length() - startIndex - 8);
return path;
}
}
#elif defined(Q_OS_MACOS)
QProcess process;
QStringList args;
args << "-e";
args << R"(tell application "Finder" to get POSIX path of (desktop picture as alias))";
process.start("osascript", args);
process.waitForFinished();
QByteArray result = process.readAllStandardOutput().trimmed();
if (result.isEmpty()) {
return "/System/Library/CoreServices/DefaultDesktop.heic";
}
return result;
#else
return {};
#endif
}
QColor Utilities::imageMainColor(const QImage &image, double bright) {
int step = 20;
int t = 0;
int r = 0, g = 0, b = 0;
for (int i = 0; i < image.width(); i += step) {
for (int j = 0; j < image.height(); j += step) {
if (image.valid(i, j)) {
t++;
QColor c = image.pixel(i, j);
r += c.red();
b += c.blue();
g += c.green();
}
}
}
return QColor(int(bright * r / t) > 255 ? 255 : int(bright * r / t),
int(bright * g / t) > 255 ? 255 : int(bright * g / t),
int(bright * b / t) > 255 ? 255 : int(bright * b / t));
}

View File

@ -1,108 +1,175 @@
#ifndef UTILITIES_H #ifndef __UTILITIES_H__
#define UTILITIES_H #define __UTILITIES_H__
#include <QObject> #include <QObject>
#include <QQmlEngine> #include <QFile>
#include <QQuickWindow> #include <QColor>
#include <QtQml/qqml.h>
#define Q_PROPERTY_AUTO(TYPE, M) \ #include <QQuickWindow>
Q_PROPERTY(TYPE M MEMBER m_##M NOTIFY M##Changed) \
public: \ #define Q_PROPERTY_AUTO(TYPE, M) \
Q_SIGNAL void M##Changed(); \ Q_PROPERTY(TYPE M MEMBER m_##M NOTIFY M##Changed) \
void M(const TYPE &in_##M) { \ public: \
m_##M = in_##M; \ Q_SIGNAL void M##Changed(); \
Q_EMIT M##Changed(); \ void M(const TYPE &in_##M) { \
} \ m_##M = in_##M; \
TYPE M() { \ Q_EMIT M##Changed(); \
return m_##M; \ } \
} \ TYPE M() { \
\ return m_##M; \
private: \ } \
TYPE m_##M; \
private: \
#define Q_PROPERTY_READONLY_AUTO(TYPE, M) \ TYPE m_##M;
Q_PROPERTY(TYPE M READ M NOTIFY M##Changed FINAL) \
public: \ #define Q_PROPERTY_READONLY_AUTO(TYPE, M) \
Q_SIGNAL void M##Changed(); \ Q_PROPERTY(TYPE M READ M NOTIFY M##Changed FINAL) \
void M(const TYPE &in_##M) { \ public: \
m_##M = in_##M; \ Q_SIGNAL void M##Changed(); \
Q_EMIT M##Changed(); \ void M(const TYPE &in_##M) { \
} \ m_##M = in_##M; \
TYPE M() { \ Q_EMIT M##Changed(); \
return m_##M; \ } \
} \ TYPE M() { \
\ return m_##M; \
private: \ } \
TYPE m_##M; \
private: \
#define Q_PROPERTY_AUTO_P(TYPE, M) \ TYPE m_##M;
Q_PROPERTY(TYPE M MEMBER m_##M NOTIFY M##Changed) \
public: \ #define Q_PROPERTY_AUTO_P(TYPE, M) \
Q_SIGNAL void M##Changed(); \ Q_PROPERTY(TYPE M MEMBER m_##M NOTIFY M##Changed) \
void M(TYPE in_##M) { \ public: \
m_##M = in_##M; \ Q_SIGNAL void M##Changed(); \
Q_EMIT M##Changed(); \ void M(TYPE in_##M) { \
} \ m_##M = in_##M; \
TYPE M() { \ Q_EMIT M##Changed(); \
return m_##M; \ } \
} \ TYPE M() { \
\ return m_##M; \
private: \ } \
TYPE m_##M; \
private: \
namespace WindowType { TYPE m_##M;
Q_NAMESPACE
enum LaunchMode { namespace WindowType {
Standard = 0x0000, Q_NAMESPACE
SingleTask = 0x0001, enum LaunchMode {
SingleInstance = 0x0002, Standard = 0x0000,
}; SingleTask = 0x0001,
Q_ENUM_NS(LaunchMode) SingleInstance = 0x0002,
QML_ELEMENT };
} // namespace WindowType Q_ENUM_NS(LaunchMode)
QML_ELEMENT
namespace ThemeType { } // namespace WindowType
Q_NAMESPACE
enum DarkMode { namespace ThemeType {
System = 0x0000, Q_NAMESPACE
Light = 0x0001, enum DarkMode {
Dark = 0x0002, System = 0x0000,
}; Light = 0x0001,
Q_ENUM_NS(DarkMode) Dark = 0x0002,
QML_ELEMENT };
} // namespace ThemeType Q_ENUM_NS(DarkMode)
QML_ELEMENT
namespace ContentDialogType { } // namespace ThemeType
Q_NAMESPACE
enum ButtonFlag { namespace ContentDialogType {
NeutralButton = 0x0001, Q_NAMESPACE
NegativeButton = 0x0002, enum ButtonFlag {
PositiveButton = 0x0004, NeutralButton = 0x0001,
}; NegativeButton = 0x0002,
Q_ENUM_NS(ButtonFlag) PositiveButton = 0x0004,
QML_ELEMENT };
} // namespace ContentDialogType Q_ENUM_NS(ButtonFlag)
QML_ELEMENT
class Utilities : public QObject { } // namespace ContentDialogType
Q_OBJECT
QML_ELEMENT class Utilities : public QObject {
QML_SINGLETON Q_OBJECT
public: QML_ELEMENT
static Utilities *instance(); QML_SINGLETON
static Utilities *create(QQmlEngine *, QJSEngine *);
Q_INVOKABLE int windowBuildNumber(); private:
Q_INVOKABLE bool isWindows11OrGreater(); explicit Utilities(QObject *parent = nullptr);
Q_INVOKABLE bool isWin();
Q_INVOKABLE bool isMacos(); public:
Q_INVOKABLE QRect desktopAvailableGeometry(QQuickWindow *window); static Utilities *instance();
Q_INVOKABLE QUrl getUrlByFilePath(const QString &path); static Utilities *create(QQmlEngine *, QJSEngine *);
Q_INVOKABLE bool isSoftware();
Q_INVOKABLE void deleteLater(QObject *p); Q_INVOKABLE int qtMajor();
Q_INVOKABLE QColor withOpacity(const QColor &, qreal alpha);
Q_INVOKABLE QString getWallpaperFilePath(); Q_INVOKABLE int qtMinor();
protected: Q_INVOKABLE bool isMacos();
Utilities(QObject *parent = nullptr);
}; Q_INVOKABLE bool isLinux();
#endif // UTILITIES_H Q_INVOKABLE bool isWin();
Q_INVOKABLE void clipText(const QString &text);
Q_INVOKABLE QString uuid();
Q_INVOKABLE QString readFile(const QString &fileName);
Q_INVOKABLE void setQuitOnLastWindowClosed(bool val);
Q_INVOKABLE void setOverrideCursor(Qt::CursorShape shape);
Q_INVOKABLE void restoreOverrideCursor();
Q_INVOKABLE QString html2PlantText(const QString &html);
Q_INVOKABLE QString toLocalPath(const QUrl &url);
Q_INVOKABLE void deleteLater(QObject *p);
Q_INVOKABLE QString getFileNameByUrl(const QUrl &url);
Q_INVOKABLE QRect getVirtualGeometry();
Q_INVOKABLE QString getApplicationDirPath();
Q_INVOKABLE QUrl getUrlByFilePath(const QString &path);
Q_INVOKABLE QColor withOpacity(const QColor &, qreal alpha);
Q_INVOKABLE QString md5(const QString &text);
Q_INVOKABLE QString sha256(const QString &text);
Q_INVOKABLE QString toBase64(const QString &text);
Q_INVOKABLE QString fromBase64(const QString &text);
Q_INVOKABLE bool removeDir(const QString &dirPath);
Q_INVOKABLE bool removeFile(const QString &filePath);
Q_INVOKABLE void showFileInFolder(const QString &path);
Q_INVOKABLE bool isSoftware();
Q_INVOKABLE qint64 currentTimestamp();
Q_INVOKABLE QPoint cursorPos();
Q_INVOKABLE QIcon windowIcon();
Q_INVOKABLE int cursorScreenIndex();
Q_INVOKABLE int windowBuildNumber();
Q_INVOKABLE bool isWindows11OrGreater();
Q_INVOKABLE bool isWindows10OrGreater();
Q_INVOKABLE QRect desktopAvailableGeometry(QQuickWindow *window);
Q_INVOKABLE QString getWallpaperFilePath();
Q_INVOKABLE QColor imageMainColor(const QImage &image, double bright = 1);
};
#endif // __UTILITIES_H__

View File

@ -316,7 +316,7 @@ Quick.Window {
id:loader_border id:loader_border
anchors.fill: parent anchors.fill: parent
sourceComponent: { sourceComponent: {
if(window.useSystemAppBar || Utilities.isWin() || window.visibility === Window.Maximized || window.visibility === Window.FullScreen){ if(window.useSystemAppBar || Utilities.isWin() || window.visibility === Quick.Window.Maximized || window.visibility === Quick.Window.FullScreen){
return undefined return undefined
} }
return com_border return com_border