diff -Nru ukui-window-switch-4.10.1.10/debian/changelog ukui-window-switch-4.10.1.10/debian/changelog --- ukui-window-switch-4.10.1.10/debian/changelog 2025-01-03 17:52:20.000000000 +0800 +++ ukui-window-switch-4.10.1.10/debian/changelog 2025-03-07 14:07:48.000000000 +0800 @@ -1,3 +1,22 @@ +ukui-window-switch (4.10.1.10-ok2.0) nile; urgency=medium + + * Issue:#IB24M1 【多任务视图】开启多个窗口,鼠标按住空白处无法上下滑动翻页 + * 其他: + -refactor:重构model-view实现及前后端通信 + -perf:优化CmakeLists.txt结构,调整翻译文件生成与安装机制 + -feat:增加自定义flow UkuiFlow,增加编译依赖qtdeclarative5-private-dev + -perf:优化应用预览窗居中动画和键盘走焦 + -perf:优化应用区域和工作区滑动交互 + + -- zhangyuanyuan1 <zhangyuanyuan1@kylinos.cn> Fri, 07 Mar 2025 14:07:48 +0800 + +ukui-window-switch (4.10.1.10-ok1.6) nile; urgency=medium + + * Issue:无 + * 其他:增加阿越翻译文件 + + -- Kevin Duan <duankaiwen@kylinos.cn> Fri, 03 Jan 2025 17:52:20 +0800 + ukui-window-switch (4.10.1.10-ok1.5) nile; urgency=medium * Issue:无 diff -Nru ukui-window-switch-4.10.1.10/debian/control ukui-window-switch-4.10.1.10/debian/control --- ukui-window-switch-4.10.1.10/debian/control 2025-01-03 17:52:20.000000000 +0800 +++ ukui-window-switch-4.10.1.10/debian/control 2025-03-07 14:07:48.000000000 +0800 @@ -30,6 +30,7 @@ qtbase5-dev, qtbase5-private-dev, qtdeclarative5-dev, + qtdeclarative5-private-dev, qttools5-dev, qttools5-dev-tools, kylin-wayland-compositor-client diff -Nru ukui-window-switch-4.10.1.10/debian/patches/0007-Added-translation-using-Weblate-Arabic.patch ukui-window-switch-4.10.1.10/debian/patches/0007-Added-translation-using-Weblate-Arabic.patch --- ukui-window-switch-4.10.1.10/debian/patches/0007-Added-translation-using-Weblate-Arabic.patch 1970-01-01 08:00:00.000000000 +0800 +++ ukui-window-switch-4.10.1.10/debian/patches/0007-Added-translation-using-Weblate-Arabic.patch 2025-03-07 14:07:48.000000000 +0800 @@ -0,0 +1,77 @@ +From: KevinDuan <duankaiwen@kylinos.cn> +Date: Mon, 17 Feb 2025 09:36:23 +0800 +Subject: Added translation using Weblate (Arabic) + +--- + windowsview/ukui-window-switch_ar.ts | 62 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 62 insertions(+) + create mode 100644 windowsview/ukui-window-switch_ar.ts + +diff --git a/windowsview/ukui-window-switch_ar.ts b/windowsview/ukui-window-switch_ar.ts +new file mode 100644 +index 0000000..3538253 +--- /dev/null ++++ b/windowsview/ukui-window-switch_ar.ts +@@ -0,0 +1,62 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="ar" sourcelanguage="en_US"> ++<context> ++ <name>DesktopArea</name> ++ <message> ++ <source>Desktop</source> ++ <translatorcomment>工作区</translatorcomment> ++ <translation type="vanished">工作区</translation> ++ </message> ++ <message> ++ <source>New Desktop</source> ++ <translatorcomment>新建工作区</translatorcomment> ++ <translation type="vanished">新建工作区</translation> ++ </message> ++</context> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation type="unfinished"></translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewClearAllWindowButton</name> ++ <message> ++ <source>Clear</source> ++ <translatorcomment>清除</translatorcomment> ++ <translation type="vanished">清除</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="174"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="357"/> ++ <source>Clear</source> ++ <translation type="unfinished"></translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewRootWindow</name> ++ <message> ++ <source>No recent tasks</source> ++ <translatorcomment>无应用开启</translatorcomment> ++ <translation type="vanished">无应用开启</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="qml/VirtualDesktopWindow.qml" line="187"/> ++ <source>Desktop</source> ++ <translation type="unfinished"></translation> ++ </message> ++</context> ++</TS> diff -Nru ukui-window-switch-4.10.1.10/debian/patches/0008-Added-translation-using-Weblate-Vietnamese.patch ukui-window-switch-4.10.1.10/debian/patches/0008-Added-translation-using-Weblate-Vietnamese.patch --- ukui-window-switch-4.10.1.10/debian/patches/0008-Added-translation-using-Weblate-Vietnamese.patch 1970-01-01 08:00:00.000000000 +0800 +++ ukui-window-switch-4.10.1.10/debian/patches/0008-Added-translation-using-Weblate-Vietnamese.patch 2025-03-07 14:07:48.000000000 +0800 @@ -0,0 +1,77 @@ +From: KevinDuan <duankaiwen@kylinos.cn> +Date: Mon, 17 Feb 2025 15:02:04 +0800 +Subject: Added translation using Weblate (Vietnamese) + +--- + windowsview/ukui-window-switch_vi.ts | 62 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 62 insertions(+) + create mode 100644 windowsview/ukui-window-switch_vi.ts + +diff --git a/windowsview/ukui-window-switch_vi.ts b/windowsview/ukui-window-switch_vi.ts +new file mode 100644 +index 0000000..259ee5d +--- /dev/null ++++ b/windowsview/ukui-window-switch_vi.ts +@@ -0,0 +1,62 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="vi" sourcelanguage="en_US"> ++<context> ++ <name>DesktopArea</name> ++ <message> ++ <source>Desktop</source> ++ <translatorcomment>工作区</translatorcomment> ++ <translation type="vanished">工作区</translation> ++ </message> ++ <message> ++ <source>New Desktop</source> ++ <translatorcomment>新建工作区</translatorcomment> ++ <translation type="vanished">新建工作区</translation> ++ </message> ++</context> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation type="unfinished"></translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewClearAllWindowButton</name> ++ <message> ++ <source>Clear</source> ++ <translatorcomment>清除</translatorcomment> ++ <translation type="vanished">清除</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="174"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished"></translation> ++ </message> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="357"/> ++ <source>Clear</source> ++ <translation type="unfinished"></translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewRootWindow</name> ++ <message> ++ <source>No recent tasks</source> ++ <translatorcomment>无应用开启</translatorcomment> ++ <translation type="vanished">无应用开启</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="qml/VirtualDesktopWindow.qml" line="187"/> ++ <source>Desktop</source> ++ <translation type="unfinished"></translation> ++ </message> ++</context> ++</TS> diff -Nru ukui-window-switch-4.10.1.10/debian/patches/0009-Translated-using-Weblate-Vietnamese.patch ukui-window-switch-4.10.1.10/debian/patches/0009-Translated-using-Weblate-Vietnamese.patch --- ukui-window-switch-4.10.1.10/debian/patches/0009-Translated-using-Weblate-Vietnamese.patch 1970-01-01 08:00:00.000000000 +0800 +++ ukui-window-switch-4.10.1.10/debian/patches/0009-Translated-using-Weblate-Vietnamese.patch 2025-03-07 14:07:48.000000000 +0800 @@ -0,0 +1,87 @@ +From: KevinDuan <duankaiwen@kylinos.cn> +Date: Mon, 17 Feb 2025 09:20:36 +0000 +Subject: Translated using Weblate (Vietnamese) + +Currently translated at 100.0% (4 of 4 strings) + +Translation: openkylin-nile-new/ukui-window-switch +Translate-URL: http://weblate.openkylin.top/projects/openkylin-nile-new/ukui-window-switch/vi/ +--- + windowsview/ukui-window-switch_ar.ts | 8 ++++---- + windowsview/ukui-window-switch_vi.ts | 8 ++++---- + 2 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/windowsview/ukui-window-switch_ar.ts b/windowsview/ukui-window-switch_ar.ts +index 3538253..bf0b6c9 100644 +--- a/windowsview/ukui-window-switch_ar.ts ++++ b/windowsview/ukui-window-switch_ar.ts +@@ -19,7 +19,7 @@ + <message> + <location filename="qml/NewDesktopButton.qml" line="104"/> + <source>New Desktop</source> +- <translation type="unfinished"></translation> ++ <translation>سطح مكتب جديد</translation> + </message> + </context> + <context> +@@ -35,12 +35,12 @@ + <message> + <location filename="qml/TabletViewMain.qml" line="174"/> + <source>No recent tasks</source> +- <translation type="unfinished"></translation> ++ <translation>لا توجد مهام حديثة</translation> + </message> + <message> + <location filename="qml/TabletViewMain.qml" line="357"/> + <source>Clear</source> +- <translation type="unfinished"></translation> ++ <translation>واضح</translation> + </message> + </context> + <context> +@@ -56,7 +56,7 @@ + <message> + <location filename="qml/VirtualDesktopWindow.qml" line="187"/> + <source>Desktop</source> +- <translation type="unfinished"></translation> ++ <translation>سطح المكتب</translation> + </message> + </context> + </TS> +diff --git a/windowsview/ukui-window-switch_vi.ts b/windowsview/ukui-window-switch_vi.ts +index 259ee5d..d673d4a 100644 +--- a/windowsview/ukui-window-switch_vi.ts ++++ b/windowsview/ukui-window-switch_vi.ts +@@ -19,7 +19,7 @@ + <message> + <location filename="qml/NewDesktopButton.qml" line="104"/> + <source>New Desktop</source> +- <translation type="unfinished"></translation> ++ <translation>Máy tính để bàn mới</translation> + </message> + </context> + <context> +@@ -35,12 +35,12 @@ + <message> + <location filename="qml/TabletViewMain.qml" line="174"/> + <source>No recent tasks</source> +- <translation type="unfinished"></translation> ++ <translation>Không có nhiệm vụ gần đây</translation> + </message> + <message> + <location filename="qml/TabletViewMain.qml" line="357"/> + <source>Clear</source> +- <translation type="unfinished"></translation> ++ <translation>Trong</translation> + </message> + </context> + <context> +@@ -56,7 +56,7 @@ + <message> + <location filename="qml/VirtualDesktopWindow.qml" line="187"/> + <source>Desktop</source> +- <translation type="unfinished"></translation> ++ <translation>Bàn làm việc</translation> + </message> + </context> + </TS> diff -Nru ukui-window-switch-4.10.1.10/debian/patches/0010-perf-CMakeLists.txt.patch ukui-window-switch-4.10.1.10/debian/patches/0010-perf-CMakeLists.txt.patch --- ukui-window-switch-4.10.1.10/debian/patches/0010-perf-CMakeLists.txt.patch 1970-01-01 08:00:00.000000000 +0800 +++ ukui-window-switch-4.10.1.10/debian/patches/0010-perf-CMakeLists.txt.patch 2025-03-07 14:07:48.000000000 +0800 @@ -0,0 +1,1954 @@ +From: iaom <zhangpengfei@kylinos.cn> +Date: Thu, 20 Feb 2025 13:41:55 +0800 +Subject: =?utf-8?b?cGVyZjrkvJjljJZDTWFrZUxpc3RzLnR4dOe7k+aehCAxLuWIoOmZpA==?= + =?utf-8?b?6YOo5YiG5YaX5L2Z5YaZ5rOV77yM6LCD5pW06YOo5YiG57uT5p6EIDIu6LCD5pW0?= + =?utf-8?b?57+76K+R5paH5Lu255Sf5oiQ5LiO5a6J6KOF5py65Yi2?= + +--- + .gitignore | 1 - + CMakeLists.txt | 11 +- + windowsview/CMakeLists.txt | 71 ++---------- + windowsview/data.qrc | 10 -- + windowsview/multitaskviewmodel.h | 5 +- + windowsview/translations/ukui-window-switch_ar.ts | 33 ++++++ + .../translations/ukui-window-switch_bo_CN.ts | 33 ++++++ + windowsview/translations/ukui-window-switch_de.ts | 33 ++++++ + windowsview/translations/ukui-window-switch_es.ts | 33 ++++++ + windowsview/translations/ukui-window-switch_fr.ts | 33 ++++++ + windowsview/translations/ukui-window-switch_kk.ts | 33 ++++++ + windowsview/translations/ukui-window-switch_ky.ts | 33 ++++++ + windowsview/translations/ukui-window-switch_mn.ts | 33 ++++++ + windowsview/translations/ukui-window-switch_ug.ts | 33 ++++++ + windowsview/translations/ukui-window-switch_vi.ts | 33 ++++++ + .../translations/ukui-window-switch_zh_CN.ts | 33 ++++++ + .../translations/ukui-window-switch_zh_Hant.ts | 33 ++++++ + windowsview/ukui-window-switch | 2 +- + .../ukui-window-switch-kwineffect/CMakeLists.txt | 104 ++++-------------- + .../multitaskviewmanager.cpp | 2 +- + .../ukui-window-switch-wlcom/CMakeLists.txt | 119 +++++---------------- + windowsview/ukui-window-switch-wlcom/main.cpp | 9 +- + .../multitaskviewmanagerbywlcom.cpp | 3 +- + .../multitaskviewmodelbywlcomhandler.cpp | 2 + + .../multitaskviewmodelbywlcomhandler.h | 3 - + windowsview/ukui-window-switch_ar.ts | 62 ----------- + windowsview/ukui-window-switch_bo_CN.ts | 62 ----------- + windowsview/ukui-window-switch_de.ts | 62 ----------- + windowsview/ukui-window-switch_es.ts | 62 ----------- + windowsview/ukui-window-switch_fr.ts | 62 ----------- + windowsview/ukui-window-switch_kk.ts | 62 ----------- + windowsview/ukui-window-switch_ky.ts | 62 ----------- + windowsview/ukui-window-switch_mn.ts | 62 ----------- + windowsview/ukui-window-switch_ug.ts | 62 ----------- + windowsview/ukui-window-switch_vi.ts | 62 ----------- + windowsview/ukui-window-switch_zh_CN.ts | 62 ----------- + windowsview/ukui-window-switch_zh_Hant.ts | 62 ----------- + 37 files changed, 472 insertions(+), 1010 deletions(-) + create mode 100644 windowsview/translations/ukui-window-switch_ar.ts + create mode 100644 windowsview/translations/ukui-window-switch_bo_CN.ts + create mode 100644 windowsview/translations/ukui-window-switch_de.ts + create mode 100644 windowsview/translations/ukui-window-switch_es.ts + create mode 100644 windowsview/translations/ukui-window-switch_fr.ts + create mode 100644 windowsview/translations/ukui-window-switch_kk.ts + create mode 100644 windowsview/translations/ukui-window-switch_ky.ts + create mode 100644 windowsview/translations/ukui-window-switch_mn.ts + create mode 100644 windowsview/translations/ukui-window-switch_ug.ts + create mode 100644 windowsview/translations/ukui-window-switch_vi.ts + create mode 100644 windowsview/translations/ukui-window-switch_zh_CN.ts + create mode 100644 windowsview/translations/ukui-window-switch_zh_Hant.ts + delete mode 100644 windowsview/ukui-window-switch_ar.ts + delete mode 100644 windowsview/ukui-window-switch_bo_CN.ts + delete mode 100644 windowsview/ukui-window-switch_de.ts + delete mode 100644 windowsview/ukui-window-switch_es.ts + delete mode 100644 windowsview/ukui-window-switch_fr.ts + delete mode 100644 windowsview/ukui-window-switch_kk.ts + delete mode 100644 windowsview/ukui-window-switch_ky.ts + delete mode 100644 windowsview/ukui-window-switch_mn.ts + delete mode 100644 windowsview/ukui-window-switch_ug.ts + delete mode 100644 windowsview/ukui-window-switch_vi.ts + delete mode 100644 windowsview/ukui-window-switch_zh_CN.ts + delete mode 100644 windowsview/ukui-window-switch_zh_Hant.ts + +diff --git a/.gitignore b/.gitignore +index dd3e4fa..8f1db95 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -5,7 +5,6 @@ + *.user + *.qm + CMakeLists.txt.user* +-windowsview/globalconfig.h + + # debian files + obj-*-linux-gnu/ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index bf089b5..820482c 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1,4 +1,4 @@ +-cmake_minimum_required(VERSION 3.5) ++cmake_minimum_required(VERSION 3.16) + + project(ukui-window-switch) + +@@ -11,18 +11,13 @@ find_package(KF5WindowSystem REQUIRED) + + get_target_property(QT_QMAKE_EXECUTABLE ${Qt5Core_QMAKE_EXECUTABLE} IMPORTED_LOCATION) + macro(query_qmake args output) +- exec_program(${QT_QMAKE_EXECUTABLE} ARGS -query ${args} OUTPUT_VARIABLE ${output} RETURN_VALUE exitCode) +- +- if(NOT ${exitCode} EQUAL 0) ++ execute_process(COMMAND ${QT_QMAKE_EXECUTABLE} -query ${args} OUTPUT_VARIABLE ${output} RESULT_VARIABLE test1 RESULT_VARIABLE result OUTPUT_STRIP_TRAILING_WHITESPACE) ++ if(NOT ${result} EQUAL 0) + message(FATAL_ERROR "exec ${QT_QMAKE_EXECUTABLE} failed, with args: ${args}, error message: ${output}") + endif() + endmacro() + + query_qmake("QT_INSTALL_PLUGINS" QT_INSTALL_PLUGINS) +-message("QT_INSTALL_PLUGINS=${QT_INSTALL_PLUGINS}") +- +-set(INSTALL_PATH "${QT_INSTALL_PLUGINS}/kwin/effects/plugins") +- + + add_subdirectory(windowsview) + add_subdirectory(windowswitchers) +diff --git a/windowsview/CMakeLists.txt b/windowsview/CMakeLists.txt +index 80342cd..ae83e94 100644 +--- a/windowsview/CMakeLists.txt ++++ b/windowsview/CMakeLists.txt +@@ -1,70 +1,19 @@ +-cmake_minimum_required(VERSION 3.5) ++cmake_minimum_required(VERSION 3.16) + +-set(CMAKE_INCLUDE_CURRENT_DIR ON) +-set(CMAKE_AUTOMOC ON) +-set(CMAKE_AUTOUIC ON) +-set(CMAKE_AUTORCC ON) +- +-set(CMAKE_CXX_STANDARD 14) +-set(CMAKE_CXX_STANDARD_REQUIRED ON) +- +-set(KF5_DEP_VERSION "5.54.0") +- +-find_package(ECM 5.54.0 NO_MODULE) +-set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake) +- +-find_package(X11 MODULE) +-find_package(XCB MODULE COMPONENTS XCB COMPOSITE DAMAGE SHAPE XFIXES RENDER) +-message("XCB:"${X11_FOUND}, ${XCB_XCB_FOUND}, ${XCB_COMPOSITE_FOUND}, ${XCB_DAMAGE_FOUND}) +-if(X11_FOUND AND XCB_XCB_FOUND) +- set(HAVE_X11 1) +-endif() +-if(HAVE_X11 AND XCB_COMPOSITE_FOUND AND XCB_DAMAGE_FOUND) +- set(HAVE_XCB_COMPOSITE 1) +-endif() +- +-find_package(OpenGL) +- +-find_package(EGL MODULE) +-message("EGL:"${EGL_FOUND}) +-if (${EGL_FOUND}) +- set(HAVE_EGL 1) +-endif() +- +-message("OPENGL:"${OPENGL_FOUND},${Qt5Gui_OPENGL_IMPLEMENTATION}) +-if(OPENGL_FOUND AND (${Qt5Gui_OPENGL_IMPLEMENTATION} STREQUAL "GL")) +- set(HAVE_GLX ${HAVE_X11}) +-else() +- set(HAVE_GLX 0) +-endif() +- +-message("MACRO:"${HAVE_X11},${HAVE_XCB_COMPOSITE},${HAVE_EGL},${HAVE_GLX}) +- +-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/globalconfig.h.in ${CMAKE_CURRENT_SOURCE_DIR}/globalconfig.h) +- +-find_package(Qt5Quick REQUIRED) +-find_package(Qt5QuickWidgets REQUIRED) +-find_package(KF5Config REQUIRED) +-find_package(KF5GlobalAccel REQUIRED) +-find_package(KF5I18n REQUIRED) +-find_package(PkgConfig REQUIRED) +-find_package(Qt5LinguistTools REQUIRED) +-find_package(Qt5 REQUIRED NO_MODULE COMPONENTS X11Extras Concurrent) +- +-pkg_check_modules(KDK REQUIRED kysdk-sysinfo) +-pkg_check_modules(DATACOLLECT REQUIRED kysdk-datacollect) ++find_package(QT NAMES Qt6 Qt5 COMPONENTS LinguistTools REQUIRED) ++find_package(Qt${QT_VERSION_MAJOR} COMPONENTS LinguistTools REQUIRED) + +-include_directories(${KDK_INCLUDE_DIRS}) +-include_directories(${DATACOLLECT_INCLUDE_DIRS}) ++file(GLOB TS_FILES translations/*.ts) ++set_source_files_properties(${TS_FILES} PROPERTIES OUTPUT_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/translations) ++qt5_create_translation(QM_FILES ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/ukui-window-switch-wlcom ${CMAKE_CURRENT_SOURCE_DIR}/ukui-window-switch-kwineffect ${CMAKE_CURRENT_SOURCE_DIR}/qml ${TS_FILES} OPTIONS -no-obsolete -no-ui-lines) + +-# 注意要链接到kwin,如果本地安装了kwin的依赖,记得注意区分 +-include_directories(/usr/include/) ++add_custom_target(generate_qm ALL DEPENDS ${QM_FILES}) + ++set(TRANSLATION_DIR "/usr/share/ukui-window-switch/translations/") ++add_compile_definitions(TRANSLATION_DIR="${TRANSLATION_DIR}") + +-# translation +-find_package(QT NAMES Qt6 Qt5 COMPONENTS LinguistTools REQUIRED) +-find_package(Qt${QT_VERSION_MAJOR} COMPONENTS LinguistTools REQUIRED) + add_subdirectory(ukui-window-switch-kwineffect) + add_subdirectory(ukui-window-switch-wlcom) + install(FILES ukui-window-switch DESTINATION /usr/bin/) + install(FILES ukui-window-switch.desktop DESTINATION /etc/xdg/autostart/) ++install(FILES ${QM_FILES} DESTINATION ${TRANSLATION_DIR}) +diff --git a/windowsview/data.qrc b/windowsview/data.qrc +index a0a1fa6..9cb6b9e 100644 +--- a/windowsview/data.qrc ++++ b/windowsview/data.qrc +@@ -17,16 +17,6 @@ + <file>qml/TabletViewMain.qml</file> + <file>qml/TabletViewCloseButton.qml</file> + <file>qml/CloseButton.qml</file> +- <file>ukui-window-switch_zh_CN.qm</file> +- <file>ukui-window-switch_bo_CN.qm</file> +- <file>ukui-window-switch_de.qm</file> +- <file>ukui-window-switch_es.qm</file> +- <file>ukui-window-switch_fr.qm</file> +- <file>ukui-window-switch_kk.qm</file> +- <file>ukui-window-switch_ky.qm</file> +- <file>ukui-window-switch_mn.qm</file> +- <file>ukui-window-switch_ug.qm</file> +- <file>ukui-window-switch_zh_Hant.qm</file> + <file>qml/ArrowButton.qml</file> + <file>images/icon-arrow-white.svg</file> + <file>images/icon-arrow-black.svg</file> +diff --git a/windowsview/multitaskviewmodel.h b/windowsview/multitaskviewmodel.h +index 24bb5db..8cc7a01 100644 +--- a/windowsview/multitaskviewmodel.h ++++ b/windowsview/multitaskviewmodel.h +@@ -26,10 +26,13 @@ + #include <QRect> + #include <QVariantList> + #include <QString> +-#include <kwineffects.h> + #include "multitaskviewmodelhandler.h" + ++#ifdef KWINEFFECT ++#include <kwineffects.h> + using namespace KWin; ++#endif ++ + class QGSettings; + + class Window +diff --git a/windowsview/translations/ukui-window-switch_ar.ts b/windowsview/translations/ukui-window-switch_ar.ts +new file mode 100644 +index 0000000..ac74db9 +--- /dev/null ++++ b/windowsview/translations/ukui-window-switch_ar.ts +@@ -0,0 +1,33 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="ar" sourcelanguage="en_US"> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="../qml/NewDesktopButton.qml" line="105"/> ++ <source>New Desktop</source> ++ <translation>سطح مكتب جديد</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="176"/> ++ <source>No recent tasks</source> ++ <translation>لا توجد مهام حديثة</translation> ++ </message> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="353"/> ++ <source>Clear</source> ++ <translation>واضح</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> ++ <source>Desktop</source> ++ <translation>سطح المكتب</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/translations/ukui-window-switch_bo_CN.ts b/windowsview/translations/ukui-window-switch_bo_CN.ts +new file mode 100644 +index 0000000..7c2f960 +--- /dev/null ++++ b/windowsview/translations/ukui-window-switch_bo_CN.ts +@@ -0,0 +1,33 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="bo_CN" sourcelanguage="en_US"> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="../qml/NewDesktopButton.qml" line="105"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">གསར་དུ་བཙུགས་པའི་ལས་དོན་ཁུལ།</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="176"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">ཉེ་ལམ་གྱི་ལས་འགན་གང་ཡང་མེད།</translation> ++ </message> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="353"/> ++ <source>Clear</source> ++ <translation type="unfinished">གསལ་པོར་བཤད་ན།</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> ++ <source>Desktop</source> ++ <translation type="unfinished">ལས་སྒྲུབ་ཁུལ།</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/translations/ukui-window-switch_de.ts b/windowsview/translations/ukui-window-switch_de.ts +new file mode 100644 +index 0000000..faae1ba +--- /dev/null ++++ b/windowsview/translations/ukui-window-switch_de.ts +@@ -0,0 +1,33 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="de" sourcelanguage="en_US"> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="../qml/NewDesktopButton.qml" line="105"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">Neuer Desktop</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="176"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">Keine aktuellen Aufgaben</translation> ++ </message> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="353"/> ++ <source>Clear</source> ++ <translation type="unfinished">Klar</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> ++ <source>Desktop</source> ++ <translation type="unfinished">Desktop</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/translations/ukui-window-switch_es.ts b/windowsview/translations/ukui-window-switch_es.ts +new file mode 100644 +index 0000000..12910e8 +--- /dev/null ++++ b/windowsview/translations/ukui-window-switch_es.ts +@@ -0,0 +1,33 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="es" sourcelanguage="en_US"> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="../qml/NewDesktopButton.qml" line="105"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">Nuevo escritorio</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="176"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">No hay tareas recientes</translation> ++ </message> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="353"/> ++ <source>Clear</source> ++ <translation type="unfinished">Claro</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> ++ <source>Desktop</source> ++ <translation type="unfinished">Escritorio</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/translations/ukui-window-switch_fr.ts b/windowsview/translations/ukui-window-switch_fr.ts +new file mode 100644 +index 0000000..a45c5f6 +--- /dev/null ++++ b/windowsview/translations/ukui-window-switch_fr.ts +@@ -0,0 +1,33 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="fr" sourcelanguage="en_US"> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="../qml/NewDesktopButton.qml" line="105"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">Nouveau bureau</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="176"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">Pas de tâches récentes</translation> ++ </message> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="353"/> ++ <source>Clear</source> ++ <translation type="unfinished">Clair</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> ++ <source>Desktop</source> ++ <translation type="unfinished">Bureau</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/translations/ukui-window-switch_kk.ts b/windowsview/translations/ukui-window-switch_kk.ts +new file mode 100644 +index 0000000..36a1339 +--- /dev/null ++++ b/windowsview/translations/ukui-window-switch_kk.ts +@@ -0,0 +1,33 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="kk" sourcelanguage="en_US"> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="../qml/NewDesktopButton.qml" line="105"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">Жаңа үстел</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="176"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">Соңғы тапсырмалар жоқ</translation> ++ </message> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="353"/> ++ <source>Clear</source> ++ <translation type="unfinished">Тазалау</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> ++ <source>Desktop</source> ++ <translation type="unfinished">Жұмыс үстелі</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/translations/ukui-window-switch_ky.ts b/windowsview/translations/ukui-window-switch_ky.ts +new file mode 100644 +index 0000000..49dbde9 +--- /dev/null ++++ b/windowsview/translations/ukui-window-switch_ky.ts +@@ -0,0 +1,33 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="ky" sourcelanguage="en_US"> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="../qml/NewDesktopButton.qml" line="105"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">Жаңы иш столу</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="176"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">Акыркы милдеттер жок</translation> ++ </message> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="353"/> ++ <source>Clear</source> ++ <translation type="unfinished">Тазалоо</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> ++ <source>Desktop</source> ++ <translation type="unfinished">Иш столу</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/translations/ukui-window-switch_mn.ts b/windowsview/translations/ukui-window-switch_mn.ts +new file mode 100644 +index 0000000..c288363 +--- /dev/null ++++ b/windowsview/translations/ukui-window-switch_mn.ts +@@ -0,0 +1,33 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="mn" sourcelanguage="en_US"> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="../qml/NewDesktopButton.qml" line="105"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">ᠱᠢᠨᠡᠪᠡᠷ ᠪᠠᠢᠭᠤᠯᠤᠭ᠍ᠰᠠᠨ ᠠᠵᠢᠯᠯᠠᠬᠤ ᠤᠷᠤᠨ</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="176"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">ᠨᠡᠬᠡᠬᠡᠬᠦ᠌ ᠬᠡᠷᠡᠭᠯᠡᠭᠡ ᠪᠠᠢᠬᠤ ᠦᠬᠡᠢ</translation> ++ </message> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="353"/> ++ <source>Clear</source> ++ <translation type="unfinished">ᠠᠷᠢᠯᠭᠠᠬᠤ</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> ++ <source>Desktop</source> ++ <translation type="unfinished">ᠠᠵᠢᠯᠯᠠᠬᠤ ᠤᠷᠤᠨ</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/translations/ukui-window-switch_ug.ts b/windowsview/translations/ukui-window-switch_ug.ts +new file mode 100644 +index 0000000..06db3df +--- /dev/null ++++ b/windowsview/translations/ukui-window-switch_ug.ts +@@ -0,0 +1,33 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="ug" sourcelanguage="en_US"> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="../qml/NewDesktopButton.qml" line="105"/> ++ <source>New Desktop</source> ++ <translation>يېڭى ئۈستەلئۈستى</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="176"/> ++ <source>No recent tasks</source> ++ <translation>يېقىنقى ۋەزىپىلەر يوق</translation> ++ </message> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="353"/> ++ <source>Clear</source> ++ <translation>تازىلاش</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> ++ <source>Desktop</source> ++ <translation>ئۈستەل يۈزى</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/translations/ukui-window-switch_vi.ts b/windowsview/translations/ukui-window-switch_vi.ts +new file mode 100644 +index 0000000..5650eb2 +--- /dev/null ++++ b/windowsview/translations/ukui-window-switch_vi.ts +@@ -0,0 +1,33 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="vi" sourcelanguage="en_US"> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="../qml/NewDesktopButton.qml" line="105"/> ++ <source>New Desktop</source> ++ <translation>Máy tính để bàn mới</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="176"/> ++ <source>No recent tasks</source> ++ <translation>Không có nhiệm vụ gần đây</translation> ++ </message> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="353"/> ++ <source>Clear</source> ++ <translation>Trong</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> ++ <source>Desktop</source> ++ <translation>Bàn làm việc</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/translations/ukui-window-switch_zh_CN.ts b/windowsview/translations/ukui-window-switch_zh_CN.ts +new file mode 100644 +index 0000000..68a5278 +--- /dev/null ++++ b/windowsview/translations/ukui-window-switch_zh_CN.ts +@@ -0,0 +1,33 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="zh_CN" sourcelanguage="en_US"> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="../qml/NewDesktopButton.qml" line="105"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">新建工作区</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="176"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">无应用开启</translation> ++ </message> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="353"/> ++ <source>Clear</source> ++ <translation type="unfinished">清除</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> ++ <source>Desktop</source> ++ <translation type="unfinished">工作区</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/translations/ukui-window-switch_zh_Hant.ts b/windowsview/translations/ukui-window-switch_zh_Hant.ts +new file mode 100644 +index 0000000..cf3b024 +--- /dev/null ++++ b/windowsview/translations/ukui-window-switch_zh_Hant.ts +@@ -0,0 +1,33 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="zh_Hant" sourcelanguage="en_US"> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="../qml/NewDesktopButton.qml" line="105"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">新桌面</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="176"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">無應用開啟</translation> ++ </message> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="353"/> ++ <source>Clear</source> ++ <translation type="unfinished">清除</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> ++ <source>Desktop</source> ++ <translation type="unfinished">桌面</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/ukui-window-switch b/windowsview/ukui-window-switch +index ee703c1..153c407 100755 +--- a/windowsview/ukui-window-switch ++++ b/windowsview/ukui-window-switch +@@ -13,4 +13,4 @@ else + if [ $process_count -gt 0 ]; then + /usr/bin/ukui-window-switch-wlcom + fi +-fi ++fi +\ No newline at end of file +diff --git a/windowsview/ukui-window-switch-kwineffect/CMakeLists.txt b/windowsview/ukui-window-switch-kwineffect/CMakeLists.txt +index b572c2e..9836fdc 100644 +--- a/windowsview/ukui-window-switch-kwineffect/CMakeLists.txt ++++ b/windowsview/ukui-window-switch-kwineffect/CMakeLists.txt +@@ -1,4 +1,4 @@ +-cmake_minimum_required(VERSION 3.5) ++cmake_minimum_required(VERSION 3.16) + + # 调试多任务视图需要取消注释下面 + # add_definitions("-Wall -g") +@@ -6,7 +6,6 @@ set(PLUGIN_NAME "windowsview") + + set(CMAKE_INCLUDE_CURRENT_DIR ON) + set(CMAKE_AUTOMOC ON) +-set(CMAKE_AUTOUIC ON) + set(CMAKE_AUTORCC ON) + + set(CMAKE_CXX_STANDARD 14) +@@ -17,43 +16,14 @@ set(KF5_DEP_VERSION "5.54.0") + find_package(ECM 5.54.0 NO_MODULE) + set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake) + +-find_package(X11 MODULE) +-find_package(XCB MODULE COMPONENTS XCB COMPOSITE DAMAGE SHAPE XFIXES RENDER) +-message("XCB:"${X11_FOUND}, ${XCB_XCB_FOUND}, ${XCB_COMPOSITE_FOUND}, ${XCB_DAMAGE_FOUND}) +-if(X11_FOUND AND XCB_XCB_FOUND) +- set(HAVE_X11 1) +-endif() +-if(HAVE_X11 AND XCB_COMPOSITE_FOUND AND XCB_DAMAGE_FOUND) +- set(HAVE_XCB_COMPOSITE 1) +-endif() +- + find_package(OpenGL) +- + find_package(EGL MODULE) +-message("EGL:"${EGL_FOUND}) +-if (${EGL_FOUND}) +- set(HAVE_EGL 1) +-endif() +- +-message("OPENGL:"${OPENGL_FOUND},${Qt5Gui_OPENGL_IMPLEMENTATION}) +-if(OPENGL_FOUND AND (${Qt5Gui_OPENGL_IMPLEMENTATION} STREQUAL "GL")) +- set(HAVE_GLX ${HAVE_X11}) +-else() +- set(HAVE_GLX 0) +-endif() +- +-message("MACRO:"${HAVE_X11},${HAVE_XCB_COMPOSITE},${HAVE_EGL},${HAVE_GLX}) +- +-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../globalconfig.h.in ${CMAKE_CURRENT_SOURCE_DIR}/../globalconfig.h) +- +-find_package(Qt5Quick REQUIRED) +-find_package(Qt5QuickWidgets REQUIRED) + find_package(KF5Config REQUIRED) + find_package(KF5GlobalAccel REQUIRED) + find_package(KF5I18n REQUIRED) + find_package(PkgConfig REQUIRED) + find_package(Qt5LinguistTools REQUIRED) +-find_package(Qt5 REQUIRED NO_MODULE COMPONENTS X11Extras Concurrent) ++find_package(Qt5 REQUIRED NO_MODULE COMPONENTS X11Extras Concurrent Quick DBus) + + pkg_check_modules(KDK REQUIRED kysdk-sysinfo) + pkg_check_modules(DATACOLLECT REQUIRED kysdk-datacollect) +@@ -61,9 +31,6 @@ pkg_check_modules(DATACOLLECT REQUIRED kysdk-datacollect) + include_directories(${KDK_INCLUDE_DIRS}) + include_directories(${DATACOLLECT_INCLUDE_DIRS}) + +-# 注意要链接到kwin,如果本地安装了kwin的依赖,记得注意区分 +-include_directories(/usr/include/) +- + add_definitions(-DKWINEFFECT=1) + + set(SRCS ../desktopbackground.cpp +@@ -76,60 +43,29 @@ set(SRCS ../desktopbackground.cpp + multitaskviewmodelbycompositehandler.cpp + ) + +-# translation +-find_package(QT NAMES Qt6 Qt5 COMPONENTS LinguistTools REQUIRED) +-find_package(Qt${QT_VERSION_MAJOR} COMPONENTS LinguistTools REQUIRED) +- +-set(TS_FILES) +-set(QM_FILES) +- +-file(GLOB QML_FILES "../qml/*.qml") +- +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_zh_CN.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_bo_CN.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_zh_Hant.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_ug.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_mn.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_ky.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_kk.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_fr.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_es.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_de.ts) +- +-set_source_files_properties(${TS_FILES} +- PROPERTIES OUTPUT_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/../) +- +-qt5_create_translation(QM_FILES ${TS_FILES} ${QML_FILES}) +- +-add_custom_target(lupdate_task DEPENDS ${TS_FILES}) +- +-add_custom_target(lrelease_task DEPENDS ${QM_FILES}) +- + qt5_add_resources(SRCS ../data.qrc) + add_library( + ${PLUGIN_NAME} MODULE + ${SRCS} +- ${QM_FILES} + ) + + target_link_libraries( +- ${PLUGIN_NAME} +- PUBLIC +- Qt5::Core +- Qt5::Gui +- Qt5::Widgets +- Qt5::Quick +- Qt5::QuickWidgets +- PRIVATE +- KF5::ConfigCore +- KF5::WindowSystem +- KF5::CoreAddons +- KF5::GlobalAccel +- Qt5::X11Extras +- Qt5::Concurrent +- ${QGSettings_LIBRARIES} +- ${KDK_LINK_LIBRARIES} +- ${DATACOLLECT_LINK_LIBRARIES} ++ ${PLUGIN_NAME} ++ PUBLIC ++ Qt5::Core ++ Qt5::Gui ++ Qt5::Quick ++ PRIVATE ++ KF5::ConfigCore ++ KF5::WindowSystem ++ KF5::CoreAddons ++ KF5::GlobalAccel ++ Qt5::X11Extras ++ Qt5::Concurrent ++ Qt5::DBus ++ ${QGSettings_LIBRARIES} ++ ${KDK_LINK_LIBRARIES} ++ ${DATACOLLECT_LINK_LIBRARIES} + ) +- +-install(TARGETS ${PLUGIN_NAME} DESTINATION ${INSTALL_PATH}) ++set(INSTALL_PATH ${QT_INSTALL_PLUGINS}/kwin/effects/plugins/) ++install(TARGETS ${PLUGIN_NAME} DESTINATION ${INSTALL_PATH}) +\ No newline at end of file +diff --git a/windowsview/ukui-window-switch-kwineffect/multitaskviewmanager.cpp b/windowsview/ukui-window-switch-kwineffect/multitaskviewmanager.cpp +index 05810dd..9c7a185 100644 +--- a/windowsview/ukui-window-switch-kwineffect/multitaskviewmanager.cpp ++++ b/windowsview/ukui-window-switch-kwineffect/multitaskviewmanager.cpp +@@ -275,7 +275,7 @@ void MultitaskViewManager::installTranslator() + { + m_translator = new QTranslator(qApp); + m_translator->load(QLocale::system(), QLatin1String("ukui-window-switch"), +- QLatin1String("_"), QLatin1String(":/")); ++ QLatin1String("_"), TRANSLATION_DIR); + QApplication::installTranslator(m_translator); + } + +diff --git a/windowsview/ukui-window-switch-wlcom/CMakeLists.txt b/windowsview/ukui-window-switch-wlcom/CMakeLists.txt +index 3128c93..ea7dbfb 100644 +--- a/windowsview/ukui-window-switch-wlcom/CMakeLists.txt ++++ b/windowsview/ukui-window-switch-wlcom/CMakeLists.txt +@@ -1,4 +1,4 @@ +-cmake_minimum_required(VERSION 3.5) ++cmake_minimum_required(VERSION 3.16) + + # 调试多任务视图需要取消注释下面 + add_definitions("-Wall -g") +@@ -7,7 +7,6 @@ project(ukui-window-switch-wlcom) + + set(CMAKE_INCLUDE_CURRENT_DIR ON) + set(CMAKE_AUTOMOC ON) +-set(CMAKE_AUTOUIC ON) + set(CMAKE_AUTORCC ON) + + set(CMAKE_CXX_STANDARD 14) +@@ -15,55 +14,23 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) + + set(KF5_DEP_VERSION "5.54.0") + +-find_package(ECM 5.54.0 NO_MODULE) +-set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake) +- +-find_package(X11 MODULE) +-find_package(XCB MODULE COMPONENTS XCB COMPOSITE DAMAGE SHAPE XFIXES RENDER) +-message("XCB:"${X11_FOUND}, ${XCB_XCB_FOUND}, ${XCB_COMPOSITE_FOUND}, ${XCB_DAMAGE_FOUND}) +-if(X11_FOUND AND XCB_XCB_FOUND) +- set(HAVE_X11 1) +-endif() +-if(HAVE_X11 AND XCB_COMPOSITE_FOUND AND XCB_DAMAGE_FOUND) +- set(HAVE_XCB_COMPOSITE 1) +-endif() +- +-find_package(OpenGL) +- +-find_package(EGL MODULE) +-message("EGL:"${EGL_FOUND}) +-if (${EGL_FOUND}) +- set(HAVE_EGL 1) +-endif() +- +-message("OPENGL:"${OPENGL_FOUND},${Qt5Gui_OPENGL_IMPLEMENTATION}) +-if(OPENGL_FOUND AND (${Qt5Gui_OPENGL_IMPLEMENTATION} STREQUAL "GL")) +- set(HAVE_GLX ${HAVE_X11}) +-else() +- set(HAVE_GLX 0) +-endif() +- +-message("MACRO:"${HAVE_X11},${HAVE_XCB_COMPOSITE},${HAVE_EGL},${HAVE_GLX}) +- +-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../globalconfig.h.in ${CMAKE_CURRENT_SOURCE_DIR}/../globalconfig.h) +- +-find_package(Qt5Quick REQUIRED) +-find_package(Qt5QuickWidgets REQUIRED) + find_package(KF5Config REQUIRED) + find_package(KF5GlobalAccel REQUIRED) ++find_package(KF5WindowSystem) + find_package(KF5I18n REQUIRED) + find_package(PkgConfig REQUIRED) +-find_package(Qt5LinguistTools REQUIRED) +-find_package(Qt5 REQUIRED NO_MODULE COMPONENTS X11Extras Concurrent) ++find_package(Qt5 REQUIRED NO_MODULE COMPONENTS Concurrent Quick LinguistTools DBus) + + pkg_check_modules(KDK REQUIRED kysdk-sysinfo) + pkg_check_modules(DATACOLLECT REQUIRED kysdk-datacollect) + pkg_check_modules(KYSDKWAYLANDHELPER_PKG kysdk-waylandhelper) ++pkg_check_modules(GL REQUIRED gl) + + include_directories(${KDK_INCLUDE_DIRS}) + include_directories(${DATACOLLECT_INCLUDE_DIRS}) + include_directories(${WAYLANDHELPER_INCLUDE_DIRS}) + include_directories(${OPENGL_INCLUDE_DIR}) ++include_directories(${GL}) + + set(WLCSRCS main.cpp + log-utils.h log-utils.cpp +@@ -82,35 +49,6 @@ set(WLCSRCS main.cpp + ThumbnailItem.cpp + ) + +-# translation +-find_package(QT NAMES Qt6 Qt5 COMPONENTS LinguistTools REQUIRED) +-find_package(Qt${QT_VERSION_MAJOR} COMPONENTS LinguistTools REQUIRED) +- +-set(TS_FILES) +-set(QM_FILES) +- +-file(GLOB QML_FILES "../qml/*.qml") +- +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_zh_CN.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_bo_CN.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_zh_Hant.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_ug.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_mn.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_ky.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_kk.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_fr.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_es.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_de.ts) +- +-set_source_files_properties(${TS_FILES} +- PROPERTIES OUTPUT_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/../) +- +-qt5_create_translation(QM_FILES ${TS_FILES} ${QML_FILES}) +- +-add_custom_target(wlupdate_task DEPENDS ${TS_FILES}) +- +-add_custom_target(wlrelease_task DEPENDS ${QM_FILES}) +- + add_subdirectory(qtsingleapplication) + include_directories(qtsingleapplication/src) + +@@ -118,35 +56,34 @@ qt5_add_resources(WLCSRCS ../data.qrc) + + add_executable(ukui-window-switch-wlcom + ${WLCSRCS} +- ${QM_FILES} + ) + + target_include_directories(ukui-window-switch-wlcom PRIVATE ${KYSDKWAYLANDHELPER_PKG_INCLUDE_DIRS}) + target_link_directories(ukui-window-switch-wlcom PRIVATE ${KYSDKWAYLANDHELPER_PKG_LIBRARY_DIRS} KF5::WindowSystem) + ++target_compile_definitions(${PROJECT_NAME} PRIVATE $<$<CONFIG:Debug>:DISABLE_LOG_FILE>) ++target_compile_definitions(${PROJECT_NAME} PRIVATE $<$<CONFIG:Debug>:QT_QML_DEBUG>) ++ + target_link_libraries( +- ukui-window-switch-wlcom +- PUBLIC +- Qt5::Core +- Qt5::GuiPrivate +- Qt5::Widgets +- Qt5::Quick +- Qt5::QuickWidgets +- PRIVATE +- KF5::ConfigCore +- KF5::WindowSystem +- KF5::CoreAddons +- KF5::GlobalAccel +- Qt5::X11Extras +- Qt5::Concurrent +- qtsingleapplication +- kywc +- ${QGSettings_LIBRARIES} +- ${KYSDKWAYLANDHELPER_PKG_LIBRARIES} +- ${KDK_LINK_LIBRARIES} +- ${DATACOLLECT_LINK_LIBRARIES} +- ${OPENGL_gl_LIBRARY} +- ${EGL_LIBRARY} ++ ukui-window-switch-wlcom ++ PUBLIC ++ Qt5::Core ++ Qt5::GuiPrivate ++ Qt5::Quick ++ PRIVATE ++ KF5::WindowSystem ++ KF5::GlobalAccel ++ Qt5::Concurrent ++ Qt5::DBus ++ qtsingleapplication ++ kywc ++ ${QGSettings_LIBRARIES} ++ ${KYSDKWAYLANDHELPER_PKG_LIBRARIES} ++ ${KDK_LINK_LIBRARIES} ++ ${DATACOLLECT_LINK_LIBRARIES} ++ ${OPENGL_gl_LIBRARY} ++ ${EGL_LIBRARY} ++ ${GL_LIBRARIES} + ) + +-install(TARGETS ukui-window-switch-wlcom ${INSTALL_TARGETS_DEFAULT_ARGS}) ++install(TARGETS ukui-window-switch-wlcom DESTINATION /usr/bin) +diff --git a/windowsview/ukui-window-switch-wlcom/main.cpp b/windowsview/ukui-window-switch-wlcom/main.cpp +index c962097..9950d0c 100644 +--- a/windowsview/ukui-window-switch-wlcom/main.cpp ++++ b/windowsview/ukui-window-switch-wlcom/main.cpp +@@ -28,7 +28,7 @@ + + int main(int argc, char *argv[]) + { +-#ifndef PANEL_DISABLE_LOG_FILE ++#ifndef DISABLE_LOG_FILE + LogUtils::initLogFile("ukui-window-switch-wlcom"); + qInstallMessageHandler(LogUtils::messageOutput); + #endif +@@ -39,15 +39,18 @@ int main(int argc, char *argv[]) + parser.process(a); + if (a.isRunning()) + { +- if (parser.isSet("show-workspace")) { ++ if (parser.isSet(showWorkSpaceOption)) { + a.sendMessage(QApplication::arguments().length() > 1 ? QApplication::arguments().at(1) : a.applicationFilePath()); + } + return EXIT_SUCCESS; + } + + MultitaskViewManagerByWlcom m; ++ if (parser.isSet(showWorkSpaceOption)) { ++ m.open(); ++ } + QObject::connect(&a, &QtSingleApplication::messageReceived, [&m](){ + m.open(); + }); +- return a.exec(); ++ return QtSingleApplication::exec(); + } +diff --git a/windowsview/ukui-window-switch-wlcom/multitaskviewmanagerbywlcom.cpp b/windowsview/ukui-window-switch-wlcom/multitaskviewmanagerbywlcom.cpp +index d4420f1..74e54df 100644 +--- a/windowsview/ukui-window-switch-wlcom/multitaskviewmanagerbywlcom.cpp ++++ b/windowsview/ukui-window-switch-wlcom/multitaskviewmanagerbywlcom.cpp +@@ -20,7 +20,6 @@ + + // kf5 + #include <KF5/KGlobalAccel/KGlobalAccel> +-#include <KF5/KWindowSystem/KWindowSystem> + #include <KF5/KWindowSystem/KWindowEffects> + + // kysdk +@@ -369,7 +368,7 @@ void MultitaskViewManagerByWlcom::installTranslator() + { + m_translator = new QTranslator(qApp); + m_translator->load(QLocale::system(), QLatin1String("ukui-window-switch"), +- QLatin1String("_"), QLatin1String(":/")); ++ QLatin1String("_"), TRANSLATION_DIR); + QApplication::installTranslator(m_translator); + } + +diff --git a/windowsview/ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.cpp b/windowsview/ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.cpp +index 95f354c..8a698dd 100644 +--- a/windowsview/ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.cpp ++++ b/windowsview/ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.cpp +@@ -28,6 +28,8 @@ + #include <QEventLoop> + #include <qpa/qplatformnativeinterface.h> + #include <iostream> ++#include <KWindowSystem> ++ + #include "multitaskviewmanagerbywlcom.h" + using namespace std; + +diff --git a/windowsview/ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.h b/windowsview/ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.h +index 6f3417a..4762469 100644 +--- a/windowsview/ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.h ++++ b/windowsview/ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.h +@@ -26,9 +26,6 @@ + #include <QMap> + #include <QRect> + #include <QVariantList> +-#include <KWindowSystem/KWindowSystem> +-#include <KWindowSystem/KWindowInfo> +-#include <KWindowSystem/NETWM> + #include "context.h" + + class MultitaskViewModelByWlcomHandler : public MultitaskViewModelHandler +diff --git a/windowsview/ukui-window-switch_ar.ts b/windowsview/ukui-window-switch_ar.ts +deleted file mode 100644 +index bf0b6c9..0000000 +--- a/windowsview/ukui-window-switch_ar.ts ++++ /dev/null +@@ -1,62 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="ar" sourcelanguage="en_US"> +-<context> +- <name>DesktopArea</name> +- <message> +- <source>Desktop</source> +- <translatorcomment>工作区</translatorcomment> +- <translation type="vanished">工作区</translation> +- </message> +- <message> +- <source>New Desktop</source> +- <translatorcomment>新建工作区</translatorcomment> +- <translation type="vanished">新建工作区</translation> +- </message> +-</context> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="qml/NewDesktopButton.qml" line="104"/> +- <source>New Desktop</source> +- <translation>سطح مكتب جديد</translation> +- </message> +-</context> +-<context> +- <name>TabletViewClearAllWindowButton</name> +- <message> +- <source>Clear</source> +- <translatorcomment>清除</translatorcomment> +- <translation type="vanished">清除</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="qml/TabletViewMain.qml" line="174"/> +- <source>No recent tasks</source> +- <translation>لا توجد مهام حديثة</translation> +- </message> +- <message> +- <location filename="qml/TabletViewMain.qml" line="357"/> +- <source>Clear</source> +- <translation>واضح</translation> +- </message> +-</context> +-<context> +- <name>TabletViewRootWindow</name> +- <message> +- <source>No recent tasks</source> +- <translatorcomment>无应用开启</translatorcomment> +- <translation type="vanished">无应用开启</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="qml/VirtualDesktopWindow.qml" line="187"/> +- <source>Desktop</source> +- <translation>سطح المكتب</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/ukui-window-switch_bo_CN.ts b/windowsview/ukui-window-switch_bo_CN.ts +deleted file mode 100644 +index 210d9a1..0000000 +--- a/windowsview/ukui-window-switch_bo_CN.ts ++++ /dev/null +@@ -1,62 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="bo_CN" sourcelanguage="en_US"> +-<context> +- <name>DesktopArea</name> +- <message> +- <source>Desktop</source> +- <translatorcomment>工作区</translatorcomment> +- <translation type="vanished">ལས་སྒྲུབ་ཁུལ།</translation> +- </message> +- <message> +- <source>New Desktop</source> +- <translatorcomment>新建工作区</translatorcomment> +- <translation type="vanished">གསར་དུ་བཙུགས་པའི་ལས་དོན་ཁུལ།</translation> +- </message> +-</context> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="qml/NewDesktopButton.qml" line="104"/> +- <source>New Desktop</source> +- <translation type="unfinished">གསར་དུ་བཙུགས་པའི་ལས་དོན་ཁུལ།</translation> +- </message> +-</context> +-<context> +- <name>TabletViewClearAllWindowButton</name> +- <message> +- <source>Clear</source> +- <translatorcomment>清除</translatorcomment> +- <translation type="vanished">གསལ་པོར་བཤད་ན།</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="qml/TabletViewMain.qml" line="174"/> +- <source>No recent tasks</source> +- <translation type="unfinished">ཉེ་ལམ་གྱི་ལས་འགན་གང་ཡང་མེད།</translation> +- </message> +- <message> +- <location filename="qml/TabletViewMain.qml" line="357"/> +- <source>Clear</source> +- <translation type="unfinished">གསལ་པོར་བཤད་ན།</translation> +- </message> +-</context> +-<context> +- <name>TabletViewRootWindow</name> +- <message> +- <source>No recent tasks</source> +- <translatorcomment>无应用开启</translatorcomment> +- <translation type="vanished">ཉེ་ལམ་གྱི་ལས་འགན་གང་ཡང་མེད།</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="qml/VirtualDesktopWindow.qml" line="187"/> +- <source>Desktop</source> +- <translation type="unfinished">ལས་སྒྲུབ་ཁུལ།</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/ukui-window-switch_de.ts b/windowsview/ukui-window-switch_de.ts +deleted file mode 100644 +index b79eefa..0000000 +--- a/windowsview/ukui-window-switch_de.ts ++++ /dev/null +@@ -1,62 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="de" sourcelanguage="en_US"> +-<context> +- <name>DesktopArea</name> +- <message> +- <source>Desktop</source> +- <translatorcomment>工作区</translatorcomment> +- <translation type="vanished">Desktop</translation> +- </message> +- <message> +- <source>New Desktop</source> +- <translatorcomment>新建工作区</translatorcomment> +- <translation type="vanished">Neuer Desktop</translation> +- </message> +-</context> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="qml/NewDesktopButton.qml" line="104"/> +- <source>New Desktop</source> +- <translation type="unfinished">Neuer Desktop</translation> +- </message> +-</context> +-<context> +- <name>TabletViewClearAllWindowButton</name> +- <message> +- <source>Clear</source> +- <translatorcomment>清除</translatorcomment> +- <translation type="vanished">Klar</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="qml/TabletViewMain.qml" line="174"/> +- <source>No recent tasks</source> +- <translation type="unfinished">Keine aktuellen Aufgaben</translation> +- </message> +- <message> +- <location filename="qml/TabletViewMain.qml" line="357"/> +- <source>Clear</source> +- <translation type="unfinished">Klar</translation> +- </message> +-</context> +-<context> +- <name>TabletViewRootWindow</name> +- <message> +- <source>No recent tasks</source> +- <translatorcomment>无应用开启</translatorcomment> +- <translation type="vanished">Keine aktuellen Aufgaben</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="qml/VirtualDesktopWindow.qml" line="187"/> +- <source>Desktop</source> +- <translation type="unfinished">Desktop</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/ukui-window-switch_es.ts b/windowsview/ukui-window-switch_es.ts +deleted file mode 100644 +index f316292..0000000 +--- a/windowsview/ukui-window-switch_es.ts ++++ /dev/null +@@ -1,62 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="es" sourcelanguage="en_US"> +-<context> +- <name>DesktopArea</name> +- <message> +- <source>Desktop</source> +- <translatorcomment>工作区</translatorcomment> +- <translation type="vanished">Escritorio</translation> +- </message> +- <message> +- <source>New Desktop</source> +- <translatorcomment>新建工作区</translatorcomment> +- <translation type="vanished">Nuevo escritorio</translation> +- </message> +-</context> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="qml/NewDesktopButton.qml" line="104"/> +- <source>New Desktop</source> +- <translation type="unfinished">Nuevo escritorio</translation> +- </message> +-</context> +-<context> +- <name>TabletViewClearAllWindowButton</name> +- <message> +- <source>Clear</source> +- <translatorcomment>清除</translatorcomment> +- <translation type="vanished">Claro</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="qml/TabletViewMain.qml" line="174"/> +- <source>No recent tasks</source> +- <translation type="unfinished">No hay tareas recientes</translation> +- </message> +- <message> +- <location filename="qml/TabletViewMain.qml" line="357"/> +- <source>Clear</source> +- <translation type="unfinished">Claro</translation> +- </message> +-</context> +-<context> +- <name>TabletViewRootWindow</name> +- <message> +- <source>No recent tasks</source> +- <translatorcomment>无应用开启</translatorcomment> +- <translation type="vanished">No hay tareas recientes</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="qml/VirtualDesktopWindow.qml" line="187"/> +- <source>Desktop</source> +- <translation type="unfinished">Escritorio</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/ukui-window-switch_fr.ts b/windowsview/ukui-window-switch_fr.ts +deleted file mode 100644 +index bb4aac9..0000000 +--- a/windowsview/ukui-window-switch_fr.ts ++++ /dev/null +@@ -1,62 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="fr" sourcelanguage="en_US"> +-<context> +- <name>DesktopArea</name> +- <message> +- <source>Desktop</source> +- <translatorcomment>工作区</translatorcomment> +- <translation type="vanished">Bureau</translation> +- </message> +- <message> +- <source>New Desktop</source> +- <translatorcomment>新建工作区</translatorcomment> +- <translation type="vanished">Nouveau bureau</translation> +- </message> +-</context> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="qml/NewDesktopButton.qml" line="104"/> +- <source>New Desktop</source> +- <translation type="unfinished">Nouveau bureau</translation> +- </message> +-</context> +-<context> +- <name>TabletViewClearAllWindowButton</name> +- <message> +- <source>Clear</source> +- <translatorcomment>清除</translatorcomment> +- <translation type="vanished">Clair</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="qml/TabletViewMain.qml" line="174"/> +- <source>No recent tasks</source> +- <translation type="unfinished">Pas de tâches récentes</translation> +- </message> +- <message> +- <location filename="qml/TabletViewMain.qml" line="357"/> +- <source>Clear</source> +- <translation type="unfinished">Clair</translation> +- </message> +-</context> +-<context> +- <name>TabletViewRootWindow</name> +- <message> +- <source>No recent tasks</source> +- <translatorcomment>无应用开启</translatorcomment> +- <translation type="vanished">Pas de tâches récentes</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="qml/VirtualDesktopWindow.qml" line="187"/> +- <source>Desktop</source> +- <translation type="unfinished">Bureau</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/ukui-window-switch_kk.ts b/windowsview/ukui-window-switch_kk.ts +deleted file mode 100644 +index b70f893..0000000 +--- a/windowsview/ukui-window-switch_kk.ts ++++ /dev/null +@@ -1,62 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="kk" sourcelanguage="en_US"> +-<context> +- <name>DesktopArea</name> +- <message> +- <source>Desktop</source> +- <translatorcomment>工作区</translatorcomment> +- <translation type="vanished">Жұмыс үстелі</translation> +- </message> +- <message> +- <source>New Desktop</source> +- <translatorcomment>新建工作区</translatorcomment> +- <translation type="vanished">Жаңа үстел</translation> +- </message> +-</context> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="qml/NewDesktopButton.qml" line="104"/> +- <source>New Desktop</source> +- <translation>جاڭا ئۈستەلئۈستى</translation> +- </message> +-</context> +-<context> +- <name>TabletViewClearAllWindowButton</name> +- <message> +- <source>Clear</source> +- <translatorcomment>清除</translatorcomment> +- <translation type="vanished">Тазалау</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="qml/TabletViewMain.qml" line="174"/> +- <source>No recent tasks</source> +- <translation>جاقىنعى مىندەتتەر جوق</translation> +- </message> +- <message> +- <location filename="qml/TabletViewMain.qml" line="357"/> +- <source>Clear</source> +- <translation>تازالاۋ</translation> +- </message> +-</context> +-<context> +- <name>TabletViewRootWindow</name> +- <message> +- <source>No recent tasks</source> +- <translatorcomment>无应用开启</translatorcomment> +- <translation type="vanished">Соңғы тапсырмалар жоқ</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="qml/VirtualDesktopWindow.qml" line="187"/> +- <source>Desktop</source> +- <translation>ئۈستەلئۈستى</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/ukui-window-switch_ky.ts b/windowsview/ukui-window-switch_ky.ts +deleted file mode 100644 +index 77a2a21..0000000 +--- a/windowsview/ukui-window-switch_ky.ts ++++ /dev/null +@@ -1,62 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="ky" sourcelanguage="en_US"> +-<context> +- <name>DesktopArea</name> +- <message> +- <source>Desktop</source> +- <translatorcomment>工作区</translatorcomment> +- <translation type="vanished">Иш столу</translation> +- </message> +- <message> +- <source>New Desktop</source> +- <translatorcomment>新建工作区</translatorcomment> +- <translation type="vanished">Жаңы иш столу</translation> +- </message> +-</context> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="qml/NewDesktopButton.qml" line="104"/> +- <source>New Desktop</source> +- <translation>جاڭى ئۈستەلئۈستى</translation> +- </message> +-</context> +-<context> +- <name>TabletViewClearAllWindowButton</name> +- <message> +- <source>Clear</source> +- <translatorcomment>清除</translatorcomment> +- <translation type="vanished">Тазалоо</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="qml/TabletViewMain.qml" line="174"/> +- <source>No recent tasks</source> +- <translation>جاقىندا مٸلدەتتەر جوق</translation> +- </message> +- <message> +- <location filename="qml/TabletViewMain.qml" line="357"/> +- <source>Clear</source> +- <translation>تازالوو</translation> +- </message> +-</context> +-<context> +- <name>TabletViewRootWindow</name> +- <message> +- <source>No recent tasks</source> +- <translatorcomment>无应用开启</translatorcomment> +- <translation type="vanished">Акыркы милдеттер жок</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="qml/VirtualDesktopWindow.qml" line="187"/> +- <source>Desktop</source> +- <translation>ئۈستەلئۈستى</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/ukui-window-switch_mn.ts b/windowsview/ukui-window-switch_mn.ts +deleted file mode 100644 +index 179ef7d..0000000 +--- a/windowsview/ukui-window-switch_mn.ts ++++ /dev/null +@@ -1,62 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="mn" sourcelanguage="en_US"> +-<context> +- <name>DesktopArea</name> +- <message> +- <source>Desktop</source> +- <translatorcomment>工作区</translatorcomment> +- <translation type="vanished">ᠠᠵᠢᠯᠯᠠᠬᠤ ᠤᠷᠤᠨ</translation> +- </message> +- <message> +- <source>New Desktop</source> +- <translatorcomment>新建工作区</translatorcomment> +- <translation type="vanished">ᠱᠢᠨᠡᠪᠡᠷ ᠪᠠᠢᠭᠤᠯᠤᠭ᠍ᠰᠠᠨ ᠠᠵᠢᠯᠯᠠᠬᠤ ᠤᠷᠤᠨ</translation> +- </message> +-</context> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="qml/NewDesktopButton.qml" line="104"/> +- <source>New Desktop</source> +- <translation type="unfinished">ᠱᠢᠨᠡᠪᠡᠷ ᠪᠠᠢᠭᠤᠯᠤᠭ᠍ᠰᠠᠨ ᠠᠵᠢᠯᠯᠠᠬᠤ ᠤᠷᠤᠨ</translation> +- </message> +-</context> +-<context> +- <name>TabletViewClearAllWindowButton</name> +- <message> +- <source>Clear</source> +- <translatorcomment>清除</translatorcomment> +- <translation type="vanished">ᠠᠷᠢᠯᠭᠠᠬᠤ</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="qml/TabletViewMain.qml" line="174"/> +- <source>No recent tasks</source> +- <translation type="unfinished">ᠨᠡᠬᠡᠬᠡᠬᠦ᠌ ᠬᠡᠷᠡᠭᠯᠡᠭᠡ ᠪᠠᠢᠬᠤ ᠦᠬᠡᠢ</translation> +- </message> +- <message> +- <location filename="qml/TabletViewMain.qml" line="357"/> +- <source>Clear</source> +- <translation type="unfinished">ᠠᠷᠢᠯᠭᠠᠬᠤ</translation> +- </message> +-</context> +-<context> +- <name>TabletViewRootWindow</name> +- <message> +- <source>No recent tasks</source> +- <translatorcomment>无应用开启</translatorcomment> +- <translation type="vanished">ᠨᠡᠬᠡᠬᠡᠬᠦ᠌ ᠬᠡᠷᠡᠭᠯᠡᠭᠡ ᠪᠠᠢᠬᠤ ᠦᠬᠡᠢ</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="qml/VirtualDesktopWindow.qml" line="187"/> +- <source>Desktop</source> +- <translation type="unfinished">ᠠᠵᠢᠯᠯᠠᠬᠤ ᠤᠷᠤᠨ</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/ukui-window-switch_ug.ts b/windowsview/ukui-window-switch_ug.ts +deleted file mode 100644 +index f9d529f..0000000 +--- a/windowsview/ukui-window-switch_ug.ts ++++ /dev/null +@@ -1,62 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="ug" sourcelanguage="en_US"> +-<context> +- <name>DesktopArea</name> +- <message> +- <source>Desktop</source> +- <translatorcomment>工作区</translatorcomment> +- <translation type="vanished">ئۈستەلئۈستى</translation> +- </message> +- <message> +- <source>New Desktop</source> +- <translatorcomment>新建工作区</translatorcomment> +- <translation type="vanished">يېڭى ئۈستەلئۈستى</translation> +- </message> +-</context> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="qml/NewDesktopButton.qml" line="104"/> +- <source>New Desktop</source> +- <translation>يېڭى ئۈستەلئۈستى</translation> +- </message> +-</context> +-<context> +- <name>TabletViewClearAllWindowButton</name> +- <message> +- <source>Clear</source> +- <translatorcomment>清除</translatorcomment> +- <translation type="vanished">تازىلاش</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="qml/TabletViewMain.qml" line="174"/> +- <source>No recent tasks</source> +- <translation>يېقىنقى ۋەزىپىلەر يوق</translation> +- </message> +- <message> +- <location filename="qml/TabletViewMain.qml" line="357"/> +- <source>Clear</source> +- <translation>تازىلاش</translation> +- </message> +-</context> +-<context> +- <name>TabletViewRootWindow</name> +- <message> +- <source>No recent tasks</source> +- <translatorcomment>无应用开启</translatorcomment> +- <translation type="vanished">يېقىنقى ۋەزىپىلەر يوق</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="qml/VirtualDesktopWindow.qml" line="187"/> +- <source>Desktop</source> +- <translation>ئۈستەل يۈزى</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/ukui-window-switch_vi.ts b/windowsview/ukui-window-switch_vi.ts +deleted file mode 100644 +index d673d4a..0000000 +--- a/windowsview/ukui-window-switch_vi.ts ++++ /dev/null +@@ -1,62 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="vi" sourcelanguage="en_US"> +-<context> +- <name>DesktopArea</name> +- <message> +- <source>Desktop</source> +- <translatorcomment>工作区</translatorcomment> +- <translation type="vanished">工作区</translation> +- </message> +- <message> +- <source>New Desktop</source> +- <translatorcomment>新建工作区</translatorcomment> +- <translation type="vanished">新建工作区</translation> +- </message> +-</context> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="qml/NewDesktopButton.qml" line="104"/> +- <source>New Desktop</source> +- <translation>Máy tính để bàn mới</translation> +- </message> +-</context> +-<context> +- <name>TabletViewClearAllWindowButton</name> +- <message> +- <source>Clear</source> +- <translatorcomment>清除</translatorcomment> +- <translation type="vanished">清除</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="qml/TabletViewMain.qml" line="174"/> +- <source>No recent tasks</source> +- <translation>Không có nhiệm vụ gần đây</translation> +- </message> +- <message> +- <location filename="qml/TabletViewMain.qml" line="357"/> +- <source>Clear</source> +- <translation>Trong</translation> +- </message> +-</context> +-<context> +- <name>TabletViewRootWindow</name> +- <message> +- <source>No recent tasks</source> +- <translatorcomment>无应用开启</translatorcomment> +- <translation type="vanished">无应用开启</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="qml/VirtualDesktopWindow.qml" line="187"/> +- <source>Desktop</source> +- <translation>Bàn làm việc</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/ukui-window-switch_zh_CN.ts b/windowsview/ukui-window-switch_zh_CN.ts +deleted file mode 100644 +index 397f1fe..0000000 +--- a/windowsview/ukui-window-switch_zh_CN.ts ++++ /dev/null +@@ -1,62 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="zh_CN" sourcelanguage="en_US"> +-<context> +- <name>DesktopArea</name> +- <message> +- <source>Desktop</source> +- <translatorcomment>工作区</translatorcomment> +- <translation type="vanished">工作区</translation> +- </message> +- <message> +- <source>New Desktop</source> +- <translatorcomment>新建工作区</translatorcomment> +- <translation type="vanished">新建工作区</translation> +- </message> +-</context> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="qml/NewDesktopButton.qml" line="104"/> +- <source>New Desktop</source> +- <translation type="unfinished">新建工作区</translation> +- </message> +-</context> +-<context> +- <name>TabletViewClearAllWindowButton</name> +- <message> +- <source>Clear</source> +- <translatorcomment>清除</translatorcomment> +- <translation type="vanished">清除</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="qml/TabletViewMain.qml" line="174"/> +- <source>No recent tasks</source> +- <translation type="unfinished">无应用开启</translation> +- </message> +- <message> +- <location filename="qml/TabletViewMain.qml" line="357"/> +- <source>Clear</source> +- <translation type="unfinished">清除</translation> +- </message> +-</context> +-<context> +- <name>TabletViewRootWindow</name> +- <message> +- <source>No recent tasks</source> +- <translatorcomment>无应用开启</translatorcomment> +- <translation type="vanished">无应用开启</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="qml/VirtualDesktopWindow.qml" line="187"/> +- <source>Desktop</source> +- <translation type="unfinished">工作区</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/ukui-window-switch_zh_Hant.ts b/windowsview/ukui-window-switch_zh_Hant.ts +deleted file mode 100644 +index 35f0bda..0000000 +--- a/windowsview/ukui-window-switch_zh_Hant.ts ++++ /dev/null +@@ -1,62 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="zh_Hant" sourcelanguage="en_US"> +-<context> +- <name>DesktopArea</name> +- <message> +- <source>Desktop</source> +- <translatorcomment>工作区</translatorcomment> +- <translation type="vanished">桌面</translation> +- </message> +- <message> +- <source>New Desktop</source> +- <translatorcomment>新建工作区</translatorcomment> +- <translation type="vanished">新桌面</translation> +- </message> +-</context> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="qml/NewDesktopButton.qml" line="104"/> +- <source>New Desktop</source> +- <translation type="unfinished">新桌面</translation> +- </message> +-</context> +-<context> +- <name>TabletViewClearAllWindowButton</name> +- <message> +- <source>Clear</source> +- <translatorcomment>清除</translatorcomment> +- <translation type="vanished">清除</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="qml/TabletViewMain.qml" line="174"/> +- <source>No recent tasks</source> +- <translation type="unfinished">無應用開啟</translation> +- </message> +- <message> +- <location filename="qml/TabletViewMain.qml" line="357"/> +- <source>Clear</source> +- <translation type="unfinished">清除</translation> +- </message> +-</context> +-<context> +- <name>TabletViewRootWindow</name> +- <message> +- <source>No recent tasks</source> +- <translatorcomment>无应用开启</translatorcomment> +- <translation type="vanished">無應用開啟</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="qml/VirtualDesktopWindow.qml" line="187"/> +- <source>Desktop</source> +- <translation type="unfinished">桌面</translation> +- </message> +-</context> +-</TS> diff -Nru ukui-window-switch-4.10.1.10/debian/patches/0011-Revert-perf-CMakeLists.txt.patch ukui-window-switch-4.10.1.10/debian/patches/0011-Revert-perf-CMakeLists.txt.patch --- ukui-window-switch-4.10.1.10/debian/patches/0011-Revert-perf-CMakeLists.txt.patch 1970-01-01 08:00:00.000000000 +0800 +++ ukui-window-switch-4.10.1.10/debian/patches/0011-Revert-perf-CMakeLists.txt.patch 2025-03-07 14:07:48.000000000 +0800 @@ -0,0 +1,1953 @@ +From: zhangyuanyuan1 <zhangyuanyuan1@kylinos.cn> +Date: Thu, 6 Mar 2025 07:56:00 +0000 +Subject: =?utf-8?b?UmV2ZXJ0ICJwZXJmOuS8mOWMlkNNYWtlTGlzdHMudHh057uT5p6EIg==?= + +This reverts commit bba2491238a8d674b5481d2746a85a2ecda87862. +--- + .gitignore | 1 + + CMakeLists.txt | 11 +- + windowsview/CMakeLists.txt | 71 ++++++++++-- + windowsview/data.qrc | 10 ++ + windowsview/multitaskviewmodel.h | 5 +- + windowsview/translations/ukui-window-switch_ar.ts | 33 ------ + .../translations/ukui-window-switch_bo_CN.ts | 33 ------ + windowsview/translations/ukui-window-switch_de.ts | 33 ------ + windowsview/translations/ukui-window-switch_es.ts | 33 ------ + windowsview/translations/ukui-window-switch_fr.ts | 33 ------ + windowsview/translations/ukui-window-switch_kk.ts | 33 ------ + windowsview/translations/ukui-window-switch_ky.ts | 33 ------ + windowsview/translations/ukui-window-switch_mn.ts | 33 ------ + windowsview/translations/ukui-window-switch_ug.ts | 33 ------ + windowsview/translations/ukui-window-switch_vi.ts | 33 ------ + .../translations/ukui-window-switch_zh_CN.ts | 33 ------ + .../translations/ukui-window-switch_zh_Hant.ts | 33 ------ + windowsview/ukui-window-switch | 2 +- + .../ukui-window-switch-kwineffect/CMakeLists.txt | 104 ++++++++++++++---- + .../multitaskviewmanager.cpp | 2 +- + .../ukui-window-switch-wlcom/CMakeLists.txt | 119 ++++++++++++++++----- + windowsview/ukui-window-switch-wlcom/main.cpp | 9 +- + .../multitaskviewmanagerbywlcom.cpp | 3 +- + .../multitaskviewmodelbywlcomhandler.cpp | 2 - + .../multitaskviewmodelbywlcomhandler.h | 3 + + windowsview/ukui-window-switch_ar.ts | 62 +++++++++++ + windowsview/ukui-window-switch_bo_CN.ts | 62 +++++++++++ + windowsview/ukui-window-switch_de.ts | 62 +++++++++++ + windowsview/ukui-window-switch_es.ts | 62 +++++++++++ + windowsview/ukui-window-switch_fr.ts | 62 +++++++++++ + windowsview/ukui-window-switch_kk.ts | 62 +++++++++++ + windowsview/ukui-window-switch_ky.ts | 62 +++++++++++ + windowsview/ukui-window-switch_mn.ts | 62 +++++++++++ + windowsview/ukui-window-switch_ug.ts | 62 +++++++++++ + windowsview/ukui-window-switch_vi.ts | 62 +++++++++++ + windowsview/ukui-window-switch_zh_CN.ts | 62 +++++++++++ + windowsview/ukui-window-switch_zh_Hant.ts | 62 +++++++++++ + 37 files changed, 1010 insertions(+), 472 deletions(-) + delete mode 100644 windowsview/translations/ukui-window-switch_ar.ts + delete mode 100644 windowsview/translations/ukui-window-switch_bo_CN.ts + delete mode 100644 windowsview/translations/ukui-window-switch_de.ts + delete mode 100644 windowsview/translations/ukui-window-switch_es.ts + delete mode 100644 windowsview/translations/ukui-window-switch_fr.ts + delete mode 100644 windowsview/translations/ukui-window-switch_kk.ts + delete mode 100644 windowsview/translations/ukui-window-switch_ky.ts + delete mode 100644 windowsview/translations/ukui-window-switch_mn.ts + delete mode 100644 windowsview/translations/ukui-window-switch_ug.ts + delete mode 100644 windowsview/translations/ukui-window-switch_vi.ts + delete mode 100644 windowsview/translations/ukui-window-switch_zh_CN.ts + delete mode 100644 windowsview/translations/ukui-window-switch_zh_Hant.ts + create mode 100644 windowsview/ukui-window-switch_ar.ts + create mode 100644 windowsview/ukui-window-switch_bo_CN.ts + create mode 100644 windowsview/ukui-window-switch_de.ts + create mode 100644 windowsview/ukui-window-switch_es.ts + create mode 100644 windowsview/ukui-window-switch_fr.ts + create mode 100644 windowsview/ukui-window-switch_kk.ts + create mode 100644 windowsview/ukui-window-switch_ky.ts + create mode 100644 windowsview/ukui-window-switch_mn.ts + create mode 100644 windowsview/ukui-window-switch_ug.ts + create mode 100644 windowsview/ukui-window-switch_vi.ts + create mode 100644 windowsview/ukui-window-switch_zh_CN.ts + create mode 100644 windowsview/ukui-window-switch_zh_Hant.ts + +diff --git a/.gitignore b/.gitignore +index 8f1db95..dd3e4fa 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -5,6 +5,7 @@ + *.user + *.qm + CMakeLists.txt.user* ++windowsview/globalconfig.h + + # debian files + obj-*-linux-gnu/ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 820482c..bf089b5 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1,4 +1,4 @@ +-cmake_minimum_required(VERSION 3.16) ++cmake_minimum_required(VERSION 3.5) + + project(ukui-window-switch) + +@@ -11,13 +11,18 @@ find_package(KF5WindowSystem REQUIRED) + + get_target_property(QT_QMAKE_EXECUTABLE ${Qt5Core_QMAKE_EXECUTABLE} IMPORTED_LOCATION) + macro(query_qmake args output) +- execute_process(COMMAND ${QT_QMAKE_EXECUTABLE} -query ${args} OUTPUT_VARIABLE ${output} RESULT_VARIABLE test1 RESULT_VARIABLE result OUTPUT_STRIP_TRAILING_WHITESPACE) +- if(NOT ${result} EQUAL 0) ++ exec_program(${QT_QMAKE_EXECUTABLE} ARGS -query ${args} OUTPUT_VARIABLE ${output} RETURN_VALUE exitCode) ++ ++ if(NOT ${exitCode} EQUAL 0) + message(FATAL_ERROR "exec ${QT_QMAKE_EXECUTABLE} failed, with args: ${args}, error message: ${output}") + endif() + endmacro() + + query_qmake("QT_INSTALL_PLUGINS" QT_INSTALL_PLUGINS) ++message("QT_INSTALL_PLUGINS=${QT_INSTALL_PLUGINS}") ++ ++set(INSTALL_PATH "${QT_INSTALL_PLUGINS}/kwin/effects/plugins") ++ + + add_subdirectory(windowsview) + add_subdirectory(windowswitchers) +diff --git a/windowsview/CMakeLists.txt b/windowsview/CMakeLists.txt +index ae83e94..80342cd 100644 +--- a/windowsview/CMakeLists.txt ++++ b/windowsview/CMakeLists.txt +@@ -1,19 +1,70 @@ +-cmake_minimum_required(VERSION 3.16) ++cmake_minimum_required(VERSION 3.5) + +-find_package(QT NAMES Qt6 Qt5 COMPONENTS LinguistTools REQUIRED) +-find_package(Qt${QT_VERSION_MAJOR} COMPONENTS LinguistTools REQUIRED) ++set(CMAKE_INCLUDE_CURRENT_DIR ON) ++set(CMAKE_AUTOMOC ON) ++set(CMAKE_AUTOUIC ON) ++set(CMAKE_AUTORCC ON) ++ ++set(CMAKE_CXX_STANDARD 14) ++set(CMAKE_CXX_STANDARD_REQUIRED ON) ++ ++set(KF5_DEP_VERSION "5.54.0") ++ ++find_package(ECM 5.54.0 NO_MODULE) ++set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake) ++ ++find_package(X11 MODULE) ++find_package(XCB MODULE COMPONENTS XCB COMPOSITE DAMAGE SHAPE XFIXES RENDER) ++message("XCB:"${X11_FOUND}, ${XCB_XCB_FOUND}, ${XCB_COMPOSITE_FOUND}, ${XCB_DAMAGE_FOUND}) ++if(X11_FOUND AND XCB_XCB_FOUND) ++ set(HAVE_X11 1) ++endif() ++if(HAVE_X11 AND XCB_COMPOSITE_FOUND AND XCB_DAMAGE_FOUND) ++ set(HAVE_XCB_COMPOSITE 1) ++endif() ++ ++find_package(OpenGL) ++ ++find_package(EGL MODULE) ++message("EGL:"${EGL_FOUND}) ++if (${EGL_FOUND}) ++ set(HAVE_EGL 1) ++endif() + +-file(GLOB TS_FILES translations/*.ts) +-set_source_files_properties(${TS_FILES} PROPERTIES OUTPUT_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/translations) +-qt5_create_translation(QM_FILES ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/ukui-window-switch-wlcom ${CMAKE_CURRENT_SOURCE_DIR}/ukui-window-switch-kwineffect ${CMAKE_CURRENT_SOURCE_DIR}/qml ${TS_FILES} OPTIONS -no-obsolete -no-ui-lines) ++message("OPENGL:"${OPENGL_FOUND},${Qt5Gui_OPENGL_IMPLEMENTATION}) ++if(OPENGL_FOUND AND (${Qt5Gui_OPENGL_IMPLEMENTATION} STREQUAL "GL")) ++ set(HAVE_GLX ${HAVE_X11}) ++else() ++ set(HAVE_GLX 0) ++endif() + +-add_custom_target(generate_qm ALL DEPENDS ${QM_FILES}) ++message("MACRO:"${HAVE_X11},${HAVE_XCB_COMPOSITE},${HAVE_EGL},${HAVE_GLX}) + +-set(TRANSLATION_DIR "/usr/share/ukui-window-switch/translations/") +-add_compile_definitions(TRANSLATION_DIR="${TRANSLATION_DIR}") ++configure_file(${CMAKE_CURRENT_SOURCE_DIR}/globalconfig.h.in ${CMAKE_CURRENT_SOURCE_DIR}/globalconfig.h) + ++find_package(Qt5Quick REQUIRED) ++find_package(Qt5QuickWidgets REQUIRED) ++find_package(KF5Config REQUIRED) ++find_package(KF5GlobalAccel REQUIRED) ++find_package(KF5I18n REQUIRED) ++find_package(PkgConfig REQUIRED) ++find_package(Qt5LinguistTools REQUIRED) ++find_package(Qt5 REQUIRED NO_MODULE COMPONENTS X11Extras Concurrent) ++ ++pkg_check_modules(KDK REQUIRED kysdk-sysinfo) ++pkg_check_modules(DATACOLLECT REQUIRED kysdk-datacollect) ++ ++include_directories(${KDK_INCLUDE_DIRS}) ++include_directories(${DATACOLLECT_INCLUDE_DIRS}) ++ ++# 注意要链接到kwin,如果本地安装了kwin的依赖,记得注意区分 ++include_directories(/usr/include/) ++ ++ ++# translation ++find_package(QT NAMES Qt6 Qt5 COMPONENTS LinguistTools REQUIRED) ++find_package(Qt${QT_VERSION_MAJOR} COMPONENTS LinguistTools REQUIRED) + add_subdirectory(ukui-window-switch-kwineffect) + add_subdirectory(ukui-window-switch-wlcom) + install(FILES ukui-window-switch DESTINATION /usr/bin/) + install(FILES ukui-window-switch.desktop DESTINATION /etc/xdg/autostart/) +-install(FILES ${QM_FILES} DESTINATION ${TRANSLATION_DIR}) +diff --git a/windowsview/data.qrc b/windowsview/data.qrc +index 9cb6b9e..a0a1fa6 100644 +--- a/windowsview/data.qrc ++++ b/windowsview/data.qrc +@@ -17,6 +17,16 @@ + <file>qml/TabletViewMain.qml</file> + <file>qml/TabletViewCloseButton.qml</file> + <file>qml/CloseButton.qml</file> ++ <file>ukui-window-switch_zh_CN.qm</file> ++ <file>ukui-window-switch_bo_CN.qm</file> ++ <file>ukui-window-switch_de.qm</file> ++ <file>ukui-window-switch_es.qm</file> ++ <file>ukui-window-switch_fr.qm</file> ++ <file>ukui-window-switch_kk.qm</file> ++ <file>ukui-window-switch_ky.qm</file> ++ <file>ukui-window-switch_mn.qm</file> ++ <file>ukui-window-switch_ug.qm</file> ++ <file>ukui-window-switch_zh_Hant.qm</file> + <file>qml/ArrowButton.qml</file> + <file>images/icon-arrow-white.svg</file> + <file>images/icon-arrow-black.svg</file> +diff --git a/windowsview/multitaskviewmodel.h b/windowsview/multitaskviewmodel.h +index 8cc7a01..24bb5db 100644 +--- a/windowsview/multitaskviewmodel.h ++++ b/windowsview/multitaskviewmodel.h +@@ -26,13 +26,10 @@ + #include <QRect> + #include <QVariantList> + #include <QString> ++#include <kwineffects.h> + #include "multitaskviewmodelhandler.h" + +-#ifdef KWINEFFECT +-#include <kwineffects.h> + using namespace KWin; +-#endif +- + class QGSettings; + + class Window +diff --git a/windowsview/translations/ukui-window-switch_ar.ts b/windowsview/translations/ukui-window-switch_ar.ts +deleted file mode 100644 +index ac74db9..0000000 +--- a/windowsview/translations/ukui-window-switch_ar.ts ++++ /dev/null +@@ -1,33 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="ar" sourcelanguage="en_US"> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="../qml/NewDesktopButton.qml" line="105"/> +- <source>New Desktop</source> +- <translation>سطح مكتب جديد</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="../qml/TabletViewMain.qml" line="176"/> +- <source>No recent tasks</source> +- <translation>لا توجد مهام حديثة</translation> +- </message> +- <message> +- <location filename="../qml/TabletViewMain.qml" line="353"/> +- <source>Clear</source> +- <translation>واضح</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> +- <source>Desktop</source> +- <translation>سطح المكتب</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/translations/ukui-window-switch_bo_CN.ts b/windowsview/translations/ukui-window-switch_bo_CN.ts +deleted file mode 100644 +index 7c2f960..0000000 +--- a/windowsview/translations/ukui-window-switch_bo_CN.ts ++++ /dev/null +@@ -1,33 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="bo_CN" sourcelanguage="en_US"> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="../qml/NewDesktopButton.qml" line="105"/> +- <source>New Desktop</source> +- <translation type="unfinished">གསར་དུ་བཙུགས་པའི་ལས་དོན་ཁུལ།</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="../qml/TabletViewMain.qml" line="176"/> +- <source>No recent tasks</source> +- <translation type="unfinished">ཉེ་ལམ་གྱི་ལས་འགན་གང་ཡང་མེད།</translation> +- </message> +- <message> +- <location filename="../qml/TabletViewMain.qml" line="353"/> +- <source>Clear</source> +- <translation type="unfinished">གསལ་པོར་བཤད་ན།</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> +- <source>Desktop</source> +- <translation type="unfinished">ལས་སྒྲུབ་ཁུལ།</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/translations/ukui-window-switch_de.ts b/windowsview/translations/ukui-window-switch_de.ts +deleted file mode 100644 +index faae1ba..0000000 +--- a/windowsview/translations/ukui-window-switch_de.ts ++++ /dev/null +@@ -1,33 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="de" sourcelanguage="en_US"> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="../qml/NewDesktopButton.qml" line="105"/> +- <source>New Desktop</source> +- <translation type="unfinished">Neuer Desktop</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="../qml/TabletViewMain.qml" line="176"/> +- <source>No recent tasks</source> +- <translation type="unfinished">Keine aktuellen Aufgaben</translation> +- </message> +- <message> +- <location filename="../qml/TabletViewMain.qml" line="353"/> +- <source>Clear</source> +- <translation type="unfinished">Klar</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> +- <source>Desktop</source> +- <translation type="unfinished">Desktop</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/translations/ukui-window-switch_es.ts b/windowsview/translations/ukui-window-switch_es.ts +deleted file mode 100644 +index 12910e8..0000000 +--- a/windowsview/translations/ukui-window-switch_es.ts ++++ /dev/null +@@ -1,33 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="es" sourcelanguage="en_US"> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="../qml/NewDesktopButton.qml" line="105"/> +- <source>New Desktop</source> +- <translation type="unfinished">Nuevo escritorio</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="../qml/TabletViewMain.qml" line="176"/> +- <source>No recent tasks</source> +- <translation type="unfinished">No hay tareas recientes</translation> +- </message> +- <message> +- <location filename="../qml/TabletViewMain.qml" line="353"/> +- <source>Clear</source> +- <translation type="unfinished">Claro</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> +- <source>Desktop</source> +- <translation type="unfinished">Escritorio</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/translations/ukui-window-switch_fr.ts b/windowsview/translations/ukui-window-switch_fr.ts +deleted file mode 100644 +index a45c5f6..0000000 +--- a/windowsview/translations/ukui-window-switch_fr.ts ++++ /dev/null +@@ -1,33 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="fr" sourcelanguage="en_US"> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="../qml/NewDesktopButton.qml" line="105"/> +- <source>New Desktop</source> +- <translation type="unfinished">Nouveau bureau</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="../qml/TabletViewMain.qml" line="176"/> +- <source>No recent tasks</source> +- <translation type="unfinished">Pas de tâches récentes</translation> +- </message> +- <message> +- <location filename="../qml/TabletViewMain.qml" line="353"/> +- <source>Clear</source> +- <translation type="unfinished">Clair</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> +- <source>Desktop</source> +- <translation type="unfinished">Bureau</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/translations/ukui-window-switch_kk.ts b/windowsview/translations/ukui-window-switch_kk.ts +deleted file mode 100644 +index 36a1339..0000000 +--- a/windowsview/translations/ukui-window-switch_kk.ts ++++ /dev/null +@@ -1,33 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="kk" sourcelanguage="en_US"> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="../qml/NewDesktopButton.qml" line="105"/> +- <source>New Desktop</source> +- <translation type="unfinished">Жаңа үстел</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="../qml/TabletViewMain.qml" line="176"/> +- <source>No recent tasks</source> +- <translation type="unfinished">Соңғы тапсырмалар жоқ</translation> +- </message> +- <message> +- <location filename="../qml/TabletViewMain.qml" line="353"/> +- <source>Clear</source> +- <translation type="unfinished">Тазалау</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> +- <source>Desktop</source> +- <translation type="unfinished">Жұмыс үстелі</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/translations/ukui-window-switch_ky.ts b/windowsview/translations/ukui-window-switch_ky.ts +deleted file mode 100644 +index 49dbde9..0000000 +--- a/windowsview/translations/ukui-window-switch_ky.ts ++++ /dev/null +@@ -1,33 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="ky" sourcelanguage="en_US"> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="../qml/NewDesktopButton.qml" line="105"/> +- <source>New Desktop</source> +- <translation type="unfinished">Жаңы иш столу</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="../qml/TabletViewMain.qml" line="176"/> +- <source>No recent tasks</source> +- <translation type="unfinished">Акыркы милдеттер жок</translation> +- </message> +- <message> +- <location filename="../qml/TabletViewMain.qml" line="353"/> +- <source>Clear</source> +- <translation type="unfinished">Тазалоо</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> +- <source>Desktop</source> +- <translation type="unfinished">Иш столу</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/translations/ukui-window-switch_mn.ts b/windowsview/translations/ukui-window-switch_mn.ts +deleted file mode 100644 +index c288363..0000000 +--- a/windowsview/translations/ukui-window-switch_mn.ts ++++ /dev/null +@@ -1,33 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="mn" sourcelanguage="en_US"> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="../qml/NewDesktopButton.qml" line="105"/> +- <source>New Desktop</source> +- <translation type="unfinished">ᠱᠢᠨᠡᠪᠡᠷ ᠪᠠᠢᠭᠤᠯᠤᠭ᠍ᠰᠠᠨ ᠠᠵᠢᠯᠯᠠᠬᠤ ᠤᠷᠤᠨ</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="../qml/TabletViewMain.qml" line="176"/> +- <source>No recent tasks</source> +- <translation type="unfinished">ᠨᠡᠬᠡᠬᠡᠬᠦ᠌ ᠬᠡᠷᠡᠭᠯᠡᠭᠡ ᠪᠠᠢᠬᠤ ᠦᠬᠡᠢ</translation> +- </message> +- <message> +- <location filename="../qml/TabletViewMain.qml" line="353"/> +- <source>Clear</source> +- <translation type="unfinished">ᠠᠷᠢᠯᠭᠠᠬᠤ</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> +- <source>Desktop</source> +- <translation type="unfinished">ᠠᠵᠢᠯᠯᠠᠬᠤ ᠤᠷᠤᠨ</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/translations/ukui-window-switch_ug.ts b/windowsview/translations/ukui-window-switch_ug.ts +deleted file mode 100644 +index 06db3df..0000000 +--- a/windowsview/translations/ukui-window-switch_ug.ts ++++ /dev/null +@@ -1,33 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="ug" sourcelanguage="en_US"> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="../qml/NewDesktopButton.qml" line="105"/> +- <source>New Desktop</source> +- <translation>يېڭى ئۈستەلئۈستى</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="../qml/TabletViewMain.qml" line="176"/> +- <source>No recent tasks</source> +- <translation>يېقىنقى ۋەزىپىلەر يوق</translation> +- </message> +- <message> +- <location filename="../qml/TabletViewMain.qml" line="353"/> +- <source>Clear</source> +- <translation>تازىلاش</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> +- <source>Desktop</source> +- <translation>ئۈستەل يۈزى</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/translations/ukui-window-switch_vi.ts b/windowsview/translations/ukui-window-switch_vi.ts +deleted file mode 100644 +index 5650eb2..0000000 +--- a/windowsview/translations/ukui-window-switch_vi.ts ++++ /dev/null +@@ -1,33 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="vi" sourcelanguage="en_US"> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="../qml/NewDesktopButton.qml" line="105"/> +- <source>New Desktop</source> +- <translation>Máy tính để bàn mới</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="../qml/TabletViewMain.qml" line="176"/> +- <source>No recent tasks</source> +- <translation>Không có nhiệm vụ gần đây</translation> +- </message> +- <message> +- <location filename="../qml/TabletViewMain.qml" line="353"/> +- <source>Clear</source> +- <translation>Trong</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> +- <source>Desktop</source> +- <translation>Bàn làm việc</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/translations/ukui-window-switch_zh_CN.ts b/windowsview/translations/ukui-window-switch_zh_CN.ts +deleted file mode 100644 +index 68a5278..0000000 +--- a/windowsview/translations/ukui-window-switch_zh_CN.ts ++++ /dev/null +@@ -1,33 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="zh_CN" sourcelanguage="en_US"> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="../qml/NewDesktopButton.qml" line="105"/> +- <source>New Desktop</source> +- <translation type="unfinished">新建工作区</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="../qml/TabletViewMain.qml" line="176"/> +- <source>No recent tasks</source> +- <translation type="unfinished">无应用开启</translation> +- </message> +- <message> +- <location filename="../qml/TabletViewMain.qml" line="353"/> +- <source>Clear</source> +- <translation type="unfinished">清除</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> +- <source>Desktop</source> +- <translation type="unfinished">工作区</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/translations/ukui-window-switch_zh_Hant.ts b/windowsview/translations/ukui-window-switch_zh_Hant.ts +deleted file mode 100644 +index cf3b024..0000000 +--- a/windowsview/translations/ukui-window-switch_zh_Hant.ts ++++ /dev/null +@@ -1,33 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="zh_Hant" sourcelanguage="en_US"> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="../qml/NewDesktopButton.qml" line="105"/> +- <source>New Desktop</source> +- <translation type="unfinished">新桌面</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="../qml/TabletViewMain.qml" line="176"/> +- <source>No recent tasks</source> +- <translation type="unfinished">無應用開啟</translation> +- </message> +- <message> +- <location filename="../qml/TabletViewMain.qml" line="353"/> +- <source>Clear</source> +- <translation type="unfinished">清除</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> +- <source>Desktop</source> +- <translation type="unfinished">桌面</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/ukui-window-switch b/windowsview/ukui-window-switch +index 153c407..ee703c1 100755 +--- a/windowsview/ukui-window-switch ++++ b/windowsview/ukui-window-switch +@@ -13,4 +13,4 @@ else + if [ $process_count -gt 0 ]; then + /usr/bin/ukui-window-switch-wlcom + fi +-fi +\ No newline at end of file ++fi +diff --git a/windowsview/ukui-window-switch-kwineffect/CMakeLists.txt b/windowsview/ukui-window-switch-kwineffect/CMakeLists.txt +index 9836fdc..b572c2e 100644 +--- a/windowsview/ukui-window-switch-kwineffect/CMakeLists.txt ++++ b/windowsview/ukui-window-switch-kwineffect/CMakeLists.txt +@@ -1,4 +1,4 @@ +-cmake_minimum_required(VERSION 3.16) ++cmake_minimum_required(VERSION 3.5) + + # 调试多任务视图需要取消注释下面 + # add_definitions("-Wall -g") +@@ -6,6 +6,7 @@ set(PLUGIN_NAME "windowsview") + + set(CMAKE_INCLUDE_CURRENT_DIR ON) + set(CMAKE_AUTOMOC ON) ++set(CMAKE_AUTOUIC ON) + set(CMAKE_AUTORCC ON) + + set(CMAKE_CXX_STANDARD 14) +@@ -16,14 +17,43 @@ set(KF5_DEP_VERSION "5.54.0") + find_package(ECM 5.54.0 NO_MODULE) + set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake) + ++find_package(X11 MODULE) ++find_package(XCB MODULE COMPONENTS XCB COMPOSITE DAMAGE SHAPE XFIXES RENDER) ++message("XCB:"${X11_FOUND}, ${XCB_XCB_FOUND}, ${XCB_COMPOSITE_FOUND}, ${XCB_DAMAGE_FOUND}) ++if(X11_FOUND AND XCB_XCB_FOUND) ++ set(HAVE_X11 1) ++endif() ++if(HAVE_X11 AND XCB_COMPOSITE_FOUND AND XCB_DAMAGE_FOUND) ++ set(HAVE_XCB_COMPOSITE 1) ++endif() ++ + find_package(OpenGL) ++ + find_package(EGL MODULE) ++message("EGL:"${EGL_FOUND}) ++if (${EGL_FOUND}) ++ set(HAVE_EGL 1) ++endif() ++ ++message("OPENGL:"${OPENGL_FOUND},${Qt5Gui_OPENGL_IMPLEMENTATION}) ++if(OPENGL_FOUND AND (${Qt5Gui_OPENGL_IMPLEMENTATION} STREQUAL "GL")) ++ set(HAVE_GLX ${HAVE_X11}) ++else() ++ set(HAVE_GLX 0) ++endif() ++ ++message("MACRO:"${HAVE_X11},${HAVE_XCB_COMPOSITE},${HAVE_EGL},${HAVE_GLX}) ++ ++configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../globalconfig.h.in ${CMAKE_CURRENT_SOURCE_DIR}/../globalconfig.h) ++ ++find_package(Qt5Quick REQUIRED) ++find_package(Qt5QuickWidgets REQUIRED) + find_package(KF5Config REQUIRED) + find_package(KF5GlobalAccel REQUIRED) + find_package(KF5I18n REQUIRED) + find_package(PkgConfig REQUIRED) + find_package(Qt5LinguistTools REQUIRED) +-find_package(Qt5 REQUIRED NO_MODULE COMPONENTS X11Extras Concurrent Quick DBus) ++find_package(Qt5 REQUIRED NO_MODULE COMPONENTS X11Extras Concurrent) + + pkg_check_modules(KDK REQUIRED kysdk-sysinfo) + pkg_check_modules(DATACOLLECT REQUIRED kysdk-datacollect) +@@ -31,6 +61,9 @@ pkg_check_modules(DATACOLLECT REQUIRED kysdk-datacollect) + include_directories(${KDK_INCLUDE_DIRS}) + include_directories(${DATACOLLECT_INCLUDE_DIRS}) + ++# 注意要链接到kwin,如果本地安装了kwin的依赖,记得注意区分 ++include_directories(/usr/include/) ++ + add_definitions(-DKWINEFFECT=1) + + set(SRCS ../desktopbackground.cpp +@@ -43,29 +76,60 @@ set(SRCS ../desktopbackground.cpp + multitaskviewmodelbycompositehandler.cpp + ) + ++# translation ++find_package(QT NAMES Qt6 Qt5 COMPONENTS LinguistTools REQUIRED) ++find_package(Qt${QT_VERSION_MAJOR} COMPONENTS LinguistTools REQUIRED) ++ ++set(TS_FILES) ++set(QM_FILES) ++ ++file(GLOB QML_FILES "../qml/*.qml") ++ ++list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_zh_CN.ts) ++list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_bo_CN.ts) ++list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_zh_Hant.ts) ++list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_ug.ts) ++list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_mn.ts) ++list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_ky.ts) ++list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_kk.ts) ++list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_fr.ts) ++list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_es.ts) ++list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_de.ts) ++ ++set_source_files_properties(${TS_FILES} ++ PROPERTIES OUTPUT_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/../) ++ ++qt5_create_translation(QM_FILES ${TS_FILES} ${QML_FILES}) ++ ++add_custom_target(lupdate_task DEPENDS ${TS_FILES}) ++ ++add_custom_target(lrelease_task DEPENDS ${QM_FILES}) ++ + qt5_add_resources(SRCS ../data.qrc) + add_library( + ${PLUGIN_NAME} MODULE + ${SRCS} ++ ${QM_FILES} + ) + + target_link_libraries( +- ${PLUGIN_NAME} +- PUBLIC +- Qt5::Core +- Qt5::Gui +- Qt5::Quick +- PRIVATE +- KF5::ConfigCore +- KF5::WindowSystem +- KF5::CoreAddons +- KF5::GlobalAccel +- Qt5::X11Extras +- Qt5::Concurrent +- Qt5::DBus +- ${QGSettings_LIBRARIES} +- ${KDK_LINK_LIBRARIES} +- ${DATACOLLECT_LINK_LIBRARIES} ++ ${PLUGIN_NAME} ++ PUBLIC ++ Qt5::Core ++ Qt5::Gui ++ Qt5::Widgets ++ Qt5::Quick ++ Qt5::QuickWidgets ++ PRIVATE ++ KF5::ConfigCore ++ KF5::WindowSystem ++ KF5::CoreAddons ++ KF5::GlobalAccel ++ Qt5::X11Extras ++ Qt5::Concurrent ++ ${QGSettings_LIBRARIES} ++ ${KDK_LINK_LIBRARIES} ++ ${DATACOLLECT_LINK_LIBRARIES} + ) +-set(INSTALL_PATH ${QT_INSTALL_PLUGINS}/kwin/effects/plugins/) +-install(TARGETS ${PLUGIN_NAME} DESTINATION ${INSTALL_PATH}) +\ No newline at end of file ++ ++install(TARGETS ${PLUGIN_NAME} DESTINATION ${INSTALL_PATH}) +diff --git a/windowsview/ukui-window-switch-kwineffect/multitaskviewmanager.cpp b/windowsview/ukui-window-switch-kwineffect/multitaskviewmanager.cpp +index 9c7a185..05810dd 100644 +--- a/windowsview/ukui-window-switch-kwineffect/multitaskviewmanager.cpp ++++ b/windowsview/ukui-window-switch-kwineffect/multitaskviewmanager.cpp +@@ -275,7 +275,7 @@ void MultitaskViewManager::installTranslator() + { + m_translator = new QTranslator(qApp); + m_translator->load(QLocale::system(), QLatin1String("ukui-window-switch"), +- QLatin1String("_"), TRANSLATION_DIR); ++ QLatin1String("_"), QLatin1String(":/")); + QApplication::installTranslator(m_translator); + } + +diff --git a/windowsview/ukui-window-switch-wlcom/CMakeLists.txt b/windowsview/ukui-window-switch-wlcom/CMakeLists.txt +index ea7dbfb..3128c93 100644 +--- a/windowsview/ukui-window-switch-wlcom/CMakeLists.txt ++++ b/windowsview/ukui-window-switch-wlcom/CMakeLists.txt +@@ -1,4 +1,4 @@ +-cmake_minimum_required(VERSION 3.16) ++cmake_minimum_required(VERSION 3.5) + + # 调试多任务视图需要取消注释下面 + add_definitions("-Wall -g") +@@ -7,6 +7,7 @@ project(ukui-window-switch-wlcom) + + set(CMAKE_INCLUDE_CURRENT_DIR ON) + set(CMAKE_AUTOMOC ON) ++set(CMAKE_AUTOUIC ON) + set(CMAKE_AUTORCC ON) + + set(CMAKE_CXX_STANDARD 14) +@@ -14,23 +15,55 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) + + set(KF5_DEP_VERSION "5.54.0") + ++find_package(ECM 5.54.0 NO_MODULE) ++set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake) ++ ++find_package(X11 MODULE) ++find_package(XCB MODULE COMPONENTS XCB COMPOSITE DAMAGE SHAPE XFIXES RENDER) ++message("XCB:"${X11_FOUND}, ${XCB_XCB_FOUND}, ${XCB_COMPOSITE_FOUND}, ${XCB_DAMAGE_FOUND}) ++if(X11_FOUND AND XCB_XCB_FOUND) ++ set(HAVE_X11 1) ++endif() ++if(HAVE_X11 AND XCB_COMPOSITE_FOUND AND XCB_DAMAGE_FOUND) ++ set(HAVE_XCB_COMPOSITE 1) ++endif() ++ ++find_package(OpenGL) ++ ++find_package(EGL MODULE) ++message("EGL:"${EGL_FOUND}) ++if (${EGL_FOUND}) ++ set(HAVE_EGL 1) ++endif() ++ ++message("OPENGL:"${OPENGL_FOUND},${Qt5Gui_OPENGL_IMPLEMENTATION}) ++if(OPENGL_FOUND AND (${Qt5Gui_OPENGL_IMPLEMENTATION} STREQUAL "GL")) ++ set(HAVE_GLX ${HAVE_X11}) ++else() ++ set(HAVE_GLX 0) ++endif() ++ ++message("MACRO:"${HAVE_X11},${HAVE_XCB_COMPOSITE},${HAVE_EGL},${HAVE_GLX}) ++ ++configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../globalconfig.h.in ${CMAKE_CURRENT_SOURCE_DIR}/../globalconfig.h) ++ ++find_package(Qt5Quick REQUIRED) ++find_package(Qt5QuickWidgets REQUIRED) + find_package(KF5Config REQUIRED) + find_package(KF5GlobalAccel REQUIRED) +-find_package(KF5WindowSystem) + find_package(KF5I18n REQUIRED) + find_package(PkgConfig REQUIRED) +-find_package(Qt5 REQUIRED NO_MODULE COMPONENTS Concurrent Quick LinguistTools DBus) ++find_package(Qt5LinguistTools REQUIRED) ++find_package(Qt5 REQUIRED NO_MODULE COMPONENTS X11Extras Concurrent) + + pkg_check_modules(KDK REQUIRED kysdk-sysinfo) + pkg_check_modules(DATACOLLECT REQUIRED kysdk-datacollect) + pkg_check_modules(KYSDKWAYLANDHELPER_PKG kysdk-waylandhelper) +-pkg_check_modules(GL REQUIRED gl) + + include_directories(${KDK_INCLUDE_DIRS}) + include_directories(${DATACOLLECT_INCLUDE_DIRS}) + include_directories(${WAYLANDHELPER_INCLUDE_DIRS}) + include_directories(${OPENGL_INCLUDE_DIR}) +-include_directories(${GL}) + + set(WLCSRCS main.cpp + log-utils.h log-utils.cpp +@@ -49,6 +82,35 @@ set(WLCSRCS main.cpp + ThumbnailItem.cpp + ) + ++# translation ++find_package(QT NAMES Qt6 Qt5 COMPONENTS LinguistTools REQUIRED) ++find_package(Qt${QT_VERSION_MAJOR} COMPONENTS LinguistTools REQUIRED) ++ ++set(TS_FILES) ++set(QM_FILES) ++ ++file(GLOB QML_FILES "../qml/*.qml") ++ ++list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_zh_CN.ts) ++list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_bo_CN.ts) ++list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_zh_Hant.ts) ++list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_ug.ts) ++list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_mn.ts) ++list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_ky.ts) ++list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_kk.ts) ++list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_fr.ts) ++list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_es.ts) ++list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_de.ts) ++ ++set_source_files_properties(${TS_FILES} ++ PROPERTIES OUTPUT_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/../) ++ ++qt5_create_translation(QM_FILES ${TS_FILES} ${QML_FILES}) ++ ++add_custom_target(wlupdate_task DEPENDS ${TS_FILES}) ++ ++add_custom_target(wlrelease_task DEPENDS ${QM_FILES}) ++ + add_subdirectory(qtsingleapplication) + include_directories(qtsingleapplication/src) + +@@ -56,34 +118,35 @@ qt5_add_resources(WLCSRCS ../data.qrc) + + add_executable(ukui-window-switch-wlcom + ${WLCSRCS} ++ ${QM_FILES} + ) + + target_include_directories(ukui-window-switch-wlcom PRIVATE ${KYSDKWAYLANDHELPER_PKG_INCLUDE_DIRS}) + target_link_directories(ukui-window-switch-wlcom PRIVATE ${KYSDKWAYLANDHELPER_PKG_LIBRARY_DIRS} KF5::WindowSystem) + +-target_compile_definitions(${PROJECT_NAME} PRIVATE $<$<CONFIG:Debug>:DISABLE_LOG_FILE>) +-target_compile_definitions(${PROJECT_NAME} PRIVATE $<$<CONFIG:Debug>:QT_QML_DEBUG>) +- + target_link_libraries( +- ukui-window-switch-wlcom +- PUBLIC +- Qt5::Core +- Qt5::GuiPrivate +- Qt5::Quick +- PRIVATE +- KF5::WindowSystem +- KF5::GlobalAccel +- Qt5::Concurrent +- Qt5::DBus +- qtsingleapplication +- kywc +- ${QGSettings_LIBRARIES} +- ${KYSDKWAYLANDHELPER_PKG_LIBRARIES} +- ${KDK_LINK_LIBRARIES} +- ${DATACOLLECT_LINK_LIBRARIES} +- ${OPENGL_gl_LIBRARY} +- ${EGL_LIBRARY} +- ${GL_LIBRARIES} ++ ukui-window-switch-wlcom ++ PUBLIC ++ Qt5::Core ++ Qt5::GuiPrivate ++ Qt5::Widgets ++ Qt5::Quick ++ Qt5::QuickWidgets ++ PRIVATE ++ KF5::ConfigCore ++ KF5::WindowSystem ++ KF5::CoreAddons ++ KF5::GlobalAccel ++ Qt5::X11Extras ++ Qt5::Concurrent ++ qtsingleapplication ++ kywc ++ ${QGSettings_LIBRARIES} ++ ${KYSDKWAYLANDHELPER_PKG_LIBRARIES} ++ ${KDK_LINK_LIBRARIES} ++ ${DATACOLLECT_LINK_LIBRARIES} ++ ${OPENGL_gl_LIBRARY} ++ ${EGL_LIBRARY} + ) + +-install(TARGETS ukui-window-switch-wlcom DESTINATION /usr/bin) ++install(TARGETS ukui-window-switch-wlcom ${INSTALL_TARGETS_DEFAULT_ARGS}) +diff --git a/windowsview/ukui-window-switch-wlcom/main.cpp b/windowsview/ukui-window-switch-wlcom/main.cpp +index 9950d0c..c962097 100644 +--- a/windowsview/ukui-window-switch-wlcom/main.cpp ++++ b/windowsview/ukui-window-switch-wlcom/main.cpp +@@ -28,7 +28,7 @@ + + int main(int argc, char *argv[]) + { +-#ifndef DISABLE_LOG_FILE ++#ifndef PANEL_DISABLE_LOG_FILE + LogUtils::initLogFile("ukui-window-switch-wlcom"); + qInstallMessageHandler(LogUtils::messageOutput); + #endif +@@ -39,18 +39,15 @@ int main(int argc, char *argv[]) + parser.process(a); + if (a.isRunning()) + { +- if (parser.isSet(showWorkSpaceOption)) { ++ if (parser.isSet("show-workspace")) { + a.sendMessage(QApplication::arguments().length() > 1 ? QApplication::arguments().at(1) : a.applicationFilePath()); + } + return EXIT_SUCCESS; + } + + MultitaskViewManagerByWlcom m; +- if (parser.isSet(showWorkSpaceOption)) { +- m.open(); +- } + QObject::connect(&a, &QtSingleApplication::messageReceived, [&m](){ + m.open(); + }); +- return QtSingleApplication::exec(); ++ return a.exec(); + } +diff --git a/windowsview/ukui-window-switch-wlcom/multitaskviewmanagerbywlcom.cpp b/windowsview/ukui-window-switch-wlcom/multitaskviewmanagerbywlcom.cpp +index 74e54df..d4420f1 100644 +--- a/windowsview/ukui-window-switch-wlcom/multitaskviewmanagerbywlcom.cpp ++++ b/windowsview/ukui-window-switch-wlcom/multitaskviewmanagerbywlcom.cpp +@@ -20,6 +20,7 @@ + + // kf5 + #include <KF5/KGlobalAccel/KGlobalAccel> ++#include <KF5/KWindowSystem/KWindowSystem> + #include <KF5/KWindowSystem/KWindowEffects> + + // kysdk +@@ -368,7 +369,7 @@ void MultitaskViewManagerByWlcom::installTranslator() + { + m_translator = new QTranslator(qApp); + m_translator->load(QLocale::system(), QLatin1String("ukui-window-switch"), +- QLatin1String("_"), TRANSLATION_DIR); ++ QLatin1String("_"), QLatin1String(":/")); + QApplication::installTranslator(m_translator); + } + +diff --git a/windowsview/ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.cpp b/windowsview/ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.cpp +index 8a698dd..95f354c 100644 +--- a/windowsview/ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.cpp ++++ b/windowsview/ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.cpp +@@ -28,8 +28,6 @@ + #include <QEventLoop> + #include <qpa/qplatformnativeinterface.h> + #include <iostream> +-#include <KWindowSystem> +- + #include "multitaskviewmanagerbywlcom.h" + using namespace std; + +diff --git a/windowsview/ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.h b/windowsview/ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.h +index 4762469..6f3417a 100644 +--- a/windowsview/ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.h ++++ b/windowsview/ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.h +@@ -26,6 +26,9 @@ + #include <QMap> + #include <QRect> + #include <QVariantList> ++#include <KWindowSystem/KWindowSystem> ++#include <KWindowSystem/KWindowInfo> ++#include <KWindowSystem/NETWM> + #include "context.h" + + class MultitaskViewModelByWlcomHandler : public MultitaskViewModelHandler +diff --git a/windowsview/ukui-window-switch_ar.ts b/windowsview/ukui-window-switch_ar.ts +new file mode 100644 +index 0000000..bf0b6c9 +--- /dev/null ++++ b/windowsview/ukui-window-switch_ar.ts +@@ -0,0 +1,62 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="ar" sourcelanguage="en_US"> ++<context> ++ <name>DesktopArea</name> ++ <message> ++ <source>Desktop</source> ++ <translatorcomment>工作区</translatorcomment> ++ <translation type="vanished">工作区</translation> ++ </message> ++ <message> ++ <source>New Desktop</source> ++ <translatorcomment>新建工作区</translatorcomment> ++ <translation type="vanished">新建工作区</translation> ++ </message> ++</context> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation>سطح مكتب جديد</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewClearAllWindowButton</name> ++ <message> ++ <source>Clear</source> ++ <translatorcomment>清除</translatorcomment> ++ <translation type="vanished">清除</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="174"/> ++ <source>No recent tasks</source> ++ <translation>لا توجد مهام حديثة</translation> ++ </message> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="357"/> ++ <source>Clear</source> ++ <translation>واضح</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewRootWindow</name> ++ <message> ++ <source>No recent tasks</source> ++ <translatorcomment>无应用开启</translatorcomment> ++ <translation type="vanished">无应用开启</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="qml/VirtualDesktopWindow.qml" line="187"/> ++ <source>Desktop</source> ++ <translation>سطح المكتب</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/ukui-window-switch_bo_CN.ts b/windowsview/ukui-window-switch_bo_CN.ts +new file mode 100644 +index 0000000..210d9a1 +--- /dev/null ++++ b/windowsview/ukui-window-switch_bo_CN.ts +@@ -0,0 +1,62 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="bo_CN" sourcelanguage="en_US"> ++<context> ++ <name>DesktopArea</name> ++ <message> ++ <source>Desktop</source> ++ <translatorcomment>工作区</translatorcomment> ++ <translation type="vanished">ལས་སྒྲུབ་ཁུལ།</translation> ++ </message> ++ <message> ++ <source>New Desktop</source> ++ <translatorcomment>新建工作区</translatorcomment> ++ <translation type="vanished">གསར་དུ་བཙུགས་པའི་ལས་དོན་ཁུལ།</translation> ++ </message> ++</context> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">གསར་དུ་བཙུགས་པའི་ལས་དོན་ཁུལ།</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewClearAllWindowButton</name> ++ <message> ++ <source>Clear</source> ++ <translatorcomment>清除</translatorcomment> ++ <translation type="vanished">གསལ་པོར་བཤད་ན།</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="174"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">ཉེ་ལམ་གྱི་ལས་འགན་གང་ཡང་མེད།</translation> ++ </message> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="357"/> ++ <source>Clear</source> ++ <translation type="unfinished">གསལ་པོར་བཤད་ན།</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewRootWindow</name> ++ <message> ++ <source>No recent tasks</source> ++ <translatorcomment>无应用开启</translatorcomment> ++ <translation type="vanished">ཉེ་ལམ་གྱི་ལས་འགན་གང་ཡང་མེད།</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="qml/VirtualDesktopWindow.qml" line="187"/> ++ <source>Desktop</source> ++ <translation type="unfinished">ལས་སྒྲུབ་ཁུལ།</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/ukui-window-switch_de.ts b/windowsview/ukui-window-switch_de.ts +new file mode 100644 +index 0000000..b79eefa +--- /dev/null ++++ b/windowsview/ukui-window-switch_de.ts +@@ -0,0 +1,62 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="de" sourcelanguage="en_US"> ++<context> ++ <name>DesktopArea</name> ++ <message> ++ <source>Desktop</source> ++ <translatorcomment>工作区</translatorcomment> ++ <translation type="vanished">Desktop</translation> ++ </message> ++ <message> ++ <source>New Desktop</source> ++ <translatorcomment>新建工作区</translatorcomment> ++ <translation type="vanished">Neuer Desktop</translation> ++ </message> ++</context> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">Neuer Desktop</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewClearAllWindowButton</name> ++ <message> ++ <source>Clear</source> ++ <translatorcomment>清除</translatorcomment> ++ <translation type="vanished">Klar</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="174"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">Keine aktuellen Aufgaben</translation> ++ </message> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="357"/> ++ <source>Clear</source> ++ <translation type="unfinished">Klar</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewRootWindow</name> ++ <message> ++ <source>No recent tasks</source> ++ <translatorcomment>无应用开启</translatorcomment> ++ <translation type="vanished">Keine aktuellen Aufgaben</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="qml/VirtualDesktopWindow.qml" line="187"/> ++ <source>Desktop</source> ++ <translation type="unfinished">Desktop</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/ukui-window-switch_es.ts b/windowsview/ukui-window-switch_es.ts +new file mode 100644 +index 0000000..f316292 +--- /dev/null ++++ b/windowsview/ukui-window-switch_es.ts +@@ -0,0 +1,62 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="es" sourcelanguage="en_US"> ++<context> ++ <name>DesktopArea</name> ++ <message> ++ <source>Desktop</source> ++ <translatorcomment>工作区</translatorcomment> ++ <translation type="vanished">Escritorio</translation> ++ </message> ++ <message> ++ <source>New Desktop</source> ++ <translatorcomment>新建工作区</translatorcomment> ++ <translation type="vanished">Nuevo escritorio</translation> ++ </message> ++</context> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">Nuevo escritorio</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewClearAllWindowButton</name> ++ <message> ++ <source>Clear</source> ++ <translatorcomment>清除</translatorcomment> ++ <translation type="vanished">Claro</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="174"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">No hay tareas recientes</translation> ++ </message> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="357"/> ++ <source>Clear</source> ++ <translation type="unfinished">Claro</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewRootWindow</name> ++ <message> ++ <source>No recent tasks</source> ++ <translatorcomment>无应用开启</translatorcomment> ++ <translation type="vanished">No hay tareas recientes</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="qml/VirtualDesktopWindow.qml" line="187"/> ++ <source>Desktop</source> ++ <translation type="unfinished">Escritorio</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/ukui-window-switch_fr.ts b/windowsview/ukui-window-switch_fr.ts +new file mode 100644 +index 0000000..bb4aac9 +--- /dev/null ++++ b/windowsview/ukui-window-switch_fr.ts +@@ -0,0 +1,62 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="fr" sourcelanguage="en_US"> ++<context> ++ <name>DesktopArea</name> ++ <message> ++ <source>Desktop</source> ++ <translatorcomment>工作区</translatorcomment> ++ <translation type="vanished">Bureau</translation> ++ </message> ++ <message> ++ <source>New Desktop</source> ++ <translatorcomment>新建工作区</translatorcomment> ++ <translation type="vanished">Nouveau bureau</translation> ++ </message> ++</context> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">Nouveau bureau</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewClearAllWindowButton</name> ++ <message> ++ <source>Clear</source> ++ <translatorcomment>清除</translatorcomment> ++ <translation type="vanished">Clair</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="174"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">Pas de tâches récentes</translation> ++ </message> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="357"/> ++ <source>Clear</source> ++ <translation type="unfinished">Clair</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewRootWindow</name> ++ <message> ++ <source>No recent tasks</source> ++ <translatorcomment>无应用开启</translatorcomment> ++ <translation type="vanished">Pas de tâches récentes</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="qml/VirtualDesktopWindow.qml" line="187"/> ++ <source>Desktop</source> ++ <translation type="unfinished">Bureau</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/ukui-window-switch_kk.ts b/windowsview/ukui-window-switch_kk.ts +new file mode 100644 +index 0000000..b70f893 +--- /dev/null ++++ b/windowsview/ukui-window-switch_kk.ts +@@ -0,0 +1,62 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="kk" sourcelanguage="en_US"> ++<context> ++ <name>DesktopArea</name> ++ <message> ++ <source>Desktop</source> ++ <translatorcomment>工作区</translatorcomment> ++ <translation type="vanished">Жұмыс үстелі</translation> ++ </message> ++ <message> ++ <source>New Desktop</source> ++ <translatorcomment>新建工作区</translatorcomment> ++ <translation type="vanished">Жаңа үстел</translation> ++ </message> ++</context> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation>جاڭا ئۈستەلئۈستى</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewClearAllWindowButton</name> ++ <message> ++ <source>Clear</source> ++ <translatorcomment>清除</translatorcomment> ++ <translation type="vanished">Тазалау</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="174"/> ++ <source>No recent tasks</source> ++ <translation>جاقىنعى مىندەتتەر جوق</translation> ++ </message> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="357"/> ++ <source>Clear</source> ++ <translation>تازالاۋ</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewRootWindow</name> ++ <message> ++ <source>No recent tasks</source> ++ <translatorcomment>无应用开启</translatorcomment> ++ <translation type="vanished">Соңғы тапсырмалар жоқ</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="qml/VirtualDesktopWindow.qml" line="187"/> ++ <source>Desktop</source> ++ <translation>ئۈستەلئۈستى</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/ukui-window-switch_ky.ts b/windowsview/ukui-window-switch_ky.ts +new file mode 100644 +index 0000000..77a2a21 +--- /dev/null ++++ b/windowsview/ukui-window-switch_ky.ts +@@ -0,0 +1,62 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="ky" sourcelanguage="en_US"> ++<context> ++ <name>DesktopArea</name> ++ <message> ++ <source>Desktop</source> ++ <translatorcomment>工作区</translatorcomment> ++ <translation type="vanished">Иш столу</translation> ++ </message> ++ <message> ++ <source>New Desktop</source> ++ <translatorcomment>新建工作区</translatorcomment> ++ <translation type="vanished">Жаңы иш столу</translation> ++ </message> ++</context> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation>جاڭى ئۈستەلئۈستى</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewClearAllWindowButton</name> ++ <message> ++ <source>Clear</source> ++ <translatorcomment>清除</translatorcomment> ++ <translation type="vanished">Тазалоо</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="174"/> ++ <source>No recent tasks</source> ++ <translation>جاقىندا مٸلدەتتەر جوق</translation> ++ </message> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="357"/> ++ <source>Clear</source> ++ <translation>تازالوو</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewRootWindow</name> ++ <message> ++ <source>No recent tasks</source> ++ <translatorcomment>无应用开启</translatorcomment> ++ <translation type="vanished">Акыркы милдеттер жок</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="qml/VirtualDesktopWindow.qml" line="187"/> ++ <source>Desktop</source> ++ <translation>ئۈستەلئۈستى</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/ukui-window-switch_mn.ts b/windowsview/ukui-window-switch_mn.ts +new file mode 100644 +index 0000000..179ef7d +--- /dev/null ++++ b/windowsview/ukui-window-switch_mn.ts +@@ -0,0 +1,62 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="mn" sourcelanguage="en_US"> ++<context> ++ <name>DesktopArea</name> ++ <message> ++ <source>Desktop</source> ++ <translatorcomment>工作区</translatorcomment> ++ <translation type="vanished">ᠠᠵᠢᠯᠯᠠᠬᠤ ᠤᠷᠤᠨ</translation> ++ </message> ++ <message> ++ <source>New Desktop</source> ++ <translatorcomment>新建工作区</translatorcomment> ++ <translation type="vanished">ᠱᠢᠨᠡᠪᠡᠷ ᠪᠠᠢᠭᠤᠯᠤᠭ᠍ᠰᠠᠨ ᠠᠵᠢᠯᠯᠠᠬᠤ ᠤᠷᠤᠨ</translation> ++ </message> ++</context> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">ᠱᠢᠨᠡᠪᠡᠷ ᠪᠠᠢᠭᠤᠯᠤᠭ᠍ᠰᠠᠨ ᠠᠵᠢᠯᠯᠠᠬᠤ ᠤᠷᠤᠨ</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewClearAllWindowButton</name> ++ <message> ++ <source>Clear</source> ++ <translatorcomment>清除</translatorcomment> ++ <translation type="vanished">ᠠᠷᠢᠯᠭᠠᠬᠤ</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="174"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">ᠨᠡᠬᠡᠬᠡᠬᠦ᠌ ᠬᠡᠷᠡᠭᠯᠡᠭᠡ ᠪᠠᠢᠬᠤ ᠦᠬᠡᠢ</translation> ++ </message> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="357"/> ++ <source>Clear</source> ++ <translation type="unfinished">ᠠᠷᠢᠯᠭᠠᠬᠤ</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewRootWindow</name> ++ <message> ++ <source>No recent tasks</source> ++ <translatorcomment>无应用开启</translatorcomment> ++ <translation type="vanished">ᠨᠡᠬᠡᠬᠡᠬᠦ᠌ ᠬᠡᠷᠡᠭᠯᠡᠭᠡ ᠪᠠᠢᠬᠤ ᠦᠬᠡᠢ</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="qml/VirtualDesktopWindow.qml" line="187"/> ++ <source>Desktop</source> ++ <translation type="unfinished">ᠠᠵᠢᠯᠯᠠᠬᠤ ᠤᠷᠤᠨ</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/ukui-window-switch_ug.ts b/windowsview/ukui-window-switch_ug.ts +new file mode 100644 +index 0000000..f9d529f +--- /dev/null ++++ b/windowsview/ukui-window-switch_ug.ts +@@ -0,0 +1,62 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="ug" sourcelanguage="en_US"> ++<context> ++ <name>DesktopArea</name> ++ <message> ++ <source>Desktop</source> ++ <translatorcomment>工作区</translatorcomment> ++ <translation type="vanished">ئۈستەلئۈستى</translation> ++ </message> ++ <message> ++ <source>New Desktop</source> ++ <translatorcomment>新建工作区</translatorcomment> ++ <translation type="vanished">يېڭى ئۈستەلئۈستى</translation> ++ </message> ++</context> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation>يېڭى ئۈستەلئۈستى</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewClearAllWindowButton</name> ++ <message> ++ <source>Clear</source> ++ <translatorcomment>清除</translatorcomment> ++ <translation type="vanished">تازىلاش</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="174"/> ++ <source>No recent tasks</source> ++ <translation>يېقىنقى ۋەزىپىلەر يوق</translation> ++ </message> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="357"/> ++ <source>Clear</source> ++ <translation>تازىلاش</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewRootWindow</name> ++ <message> ++ <source>No recent tasks</source> ++ <translatorcomment>无应用开启</translatorcomment> ++ <translation type="vanished">يېقىنقى ۋەزىپىلەر يوق</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="qml/VirtualDesktopWindow.qml" line="187"/> ++ <source>Desktop</source> ++ <translation>ئۈستەل يۈزى</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/ukui-window-switch_vi.ts b/windowsview/ukui-window-switch_vi.ts +new file mode 100644 +index 0000000..d673d4a +--- /dev/null ++++ b/windowsview/ukui-window-switch_vi.ts +@@ -0,0 +1,62 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="vi" sourcelanguage="en_US"> ++<context> ++ <name>DesktopArea</name> ++ <message> ++ <source>Desktop</source> ++ <translatorcomment>工作区</translatorcomment> ++ <translation type="vanished">工作区</translation> ++ </message> ++ <message> ++ <source>New Desktop</source> ++ <translatorcomment>新建工作区</translatorcomment> ++ <translation type="vanished">新建工作区</translation> ++ </message> ++</context> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation>Máy tính để bàn mới</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewClearAllWindowButton</name> ++ <message> ++ <source>Clear</source> ++ <translatorcomment>清除</translatorcomment> ++ <translation type="vanished">清除</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="174"/> ++ <source>No recent tasks</source> ++ <translation>Không có nhiệm vụ gần đây</translation> ++ </message> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="357"/> ++ <source>Clear</source> ++ <translation>Trong</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewRootWindow</name> ++ <message> ++ <source>No recent tasks</source> ++ <translatorcomment>无应用开启</translatorcomment> ++ <translation type="vanished">无应用开启</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="qml/VirtualDesktopWindow.qml" line="187"/> ++ <source>Desktop</source> ++ <translation>Bàn làm việc</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/ukui-window-switch_zh_CN.ts b/windowsview/ukui-window-switch_zh_CN.ts +new file mode 100644 +index 0000000..397f1fe +--- /dev/null ++++ b/windowsview/ukui-window-switch_zh_CN.ts +@@ -0,0 +1,62 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="zh_CN" sourcelanguage="en_US"> ++<context> ++ <name>DesktopArea</name> ++ <message> ++ <source>Desktop</source> ++ <translatorcomment>工作区</translatorcomment> ++ <translation type="vanished">工作区</translation> ++ </message> ++ <message> ++ <source>New Desktop</source> ++ <translatorcomment>新建工作区</translatorcomment> ++ <translation type="vanished">新建工作区</translation> ++ </message> ++</context> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">新建工作区</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewClearAllWindowButton</name> ++ <message> ++ <source>Clear</source> ++ <translatorcomment>清除</translatorcomment> ++ <translation type="vanished">清除</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="174"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">无应用开启</translation> ++ </message> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="357"/> ++ <source>Clear</source> ++ <translation type="unfinished">清除</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewRootWindow</name> ++ <message> ++ <source>No recent tasks</source> ++ <translatorcomment>无应用开启</translatorcomment> ++ <translation type="vanished">无应用开启</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="qml/VirtualDesktopWindow.qml" line="187"/> ++ <source>Desktop</source> ++ <translation type="unfinished">工作区</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/ukui-window-switch_zh_Hant.ts b/windowsview/ukui-window-switch_zh_Hant.ts +new file mode 100644 +index 0000000..35f0bda +--- /dev/null ++++ b/windowsview/ukui-window-switch_zh_Hant.ts +@@ -0,0 +1,62 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="zh_Hant" sourcelanguage="en_US"> ++<context> ++ <name>DesktopArea</name> ++ <message> ++ <source>Desktop</source> ++ <translatorcomment>工作区</translatorcomment> ++ <translation type="vanished">桌面</translation> ++ </message> ++ <message> ++ <source>New Desktop</source> ++ <translatorcomment>新建工作区</translatorcomment> ++ <translation type="vanished">新桌面</translation> ++ </message> ++</context> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">新桌面</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewClearAllWindowButton</name> ++ <message> ++ <source>Clear</source> ++ <translatorcomment>清除</translatorcomment> ++ <translation type="vanished">清除</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="174"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">無應用開啟</translation> ++ </message> ++ <message> ++ <location filename="qml/TabletViewMain.qml" line="357"/> ++ <source>Clear</source> ++ <translation type="unfinished">清除</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewRootWindow</name> ++ <message> ++ <source>No recent tasks</source> ++ <translatorcomment>无应用开启</translatorcomment> ++ <translation type="vanished">無應用開啟</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="qml/VirtualDesktopWindow.qml" line="187"/> ++ <source>Desktop</source> ++ <translation type="unfinished">桌面</translation> ++ </message> ++</context> ++</TS> diff -Nru ukui-window-switch-4.10.1.10/debian/patches/0012-update-changelog-4.10.1.10-ok2.0.patch ukui-window-switch-4.10.1.10/debian/patches/0012-update-changelog-4.10.1.10-ok2.0.patch --- ukui-window-switch-4.10.1.10/debian/patches/0012-update-changelog-4.10.1.10-ok2.0.patch 1970-01-01 08:00:00.000000000 +0800 +++ ukui-window-switch-4.10.1.10/debian/patches/0012-update-changelog-4.10.1.10-ok2.0.patch 2025-03-07 14:07:48.000000000 +0800 @@ -0,0 +1,8412 @@ +From: zhangyuanyuan1 <zhangyuanyuan1@kylinos.cn> +Date: Fri, 7 Mar 2025 14:45:20 +0800 +Subject: update changelog 4.10.1.10-ok2.0 + +--- + .gitignore | 1 - + CMakeLists.txt | 11 +- + windowsview/CMakeLists.txt | 71 +- + windowsview/appwindowfiltermodel.cpp | 74 ++ + windowsview/appwindowfiltermodel.h | 54 ++ + windowsview/appwindowlistmodel.cpp | 173 ++++ + windowsview/appwindowlistmodel.h | 77 ++ + windowsview/data.qrc | 14 +- + windowsview/desktopbackground.cpp | 2 +- + windowsview/desktoplistmodel.cpp | 199 +++++ + windowsview/desktoplistmodel.h | 81 ++ + windowsview/multitaskviewabstractmodelhandler.h | 185 +++++ + windowsview/multitaskviewmodel.cpp | 479 ----------- + windowsview/multitaskviewmodel.h | 203 ----- + windowsview/multitaskviewmodelhandler.h | 69 -- + windowsview/qml/AppArea.qml | 330 +++----- + windowsview/qml/AppPreviewWindow.qml | 2 +- + windowsview/qml/CloseButton.qml | 1 + + windowsview/qml/DesktopArea.qml | 40 +- + windowsview/qml/MasterDesktopArea.qml | 36 +- + windowsview/qml/MultitaskView.qml | 221 +++++ + windowsview/qml/NewDesktopButton.qml | 6 +- + windowsview/qml/Tabbox.qml | 286 +++++++ + windowsview/qml/TabletPreviewWindow.qml | 1 - + windowsview/qml/TabletViewMain.qml | 31 +- + windowsview/qml/VirtualDesktopWindow.qml | 14 +- + windowsview/qml/WorkSpaceThumbnailWithKwin.qml | 34 +- + windowsview/qml/multitaskview.qml | 358 -------- + windowsview/qml/tabbox.qml | 303 ------- + windowsview/translations/ukui-window-switch_ar.ts | 34 + + .../translations/ukui-window-switch_bo_CN.ts | 34 + + windowsview/translations/ukui-window-switch_de.ts | 34 + + windowsview/translations/ukui-window-switch_es.ts | 34 + + windowsview/translations/ukui-window-switch_fr.ts | 34 + + windowsview/translations/ukui-window-switch_kk.ts | 34 + + windowsview/translations/ukui-window-switch_ky.ts | 34 + + windowsview/translations/ukui-window-switch_mn.ts | 34 + + windowsview/translations/ukui-window-switch_ug.ts | 34 + + windowsview/translations/ukui-window-switch_vi.ts | 34 + + .../translations/ukui-window-switch_zh_CN.ts | 34 + + .../translations/ukui-window-switch_zh_Hant.ts | 34 + + windowsview/ukui-flow.cpp | 913 +++++++++++++++++++++ + windowsview/ukui-flow.h | 370 +++++++++ + windowsview/ukui-window-switch | 2 +- + .../ukui-window-switch-kwineffect/CMakeLists.txt | 116 +-- + .../multitaskviewmanager.cpp | 39 +- + .../multitaskviewmanager.h | 6 +- + .../multitaskviewmodelbycompositehandler.cpp | 18 +- + .../multitaskviewmodelbycompositehandler.h | 8 +- + .../ukui-window-switch-wlcom/CMakeLists.txt | 159 ++-- + windowsview/ukui-window-switch-wlcom/main.cpp | 9 +- + .../multitaskviewmanagerbywlcom.cpp | 56 +- + .../multitaskviewmanagerbywlcom.h | 10 +- + .../multitaskviewmodelbywlcomhandler.cpp | 105 +-- + .../multitaskviewmodelbywlcomhandler.h | 18 +- + windowsview/ukui-window-switch-wlcom/toplevel.cpp | 15 +- + windowsview/ukui-window-switch_ar.ts | 62 -- + windowsview/ukui-window-switch_bo_CN.ts | 62 -- + windowsview/ukui-window-switch_de.ts | 62 -- + windowsview/ukui-window-switch_es.ts | 62 -- + windowsview/ukui-window-switch_fr.ts | 62 -- + windowsview/ukui-window-switch_kk.ts | 62 -- + windowsview/ukui-window-switch_ky.ts | 62 -- + windowsview/ukui-window-switch_mn.ts | 62 -- + windowsview/ukui-window-switch_ug.ts | 62 -- + windowsview/ukui-window-switch_vi.ts | 62 -- + windowsview/ukui-window-switch_zh_CN.ts | 62 -- + windowsview/ukui-window-switch_zh_Hant.ts | 62 -- + windowsview/windowmanagerinterface.cpp | 383 +++++++++ + windowsview/windowmanagerinterface.h | 115 +++ + 70 files changed, 4028 insertions(+), 2822 deletions(-) + create mode 100644 windowsview/appwindowfiltermodel.cpp + create mode 100644 windowsview/appwindowfiltermodel.h + create mode 100644 windowsview/appwindowlistmodel.cpp + create mode 100644 windowsview/appwindowlistmodel.h + create mode 100644 windowsview/desktoplistmodel.cpp + create mode 100644 windowsview/desktoplistmodel.h + create mode 100644 windowsview/multitaskviewabstractmodelhandler.h + delete mode 100644 windowsview/multitaskviewmodel.cpp + delete mode 100644 windowsview/multitaskviewmodel.h + delete mode 100644 windowsview/multitaskviewmodelhandler.h + create mode 100644 windowsview/qml/MultitaskView.qml + create mode 100755 windowsview/qml/Tabbox.qml + delete mode 100644 windowsview/qml/multitaskview.qml + delete mode 100755 windowsview/qml/tabbox.qml + create mode 100644 windowsview/translations/ukui-window-switch_ar.ts + create mode 100644 windowsview/translations/ukui-window-switch_bo_CN.ts + create mode 100644 windowsview/translations/ukui-window-switch_de.ts + create mode 100644 windowsview/translations/ukui-window-switch_es.ts + create mode 100644 windowsview/translations/ukui-window-switch_fr.ts + create mode 100644 windowsview/translations/ukui-window-switch_kk.ts + create mode 100644 windowsview/translations/ukui-window-switch_ky.ts + create mode 100644 windowsview/translations/ukui-window-switch_mn.ts + create mode 100644 windowsview/translations/ukui-window-switch_ug.ts + create mode 100644 windowsview/translations/ukui-window-switch_vi.ts + create mode 100644 windowsview/translations/ukui-window-switch_zh_CN.ts + create mode 100644 windowsview/translations/ukui-window-switch_zh_Hant.ts + create mode 100644 windowsview/ukui-flow.cpp + create mode 100644 windowsview/ukui-flow.h + delete mode 100644 windowsview/ukui-window-switch_ar.ts + delete mode 100644 windowsview/ukui-window-switch_bo_CN.ts + delete mode 100644 windowsview/ukui-window-switch_de.ts + delete mode 100644 windowsview/ukui-window-switch_es.ts + delete mode 100644 windowsview/ukui-window-switch_fr.ts + delete mode 100644 windowsview/ukui-window-switch_kk.ts + delete mode 100644 windowsview/ukui-window-switch_ky.ts + delete mode 100644 windowsview/ukui-window-switch_mn.ts + delete mode 100644 windowsview/ukui-window-switch_ug.ts + delete mode 100644 windowsview/ukui-window-switch_vi.ts + delete mode 100644 windowsview/ukui-window-switch_zh_CN.ts + delete mode 100644 windowsview/ukui-window-switch_zh_Hant.ts + create mode 100644 windowsview/windowmanagerinterface.cpp + create mode 100644 windowsview/windowmanagerinterface.h + +diff --git a/.gitignore b/.gitignore +index dd3e4fa..8f1db95 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -5,7 +5,6 @@ + *.user + *.qm + CMakeLists.txt.user* +-windowsview/globalconfig.h + + # debian files + obj-*-linux-gnu/ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index bf089b5..820482c 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1,4 +1,4 @@ +-cmake_minimum_required(VERSION 3.5) ++cmake_minimum_required(VERSION 3.16) + + project(ukui-window-switch) + +@@ -11,18 +11,13 @@ find_package(KF5WindowSystem REQUIRED) + + get_target_property(QT_QMAKE_EXECUTABLE ${Qt5Core_QMAKE_EXECUTABLE} IMPORTED_LOCATION) + macro(query_qmake args output) +- exec_program(${QT_QMAKE_EXECUTABLE} ARGS -query ${args} OUTPUT_VARIABLE ${output} RETURN_VALUE exitCode) +- +- if(NOT ${exitCode} EQUAL 0) ++ execute_process(COMMAND ${QT_QMAKE_EXECUTABLE} -query ${args} OUTPUT_VARIABLE ${output} RESULT_VARIABLE test1 RESULT_VARIABLE result OUTPUT_STRIP_TRAILING_WHITESPACE) ++ if(NOT ${result} EQUAL 0) + message(FATAL_ERROR "exec ${QT_QMAKE_EXECUTABLE} failed, with args: ${args}, error message: ${output}") + endif() + endmacro() + + query_qmake("QT_INSTALL_PLUGINS" QT_INSTALL_PLUGINS) +-message("QT_INSTALL_PLUGINS=${QT_INSTALL_PLUGINS}") +- +-set(INSTALL_PATH "${QT_INSTALL_PLUGINS}/kwin/effects/plugins") +- + + add_subdirectory(windowsview) + add_subdirectory(windowswitchers) +diff --git a/windowsview/CMakeLists.txt b/windowsview/CMakeLists.txt +index 80342cd..ae83e94 100644 +--- a/windowsview/CMakeLists.txt ++++ b/windowsview/CMakeLists.txt +@@ -1,70 +1,19 @@ +-cmake_minimum_required(VERSION 3.5) ++cmake_minimum_required(VERSION 3.16) + +-set(CMAKE_INCLUDE_CURRENT_DIR ON) +-set(CMAKE_AUTOMOC ON) +-set(CMAKE_AUTOUIC ON) +-set(CMAKE_AUTORCC ON) +- +-set(CMAKE_CXX_STANDARD 14) +-set(CMAKE_CXX_STANDARD_REQUIRED ON) +- +-set(KF5_DEP_VERSION "5.54.0") +- +-find_package(ECM 5.54.0 NO_MODULE) +-set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake) +- +-find_package(X11 MODULE) +-find_package(XCB MODULE COMPONENTS XCB COMPOSITE DAMAGE SHAPE XFIXES RENDER) +-message("XCB:"${X11_FOUND}, ${XCB_XCB_FOUND}, ${XCB_COMPOSITE_FOUND}, ${XCB_DAMAGE_FOUND}) +-if(X11_FOUND AND XCB_XCB_FOUND) +- set(HAVE_X11 1) +-endif() +-if(HAVE_X11 AND XCB_COMPOSITE_FOUND AND XCB_DAMAGE_FOUND) +- set(HAVE_XCB_COMPOSITE 1) +-endif() +- +-find_package(OpenGL) +- +-find_package(EGL MODULE) +-message("EGL:"${EGL_FOUND}) +-if (${EGL_FOUND}) +- set(HAVE_EGL 1) +-endif() +- +-message("OPENGL:"${OPENGL_FOUND},${Qt5Gui_OPENGL_IMPLEMENTATION}) +-if(OPENGL_FOUND AND (${Qt5Gui_OPENGL_IMPLEMENTATION} STREQUAL "GL")) +- set(HAVE_GLX ${HAVE_X11}) +-else() +- set(HAVE_GLX 0) +-endif() +- +-message("MACRO:"${HAVE_X11},${HAVE_XCB_COMPOSITE},${HAVE_EGL},${HAVE_GLX}) +- +-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/globalconfig.h.in ${CMAKE_CURRENT_SOURCE_DIR}/globalconfig.h) +- +-find_package(Qt5Quick REQUIRED) +-find_package(Qt5QuickWidgets REQUIRED) +-find_package(KF5Config REQUIRED) +-find_package(KF5GlobalAccel REQUIRED) +-find_package(KF5I18n REQUIRED) +-find_package(PkgConfig REQUIRED) +-find_package(Qt5LinguistTools REQUIRED) +-find_package(Qt5 REQUIRED NO_MODULE COMPONENTS X11Extras Concurrent) +- +-pkg_check_modules(KDK REQUIRED kysdk-sysinfo) +-pkg_check_modules(DATACOLLECT REQUIRED kysdk-datacollect) ++find_package(QT NAMES Qt6 Qt5 COMPONENTS LinguistTools REQUIRED) ++find_package(Qt${QT_VERSION_MAJOR} COMPONENTS LinguistTools REQUIRED) + +-include_directories(${KDK_INCLUDE_DIRS}) +-include_directories(${DATACOLLECT_INCLUDE_DIRS}) ++file(GLOB TS_FILES translations/*.ts) ++set_source_files_properties(${TS_FILES} PROPERTIES OUTPUT_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/translations) ++qt5_create_translation(QM_FILES ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/ukui-window-switch-wlcom ${CMAKE_CURRENT_SOURCE_DIR}/ukui-window-switch-kwineffect ${CMAKE_CURRENT_SOURCE_DIR}/qml ${TS_FILES} OPTIONS -no-obsolete -no-ui-lines) + +-# 注意要链接到kwin,如果本地安装了kwin的依赖,记得注意区分 +-include_directories(/usr/include/) ++add_custom_target(generate_qm ALL DEPENDS ${QM_FILES}) + ++set(TRANSLATION_DIR "/usr/share/ukui-window-switch/translations/") ++add_compile_definitions(TRANSLATION_DIR="${TRANSLATION_DIR}") + +-# translation +-find_package(QT NAMES Qt6 Qt5 COMPONENTS LinguistTools REQUIRED) +-find_package(Qt${QT_VERSION_MAJOR} COMPONENTS LinguistTools REQUIRED) + add_subdirectory(ukui-window-switch-kwineffect) + add_subdirectory(ukui-window-switch-wlcom) + install(FILES ukui-window-switch DESTINATION /usr/bin/) + install(FILES ukui-window-switch.desktop DESTINATION /etc/xdg/autostart/) ++install(FILES ${QM_FILES} DESTINATION ${TRANSLATION_DIR}) +diff --git a/windowsview/appwindowfiltermodel.cpp b/windowsview/appwindowfiltermodel.cpp +new file mode 100644 +index 0000000..9dda220 +--- /dev/null ++++ b/windowsview/appwindowfiltermodel.cpp +@@ -0,0 +1,74 @@ ++/* ++ * Copyright (C) 2024, KylinSoft Co., Ltd. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see <https://www.gnu.org/licenses/>. ++ * ++ * Authors: zy-yuan1 <zhangyuanyuan1@kylinos.cn> ++ * ++ */ ++#include "appwindowfiltermodel.h" ++#include <QDebug> ++ ++AppWindowFilterModel::AppWindowFilterModel(QObject *parent) : QSortFilterProxyModel(parent) ++{ ++ setFilterRole(AppWindowListModel::DesktopId); ++} ++ ++void AppWindowFilterModel::setSourceModel(QAbstractItemModel *sourceModel) ++{ ++ m_sourceModel = qobject_cast<AppWindowListModel*>(sourceModel); ++ QSortFilterProxyModel::setSourceModel(sourceModel); ++ connect(sourceModel, &QAbstractItemModel::dataChanged, this, &AppWindowFilterModel::onDataChanged); ++} ++ ++int AppWindowFilterModel::desktopId() const ++{ ++ return m_desktopId; ++} ++ ++void AppWindowFilterModel::setDesktopId(const int id) ++{ ++ if (m_desktopId == id) { ++ return; ++ } ++ m_desktopId = id; ++ invalidate(); ++} ++ ++int AppWindowFilterModel::screenId() const ++{ ++ return m_screenId; ++} ++ ++void AppWindowFilterModel::setScreenId(const int id) ++{ ++ if (m_screenId == id) { ++ return; ++ } ++ m_screenId = id; ++ invalidate(); ++} ++ ++bool AppWindowFilterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const ++{ ++ int desktopId = m_sourceModel->index(source_row, 0, source_parent).data(AppWindowListModel::Role::DesktopId).toUInt(); ++ int screenId = m_sourceModel->index(source_row, 0, source_parent).data(AppWindowListModel::Role::ScreenId).toUInt(); ++ ++ return desktopId == m_desktopId && screenId == m_screenId; ++} ++ ++void AppWindowFilterModel::onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) ++{ ++ Q_EMIT dataChanged(mapFromSource(topLeft), mapFromSource(bottomRight), roles); ++} +diff --git a/windowsview/appwindowfiltermodel.h b/windowsview/appwindowfiltermodel.h +new file mode 100644 +index 0000000..44db22c +--- /dev/null ++++ b/windowsview/appwindowfiltermodel.h +@@ -0,0 +1,54 @@ ++/* ++ * Copyright (C) 2024, KylinSoft Co., Ltd. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see <https://www.gnu.org/licenses/>. ++ * ++ * Authors: zy-yuan1 <zhangyuanyuan1@kylinos.cn> ++ * ++ */ ++#ifndef APPWINDOWFILTERMODEL_H ++#define APPWINDOWFILTERMODEL_H ++ ++#include <QObject> ++#include <QSortFilterProxyModel> ++#include "appwindowlistmodel.h" ++ ++class AppWindowFilterModel : public QSortFilterProxyModel ++{ ++ Q_OBJECT ++ Q_PROPERTY(int desktopId READ desktopId WRITE setDesktopId) ++ Q_PROPERTY(int screenId READ screenId WRITE setScreenId) ++ ++public: ++ explicit AppWindowFilterModel(QObject *parent = nullptr); ++ ~AppWindowFilterModel() = default; ++ Q_INVOKABLE void setSourceModel(QAbstractItemModel *sourceModel) override; ++ ++ int desktopId() const; ++ void setDesktopId(const int id); ++ int screenId() const; ++ void setScreenId(const int id); ++ ++protected: ++ bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; ++ ++private: ++ void onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>()); ++ ++ AppWindowListModel *m_sourceModel = nullptr; ++ int m_desktopId = 1; ++ int m_screenId = 0; ++}; ++ ++#endif // APPWINDOWFILTERMODEL_H +diff --git a/windowsview/appwindowlistmodel.cpp b/windowsview/appwindowlistmodel.cpp +new file mode 100644 +index 0000000..e1e81b4 +--- /dev/null ++++ b/windowsview/appwindowlistmodel.cpp +@@ -0,0 +1,173 @@ ++/* ++ * Copyright (C) 2024, KylinSoft Co., Ltd. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see <https://www.gnu.org/licenses/>. ++ * ++ * Authors: zy-yuan1 <zhangyuanyuan1@kylinos.cn> ++ * ++ */ ++#include "appwindowlistmodel.h" ++#include "windowmanagerinterface.h" ++#include <QMetaEnum> ++#include <QDebug> ++ ++ ++AppWindowListModel::AppWindowListModel(QObject *parent) : QAbstractListModel(parent) ++{ ++ connectSignals(); ++ loadWindows(); ++} ++ ++void AppWindowListModel::connectSignals() ++{ ++ QObject::connect(WindowManagerInterface::getInstance(), &WindowManagerInterface::appWindowRemoved, ++ this, &AppWindowListModel::onAppWindowRemoved); ++ ++ QObject::connect(WindowManagerInterface::getInstance(), &WindowManagerInterface::appWindowDesktopChanged, ++ this, &AppWindowListModel::onAppWindowDesktopChanged); ++ ++ QObject::connect(WindowManagerInterface::getInstance(), &WindowManagerInterface::desktopMoved, ++ this, &AppWindowListModel::onDesktopMoved); ++} ++ ++int AppWindowListModel::rowCount(const QModelIndex &parent) const ++{ ++ return m_windowList.count(); ++} ++ ++QVariant AppWindowListModel::data(const QModelIndex &index, int role) const ++{ ++ int i = index.row(); ++ if (i < 0 || i >= m_windowList.count()) { ++ return QVariant(); ++ } ++ Window window = m_windowList.at(i); ++ switch (static_cast<Role>(role)) { ++ case Role::Id: ++ return window.id(); ++ case Role::Uuid: ++ return window.uuid(); ++ case Role::Caption: ++ return window.caption(); ++ case Role::X: ++ return window.x(); ++ case Role::Y: ++ return window.y(); ++ case Role::Width: ++ return window.width(); ++ case Role::Height: ++ return window.height(); ++ case Role::Minimized: ++ return window.minimized(); ++ case Role::DesktopId: ++ return window.desktopId(); ++ case Role::ScreenId: ++ return window.screenId(); ++ default: ++ return {}; ++ } ++} ++ ++QHash<int, QByteArray> AppWindowListModel::roleNames() const ++{ ++ QHash<int, QByteArray> roles = QAbstractItemModel::roleNames(); ++ QMetaEnum e = metaObject()->enumerator(metaObject()->indexOfEnumerator("Role")); ++ ++ for (int i = 0; i < e.keyCount(); ++i) { ++ roles.insert(e.value(i), e.key(i)); ++ } ++ return roles; ++} ++ ++void AppWindowListModel::loadWindows() ++{ ++ m_windowList.clear(); ++ beginResetModel(); ++ for (const Window &appwindow : getAllAppWindowList()) { ++ m_windowList.append(appwindow); ++ } ++ endResetModel(); ++} ++ ++void AppWindowListModel::addItem(Window window) ++{ ++ beginInsertRows(QModelIndex(), m_windowList.size(), m_windowList.size()); ++ m_windowList.append(window); ++ endInsertRows(); ++} ++ ++void AppWindowListModel::onAppWindowRemoved(QString windowId) ++{ ++ for (int index = 0; index < m_windowList.size(); ++index) { ++ auto item = m_windowList.at(index); ++ if (item.uuid() == windowId) { ++ beginRemoveRows(QModelIndex(), index, index); ++ m_windowList.removeAt(index); ++ endRemoveRows(); ++ break; ++ } ++ } ++} ++ ++void AppWindowListModel::onAppWindowDesktopChanged(QString windowId, int oldDesktopIndex, int newDesktopIndex) ++{ ++ Window tmp; ++ for (int i = 0; i < m_windowList.size(); ++i) { ++ auto &item = m_windowList.at(i); ++ if (item.uuid() == windowId) { ++ tmp = m_windowList.at(i); ++ tmp.setDesktopId(newDesktopIndex); ++ m_windowList.replace(i, tmp); ++ QModelIndex changeIndex = index(i, 0, QModelIndex()); ++ Q_EMIT dataChanged(changeIndex, changeIndex, QVector<int>{Role::DesktopId}); ++ break; ++ } ++ } ++} ++ ++void AppWindowListModel::onDesktopMoved(int oldDesktopIndex, int newDesktopIndex) ++{ ++ beginResetModel(); ++ loadWindows(); ++ endResetModel(); ++} ++ ++// TODO: remove? ++QVariant AppWindowListModel::getItemData(const QModelIndex &index) ++{ ++ int i = index.row(); ++ if (i >= 0 && i < m_windowList.count()) { ++ return QVariant::fromValue(m_windowList.at(i)); ++ } else { ++ return QVariant(); ++ } ++} ++ ++QList<Window> AppWindowListModel::getAllAppWindowList() const ++{ ++ QList<Window> allAppWindowList; ++ for(int desktopIndex = 1; desktopIndex <= WindowManagerInterface::getInstance()->getNumberOfDesktops(); desktopIndex++) { ++ for (int screenIndex = 0; screenIndex < WindowManagerInterface::getInstance()->logicalScreenCount(); screenIndex++) { ++ QList<Window> windowList; ++ windowList = WindowManagerInterface::getInstance()->createWindowList(desktopIndex, screenIndex); ++ for (auto &window : windowList) { ++ window.setDesktopId(desktopIndex); ++ window.setScreenId(screenIndex); ++ } ++ std::reverse(windowList.begin(), windowList.end()); ++ allAppWindowList += windowList; ++ } ++ } ++ return allAppWindowList; ++} +diff --git a/windowsview/appwindowlistmodel.h b/windowsview/appwindowlistmodel.h +new file mode 100644 +index 0000000..167f6f9 +--- /dev/null ++++ b/windowsview/appwindowlistmodel.h +@@ -0,0 +1,77 @@ ++/* ++ * Copyright (C) 2024, KylinSoft Co., Ltd. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see <https://www.gnu.org/licenses/>. ++ * ++ * Authors: zy-yuan1 <zhangyuanyuan1@kylinos.cn> ++ * ++ */ ++#ifndef APPWINDOWLISTMODEL_H ++#define APPWINDOWLISTMODEL_H ++ ++#include <QObject> ++#include <QAbstractListModel> ++#include <QIcon> ++#include "multitaskviewabstractmodelhandler.h" ++ ++class Window; ++class AppWindowListModel : public QAbstractListModel ++{ ++ Q_OBJECT ++ ++public: ++ enum Role { ++ Id = Qt::UserRole + 1, ++ Uuid, ++ Caption, ++ X, ++ Y, ++ Width, ++ Height, ++ Minimized, ++ DesktopId, ++ ScreenId ++ }; ++ Q_ENUM(Role) ++ ++ explicit AppWindowListModel(QObject *parent = nullptr); ++ ~AppWindowListModel() = default; ++ ++ int rowCount(const QModelIndex &parent = QModelIndex()) const override; ++ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; ++ QHash<int,QByteArray> roleNames() const override; ++ ++ ++ /* for TabletView ++ * qml里无法直接读取QMap<int, QVariant>,需要使用iterator,因此使用QVariant::fromValve(window) ++ * TODO: TabletView 加载动画优化 ++ */ ++ Q_INVOKABLE QVariant getItemData(const QModelIndex &index); ++ ++private: ++ void connectSignals(); ++ void loadWindows(); ++ void addItem(Window window); ++ QList<Window> getAllAppWindowList() const; ++ ++ QList<Window> m_windowList; ++ ++private Q_SLOTS: ++ void onAppWindowRemoved(QString windowId); ++ void onAppWindowDesktopChanged(QString windowId, int oldDesktopIndex, int newDesktopIndex); ++ void onDesktopMoved(int oldDesktopIndex, int newDesktopIndex); ++ ++}; ++ ++#endif // APPWINDOWLISTMODEL_H +diff --git a/windowsview/data.qrc b/windowsview/data.qrc +index a0a1fa6..602ad84 100644 +--- a/windowsview/data.qrc ++++ b/windowsview/data.qrc +@@ -9,7 +9,7 @@ + <file>images/ukui-taskview-close-hover.svg</file> + <file>qml/AppPreviewWindow.qml</file> + <file>qml/MasterDesktopArea.qml</file> +- <file>qml/multitaskview.qml</file> ++ <file>qml/MultitaskView.qml</file> + <file>qml/AppArea.qml</file> + <file>qml/DesktopArea.qml</file> + <file>qml/TabletPreviewWindow.qml</file> +@@ -17,16 +17,6 @@ + <file>qml/TabletViewMain.qml</file> + <file>qml/TabletViewCloseButton.qml</file> + <file>qml/CloseButton.qml</file> +- <file>ukui-window-switch_zh_CN.qm</file> +- <file>ukui-window-switch_bo_CN.qm</file> +- <file>ukui-window-switch_de.qm</file> +- <file>ukui-window-switch_es.qm</file> +- <file>ukui-window-switch_fr.qm</file> +- <file>ukui-window-switch_kk.qm</file> +- <file>ukui-window-switch_ky.qm</file> +- <file>ukui-window-switch_mn.qm</file> +- <file>ukui-window-switch_ug.qm</file> +- <file>ukui-window-switch_zh_Hant.qm</file> + <file>qml/ArrowButton.qml</file> + <file>images/icon-arrow-white.svg</file> + <file>images/icon-arrow-black.svg</file> +@@ -35,7 +25,7 @@ + <file>images/application-exit-symbolic-white.svg</file> + <file>images/application-exit-symbolic.svg</file> + <file>qml/ThumbnailWithKwin.qml</file> +- <file>qml/tabbox.qml</file> ++ <file>qml/Tabbox.qml</file> + <file>qml/ThumbnailWithWlcom.qml</file> + <file>qml/WorkSpaceThumbnailWithWlcom.qml</file> + <file>qml/WorkSpaceThumbnailWithKwin.qml</file> +diff --git a/windowsview/desktopbackground.cpp b/windowsview/desktopbackground.cpp +index 7ee58f2..1a50d34 100644 +--- a/windowsview/desktopbackground.cpp ++++ b/windowsview/desktopbackground.cpp +@@ -379,7 +379,7 @@ void DesktopBackground::bluredImage(int blur_radius, QImage &blurImage) + } + } + // 在纵方向对第一次的结果重新进行一次,先进行逆时针旋转90度进行高斯模糊,减少 scanLine() 函数的计算量 +- QMatrix matrix; ++ QTransform matrix; + matrix.rotate(-90.0); + tmpImg = tmpImg.transformed(matrix, Qt::FastTransformation); + blurImage = blurImage.transformed(matrix, Qt::FastTransformation); +diff --git a/windowsview/desktoplistmodel.cpp b/windowsview/desktoplistmodel.cpp +new file mode 100644 +index 0000000..81f32fa +--- /dev/null ++++ b/windowsview/desktoplistmodel.cpp +@@ -0,0 +1,199 @@ ++/* ++ * Copyright (C) 2024, KylinSoft Co., Ltd. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see <https://www.gnu.org/licenses/>. ++ * ++ * Authors: zy-yuan1 <zhangyuanyuan1@kylinos.cn> ++ * ++ */ ++#include "desktoplistmodel.h" ++ ++#include <algorithm> ++#include <QMetaEnum> ++#include <QGuiApplication> ++#include <QScreen> ++#include <QDBusMessage> ++#include <QDBusConnection> ++#include <QDebug> ++#include "windowmanagerinterface.h" ++ ++DesktopListModel::DesktopListModel(QObject *parent) : QAbstractListModel(parent) ++{ ++ connectSignals(); ++ init(); ++} ++ ++int DesktopListModel::rowCount(const QModelIndex &parent) const ++{ ++ return m_desktopList.count(); ++} ++ ++QVariant DesktopListModel::data(const QModelIndex &index, int role) const ++{ ++ int i = index.row(); ++ if (i < 0 || i >= m_desktopList.count()) { ++ return QVariant(); ++ } ++ ++ Desktop desktop = m_desktopList.at(i); ++ switch (static_cast<Role>(role)) { ++ case Role::Id: ++ return i + 1; ++ case Role::Uuid: ++ return desktop.uuid(); ++ case Role::ItemType: ++ return desktop.type() == Desktop::DesktopType::NewDesktop ? QString("newDesktop") ++ : QString("workSpace"); ++ default: ++ return {}; ++ } ++} ++ ++bool DesktopListModel::setData(const QModelIndex &index, const QVariant &value, int role) ++{ ++ if (!index.isValid()) { ++ return false; ++ } ++ ++ if (role == Role::ItemType) { ++ m_desktopList[index.row()].setDesktopType(Desktop::DesktopType(value.toInt())); ++ Q_EMIT dataChanged(index, index, QVector<int>{Role::ItemType}); ++ } ++ ++ return false; ++} ++ ++QHash<int, QByteArray> DesktopListModel::roleNames() const ++{ ++ QHash<int, QByteArray> roles = QAbstractItemModel::roleNames(); ++ QMetaEnum e = metaObject()->enumerator(metaObject()->indexOfEnumerator("Role")); ++ ++ for (int i = 0; i < e.keyCount(); ++i) { ++ roles.insert(e.value(i), e.key(i)); ++ } ++ return roles; ++} ++ ++bool DesktopListModel::insertRows(int row, int count, const QModelIndex &parent) ++{ ++ if (row < 0 || row > m_desktopList.count() || m_desktopList.count() > MAX_DESKTOP_COUNT) { ++ return false; ++ } ++ ++ beginInsertRows(parent, row, row); ++ ++ Desktop desktop; ++ desktop.setDesktopType(Desktop::DesktopType::WorkSpace); ++ m_desktopList.insert(m_desktopList.count() - 1, desktop); ++ ++ endInsertRows(); ++ ++ return true; ++} ++ ++bool DesktopListModel::removeRows(int row, int count, const QModelIndex &parent) ++{ ++ if (!rowIsValid(row)) { ++ return false; ++ } ++ ++ beginRemoveRows(parent, row, row); ++ m_desktopList.removeAt(row); ++ endRemoveRows(); ++ return true; ++} ++ ++bool DesktopListModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, ++ const QModelIndex &destinationParent, int destinationChild) ++{ ++ if (!rowIsValid(sourceRow) || !rowIsValid(destinationChild)) { ++ return false; ++ } ++ // only support count == 1 ++ // 需要注意 beginMoveRows 单个节点移动时,上移差是1,下移差是2 ++ if (sourceRow < destinationChild) { ++ // 右移/下移 ++ beginMoveRows(sourceParent,sourceRow, sourceRow, destinationParent, destinationChild + 1); ++ } else { ++ // 左移/上移 ++ beginMoveRows(sourceParent,sourceRow, sourceRow, destinationParent, destinationChild); ++ } ++ m_desktopList.move(sourceRow, destinationChild); ++ endMoveRows(); ++ return true; ++} ++ ++bool DesktopListModel::rowIsValid(int row) const ++{ ++ return row >= 0 && row < m_desktopList.count(); ++} ++ ++void DesktopListModel::connectSignals() ++{ ++ QObject::connect(WindowManagerInterface::getInstance(), &WindowManagerInterface::desktopAppended, ++ this, &DesktopListModel::onDesktopAppend); ++ QObject::connect(WindowManagerInterface::getInstance(), &WindowManagerInterface::desktopRemoved, ++ this, &DesktopListModel::onDesktopRemoved); ++ QObject::connect(WindowManagerInterface::getInstance(), &WindowManagerInterface::desktopMoved, ++ this, &DesktopListModel::onDesktopMoved); ++} ++ ++void DesktopListModel::init() ++{ ++ beginResetModel(); ++ m_desktopList.clear(); ++ ++ const auto desktopCount = WindowManagerInterface::getInstance()->getNumberOfDesktops(); ++ for (int desktopIndex = 1; desktopIndex <= desktopCount; desktopIndex++) { ++ Desktop desktop; ++ desktop.setDesktopType(Desktop::DesktopType::WorkSpace); ++ m_desktopList.append(desktop); ++ } ++ ++ // 在末尾添加空的Desktop,指代“newDesktop” ++ if (desktopCount < MAX_DESKTOP_COUNT) { ++ Desktop desktop; ++ desktop.setDesktopType(Desktop::DesktopType::NewDesktop); ++ m_desktopList.append(desktop); ++ } ++ ++ endResetModel(); ++} ++ ++void DesktopListModel::onDesktopAppend(int desktopIndex) ++{ ++ //当工作区数量达到最大时,再点击“新建工作区”不需要model新增item,只需将model最后一项的属性ItemType由“newDesktop”改为“workSpace”,并修改其他必须修改的属性 ++ //其他情况下则新增item ++ if (desktopIndex == MAX_DESKTOP_COUNT) { ++ setData(index(desktopIndex - 1, 0), Desktop::DesktopType::WorkSpace, Role::ItemType); ++ } else { ++ insertRows(desktopIndex - 1, 1, QModelIndex()); ++ emit desktopAppended(rowCount() + 1); ++ } ++} ++ ++void DesktopListModel::onDesktopRemoved(int desktopIndex) ++{ ++ //当工作区数量是最大时,且最后一项为“workSpace”,由于要播放删除动画,需要先添加“newDesktop”,再删除desktopIndex对应工作区 ++ if (rowCount() == MAX_DESKTOP_COUNT && index(MAX_DESKTOP_COUNT - 1, 0).data(Role::ItemType).toString() == QString("workSpace")) { ++ insertRows(MAX_DESKTOP_COUNT, 1, QModelIndex()); ++ setData(index(MAX_DESKTOP_COUNT, 0), Desktop::DesktopType::NewDesktop, Role::ItemType); ++ } ++ removeRows(desktopIndex - 1, 1, QModelIndex()); ++} ++ ++void DesktopListModel::onDesktopMoved(int srcDesktopIndex, int destDesktopIndex) ++{ ++ moveRows(QModelIndex(), srcDesktopIndex - 1, 1, QModelIndex(), destDesktopIndex - 1); ++} +diff --git a/windowsview/desktoplistmodel.h b/windowsview/desktoplistmodel.h +new file mode 100644 +index 0000000..033dc4e +--- /dev/null ++++ b/windowsview/desktoplistmodel.h +@@ -0,0 +1,81 @@ ++/* ++ * Copyright (C) 2024, KylinSoft Co., Ltd. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see <https://www.gnu.org/licenses/>. ++ * ++ * Authors: zy-yuan1 <zhangyuanyuan1@kylinos.cn> ++ * ++ */ ++#ifndef DESKTOPLISTMODEL_H ++#define DESKTOPLISTMODEL_H ++ ++#include <QObject> ++#include <QList> ++#include <QRect> ++#include <QVariantList> ++#include <QString> ++#include <QAbstractListModel> ++#include <QMetaType> ++#include "multitaskviewabstractmodelhandler.h" ++ ++class Window; ++class Screen; ++class Desktop; ++ ++ ++class DesktopListModel : public QAbstractListModel ++{ ++ Q_OBJECT ++ ++public: ++ enum Role { ++ Id = Qt::UserRole + 1, /* desktop index, 从 1 开始计数,易于和界面显示对应 */ ++ Uuid, /* desktop uuid */ ++ ItemType /*DesktopType*/ ++ }; ++ Q_ENUM(Role) ++ ++ explicit DesktopListModel(QObject *parent = nullptr); ++ ~DesktopListModel() = default; ++ ++ int rowCount(const QModelIndex &parent = QModelIndex()) const override; ++ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; ++ bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; ++ QHash<int,QByteArray> roleNames() const override; ++ bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; ++ bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; ++ bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, ++ const QModelIndex &destinationParent, int destinationChild) override; ++ ++ bool rowIsValid(int row) const; ++ void connectSignals(); ++ void init(); ++ ++private: ++ QList<Desktop> m_desktopList; ++ /* 最大虚拟桌面数量为15: 15个工作区 或 14个工作区+新建工作区*/ ++ static constexpr int MAX_DESKTOP_COUNT = 15; ++ ++signals: ++ /* 用户手动添加工作区时,需要额外执行动画使最后一个工作区(或新建工作区)显示完整;删除工作区则不需要 */ ++ void desktopAppended(int desktopIndex); ++ ++ ++private slots: ++ void onDesktopAppend(int desktopIndex); ++ void onDesktopRemoved(int desktopIndex); ++ void onDesktopMoved(int srcDesktopIndex, int destDesktopIndex); ++}; ++ ++#endif // DESKTOPLISTMODEL_H +diff --git a/windowsview/multitaskviewabstractmodelhandler.h b/windowsview/multitaskviewabstractmodelhandler.h +new file mode 100644 +index 0000000..9d5b6cb +--- /dev/null ++++ b/windowsview/multitaskviewabstractmodelhandler.h +@@ -0,0 +1,185 @@ ++/* ++ * Copyright 2024 KylinSoft Co., Ltd. ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Library General Public License as ++ * published by the Free Software Foundation; either version 2, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details ++ * ++ * You should have received a copy of the GNU Library General Public ++ * License along with this program; if not, write to the ++ * Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ */ ++ ++#ifndef MultitaskViewAbstractModelHandler_H ++#define MultitaskViewAbstractModelHandler_H ++ ++#include <QObject> ++ ++class Window ++{ ++ Q_GADGET ++ Q_PROPERTY(int id READ id) ++ Q_PROPERTY(QString caption READ caption) ++ Q_PROPERTY(int x READ x) ++ Q_PROPERTY(int y READ y) ++ Q_PROPERTY(int width READ width) ++ Q_PROPERTY(int height READ height) ++ Q_PROPERTY(bool minimized READ minimized) ++ Q_PROPERTY(QString uuid READ uuid) ++ Q_PROPERTY(int desktopId READ desktopId) ++ Q_PROPERTY(int screenId READ screenId) ++ ++public: ++ Window() = default; ++ Window(int id, QString uuid, const QString& caption, int x, int y, int width, int height, bool minimized) ++ : m_id(id), ++ m_uuid(uuid), ++ m_caption(caption), ++ m_x(x), ++ m_y(y), ++ m_width(width), ++ m_height(height), ++ m_isMinimized(minimized) {} ++ int id() const { return m_id; } ++ QString uuid() const { return m_uuid; } ++ const QString& caption() const { return m_caption; } ++ int x() const { return m_x; } ++ int y() const { return m_y; } ++ int width() const { return m_width; } ++ int height() const { return m_height; } ++ bool minimized() const { return m_isMinimized; } ++ int desktopId() const { return m_desktopId; } ++ int screenId() const { return m_screenId; } ++ void setDesktopId(const int desktopId) { ++ m_desktopId = desktopId; ++ } ++ void setScreenId(const int screenId) { ++ m_screenId = screenId; ++ } ++ ++private: ++ int m_id = 0; ++ QString m_uuid; ++ QString m_caption; ++ int m_x = 0; ++ int m_y = 0; ++ int m_width = 0; ++ int m_height = 0; ++ bool m_isMinimized = false; ++ int m_desktopId = 1; ++ int m_screenId = 0; ++}; ++Q_DECLARE_METATYPE(Window) ++ ++ ++class Screen ++{ ++ Q_GADGET ++ Q_PROPERTY(int index READ index) ++ Q_PROPERTY(QList<Window> windowList READ windowList) ++ ++public: ++ Screen() = default; ++ Screen(int index, const QList<Window>& windowList) ++ : m_index(index), ++ m_windowList(windowList) {} ++ ++ int index() const { return m_index; } ++ const QList<Window>& windowList() const { return m_windowList; } ++ ++private: ++ int m_index = 0; ++ QList<Window> m_windowList; ++}; ++Q_DECLARE_METATYPE(Screen) ++ ++ ++class Desktop ++{ ++ Q_GADGET ++ Q_PROPERTY(QString uuid READ uuid) ++ Q_PROPERTY(QList<Screen> screenList READ screenList) ++ ++public: ++ enum DesktopType { ++ WorkSpace = 0, ++ NewDesktop ++ }; ++ ++ Desktop() = default; ++ Desktop(const QList<Screen>& screenList) ++ : m_screenList(screenList) {} ++ ++ QString uuid() const { return m_uuid; } ++ const QList<Screen>& screenList() { return m_screenList; } ++ DesktopType type() const { return m_type; }; ++ ++ void setUuid(const QString uuid) { ++ m_uuid = uuid; ++ } ++ void setScreenList(const QList<Screen>& screenList) { ++ m_screenList = screenList; ++ } ++ void setDesktopType(DesktopType type) { ++ m_type = type; ++ } ++ ++private: ++ QString m_uuid; ++ QList<Screen> m_screenList; ++ DesktopType m_type = DesktopType::WorkSpace; ++}; ++Q_DECLARE_METATYPE(Desktop) ++ ++class MultitaskViewAbstractModelHandler : public QObject ++{ ++ Q_OBJECT ++ Q_DISABLE_COPY(MultitaskViewAbstractModelHandler) ++ ++public: ++ explicit MultitaskViewAbstractModelHandler() = default; ++ ~MultitaskViewAbstractModelHandler() = default; ++ ++ virtual void removeAppWindow(QString windowId) = 0; ++ virtual void moveAppWindowToDesktop(QString windowId, int srcDesktopInex, int destDesktopInex) = 0; ++ virtual void activateAppWindow(QString windowId) = 0; ++ virtual QIcon getWindowIcon(QString windowId) = 0; ++ virtual void removeDesktop(int desktopIndex) = 0; ++ virtual void appendDesktop() = 0; ++ virtual void moveDesktop(int srcDesktopIndex, int destDesktopIndex) = 0; ++ virtual int getCurrentDesktop() = 0; ++ virtual bool isCurrentDesktopShowingDesktop() = 0; ++ virtual void setCurrentDesktop(int desktopIndex) = 0; ++ virtual QRect getFullScreenGeometry(int desktopIndex, int screenIndex) =0; ++ virtual bool hasModalChildWindow(QString windowId) = 0; ++ virtual bool isExtensionMode() = 0; ++ virtual int logicalScreenCount() = 0; ++ virtual QList<Window> createWindowList(int desktopIndex, int screenIndex) = 0; ++ virtual int getNumberOfDesktops() = 0; ++ virtual QString getDesktopUuid(int desktopIndex) = 0; ++ virtual QString getOutputUuid(int outputIndex) = 0; ++ ++signals: ++ void appWindowCreated(); ++ void appWindowRemoved(QString windowId); ++ void appWindowActivated(); ++ void appWindowDesktopChanged(QString windowId, int oldDesktopIndex,int newDesktopIndex); ++ void desktopRemoved(int desktopIndex); ++ void desktopAppended(int desktopIndex); ++ void desktopMoved(int oldDesktopIndex, int newDesktopIndex); ++ void currentDesktopChanged(int oldCurrentDesktopIndex, int newCurrentDesktopIndex); ++ void screenCountChanged(); ++ void screenSizeChanged(); ++ void desktopNumberChanged(); ++ void tabletModeChanged(bool tabletMode); ++ ++}; ++ ++ ++#endif // MultitaskViewAbstractModelHandler_H +diff --git a/windowsview/multitaskviewmodel.cpp b/windowsview/multitaskviewmodel.cpp +deleted file mode 100644 +index b88a1bd..0000000 +--- a/windowsview/multitaskviewmodel.cpp ++++ /dev/null +@@ -1,479 +0,0 @@ +-/* +- * Copyright 2022 KylinSoft Co., Ltd. +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU Library General Public License as +- * published by the Free Software Foundation; either version 2, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details +- * +- * You should have received a copy of the GNU Library General Public +- * License along with this program; if not, write to the +- * Free Software Foundation, Inc., +- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +- */ +- +-#include "multitaskviewmodel.h" +-#ifdef KWINEFFECT +- #include "ukui-window-switch-kwineffect/multitaskviewmodelbycompositehandler.h" +-#else +- #include "ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.h" +-#endif +- +-#include <algorithm> +- +-#include <QGSettings> +-#include <QSettings> +-#include <QGuiApplication> +-#include <QScreen> +-#include <QDBusConnection> +-#include <QDBusMessage> +-#include <QFile> +-#include <QJsonDocument> +-#include <QJsonObject> +- +-static const QString UKUI_STYLE_SCHEMA = "org.ukui.style"; +-static const QString UKUI_STYLE_SCHEMA_STYLENAME = "styleName"; +-static const QString UKUI_STYLE_SCHEMA_FONTSIZE = "systemFontSize"; +-static const QString UKUI_STYLE_SCHEMA_FONT = "systemFont"; +-static const QString UKUI_STYLE_SCHEMA_WIDGETNAME = "widgetThemeName"; +-const QString IGNORE_WINDOW_CONFIG = "/usr/share/ukui/ukui-panel/panel-commission.ini"; +- +-MultitaskViewModel::MultitaskViewModel(QObject *parent) : QObject(parent) +-{ +- //kwineffect相关接口无法在非effect插件的环境下编译通过,需要通过预编译来进行判断 +-#ifdef KWINEFFECT +- model_handler = new MultitaskViewModelByCompositeHandler(this); +-#else +- model_handler = new MultitaskViewModelByWlcomHandler(this); +- connect(model_handler, &MultitaskViewModelByWlcomHandler::desktopRemoved, this, &MultitaskViewModel::desktopRemoved); +-#endif +- updateModelData(); +- updateInputMode(); +- connectSignals(); +- if (QGSettings::isSchemaInstalled(UKUI_STYLE_SCHEMA.toUtf8())) { +- m_settings = new QGSettings(UKUI_STYLE_SCHEMA.toUtf8()); +- } +-} +- +-MultitaskViewModel::~MultitaskViewModel() +-{ +- delete model_handler; +-} +- +-bool MultitaskViewModel::currentDesktopHasWindow() const +-{ +- for (int screenIndex = 0; screenIndex < logicalScreenCount(); screenIndex++) { +- qDebug()<<"getAppWindowList(getCurrentDesktop(), screenIndex).size()"<<getAppWindowList(getCurrentDesktop(), screenIndex).size(); +- if (getAppWindowList(getCurrentDesktop(), screenIndex).size() > 0) { +- return true; +- } +- } +- return false; +-} +- +-QList<QVariant> MultitaskViewModel::getAppWindowList(int desktopIndex, int screenIndex) const +-{ +- if (!validateDesktopIndex(desktopIndex) ||!validateScreenIndex(screenIndex)) { +- return QList<QVariant>(); +- } +- +- auto desktopIter = std::find_if(m_desktopList.cbegin(), +- m_desktopList.cend(), +- [desktopIndex](const QVariant& desktop) { +- return desktop.value<Desktop>().index() == desktopIndex; +- }); +- if (desktopIter == m_desktopList.cend()) { +- return QList<QVariant>(); +- } +- +- const auto& desktop = desktopIter->value<Desktop>(); +- const auto& screenList = desktop.screenList(); +- auto screenIter = std::find_if(screenList.cbegin(), +- screenList.cend(), +- [screenIndex](const QVariant& screen) { +- return screen.value<Screen>().index() == screenIndex; +- }); +- if (screenIter == screenList.cend()) { +- return QList<QVariant>(); +- } +- +- const auto& screen = screenIter->value<Screen>(); +- auto appWindowList = screen.windowList(); +- std::reverse(appWindowList.begin(), appWindowList.end()); +- return appWindowList; +-} +- +- +-QList<QVariant> MultitaskViewModel::getAllAppWindowList() const +-{ +- QList<QVariant> allAppWindowList; +- for(int desktopIndex = 1; desktopIndex <= m_desktopList.size(); desktopIndex++) { +- for (int screenIndex = 0; screenIndex < logicalScreenCount(); screenIndex++) { +- allAppWindowList += getAppWindowList(desktopIndex, screenIndex); +- } +- } +- return allAppWindowList; +-} +- +-QString MultitaskViewModel::getDesktopUuid(int desktopIndex) +-{ +- return model_handler->getDesktopUuid(desktopIndex); +-} +- +-QString MultitaskViewModel::getOutputUuid(int outputIndex) +-{ +- return model_handler->getOutputUuid(outputIndex); +-} +- +-void MultitaskViewModel::removeAppWindow(QString windowId) +-{ +- model_handler->removeAppWindow(windowId); +-} +- +-void MultitaskViewModel::removeAllAppWindowOnDesktop(int desktopIndex, int screenIndex) +-{ +- QList<QVariant> windowList = getAppWindowList(desktopIndex, screenIndex); +- for (QVariant &windowVariant : windowList) { +- Window window = windowVariant.value<Window>(); +- removeAppWindow(window.uuid()); +- } +-} +- +-void MultitaskViewModel::moveAppWindowToDesktop(QString windowId, +- int srcDesktopInex, +- int destDesktopInex) const +-{ +- if (!validateDesktopIndex(srcDesktopInex) || !validateDesktopIndex(destDesktopInex)) { +- return; +- } +- model_handler->moveAppWindowToDesktop(windowId, srcDesktopInex, destDesktopInex); +-} +- +-void MultitaskViewModel::activateAppWindow(QString windowId) +-{ +- model_handler->activateAppWindow(windowId); +-} +- +-QIcon MultitaskViewModel::getWindowIcon(QString windowId) +-{ +- return model_handler->getWindowIcon(windowId); +-} +- +-QList<QVariant> MultitaskViewModel::getDesktopList() const +-{ +- return m_desktopList; +-} +- +-void MultitaskViewModel::removeDesktop(int desktopIndex) +-{ +- auto desktopCount = model_handler->getNumberOfDesktops(); +- if (desktopCount <= 1) { +- return; +- } +- if (!validateDesktopIndex(desktopIndex)) { +- return; +- } +- const auto oldDesktopIndex = desktopIndex; +- model_handler->removeDesktop(desktopIndex); +- updateModelData(); +-#ifdef KWINEFFECT +- emit desktopRemoved(oldDesktopIndex); +-#endif +-} +- +-void MultitaskViewModel::appendDesktop() +-{ +- auto desktopCount = model_handler->getNumberOfDesktops(); +- if (desktopCount >= MAX_DESKTOP_COUNT) { +- return; +- } +- model_handler->appendDesktop(); +- updateModelData(); +- emit desktopAppended(desktopCount + 1); +-} +- +-void MultitaskViewModel::moveDesktop(int srcDesktopIndex, int destDesktopIndex) +-{ +- if (!validateDesktopIndex(srcDesktopIndex) +- || !validateDesktopIndex(destDesktopIndex)) { +- return; +- } +- if (srcDesktopIndex == destDesktopIndex) { +- return; +- } +- model_handler->moveDesktop(srcDesktopIndex, destDesktopIndex); +- updateModelData(); +- emit desktopMoved(srcDesktopIndex, destDesktopIndex); +-} +- +-int MultitaskViewModel::getCurrentDesktop() const +-{ +- return model_handler->getCurrentDesktop(); +-} +- +-bool MultitaskViewModel::isCurrentDesktopShowingDesktop() const +-{ +- return model_handler->isCurrentDesktopShowingDesktop(); +-} +- +-void MultitaskViewModel::setCurrentDesktop(int desktopIndex) +-{ +- if (!validateDesktopIndex(desktopIndex)) { +- return; +- } +- model_handler->setCurrentDesktop(desktopIndex); +-} +- +-QRect MultitaskViewModel::getFullScreenGeometry(int desktopIndex, int screenIndex) const +-{ +- return model_handler->getFullScreenGeometry(desktopIndex, screenIndex); +-} +- +-bool MultitaskViewModel::hasModalChildWindow(QString windowId) +-{ +- return model_handler->hasModalChildWindow(windowId); +-} +- +-QString MultitaskViewModel::getUKUIStyleName() const +-{ +- // default to ukui-default +- QString styleName = "ukui-default"; +- if (m_settings && m_settings->keys().contains(UKUI_STYLE_SCHEMA_STYLENAME)) { +- styleName = m_settings->get(UKUI_STYLE_SCHEMA_STYLENAME).toString(); +- } else { +- qWarning() << QString("未查询到Gesetting的键值(%1)").arg(UKUI_STYLE_SCHEMA_STYLENAME); +- } +- return styleName; +-} +- +-double MultitaskViewModel::getUKUIFontSize() const +-{ +- // default to 11 +- double fontSize = 11; +- if (m_settings && m_settings->keys().contains(UKUI_STYLE_SCHEMA_FONTSIZE)) { +- fontSize = m_settings->get(UKUI_STYLE_SCHEMA_FONTSIZE).toDouble(); +- } else { +- qWarning() << QString("未查询到Gesetting的键值(%1)").arg(UKUI_STYLE_SCHEMA_FONTSIZE); +- } +- return fontSize; +-} +- +-QString MultitaskViewModel::getUKUIFont() const +-{ +- // default to 11 +- QString font = "Noto Sans CJK SC"; +- if (m_settings && m_settings->keys().contains(UKUI_STYLE_SCHEMA_FONT)) { +- font = m_settings->get(UKUI_STYLE_SCHEMA_FONT).toString(); +- } else { +- qWarning() << QString("未查询到Gesetting的键值(%1)").arg(UKUI_STYLE_SCHEMA_FONT); +- } +- return font; +-} +- +-void MultitaskViewModel::setIsOpenGLBackend(bool isOpenGLBackend) +-{ +- m_isOpenGLBackend = isOpenGLBackend; +-} +- +-int MultitaskViewModel::getRadius(QString type) const +-{ +- return m_isOpenGLBackend ? getUKUIRadius(type) : 0; +-} +- +-int MultitaskViewModel::getAllWindowCount() const +-{ +- return getAllAppWindowList().size(); +-} +- +-int MultitaskViewModel::getUKUIRadius(QString type) const +-{ +- // default to 8 +- QString widgetName = "default"; +- if (m_settings && m_settings->keys().contains(UKUI_STYLE_SCHEMA_WIDGETNAME)) { +- widgetName = m_settings->get(UKUI_STYLE_SCHEMA_WIDGETNAME).toString(); +- } else { +- qWarning() << QString("未查询到Gesetting的键值(%1)").arg(UKUI_STYLE_SCHEMA_WIDGETNAME); +- return 8; +- } +- +- QFile file(QString("/usr/share/qt5-ukui-platformtheme/themeconfig/%1.json").arg(widgetName)); +- if (!file.open(QIODevice::ReadOnly)) { +- qWarning() << "无法打开JSON文件"; +- return 8; +- } +- +- QByteArray jsonData = file.readAll(); +- file.close(); +- +- // 将JSON数据转换为QJsonDocument对象 +- QJsonParseError error; +- QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &error); +- if (error.error != QJsonParseError::NoError) { +- qWarning() << "JSON格式错误:" << error.errorString(); +- return 8; +- } +- +- // 获取属性 +- QJsonObject rootObj = jsonDoc.object(); +- QJsonObject radiusObj = rootObj["Radius"].toObject(); +- QJsonObject radiusValueObj = radiusObj[type].toObject(); +- +- return radiusValueObj["value"].toString().toInt(); +-} +- +-void MultitaskViewModel::onWindowAdded() +-{ +- updateModelData(); +- emit appWindowCreated(); +-} +- +-void MultitaskViewModel::onWindowDeleted(QString windowId) +-{ +- updateModelData(); +- emit appWindowRemoved(windowId); +-} +- +-void MultitaskViewModel::onWindowActivated() +-{ +- emit appWindowActivated(); +-} +- +-void MultitaskViewModel::onDesktopPresenceChanged(QString windowId, +- int oldDesktopIndex, int newDesktopIndex) +-{ +- updateModelData(); +- emit appWindowDesktopChanged(windowId, oldDesktopIndex, newDesktopIndex); +-} +- +-void MultitaskViewModel::onNumberScreensChanged() +-{ +- updateModelData(); +- emit screenCountChanged(); +-} +- +-void MultitaskViewModel::onCurrentDesktopChanged(int oldCurrentDesktopIndex, int newCurrentDesktopIndex) +-{ +- updateModelData(); +- emit currentDesktopChanged(oldCurrentDesktopIndex, newCurrentDesktopIndex); +-} +- +-bool MultitaskViewModel::isExtensionMode() +-{ +- return model_handler->isExtensionMode(); +-} +- +-int MultitaskViewModel::logicalScreenCount() const +-{ +- return model_handler->logicalScreenCount(); +-} +- +-bool MultitaskViewModel::isTabletMode() const +-{ +- // default to PC mode. +- bool tabletMode = false; +- QDBusMessage message = QDBusMessage::createMethodCall("com.kylin.statusmanager.interface", +- "/", +- "com.kylin.statusmanager.interface", +- "get_current_tabletmode"); +- QDBusMessage response = QDBusConnection::sessionBus().call(message); +- if (response.type() == QDBusMessage::ReplyMessage) { +- tabletMode = response.arguments().takeFirst().toBool(); +- } else { +- qDebug() << "get tablet mode failed " << response.type(); +- } +- return tabletMode; +-} +- +-QString MultitaskViewModel::getCurrentLanguage() const +-{ +- // default to "Chinese". +- QLocale locale = QLocale::system(); +- QString language = "Chinese"; +- if (locale.language() == QLocale::Chinese) { +- language = "Chinese"; +- } else if (locale.language() == QLocale::Tibetan) { +- language = "Tibetan"; +- } +- return language; +-} +- +-void MultitaskViewModel::updateModelData() +-{ +- QList<QVariant> desktopList; +- const auto desktopCount = model_handler->getNumberOfDesktops(); +- for (int desktopIndex = 1; desktopIndex <= desktopCount; desktopIndex++) { +- QList<QVariant> screenList; +- for (int screenIndex = 0; screenIndex < logicalScreenCount(); screenIndex++) { +- auto screen = QVariant::fromValue(Screen(screenIndex, model_handler->createWindowList(desktopIndex, screenIndex))); +- screenList.append(std::move(screen)); +- } +- auto desktop = QVariant::fromValue(Desktop(desktopIndex, screenList)); +- desktopList.append(std::move(desktop)); +- } +- m_desktopList = std::move(desktopList); +-} +- +-void MultitaskViewModel::updateInputMode() +-{ +- +- QDBusMessage message = QDBusMessage::createMethodCall("com.kylin.statusmanager.interface", +- "/", +- "com.kylin.statusmanager.interface", +- "get_inputmethod_mode"); +- QDBusMessage response = QDBusConnection::sessionBus().call(message); +- if (response.type() == QDBusMessage::ReplyMessage) { +- m_inputMode = response.arguments().takeFirst().toBool(); +- qDebug() << "m_inputMode =" << m_inputMode; +- } else { +- // invalid response, keep default. +- } +-} +- +-// static +-bool MultitaskViewModel::validateDesktopIndex(int desktopIndex) +-{ +- return desktopIndex >= 1 && desktopIndex <= MAX_DESKTOP_COUNT; +-} +- +-bool MultitaskViewModel::validateScreenIndex(int screenIndex) const +-{ +- return screenIndex >= 0 && screenIndex < logicalScreenCount(); +-} +- +-void MultitaskViewModel::connectSignals() +-{ +- QObject::connect(model_handler, &MultitaskViewModelHandler::appWindowCreated, +- this, &MultitaskViewModel::onWindowAdded); +- QObject::connect(model_handler, &MultitaskViewModelHandler::appWindowRemoved, +- this, &MultitaskViewModel::onWindowDeleted); +- QObject::connect(model_handler, &MultitaskViewModelHandler::appWindowActivated, +- this, &MultitaskViewModel::onWindowActivated); +- QObject::connect(model_handler, &MultitaskViewModelHandler::appWindowDesktopChanged, +- this, &MultitaskViewModel::onDesktopPresenceChanged); +- QObject::connect(model_handler, &MultitaskViewModelHandler::currentDesktopChanged, +- this, &MultitaskViewModel::onCurrentDesktopChanged); +- QObject::connect(model_handler, &MultitaskViewModelHandler::tabletModeChanged, +- this, &MultitaskViewModel::tabletModeChanged); +- QObject::connect(model_handler, &MultitaskViewModelHandler::screenSizeChanged, +- this, &MultitaskViewModel::screenSizeChanged); +- QObject::connect(qGuiApp, &QGuiApplication::screenAdded, +- this, &MultitaskViewModel::onNumberScreensChanged); +- QObject::connect(qGuiApp, &QGuiApplication::screenRemoved, +- this, &MultitaskViewModel::onNumberScreensChanged); +- QDBusConnection::sessionBus().connect("com.kylin.statusmanager.interface", +- "/", +- "com.kylin.statusmanager.interface", +- "inputmethod_change_signal", +- this, +- SLOT(inputModeSlot(bool))); +-} +- +-void MultitaskViewModel::inputModeSlot(bool inputMode) +-{ +- m_inputMode = inputMode; +- emit inputModeChanged(m_inputMode); +-} +diff --git a/windowsview/multitaskviewmodel.h b/windowsview/multitaskviewmodel.h +deleted file mode 100644 +index 24bb5db..0000000 +--- a/windowsview/multitaskviewmodel.h ++++ /dev/null +@@ -1,203 +0,0 @@ +-/* +- * Copyright 2022 KylinSoft Co., Ltd. +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU Library General Public License as +- * published by the Free Software Foundation; either version 2, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details +- * +- * You should have received a copy of the GNU Library General Public +- * License along with this program; if not, write to the +- * Free Software Foundation, Inc., +- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +- */ +- +-#ifndef MULTITASKVIEWMODEL_H +-#define MULTITASKVIEWMODEL_H +- +-#include <QObject> +-#include <QIcon> +-#include <QList> +-#include <QMap> +-#include <QRect> +-#include <QVariantList> +-#include <QString> +-#include <kwineffects.h> +-#include "multitaskviewmodelhandler.h" +- +-using namespace KWin; +-class QGSettings; +- +-class Window +-{ +- Q_GADGET +- Q_PROPERTY(int id READ id) +- Q_PROPERTY(QString caption READ caption) +- Q_PROPERTY(int x READ x) +- Q_PROPERTY(int y READ y) +- Q_PROPERTY(int width READ width) +- Q_PROPERTY(int height READ height) +- Q_PROPERTY(bool minimized READ minimized) +- Q_PROPERTY(QString uuid READ uuid) +- +-public: +- Window() = default; +- Window(int id, const QString& caption, int x, int y, int width, int height, bool minimized, QString uuid) +- : m_id(id), +- m_caption(caption), +- m_x(x), +- m_y(y), +- m_width(width), +- m_height(height), +- m_isMinimized(minimized), +- m_uuid(uuid) {} +- int id() const { return m_id; } +- QString uuid() const { return m_uuid; } +- const QString& caption() const { return m_caption; } +- int x() const { return m_x; } +- int y() const { return m_y; } +- int width() const { return m_width; } +- int height() const { return m_height; } +- bool minimized() const { return m_isMinimized; } +- +-private: +- int m_id = 0; +- QString m_uuid; +- QString m_caption; +- int m_x = 0; +- int m_y = 0; +- int m_width = 0; +- int m_height = 0; +- bool m_isMinimized = false; +-}; +- +- +-class Screen +-{ +- Q_GADGET +- Q_PROPERTY(int index READ index) +- Q_PROPERTY(QList<QVariant> windowList READ windowList) +- +-public: +- Screen() = default; +- Screen(int index, const QList<QVariant>& windowList) +- : m_index(index), +- m_windowList(windowList) {} +- +- int index() const { return m_index; } +- const QList<QVariant>& windowList() const { return m_windowList; } +- +-private: +- int m_index = 0; +- QList<QVariant> m_windowList; +-}; +- +-class Desktop +-{ +- Q_GADGET +- Q_PROPERTY(int index READ index) +- Q_PROPERTY(QList<QVariant> screenList READ screenList) +- +-public: +- Desktop() = default; +- Desktop(int index, const QList<QVariant>& screenList) +- : m_index(index), +- m_screenList(screenList) {} +- +- int index() const { return m_index; } +- const QList<QVariant>& screenList() const { return m_screenList; } +- +-private: +- int m_index = 1; +- QList<QVariant> m_screenList; +-}; +- +-class MultitaskViewModel : public QObject +-{ +- Q_OBJECT +- Q_PROPERTY(int logicalScreenCount READ logicalScreenCount NOTIFY screenCountChanged) +- Q_PROPERTY(bool isTabletMode READ isTabletMode NOTIFY tabletModeChanged) +- Q_PROPERTY(bool inputMode READ isInputMode NOTIFY inputModeChanged) +-public: +- explicit MultitaskViewModel(QObject *parent = nullptr); +- ~MultitaskViewModel(); +- Q_INVOKABLE bool currentDesktopHasWindow() const; +- Q_INVOKABLE QList<QVariant> getAppWindowList(int desktopIndex, int screenIndex) const; +- Q_INVOKABLE QList<QVariant> getAllAppWindowList() const; +- Q_INVOKABLE void removeAppWindow(QString windowId); +- Q_INVOKABLE void removeAllAppWindowOnDesktop(int desktopIndex, int screenIndex); +- Q_INVOKABLE void moveAppWindowToDesktop(QString windowId, int srcDesktopInex, int destDesktopInex) const; +- Q_INVOKABLE void activateAppWindow(QString windowId); +- Q_INVOKABLE QIcon getWindowIcon(QString windowId); +- Q_INVOKABLE QList<QVariant> getDesktopList() const; +- Q_INVOKABLE void removeDesktop(int desktopIndex); +- Q_INVOKABLE void appendDesktop(); +- Q_INVOKABLE void moveDesktop(int srcDesktopIndex, int destDesktopIndex); +- Q_INVOKABLE int getCurrentDesktop() const; +- Q_INVOKABLE bool isCurrentDesktopShowingDesktop() const; +- Q_INVOKABLE void setCurrentDesktop(int desktopIndex); +- Q_INVOKABLE QRect getFullScreenGeometry(int desktopIndex, int screenIndex) const; +- Q_INVOKABLE bool hasModalChildWindow(QString windowId); +- Q_INVOKABLE bool isTabletMode() const; +- Q_INVOKABLE bool isInputMode() const { return m_inputMode; } +- Q_INVOKABLE QString getCurrentLanguage() const; +- Q_INVOKABLE QString getUKUIStyleName() const; +- Q_INVOKABLE double getUKUIFontSize() const; +- Q_INVOKABLE QString getUKUIFont() const; +- Q_INVOKABLE int getRadius(QString type) const; +- Q_INVOKABLE int getAllWindowCount() const; +- Q_INVOKABLE QString getDesktopUuid(int desktopIndex); +- Q_INVOKABLE QString getOutputUuid(int outputIndex); +- void setIsOpenGLBackend(bool isOpenGLBackend); +- +-signals: +- void appWindowCreated(); +- void appWindowRemoved(QString windowId); +- void appWindowActivated(); +- void appWindowDesktopChanged(QString windowId, int oldDesktopIndex, int newDesktopIndex); +- void desktopRemoved(int desktopIndex); +- void desktopAppended(int desktopIndex); +- void desktopMoved(int oldDesktopIndex, int newDesktopIndex); +- void currentDesktopChanged(int oldCurrentDesktopIndex, int newCurrentDesktopIndex); +- void screenCountChanged(); +- void screenSizeChanged(); +- void tabletModeChanged(bool); +- void inputModeChanged(bool); +- +-private slots: +- void onWindowAdded(); +- void onWindowDeleted(QString windowId); +- void onWindowActivated(); +- void onDesktopPresenceChanged(QString windowId, int oldDesktopIndex, int newDesktopIndex); +- void onCurrentDesktopChanged(int oldCurrentDesktopIndex, int newCurrentDesktopIndex); +- void onNumberScreensChanged(); +- void inputModeSlot(bool); +- +-private: +- bool isExtensionMode(); +- int logicalScreenCount() const; +- void updateModelData(); +- void updateInputMode(); +- static bool validateDesktopIndex(int desktopIndex); +- bool validateScreenIndex(int screenIndex) const; +- void connectSignals(); +- int getUKUIRadius(QString type) const; +- +-private: +- // 虚拟桌面列表 +- QList<QVariant> m_desktopList; +- // 屏幕数量 +- int m_screenCount = 0; +- bool m_inputMode; +- // 最大虚拟桌面数量为16 +- static constexpr int MAX_DESKTOP_COUNT = 16; +- QGSettings* m_settings = nullptr; +- bool m_isOpenGLBackend = true; +- MultitaskViewModelHandler *model_handler; +-}; +- +-#endif // MULTITASKVIEWMODEL_H +diff --git a/windowsview/multitaskviewmodelhandler.h b/windowsview/multitaskviewmodelhandler.h +deleted file mode 100644 +index 0f6fe0d..0000000 +--- a/windowsview/multitaskviewmodelhandler.h ++++ /dev/null +@@ -1,69 +0,0 @@ +-/* +- * Copyright 2024 KylinSoft Co., Ltd. +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU Library General Public License as +- * published by the Free Software Foundation; either version 2, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details +- * +- * You should have received a copy of the GNU Library General Public +- * License along with this program; if not, write to the +- * Free Software Foundation, Inc., +- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +- */ +- +-#ifndef MultitaskViewModelHandler_H +-#define MultitaskViewModelHandler_H +- +-#include <QObject> +- +-class MultitaskViewModelHandler : public QObject +-{ +- Q_OBJECT +- Q_DISABLE_COPY(MultitaskViewModelHandler) +- +-public: +- explicit MultitaskViewModelHandler() = default; +- ~MultitaskViewModelHandler() = default; +- +- virtual void removeAppWindow(QString windowId) = 0; +- virtual void moveAppWindowToDesktop(QString windowId, int srcDesktopInex, int destDesktopInex) = 0; +- virtual void activateAppWindow(QString windowId) = 0; +- virtual QIcon getWindowIcon(QString windowId) = 0; +- virtual void removeDesktop(int desktopIndex) = 0; +- virtual void appendDesktop() = 0; +- virtual void moveDesktop(int srcDesktopIndex, int destDesktopIndex) = 0; +- virtual int getCurrentDesktop() = 0; +- virtual bool isCurrentDesktopShowingDesktop() = 0; +- virtual void setCurrentDesktop(int desktopIndex) = 0; +- virtual QRect getFullScreenGeometry(int desktopIndex, int screenIndex) =0; +- virtual bool hasModalChildWindow(QString windowId) = 0; +- virtual bool isExtensionMode() = 0; +- virtual int logicalScreenCount() = 0; +- virtual QList<QVariant> createWindowList(int desktopIndex, int screenIndex) = 0; +- virtual int getNumberOfDesktops() = 0; +- virtual QString getDesktopUuid(int desktopIndex) = 0; +- virtual QString getOutputUuid(int outputIndex) = 0; +- +-signals: +- void appWindowCreated(); +- void appWindowRemoved(QString windowId); +- void appWindowActivated(); +- void appWindowDesktopChanged(QString windowId, int oldDesktopIndex,int newDesktopIndex); +- void desktopRemoved(int desktopIndex); +- void desktopAppended(int desktopIndex); +- void desktopMoved(int oldDesktopIndex, int newDesktopIndex); +- void currentDesktopChanged(int oldCurrentDesktopIndex, int newCurrentDesktopIndex); +- void screenCountChanged(); +- void screenSizeChanged(); +- void desktopNumberChanged(); +- void tabletModeChanged(bool tabletMode); +- +-}; +- +- +-#endif // MultitaskViewModelHandler_H +diff --git a/windowsview/qml/AppArea.qml b/windowsview/qml/AppArea.qml +index 3035202..dda1d85 100644 +--- a/windowsview/qml/AppArea.qml ++++ b/windowsview/qml/AppArea.qml +@@ -19,62 +19,44 @@ + import QtQuick 2.12 + import QtQuick.Controls 2.5 + import QtQuick.Layouts 1.3 +-import QtQuick.Window 2.12 +-import QtQuick.Controls.Styles 1.4 + import "Controller.js" as Controller ++import AppWindowFilterModel 1.0 ++import org.ukui.positioner 1.0 + + FocusScope { + id : root + property var appAreaController : new Controller.AppController(multitaskViewModel, root, multitaskViewManager, ["none"]) +- property var currentTabIndex: 0 ++ property int currentTabIndex: 0 + +- ScrollView { ++ AppWindowFilterModel { ++ id: appAreaModel ++ desktopId: rootWindow.highlightDesktop ++ screenId: mainView.screenIndex ++ sourceModel: appWindowListModel ++ } ++ ++ Flickable { + id : scrollArea + anchors.fill : parent + anchors.margins: scrollViewLeftSpace + anchors.bottomMargin: 0 +- property var flowRows : 0 +- property var flowYAnimationNeedStart : false +- property ScrollBar vScrollBar: ScrollBar.vertical +- property int vScrollBarWidth: vScrollBar.width + property ListModel windowPosInfoModel: ListModel{} + property var rowSpacing : isVerticalLayout ? Math.floor(24 * scaleFactor) : Math.floor(10 * scaleFactor) + property var columnSpacing : isVerticalLayout ? Math.floor(24 * scaleFactor) : Math.floor(10 * scaleFactor) +- property var tabBorderVisble : false ++ property bool tabBorderVisble : false ++ height: parent.height ++ width: parent.width + contentWidth : parent.width - scrollViewLeftSpace * 2 +- contentHeight : getContentHeight() +- ScrollBar.horizontal.policy : ScrollBar.AlwaysOff +- ScrollBar.vertical.policy : ScrollBar.AsNeeded +- ScrollBar.vertical.visible : contentHeight > height ++ contentHeight : Math.max(flow.height, height) + clip : true + +- function getContentHeight() +- { +- var currentContentHeight = scrollViewYStartPoint + flowRows * (previewWindowHeight + columnSpacing) - columnSpacing +- if (currentContentHeight > scrollArea.height) { +- return currentContentHeight +- } else { +- return scrollArea.height +- } +- } +- +- function getFlowY() { +- var flowHeight = scrollArea.flowRows * (previewWindowHeight + scrollArea.columnSpacing) - scrollArea.columnSpacing +- return Math.max((scrollArea.height - flowHeight) / 2, scrollViewYStartPoint) +- } +- +- onFlowRowsChanged : { +- contentHeight = getContentHeight() +- //当多任务视图打开或者切换工作区时,同样会有flowRowsChanged信号发出 +- //这种情况下直接设置坐标即可,不需要播放居中动画 +- if (flowYAnimationNeedStart) { +- flowYChangeAnimation.stop() +- flowYChangeAnimation.to = getFlowY() +- flowYChangeAnimation.start() +- flowYAnimationNeedStart = false +- } else { +- flowLayout.y = getFlowY() +- } ++ ScrollBar.vertical: ScrollBar { ++ id: vScrollBar ++ parent: scrollArea.parent ++ anchors.top: scrollArea.top ++ anchors.left: scrollArea.right ++ anchors.bottom: scrollArea.bottom ++ visible : flow.height > scrollArea.height + } + + MouseArea{ +@@ -87,28 +69,22 @@ FocusScope { + + NumberAnimation { + id : scrollMoveAnimation +- target : scrollArea.vScrollBar ++ target : vScrollBar + property : "position" +- from : scrollArea.vScrollBar.position ++ from : vScrollBar.position + duration : 300 + easing.type : Easing.InOutQuart + } + +- NumberAnimation { +- id : flowYChangeAnimation +- target : flowLayout +- property : "y" +- from : flowLayout.y +- duration : 300 +- easing.type : Easing.InOutQuart +- } ++ UkuiFlow { ++ id : flow ++ property bool needFlowYAnimation : false + +- Flow { +- id : flowLayout + spacing : scrollArea.rowSpacing + width : parent.width + flow : Flow.LeftToRight + layoutDirection: isLayoutLeftToRight ? Qt.LeftToRight : Qt.RightToLeft ++ lineHorizontalCenterAlignment: true + + move :Transition { //子项增加时或者减少时的过度,也就是子项的visible变化的过度 + NumberAnimation { +@@ -118,21 +94,74 @@ FocusScope { + } + } + ++ onHeightChanged: { ++ y = Math.max((scrollArea.height - flow.height) / 2, scrollViewYStartPoint) ++ } ++ ++ // flow 垂直居中动画 ++ Behavior on y { ++ enabled: flow.needFlowYAnimation ++ NumberAnimation { ++ duration : isVerticalLayout ? 500 : 300 ++ easing.type : Easing.InOutQuart ++ } ++ } ++ ++ onPositioningComplete: { ++ updateWindowPosInfo() ++ } ++ ++ function updateWindowPosInfo() { ++ var rowWindowNum = 0 //窗口区域每行的窗口数 ++ var leftX = 0 ++ var rightX = 0 ++ var rowY = 0 ++ var itemCount = 0 ++ var winModel = [] ++ scrollArea.windowPosInfoModel.clear() ++ ++ for (let i = 0; i < flow.children.length; ++i) { ++ if (flow.children[i].width === 0) { ++ continue ++ } ++ ++ // 根据预览窗 Y 坐标判断是否到下一行 ++ if (flow.children[i].y !== rowY) { ++ if (winModel.length > 0) { ++ scrollArea.windowPosInfoModel.append({model : winModel, rowWindowCount : rowWindowNum}) ++ winModel = [] ++ rowWindowNum = 0 ++ } ++ rowY += previewWindowHeight + flow.spacing ++ } ++ ++ // 更新预览窗在 Flow 布局中的 X 坐标并存入局部 model ++ itemCount++ ++ leftX = flow.children[i].x ++ rightX = leftX + flow.children[i].width ++ winModel.push({index: itemCount - 1, leftX: leftX, rightX: rightX}) ++ rowWindowNum++ ++ } ++ if (winModel.length > 0) { ++ scrollArea.windowPosInfoModel.append({model : winModel, rowWindowCount : rowWindowNum}) ++ } ++ } ++ + Repeater { +- property int loadedCount : 0 + id : previewWindowRepeater +- model : appWindowModel +- activeFocusOnTab: appWindowModel.count !== 0 ? true : false ++ model : appAreaModel ++ activeFocusOnTab: count !== 0 ? true : false + focus : true + +- Rectangle { ++ delegate: Rectangle { + id : thumbnailitem + height : previewWindowHeight ++ width : Math.max(thumbWidth + 2 * appThumbnailMargin, Math.floor(root.width / 10)) + focus: true + color : "transparent" + property var thumbWidth : getThumbnailSize()[0] + property var thumbHeight : getThumbnailSize()[1] +- property var trueWidth : Math.max(thumbWidth + 2 * appThumbnailMargin, Math.floor(root.width / 10)) ++ property string uuid: model.Uuid + + states: [ + State { +@@ -148,9 +177,9 @@ FocusScope { + function getThumbnailSize() + { + var thumbHeight = thumbRectangleHeight +- var max_width = root.width / 3 +- var clientWidth = model.width +- var clientHeight = model.height ++ var max_width = parent.width / 3 ++ var clientWidth = model.Width ++ var clientHeight = model.Height + var thumbWidth = Math.floor(thumbHeight * clientWidth / clientHeight) + if (thumbWidth > max_width) { + thumbWidth = max_width +@@ -162,15 +191,15 @@ FocusScope { + AppPreviewWindow { + id : appWindow + // Warning: 因为 appWindow 的 parent 会改变,所以不要使用 parent 获取宽高 +- x : isLayoutLeftToRight ? thumbnailitem.width - thumbnailitem.trueWidth : 0 +- width : thumbnailitem.trueWidth ++ width : thumbnailitem.width + height : thumbnailitem.height + thumbHeight : thumbnailitem.thumbHeight + thumbWidth : thumbnailitem.thumbWidth + windowType : "app" +- x_wid : model.id +- wid : model.uuid +- caption : model.caption ++ x_wid : model.Id ++ wid : model.Uuid ++ caption : model.Caption ++ parent: thumbnailitem + + Drag.onActiveChanged : { + if (!Drag.active) { +@@ -187,7 +216,7 @@ FocusScope { + onActiveFocusChanged: { + if (previewWindowRepeater.activeFocus) { + currentTabIndex = 0 +- if (scrollArea.vScrollBar.position > 0) { ++ if (vScrollBar.position > 0) { + scrollMoveAnimation.to = 0 + scrollMoveAnimation.start() + } +@@ -195,96 +224,17 @@ FocusScope { + } + } + +- /* +- 窗口区域布局居中的问题: +- 组件自身不能实现布局居中,所以使用算法的方式进行计算每一个窗口的大小 +- 思路如下: +- 每一行的第一个和最后一个都是一个很长的Rectangle,缩略窗口(trueWidth)只是计算好应该放在哪个位置, +- 其他的窗口都是实际窗口大小(trueWidth),通过spacing就能等间隔的放置在相应的位置. +- 通过计算一行(lineWidth)是否可以在放下下一个窗口, +- 即当前放置的窗口所占的宽度(nowlineWidth)是否大于屏幕的宽度(lineWidth),来确定是否切换行 +- */ +- function adjustSize() +- { +- if (loadedCount !== previewWindowCount) { +- return; +- } +- if (previewWindowCount === 0) { +- //flowRows为0,说明发生了工作区切换或者所有窗口关闭 +- //这两种情况都不需要播放居中动画,所以flowYAnimationNeedStart保持为false +- scrollArea.flowRows = 0 +- return +- } +- +- var cols = 0; +- var lineWidth = root.width; +- var nowlineWidth = 0 +- var nowflowRows = 0 +- var rowWindowNum = 0 //窗口区域每行有多少窗口 +- var leftX = 0 +- var rightX = 0 +- scrollArea.windowPosInfoModel.clear() +- +- // 调整预览窗口外层矩形框的 width,并更新每行第一个预览窗口的 width +- // 每行第一个预览窗口的 width 和 trueWitdh 不一致,为的是将每一行预览窗口进行居中 +- // 对于所有预览窗口 width >= trueWidth +- for (var i = 0; i < loadedCount; i++) { +- var lastline = true +- // 单独处理每一行的第一个预览窗口,因为第一个预览窗口前面没有 rowSpacing,不应该计算进去 +- nowlineWidth = itemAt(i).trueWidth +- cols = i +- for(var j = i + 1; j < loadedCount; j++) { +- nowlineWidth = nowlineWidth + scrollArea.rowSpacing + itemAt(j).trueWidth +- if (nowlineWidth < lineWidth - 2 * scrollViewLeftSpace - scrollArea.vScrollBarWidth) { +- itemAt(j).width = itemAt(j).trueWidth +- cols = j +- } else { +- lastline = false +- nowlineWidth = nowlineWidth - scrollArea.rowSpacing - itemAt(j).trueWidth +- break; +- } +- } +- itemAt(i).width = itemAt(i).trueWidth + Math.floor((lineWidth - 2 * scrollViewLeftSpace - scrollArea.vScrollBarWidth - nowlineWidth) / 2) +- i = cols +- nowflowRows++ +- } +- if (scrollArea.flowRows > nowflowRows) { +- //行数减少时,重新计算y坐标,播放居中动画 +- scrollArea.flowYAnimationNeedStart = true +- } +- scrollArea.flowRows = nowflowRows +- // 更新缩略图在 Flow 布局中的 X 坐标并存入局部 model +- var winModel = [] +- for (var m = 0; m < loadedCount; m++) { +- if (itemAt(m).width !== itemAt(m).trueWidth) { +- nowlineWidth = itemAt(m).width +- if (winModel.length > 0) { +- scrollArea.windowPosInfoModel.append({model : winModel, rowWindowCount : rowWindowNum}); +- } +- rowWindowNum = 1 +- winModel = [] +- } else { +- nowlineWidth = nowlineWidth + scrollArea.rowSpacing + itemAt(m).trueWidth +- rowWindowNum++ +- } +- leftX = nowlineWidth - itemAt(m).trueWidth +- rightX = nowlineWidth +- winModel.push({index: m, leftX: leftX, rightX: rightX, width: itemAt(m).width}) +- } +- if (winModel.length > 0) { +- scrollArea.windowPosInfoModel.append({model : winModel, rowWindowCount : rowWindowNum}); +- winModel = [] +- } +- } + + onItemAdded : { +- loadedCount++; +- adjustSize(); ++ if (flow.needFlowYAnimation !== false) { ++ flow.needFlowYAnimation = false ++ } + } + + onItemRemoved : { +- loadedCount--; +- adjustSize(); ++ if (flow.needFlowYAnimation !== true) { ++ flow.needFlowYAnimation = true ++ } + } + + Keys.onPressed: { +@@ -292,49 +242,26 @@ FocusScope { + scrollArea.tabBorderVisble = true + if (currentTabIndex > 0) { + currentTabIndex = currentTabIndex - 1 +- var currentNextY = itemAt(currentTabIndex).mapToItem(scrollArea, 0, 0).y +- if (currentNextY < 0 ) { +- scrollMoveAnimation.to = scrollArea.vScrollBar.position - (-currentNextY) / scrollArea.contentHeight +- scrollMoveAnimation.start() +- } + } else if (currentTabIndex === 0) { +- currentTabIndex = appWindowModel.count - 1 +- var currentNextY = itemAt(currentTabIndex).mapToItem(scrollArea, 0, 0).y +- if (currentNextY + previewWindowHeight > scrollArea.height) { +- scrollMoveAnimation.to = scrollArea.vScrollBar.position + (currentNextY + previewWindowHeight - scrollArea.height) / scrollArea.contentHeight +- scrollMoveAnimation.start() +- } ++ currentTabIndex = previewWindowRepeater.count - 1 + } + event.accepted = true ++ + } else if (event.key === Qt.Key_Right ) { + scrollArea.tabBorderVisble = true +- if (currentTabIndex < appWindowModel.count - 1) { ++ if (currentTabIndex < previewWindowRepeater.count - 1) { + currentTabIndex = currentTabIndex + 1 +- var currentNextY = previewWindowRepeater.itemAt(currentTabIndex).mapToItem(scrollArea, 0, 0).y +- if (currentNextY + previewWindowHeight > scrollArea.height) { +- scrollMoveAnimation.to = scrollArea.vScrollBar.position + (currentNextY + previewWindowHeight - scrollArea.height) / scrollArea.contentHeight +- scrollMoveAnimation.start() +- } +- } else if (currentTabIndex === appWindowModel.count - 1) { ++ } else if (currentTabIndex === previewWindowRepeater.count - 1) { + currentTabIndex = 0 +- if (scrollArea.vScrollBar.position > 0) { +- scrollMoveAnimation.to = 0 +- scrollMoveAnimation.start() +- } + } + event.accepted = true ++ + } else if (event.key === Qt.Key_Up || event.key === Qt.Key_Down) { + scrollArea.tabBorderVisble = true + var isKeyUp = event.key === Qt.Key_Up + currentTabIndex = appAreaController.keyUpDownSelectWindow(isKeyUp, scrollArea.windowPosInfoModel, currentTabIndex) +- var currentNextY = itemAt(currentTabIndex).mapToItem(scrollArea, 0, 0).y +- if (currentNextY < -itemAt(currentTabIndex).height) { +- scrollMoveAnimation.to = 0 +- scrollMoveAnimation.start() +- } else if (currentNextY > root.height) { +- scrollMoveAnimation.to = scrollArea.vScrollBar.position + (currentNextY + previewWindowHeight - scrollArea.height) / scrollArea.contentHeight +- scrollMoveAnimation.start() +- } ++ event.accepted = true ++ + } else if (event.key === Qt.Key_Tab) { + if (event.modifiers & Qt.MetaModifier) { + appAreaController.closeMultitaskView() +@@ -343,42 +270,45 @@ FocusScope { + scrollArea.tabBorderVisble = true + currentTabIndex = 0 + event.accepted = false ++ + } else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter || event.key === Qt.Key_Space) { +- appAreaController.onWindowClicked(appWindowModel.get(currentTabIndex).uuid); ++ appAreaController.onWindowClicked(previewWindowRepeater.itemAt(currentTabIndex).uuid); + event.accepted = true ++ + } else if (event.key === Qt.Key_End) { + scrollArea.tabBorderVisble = true +- currentTabIndex = appWindowModel.count - 1 +- var currentNextY = previewWindowRepeater.itemAt(currentTabIndex).mapToItem(scrollArea,0,0).y +- if (currentNextY + previewWindowHeight > scrollArea.height) { +- scrollMoveAnimation.to = scrollArea.vScrollBar.position + (currentNextY + previewWindowHeight - scrollArea.height) / scrollArea.contentHeight +- scrollMoveAnimation.start() +- } ++ currentTabIndex = previewWindowRepeater.count - 1 + event.accepted = true ++ + } else if (event.key === Qt.Key_Home) { + scrollArea.tabBorderVisble = true + currentTabIndex = 0 +- if (scrollArea.vScrollBar.position > 0) { +- scrollMoveAnimation.to = 0 +- scrollMoveAnimation.start() +- } + event.accepted = true ++ + } else if (event.key === Qt.Key_PageUp || event.key === Qt.Key_PageDown) { + scrollArea.tabBorderVisble = true + var isKeyPageUp = event.key === Qt.Key_PageUp + currentTabIndex = appAreaController.keyPageUpDownSelectWindow(isKeyPageUp, scrollArea.windowPosInfoModel, currentTabIndex) +- var currentNextY = previewWindowRepeater.itemAt(currentTabIndex).mapToItem(scrollArea, 0, 0).y +- if (currentNextY < 0 ) { +- scrollMoveAnimation.to = scrollArea.vScrollBar.position - (-currentNextY) / scrollArea.contentHeight +- scrollMoveAnimation.start() +- } else if (currentNextY + previewWindowHeight > scrollArea.height) { +- scrollMoveAnimation.to = scrollArea.vScrollBar.position + (currentNextY + previewWindowHeight - scrollArea.height) / scrollArea.contentHeight +- scrollMoveAnimation.start() +- } + event.accepted = true ++ + } else if (event.key === Qt.Key_Escape) { + appAreaController.closeMultitaskView() + } ++ ++ if (event.accepted) { ++ scrollToTabItem() ++ } ++ } ++ ++ function scrollToTabItem() { ++ var currentNextY = itemAt(currentTabIndex).mapToItem(scrollArea, 0, 0).y ++ if (currentNextY < 0) { ++ scrollMoveAnimation.to = vScrollBar.position - (-currentNextY) / scrollArea.contentHeight ++ scrollMoveAnimation.start() ++ } else if (currentNextY + previewWindowHeight > scrollArea.height) { ++ scrollMoveAnimation.to = vScrollBar.position + (currentNextY + previewWindowHeight - scrollArea.height) / scrollArea.contentHeight ++ scrollMoveAnimation.start() ++ } + } + }//Repeater + Component.onCompleted: { +diff --git a/windowsview/qml/AppPreviewWindow.qml b/windowsview/qml/AppPreviewWindow.qml +index 97a641d..db41c16 100644 +--- a/windowsview/qml/AppPreviewWindow.qml ++++ b/windowsview/qml/AppPreviewWindow.qml +@@ -296,7 +296,7 @@ Rectangle { + onFinished: { + //拖拽还原动画结束后,将 appWindow 的父对象改回 thumbnailitem,并重新设置坐标 + appWindow.parent = thumbnailitem +- appWindow.x = thumbnailitem.width - thumbnailitem.trueWidth ++ appWindow.x = 0 + appWindow.y = 0 + } + } +diff --git a/windowsview/qml/CloseButton.qml b/windowsview/qml/CloseButton.qml +index 915537e..36063f1 100644 +--- a/windowsview/qml/CloseButton.qml ++++ b/windowsview/qml/CloseButton.qml +@@ -77,6 +77,7 @@ Rectangle { + id : closeButtonMouseArea + anchors.fill : parent + hoverEnabled : true ++ preventStealing: true + + onEntered: { + root.state = "hover" +diff --git a/windowsview/qml/DesktopArea.qml b/windowsview/qml/DesktopArea.qml +index 049a3bc..c50e547 100644 +--- a/windowsview/qml/DesktopArea.qml ++++ b/windowsview/qml/DesktopArea.qml +@@ -56,7 +56,7 @@ FocusScope { + orientation : ListView.Horizontal + layoutDirection: isLayoutLeftToRight ? Qt.LeftToRight : Qt.RightToLeft + property int contentXoffset : isLayoutLeftToRight ? 0 : contentWidth +- model : desktopWindowModel ++ model : desktopListModel + spacing : root.spacing + activeFocusOnTab: false + clip : true +@@ -80,10 +80,10 @@ FocusScope { + contentMoveAnimation.start() + } + } else if (event.key === Qt.Key_PageDown || event.key === Qt.Key_End) { +- if (currentIndex === desktopWindowModel.count - 2) { ++ if (currentIndex === desktopListModel.rowCount() - 2) { + return + } +- currentIndex = desktopWindowModel.count - 2 ++ currentIndex = desktopListModel.rowCount() - 2 + if (isLayoutLeftToRight && desktopListView.contentX < desktopListView.contentWidth - desktopListView.width) { + contentMoveAnimation.to = desktopListView.contentWidth - desktopListView.width + contentMoveAnimation.start() +@@ -112,6 +112,16 @@ FocusScope { + easing.type : Easing.InOutQuad + } + ++ populate: Transition { ++ NumberAnimation { ++ properties : "scale,opacity" ++ from : 0 ++ to : 1 ++ duration : 400 ++ easing.type : Easing.InOutQuad ++ } ++ } ++ + add : Transition { + NumberAnimation { + properties : "scale,opacity" +@@ -154,22 +164,18 @@ FocusScope { + + onCountChanged : { + if (initMultitask) { +- if (count === desktopWindowModel.count) { ++ if (count === desktopListModel.rowCount()) { + initMultitask = false; + } + return; + } ++ + var newWidth = desktopRectWidth * count + desktopListView.spacing * (count - 1) +- desktopListViewLeftMarginAni.to = (parent.width - newWidth) / 2 < 0 ? 0 : (parent.width - newWidth) / 2 ++ desktopListViewLeftMarginAni.to = (rootWindow.width - newWidth) / 2 < 0 ? 0 : (rootWindow.width - newWidth) / 2 + desktopListViewLeftMarginAni.start() + } + +- function getWorkspaceItemOrNewWorkspaceItem(index) { +- if (index < 0 || index > count - 1) { +- return "" +- } +- var type = desktopWindowModel.get(index).itemType +- // console.log("getWorkspaceItemOrNewWorkspaceItem", desktopWindowModel.count, index, type) ++ function getWorkspaceItemOrNewWorkspaceItem(type) { + if(type === "newDesktop") { + return "NewDesktopButton.qml" + } +@@ -189,26 +195,20 @@ FocusScope { + + function moveToScrollEnd() { + if (desktopListView.contentWidth + desktopRectWidth + root.spacing > desktopListView.width +- && desktopWindowModel.get(desktopListView.count - 1).itemType === "newDesktop") { ++ && desktopListView.count < 16) { + moveToScrollEndAnimation.restart() + } + } + + Connections { +- target: multitaskViewModel ++ target: desktopListModel + function onDesktopAppended(desktopIndex) { +- rootWindow.desktopWindowModel.insert(desktopIndex - 1,{value : desktopIndex, model : [], itemType: "workSpace" }); +- if (rootWindow.desktopWindowModel.count === 16) { +- rootWindow.desktopWindowModel.remove(desktopIndex) +- } +- multitaskViewModel.setCurrentDesktop(desktopIndex); +- rootWindow.highlightDesktop = multitaskViewModel.getCurrentDesktop() + desktopListView.moveToScrollEnd(desktopIndex) + } + } + + delegate: Loader { +- source : desktopListView.getWorkspaceItemOrNewWorkspaceItem(index) ++ source : desktopListView.getWorkspaceItemOrNewWorkspaceItem(model.ItemType) + } + } // desktopListView + +diff --git a/windowsview/qml/MasterDesktopArea.qml b/windowsview/qml/MasterDesktopArea.qml +index 88eb2c2..438d707 100644 +--- a/windowsview/qml/MasterDesktopArea.qml ++++ b/windowsview/qml/MasterDesktopArea.qml +@@ -58,7 +58,7 @@ FocusScope { + anchors.topMargin : root.listviewTopMargin + property bool initMultitask : true + orientation : ListView.Vertical +- model : desktopWindowModel ++ model : desktopListModel + spacing : root.spacing + activeFocusOnTab: false + clip : true +@@ -79,10 +79,10 @@ FocusScope { + contentMoveAnimation.start() + } + } else if (event.key === Qt.Key_PageDown || event.key === Qt.Key_End) { +- if (currentIndex === desktopWindowModel.count - 2) { ++ if (currentIndex === desktopListModel.rowCount() - 2) { + return + } +- currentIndex = desktopWindowModel.count - 2 ++ currentIndex = desktopListModel.rowCount() - 2 + if (desktopListView.contentY < desktopListView.contentHeight - desktopListView.height) { + contentMoveAnimation.to = desktopListView.contentHeight - desktopListView.height + contentMoveAnimation.start() +@@ -104,6 +104,16 @@ FocusScope { + } + } + ++ populate: Transition { ++ NumberAnimation { ++ properties : "scale,opacity" ++ from : 0 ++ to : 1 ++ duration : 400 ++ easing.type : Easing.InOutQuad ++ } ++ } ++ + add : Transition { + NumberAnimation { + properties : "scale,opacity" +@@ -144,12 +154,7 @@ FocusScope { + } + } + +- function getWorkspaceItemOrNewWorkspaceItem(index) { +- if (index < 0 || index > count - 1) { +- return "" +- } +- var type = desktopWindowModel.get(index).itemType +- // console.log("getWorkspaceItemOrNewWorkspaceItem", desktopWindowModel.count, index, type) ++ function getWorkspaceItemOrNewWorkspaceItem(type) { + if(type === "newDesktop") { + return "NewDesktopButton.qml" + } +@@ -168,27 +173,20 @@ FocusScope { + + function moveToScrollEnd() { + if (desktopListView.contentHeight + desktopRectHeight + root.spacing > desktopListView.height +- && desktopWindowModel.get(desktopListView.count - 1).itemType === "newDesktop") { ++ && desktopListView.count < 16) { + moveToScrollEndAnimation.restart() + } + } + + Connections { +- target: multitaskViewModel ++ target: desktopListModel + function onDesktopAppended(desktopIndex) { +- rootWindow.desktopWindowModel.insert(desktopIndex - 1,{value : desktopIndex, model : [], itemType: "workSpace" }); +- if (rootWindow.desktopWindowModel.count === 16) { +- rootWindow.desktopWindowModel.remove(desktopIndex) +- } +- multitaskViewModel.setCurrentDesktop(desktopIndex); +- rootWindow.highlightDesktop = multitaskViewModel.getCurrentDesktop() +- + desktopListView.moveToScrollEnd(desktopIndex) + } + } + + delegate: Loader { +- source : desktopListView.getWorkspaceItemOrNewWorkspaceItem(index) ++ source : desktopListView.getWorkspaceItemOrNewWorkspaceItem(model.ItemType) + } + } // desktopListView + } +diff --git a/windowsview/qml/MultitaskView.qml b/windowsview/qml/MultitaskView.qml +new file mode 100644 +index 0000000..1471bde +--- /dev/null ++++ b/windowsview/qml/MultitaskView.qml +@@ -0,0 +1,221 @@ ++/* ++ * Copyright 2022 KylinSoft Co., Ltd. ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Library General Public License as ++ * published by the Free Software Foundation; either version 2, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details ++ * ++ * You should have received a copy of the GNU Library General Public ++ * License along with this program; if not, write to the ++ * Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ */ ++ ++import QtQuick 2.12 ++import QtQuick.Controls 2.5 ++import QtQuick.Layouts 1.3 ++import QtQuick.Window 2.12 ++import org.kylin.background 3.0 as KWin ++import QtGraphicalEffects 1.0 ++ ++Repeater { ++ id : allroot ++ model : screencnt ++ focus: true ++ Keys.enabled: true ++ property int screencnt : multitaskViewModel.logicalScreenCount ++ ++ function closeMultitaskView() { ++ console.log("closeMultitaskView() !") ++ multitaskViewManager.close() ++ } ++ ++ Keys.onPressed : { ++ if (event.key === Qt.Key_Escape) { ++ closeMultitaskView(); ++ return; ++ } ++ if (event.modifiers & Qt.MetaModifier) { ++ if (event.key === Qt.Key_Tab) { ++ closeMultitaskView(); ++ return; ++ } ++ } ++ ++ } ++ ++ Rectangle { ++ id : rootWindow ++ x : rootWindow.screenRect.x ++ y : rootWindow.screenRect.y ++ width : rootWindow.screenRect.width ++ height : rootWindow.screenRect.height ++ property var isWlcom : multitaskViewManager.isWlcom() ++ property var isVerticalLayout : multitaskViewManager.isMultitaskViewVerticalLayout() ++ property int highlightDesktop : multitaskViewModel.highlightDesktop ++ property var screenRect : multitaskViewModel.getFullScreenGeometry(highlightDesktop, index) ++ property var scaleFactor : screenRect.width > screenRect.height ? screenRect.height / 1080 : screenRect.width / 1080 ++ property var screenId : multitaskViewModel.getOutputUuid(index) ++ property bool inputMode : multitaskViewModel.inputMode ++ property var currentTheme : multitaskViewModel.getUKUIStyleName() ++ property var closeButtonGeneralHoverColor ++ property var closeButtonGeneralClickColor ++ property var desktopCloseButtonDefaultColor ++ property var closeButtonGeneralImage ++ property var createDesktopButtonReceiveColor ++ property var createDesktopButtonDefaultColor ++ property var desktopMaskReceiveColor ++ property var desktopCaptionColor ++ property var desktopAreaColor ++ property var scrollDefaultColor ++ property var scrollHoverColor ++ property var hoverBorderColor : "#FFFFFF" ++ property var tabFocusBorderColor : "#FFFFFF" ++ // 预览图布局区域 y 轴起始高度 ++ property var scrollViewYStartPoint : Math.floor(13 * scaleFactor) ++ // 预览图布局区域距离左侧和右侧的间距 ++ property int scrollViewLeftSpace : isVerticalLayout ? 32 : 0 ++ property var iconAndCloseButtonHeight : Math.floor(24 * scaleFactor) ++ property var appBorderWidth : Math.floor(4 * scaleFactor) ++ property var appRadius : Math.floor(multitaskViewModel.getRadius("Max_Radius") * scaleFactor) ++ property var spacingWidth : Math.floor(2 * scaleFactor) ++ property var appThumbnailMargin : appBorderWidth + spacingWidth ++ property var workspaceBorderWidth : Math.floor(3 * scaleFactor) ++ property var workspaceRadius : Math.floor(multitaskViewModel.getRadius("Normal_Radius") * scaleFactor) ++ property var thumbRectangleHeight : isVerticalLayout ? Math.floor(screenRect.height * 5 / 22) : Math.floor(screenRect.height * 5 / 23) ++ property var previewWindowHeight : thumbRectangleHeight + 2 * appBorderWidth + 3 * spacingWidth + iconAndCloseButtonHeight ++ // 工作区窗口缩放比 ++ property double desktopScale : isVerticalLayout ? 16 / 135 : 57 / 480 ++ // 工作区窗口的高度和宽度 ++ property int desktopThumbnailWidth : screenRect.width * desktopScale ++ property int desktopThumbnailHeight : screenRect.height * desktopScale ++ property ListModel appWindowModel : ListModel{} ++ property ListModel desktopWindowModel : ListModel{} ++ //水平布局方向 ++ property bool isLayoutLeftToRight: multitaskViewManager.isLayoutLeftToRight() ++ ++ ++ KWin.DesktopBackground { ++ id : wholeDesktopBackground ++ width : rootWindow.width ++ height : rootWindow.height ++ blurAlpha : 0.7 ++ } ++ ++ function setItemColor() { ++ if (rootWindow.currentTheme === "ukui-default" || rootWindow.currentTheme === "ukui-white" ++ || rootWindow.currentTheme === "ukui" || rootWindow.currentTheme === "ukui-light") { ++ rootWindow.createDesktopButtonReceiveColor = Qt.rgba(0, 0, 0, 0.25) ++ rootWindow.createDesktopButtonDefaultColor = Qt.rgba(0, 0, 0, 0.15) ++ rootWindow.desktopMaskReceiveColor = Qt.rgba(0, 0, 0, 0.25) ++ rootWindow.desktopCaptionColor = Qt.rgba(0, 0, 0, 1) ++ rootWindow.desktopAreaColor = Qt.rgba(245/255, 245/255, 245/255, 0.75) ++ rootWindow.scrollDefaultColor = Qt.rgba(0, 0, 0, 0.15) ++ rootWindow.scrollHoverColor = Qt.rgba(0, 0, 0, 0.25) ++ rootWindow.tabFocusBorderColor = "#2c73c8" ++ desktopCloseButtonDefaultColor = Qt.rgba(38/255, 38/255, 38/255, 0.15) ++ closeButtonGeneralHoverColor = Qt.rgba(1, 1, 1, 1) ++ closeButtonGeneralClickColor = Qt.rgba(1, 1, 1, 0.75) ++ closeButtonGeneralImage = "qrc:/images/application-exit-symbolic.svg" ++ } else { ++ rootWindow.createDesktopButtonReceiveColor = isVerticalLayout ? Qt.rgba(0, 0, 0, 0.1) : Qt.rgba(1, 1, 1, 0.25) ++ rootWindow.createDesktopButtonDefaultColor = Qt.rgba(1, 1, 1, 0.15) ++ rootWindow.desktopMaskReceiveColor = Qt.rgba(1, 1, 1, 0.25) ++ rootWindow.desktopCaptionColor = Qt.rgba(1, 1, 1, 1) ++ rootWindow.desktopAreaColor = Qt.rgba(35/255, 36/255, 38/255, 0.75) ++ rootWindow.scrollDefaultColor = Qt.rgba(1, 1, 1, 0.15) ++ rootWindow.scrollHoverColor = Qt.rgba(1, 1, 1, 0.25) ++ rootWindow.tabFocusBorderColor = "#5fa6fb" ++ desktopCloseButtonDefaultColor = Qt.rgba(1, 1, 1, 0.15) ++ closeButtonGeneralHoverColor = "#37373B" ++ closeButtonGeneralClickColor = Qt.rgba(75/255, 75/255, 79/255, 1) ++ closeButtonGeneralImage = "qrc:/images/application-exit-symbolic-white.svg" ++ } ++ } ++ ++ FocusScope { ++ id: mainView ++ anchors.fill: parent ++ focus: true ++ width: parent.width ++ height: parent.height ++ property var screenIndex : index ++ ++ Loader { ++ id: viewLoader ++ sourceComponent: isVerticalLayout ? verticalLayoutView : horizontalLayoutView ++ anchors.fill: parent ++ } ++ ++ Component { ++ id: verticalLayoutView ++ Rectangle { ++ color: "transparent" ++ AppArea { ++ id : appArea1 ++ anchors.left : parent.left ++ anchors.right : parent.right ++ anchors.top : parent.top ++ height : Math.floor(mainView.height * 111 / 135) ++ width: parent.width ++ ++ Component.onCompleted : { ++ console.log("AppArea end! ! !") ++ } ++ } ++ DesktopArea { ++ id : desktopArea1 ++ anchors.left : parent.left ++ anchors.right : parent.right ++ anchors.top : appArea1.bottom ++ anchors.bottom : parent.bottom ++ } ++ ++ Component.onCompleted : { ++ console.log("verticalLayoutView end! ! !") ++ } ++ } ++ } ++ ++ Component { ++ id: horizontalLayoutView ++ Rectangle { ++ color: "transparent" ++ AppArea { ++ id : appArea2 ++ anchors.left : parent.left ++ anchors.bottom : parent.bottom ++ anchors.top : parent.top ++ height: parent.height ++ width : Math.floor(mainView.width * 410 / 480) ++ ++ Component.onCompleted : { ++ console.log("MasterAppArea end! ! !") ++ } ++ } ++ ++ MasterDesktopArea { ++ id : desktopArea2 ++ anchors.left : appArea2.right ++ anchors.right : parent.right ++ anchors.top : parent.top ++ anchors.bottom : parent.bottom ++ } ++ ++ Component.onCompleted : { ++ console.log("horizontalLayoutView end! ! !") ++ } ++ } ++ } ++ } ++ ++ Component.onCompleted : { ++ setItemColor() ++ } ++ } ++} +diff --git a/windowsview/qml/NewDesktopButton.qml b/windowsview/qml/NewDesktopButton.qml +index 44bb7b1..641b218 100644 +--- a/windowsview/qml/NewDesktopButton.qml ++++ b/windowsview/qml/NewDesktopButton.qml +@@ -29,14 +29,13 @@ Item { + height : isVerticalLayout ? desktopRect.height : desktopRectHeight + activeFocusOnTab: true + focus : true +- visible : desktopListView.count < 16 ? true : false + property string windowType : "creation" + property var newWorkspaceController : new Controller.CreationController(multitaskViewModel, root, multitaskViewManager, ["app","desktop"]); + + onActiveFocusChanged: { + if (root.activeFocus) { + desktopRect.desktopTabBorderVisble = true +- desktopListView.currentIndex = desktopWindowModel.count - 1 ++ desktopListView.currentIndex = desktopListView.count - 1 + if (isVerticalLayout && desktopListView.contentX + desktopListView.contentXoffset < desktopListView.contentWidth - desktopListView.width) { + contentMoveAnimation.to = isLayoutLeftToRight ? desktopListView.contentWidth - desktopListView.width : -desktopListView.contentWidth + contentMoveAnimation.start() +@@ -157,8 +156,7 @@ Item { + } + onDropped : { + createDesktopButton.color = rootWindow.createDesktopButtonDefaultColor +- newWorkspaceController.onSourceDropped(drop.source, rootWindow.highlightDesktop, desktopWindowModel.count); +- rootWindow.updateDesktopWindowModel() ++ newWorkspaceController.onSourceDropped(drop.source, rootWindow.highlightDesktop, desktopListView.count); + } + } + } +diff --git a/windowsview/qml/Tabbox.qml b/windowsview/qml/Tabbox.qml +new file mode 100755 +index 0000000..9883f0f +--- /dev/null ++++ b/windowsview/qml/Tabbox.qml +@@ -0,0 +1,286 @@ ++/* ++ * Copyright 2024 KylinSoft Co., Ltd. ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Library General Public License as ++ * published by the Free Software Foundation; either version 2, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details ++ * ++ * You should have received a copy of the GNU Library General Public ++ * License along with this program; if not, write to the ++ * Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ */ ++ ++import QtQuick 2.0 ++import QtQuick.Layouts 1.3 ++import QtQuick.Controls 2.5 ++import QtGraphicalEffects 1.0 ++import "Controller.js" as Controller ++import IconTheme 1.0 ++import org.kylin.thumbnail 1.0 as WlcomThumbnail ++import AppWindowFilterModel 1.0 ++ ++// https://techbase.kde.org/Development/Tutorials/KWin/WindowSwitcher ++// https://github.com/KDE/kwin/blob/master/tabbox/switcheritem.h ++Rectangle { ++ id : tabbox ++ property var controller : new Controller.AppController(multitaskViewModel, tabbox, multitaskViewManager, ["none"]); ++ property int currentIndex : 0 ++ property var screenGeometry : multitaskViewModel.getFullScreenGeometry(multitaskViewModel.highlightDesktop, 0) ++ property var theme : multitaskViewModel.getUKUIStyleName() ++ property var isOpenGL : true ++ property int maxHeight : screenGeometry.height * 0.8 ++ property int maxGridColumnsByWidth: Math.floor(screenGeometry.width / thumbnailGridView.cellWidth) ++ property var scaleFactor : Math.min(screenGeometry.width, screenGeometry.height) / 1080 ++ property int gridColumns : maxGridColumnsByWidth ++ property int gridRows : Math.ceil(appWindowListModel.rowCount() / gridColumns) ++ property int optimalWidth : thumbnailGridView.cellWidth * gridColumns ++ property int optimalHeight : thumbnailGridView.cellHeight * gridRows ++ property int gridViewMargin : 40 * scaleFactor ++ property bool isLayoutLeftToRight: Qt.application.layoutDirection === Qt.LeftToRight ++ focus : true ++ color : (theme === "ukui-white" || theme === "ukui" || theme === "ukui-light")? Qt.rgba(245/255, 245/255, 245/255, 0.45) : Qt.rgba(35/255, 36/255, 38/255, 0.45) ++ width : screenGeometry.width ++ height : Math.min(optimalHeight + 2 * gridViewMargin, maxHeight) ++ clip : true ++ Keys.enabled : true ++ onActiveFocusChanged : { ++ if(!tabbox.activeFocus) { ++ multitaskViewManager.close() ++ } else { ++ /** ++ 1. wlcom环境特定情况(快速操作按下alt+tab并松开)下,会出现本界面不隐藏问题,原因如下: ++ 由于wlcom合成器与窗口选择器是两个独立的进程,使得窗口选择器被快捷键拉起时,向合成器发出的GrabKeyboard请求未被及时响应 ++ 导致在特定情况下窗口选择器无法收到Key_Alt的Released信号,进而无法通过响应alt released事件来关闭此界面 ++ 2. 当前实现,此界面显示时可以认为Key_Alt必定处于按下状态,因此针对特定情况处理如下: ++ 在此界面显示并获取键盘焦点后,立即查询Key_Alt是否处于按下状态 ++ 如果按未处于按下状态,则激活选定窗口并退出;否则,不做特殊处理 ++ **/ ++ // fix https://gitee.com/openkylin/ukui-window-switch/issues/IAID8L?from=project-issue ++ if (!multitaskViewManager.isAltKeyPressed()) { ++ activateSelectedWindow(); ++ } ++ } ++ } ++ ++ GridView { ++ id : thumbnailGridView ++ anchors.fill : parent ++ anchors.bottomMargin : tabbox.gridViewMargin ++ anchors.topMargin : tabbox.gridViewMargin ++ anchors.leftMargin : count > tabbox.maxGridColumnsByWidth ? (tabbox.width-tabbox.maxGridColumnsByWidth * cellWidth) / 2 : ++ (tabbox.width-count * cellWidth) / 2 ++ anchors.rightMargin : count > tabbox.maxGridColumnsByWidth ? (tabbox.width-tabbox.maxGridColumnsByWidth * cellWidth) / 2 : ++ (tabbox.width-count * cellWidth) / 2 ++ LayoutMirroring.enabled: !isLayoutLeftToRight ++ model : appWindowListModel ++ property int iconSize : 24 * tabbox.scaleFactor ++ property int captionRowHeight : 33 * tabbox.scaleFactor ++ property int thumbnailWidth : (tabbox.screenGeometry.width - 2 * tabbox.gridViewMargin) / 4 ++ property int thumbnailHeight : tabbox.screenGeometry.height / 22 * 5 ++ property int spaceWidth : 2 * tabbox.scaleFactor ++ property int outerBorderWidth : 4 * tabbox.scaleFactor ++ property int innerBorderWidth : 2 * tabbox.scaleFactor ++ property int appRadius : 8 * tabbox.scaleFactor ++ property int thumbnailOuterRadius : tabbox.isOpenGL ? appRadius + outerBorderWidth + innerBorderWidth + 2 * spaceWidth : 0 ++ property int thumbnailInterRadius : tabbox.isOpenGL ? appRadius + innerBorderWidth + spaceWidth : 0 ++ cellWidth : 2 * (innerBorderWidth + outerBorderWidth) + 4 * spaceWidth + thumbnailWidth ++ cellHeight : 2 * (innerBorderWidth + outerBorderWidth) + 5 * spaceWidth + captionRowHeight + thumbnailHeight ++ keyNavigationWraps : true ++ focus : true ++ ++ delegate : Rectangle { ++ id : thumbnailGridItem ++ property alias uuid: thumbnailItem.windowId ++ width : thumbnailGridView.cellWidth ++ height : thumbnailGridView.cellHeight ++ color : "transparent" ++ border.color : (tabbox.theme === "ukui-white" || tabbox.theme === "ukui" || tabbox.theme === "ukui-light") ? "#262626" : "#FFFFFF" ++ border.width : index == thumbnailGridView.currentIndex ? thumbnailGridView.outerBorderWidth : 0 ++ // highlight在快速绘制的时候会出现绘制的坐标偏移的问题,故不使用 ++ radius : thumbnailGridView.thumbnailOuterRadius ++ ++ MouseArea { ++ anchors.fill : parent ++ onClicked : { ++ thumbnailGridItem.select(); ++ } ++ hoverEnabled : true ++ ++ onEntered : { ++ thumbnailBorderItem.border.width = thumbnailGridView.innerBorderWidth; ++ } ++ ++ onExited : { ++ thumbnailBorderItem.border.width = 0; ++ } ++ } ++ function select() { ++ thumbnailGridView.currentIndex = index; ++ controller.onWindowClicked(uuid); ++ } ++ ++ function getThumbnailSize() ++ { ++ var thumbHeight = thumbnailGridView.thumbnailHeight ++ var max_width = thumbnailGridView.thumbnailWidth ++ var clientWidth = model.Width ++ var clientHeight = model.Height ++ var thumbWidth = Math.floor(thumbHeight * clientWidth / clientHeight) ++ if (thumbWidth > max_width) { ++ thumbWidth = max_width ++ thumbHeight = Math.floor(thumbWidth * clientHeight / clientWidth) ++ } ++ return [thumbWidth, thumbHeight] ++ } ++ ++ ColumnLayout { ++ spacing : 0 ++ anchors.centerIn : parent ++ height : parent.height - 2 * (thumbnailGridView.outerBorderWidth + thumbnailGridView.spaceWidth) ++ width : parent.width - 2 * (thumbnailGridView.outerBorderWidth + thumbnailGridView.spaceWidth) ++ x : thumbnailGridView.outerBorderWidth + thumbnailGridView.spaceWidth ++ y : thumbnailGridView.outerBorderWidth + thumbnailGridView.spaceWidth ++ RowLayout { ++ id : captionRow ++ spacing : 2 * thumbnailGridView.spaceWidth ++ Layout.fillHeight : true ++ layoutDirection: isLayoutLeftToRight ? Qt.LeftToRight : Qt.RightToLeft ++ ++ IconTheme { ++ id : iconItem ++ width : thumbnailGridView.iconSize ++ height : thumbnailGridView.iconSize ++ icon : multitaskViewModel.getWindowIcon(model.Uuid) ++ } ++ ++ Label { ++ id : label ++ verticalAlignment : Qt.AlignVCenter ++ Layout.fillWidth : true ++ color : (tabbox.theme === "ukui-white" || tabbox.theme === "ukui" || tabbox.theme === "ukui-light") ? "#000000" : "#FFFFFF" ++ text : model.Caption ++ horizontalAlignment: isLayoutLeftToRight ? Qt.AlignLeft : Qt.AlignRight ++ elide : isLayoutLeftToRight ? Text.ElideRight : Text.ElideLeft ++ } ++ ++ //label高度受字号控制,此Rectangle起占位作用,防止字号改变时缩略图位置改变 ++ Rectangle { ++ width : 1 ++ height : thumbnailGridView.captionRowHeight ++ color : "transparent" ++ } ++ } ++ ++ // KWin.ThumbnailItem needs a container ++ // otherwise it will be drawn the same size as the parent ColumnLayout ++ Rectangle { ++ color : "transparent" ++ Layout.fillHeight : true ++ Layout.fillWidth : true ++ Rectangle { ++ id : thumbnailBorderItem ++ x : (parent.width - thumbnailBorderItem.width) / 2 ++ y : thumbnailGridView.spaceWidth ++ width : getThumbnailSize()[0] + 2 * (thumbnailGridView.innerBorderWidth + thumbnailGridView.spaceWidth) ++ height : thumbnailGridView.thumbnailHeight + 2 * (thumbnailGridView.innerBorderWidth + thumbnailGridView.spaceWidth) ++ color : "transparent" ++ border.color : (tabbox.theme === "ukui-white" || tabbox.theme === "ukui" || tabbox.theme === "ukui-light") ? "#262626" : "#FFFFFF" ++ border.width : 0 ++ radius : thumbnailGridView.thumbnailInterRadius ++ Rectangle { ++ id : thumbnailBackItem ++ width : getThumbnailSize()[0] ++ height : getThumbnailSize()[1] ++ anchors.centerIn : parent ++ color : "transparent" ++ clip : true ++ layer.enabled : tabbox.isOpenGL ? true : false ++ layer.effect : OpacityMask { ++ maskSource : Rectangle { ++ width : thumbnailBackItem.width ++ height : thumbnailBackItem.height ++ radius : Math.min(thumbnailGridView.appRadius, Math.floor(Math.min(width, height) / 2)) ++ } ++ } ++ ++ ++ WlcomThumbnail.ThumbnailItem { ++ id: thumbnailItem ++ anchors.fill: parent ++ windowId: model.Uuid ++ visible: thumbnailGridView.visible ++ } ++ } ++ } ++ } ++ } ++ } // GridView.delegate ++ ++ Connections { ++ target : tabbox ++ function onCurrentIndexChanged() { ++ thumbnailGridView.currentIndex = tabbox.currentIndex; ++ } ++ } ++ } // GridView ++ ++ Keys.onDeletePressed : { ++ multitaskViewManager.close() ++ } ++ ++ Keys.onEscapePressed : { ++ multitaskViewManager.close() ++ } ++ ++ Keys.onBacktabPressed : { ++ if (!multitaskViewManager.isAltKeyPressed()) { ++ return; ++ } ++ if (isLayoutLeftToRight) { ++ thumbnailGridView.moveCurrentIndexLeft(); ++ } else { ++ thumbnailGridView.moveCurrentIndexRight(); ++ } ++ } ++ ++ Keys.onTabPressed : { ++ if (isLayoutLeftToRight) { ++ thumbnailGridView.moveCurrentIndexRight(); ++ } else { ++ thumbnailGridView.moveCurrentIndexLeft(); ++ } ++ } ++ ++ Keys.onPressed : { ++ if (event.key === Qt.Key_Left) { ++ thumbnailGridView.moveCurrentIndexLeft(); ++ } else if (event.key === Qt.Key_Right) { ++ thumbnailGridView.moveCurrentIndexRight(); ++ } else if (event.key === Qt.Key_Up) { ++ thumbnailGridView.moveCurrentIndexUp(); ++ } else if (event.key === Qt.Key_Down) { ++ thumbnailGridView.moveCurrentIndexDown(); ++ } else { ++ return; ++ } ++ } ++ ++ Keys.onReleased : { ++ if (event.key === Qt.Key_Alt) { ++ activateSelectedWindow(); ++ } else if (event.key === Qt.Key_Shift && !multitaskViewManager.isAltKeyPressed()) { ++ activateSelectedWindow(); ++ } ++ } ++ ++ function activateSelectedWindow() { ++ controller.onWindowClicked(thumbnailGridView.currentItem.uuid); ++ thumbnailGridView.visible = false; ++ } ++} +diff --git a/windowsview/qml/TabletPreviewWindow.qml b/windowsview/qml/TabletPreviewWindow.qml +index e44fd8e..90bb1f4 100644 +--- a/windowsview/qml/TabletPreviewWindow.qml ++++ b/windowsview/qml/TabletPreviewWindow.qml +@@ -24,7 +24,6 @@ import QtGraphicalEffects 1.0 + + Item { + id : root +- property ListModel previewWindowModel : null + property bool closeButtonVisble : false + property var screenIndex : null + state : "default" +diff --git a/windowsview/qml/TabletViewMain.qml b/windowsview/qml/TabletViewMain.qml +index 34704dc..d15c2cd 100644 +--- a/windowsview/qml/TabletViewMain.qml ++++ b/windowsview/qml/TabletViewMain.qml +@@ -22,6 +22,7 @@ import QtQuick.Layouts 1.3 + import QtQuick.Window 2.12 + import QtGraphicalEffects 1.0 + import org.kylin.background 3.0 as KWin ++import AppWindowFilterModel 1.0 + + Repeater{ + id : allrootRepeater +@@ -33,7 +34,7 @@ Repeater{ + Item { + id : tabletViewMain + property var isWlcom : multitaskViewManager.isWlcom() +- property var screenRect : multitaskViewModel.getFullScreenGeometry(multitaskViewModel.getCurrentDesktop(), index) ++ property var screenRect : multitaskViewModel.getFullScreenGeometry(multitaskViewModel.highlightDesktop, index) + // 整体缩放比 + property var tabletScaleFactor : screenRect.width > screenRect.height ? screenRect.height / 1080 : screenRect.width / 1080 + // 预览窗口宽高比 +@@ -59,6 +60,7 @@ Repeater{ + property var scrollViewYStartPoint : getCurrentPreWindowHeight() + property ListModel tabletViewRootModel : ListModel{} + property var language : multitaskViewModel.getCurrentLanguage() ++ property int screenId: index + + x : Math.floor(screenRect.x) + y : Math.floor(screenRect.y) +@@ -107,10 +109,10 @@ Repeater{ + property bool alreadyCloseView: false + + function sequentialLoadWindow() { +- var appWindowList = multitaskViewModel.getAppWindowList(multitaskViewModel.getCurrentDesktop(), tabletViewMain.index) +- var appWindowCount = appWindowList.length ++ var appWindowCount = appListModel.rowCount() ++ var info + if (loadedWindowNum < appWindowCount && loadedWindowNum < 6 ) { +- var info = appWindowList[loadedWindowNum] ++ info = appWindowListModel.getItemData(appListModel.mapToSource(appListModel.index(loadedWindowNum, 0))) + tabletViewRootModel.append({"x": info.x, "y": info.y, + "width": info.width, "height": info.height, + "id": info.id, "minimized": info.minimized, +@@ -126,7 +128,7 @@ Repeater{ + sequentialLoadWindowTimer.stop() + console.log("计时器停止,接下来一次性加载所有窗口") + while (loadedWindowNum < appWindowCount) { +- var info = appWindowList[loadedWindowNum] ++ info = appWindowListModel.getItemData(appListModel.mapToSource(appListModel.index(loadedWindowNum, 0))) + tabletViewRootModel.append({"x": info.x, "y": info.y, + "width": info.width, "height": info.height, + "id": info.id, "minimized": info.minimized, +@@ -309,7 +311,6 @@ Repeater{ + width : parent.width + x_wid : model.id + wid : model.uuid +- previewWindowModel : tabletViewRootModel + screenIndex : tabletViewMain.index + captionText : model.caption + preViewNoScaledWidth : model.width +@@ -439,19 +440,29 @@ Repeater{ + } + } + ++ AppWindowFilterModel { ++ id: appListModel ++ desktopId: multitaskViewModel.highlightDesktop ++ screenId: tabletViewMain.screenId ++ sourceModel: appWindowListModel ++ } ++ + Connections { + target: multitaskViewModel + function onAppWindowRemoved(windowId) { ++ multitaskViewModel.removeAppWindow(windowId) ++ ++ // remove window from tabletViewRootModel + for(var i = 0; i < tabletViewRootModel.count; i++){ + var info = tabletViewRootModel.get(i); + if(info.uuid === windowId) { + tabletViewRootModel.remove(i); +- if (!multitaskViewModel.currentDesktopHasWindow()) { +- closeViewTimer.start() +- } +- return; ++ break; + } + } ++ if (!multitaskViewModel.currentDesktopHasWindow()) { ++ closeViewTimer.start() ++ } + } + } + } +diff --git a/windowsview/qml/VirtualDesktopWindow.qml b/windowsview/qml/VirtualDesktopWindow.qml +index e2d13d0..3108dbd 100644 +--- a/windowsview/qml/VirtualDesktopWindow.qml ++++ b/windowsview/qml/VirtualDesktopWindow.qml +@@ -36,7 +36,7 @@ Item { + activeFocusOnTab: index === 0 ? true : false + focus : true + property string windowType : "desktop" +- property var wid : value ++ property var wid : index + 1 + // Using the Drag attached property, any Item can be made a source of drag and drop events within a scene + Drag.active : previewMouseArea.drag.active + Drag.hotSpot.x : width / 2 +@@ -79,7 +79,7 @@ Item { + } + } else if (event.key === Qt.Key_Tab) { + if (index === 0 ) { +- desktopListView.currentIndex = desktopWindowModel.count - 1 ++ desktopListView.currentIndex = desktopListView.count - 1 + } + console.log("visble",desktopRect.desktopTabBorderVisble) + } +@@ -125,7 +125,7 @@ Item { + height : mainVerticalLayout.height + anchors.centerIn : parent + state : "default" +- property ListModel appmodel : desktopWindowModel.get(index).model ++ property int desktopIndex: root.wid + + states : [ + State { +@@ -191,6 +191,12 @@ Item { + font.family : multitaskViewModel.getUKUIFont() + color: rootWindow.desktopCaptionColor + } ++ Binding { ++ id: defaultTextBinding ++ target: caption ++ property: "text" ++ value: qsTr("Desktop") + " " + root.wid ++ } + + Rectangle { + id : iconSpace +@@ -206,6 +212,7 @@ Item { + radius : width / 2 + windowType : "desktop" + onClicked : { ++ defaultTextBinding.when = false + controller.removePreviewWindow(root.wid) + } + onExited: { +@@ -287,7 +294,6 @@ Item { + onDropped : { + desktopMaskColor.visible = false + controller.onSourceDropped(drop.source, rootWindow.highlightDesktop, root.wid); +- rootWindow.updateDesktopWindowModel() + } + } + +diff --git a/windowsview/qml/WorkSpaceThumbnailWithKwin.qml b/windowsview/qml/WorkSpaceThumbnailWithKwin.qml +index 3c76d11..61ac2a7 100644 +--- a/windowsview/qml/WorkSpaceThumbnailWithKwin.qml ++++ b/windowsview/qml/WorkSpaceThumbnailWithKwin.qml +@@ -19,19 +19,29 @@ + import QtQuick 2.12 + import QtQuick.Window 2.12 + import org.kde.kwin 3.0 as KWinComponents ++import AppWindowFilterModel 1.0 + +-Repeater { +- id : desktopWindowRepeater +- model : desktopDragRect.appmodel +- KWinComponents.WindowThumbnailItem { +- width : Math.floor(model.width * desktopScale) +- height : Math.floor(model.height * desktopScale) +- visible : !(model.minimized) +- x : Math.floor((model.x - screenRect.x) * desktopScale) +- y : Math.floor((model.y - screenRect.y) * desktopScale) +- wId: model.uuid +- } +-} ++Item { ++ id: root ++ anchors.fill: parent + ++ Repeater { ++ id : desktopWindowRepeater + ++ model : AppWindowFilterModel { ++ id: kwinWorkspaceThumbnailModel ++ desktopId: desktopDragRect.desktopIndex ++ screenId: mainView.screenIndex ++ sourceModel: multitaskViewModel.isCurrentDesktopShowingDesktop() ? {} : appWindowListModel ++ } + ++ KWinComponents.WindowThumbnailItem { ++ width : Math.floor(model.Width * desktopScale) ++ height : Math.floor(model.Height * desktopScale) ++ visible : !(model.Minimized) ++ x : Math.floor((model.X - screenRect.x) * desktopScale) ++ y : Math.floor((model.Y - screenRect.y) * desktopScale) ++ wId: model.Uuid ++ } ++ } ++} +diff --git a/windowsview/qml/multitaskview.qml b/windowsview/qml/multitaskview.qml +deleted file mode 100644 +index fea899d..0000000 +--- a/windowsview/qml/multitaskview.qml ++++ /dev/null +@@ -1,358 +0,0 @@ +-/* +- * Copyright 2022 KylinSoft Co., Ltd. +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU Library General Public License as +- * published by the Free Software Foundation; either version 2, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details +- * +- * You should have received a copy of the GNU Library General Public +- * License along with this program; if not, write to the +- * Free Software Foundation, Inc., +- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +- */ +- +-import QtQuick 2.12 +-import QtQuick.Controls 2.5 +-import QtQuick.Layouts 1.3 +-import QtQuick.Window 2.12 +-import org.kylin.background 3.0 as KWin +-import QtGraphicalEffects 1.0 +- +-Repeater { +- id : allroot +- model : screencnt +- focus: true +- Keys.enabled: true +- property int screencnt : multitaskViewModel.logicalScreenCount +- +- function closeMultitaskView() { +- console.log("closeMultitaskView() !") +- multitaskViewManager.close() +- } +- +- Keys.onPressed : { +- if (event.key === Qt.Key_Escape) { +- closeMultitaskView(); +- return; +- } +- if (event.modifiers & Qt.MetaModifier) { +- if (event.key === Qt.Key_Tab) { +- closeMultitaskView(); +- return; +- } +- } +- +- } +- +- Rectangle { +- id : rootWindow +- x : rootWindow.screenRect.x +- y : rootWindow.screenRect.y +- width : rootWindow.screenRect.width +- height : rootWindow.screenRect.height +- property var isWlcom : multitaskViewManager.isWlcom() +- property var isVerticalLayout : multitaskViewManager.isMultitaskViewVerticalLayout() +- property var screenRect : multitaskViewModel.getFullScreenGeometry(multitaskViewModel.getCurrentDesktop(), index) +- property var scaleFactor : screenRect.width > screenRect.height ? screenRect.height / 1080 : screenRect.width / 1080 +- property int highlightDesktop : multitaskViewModel.getCurrentDesktop() +- property bool isShowingDesktop : multitaskViewModel.isCurrentDesktopShowingDesktop() +- property bool inputMode : multitaskViewModel.inputMode +- property var currentTheme : multitaskViewModel.getUKUIStyleName() +- property var screenId : multitaskViewModel.getOutputUuid(index) +- property var closeButtonGeneralHoverColor +- property var closeButtonGeneralClickColor +- property var desktopCloseButtonDefaultColor +- property var closeButtonGeneralImage +- property var createDesktopButtonReceiveColor +- property var createDesktopButtonDefaultColor +- property var desktopMaskReceiveColor +- property var desktopCaptionColor +- property var desktopAreaColor +- property var scrollDefaultColor +- property var scrollHoverColor +- property var hoverBorderColor : "#FFFFFF" +- property var tabFocusBorderColor : "#FFFFFF" +- // 预览图布局区域 y 轴起始高度 +- property var scrollViewYStartPoint : Math.floor(13 * scaleFactor) +- // 预览图布局区域距离左侧和右侧的间距 +- property int scrollViewLeftSpace : isVerticalLayout ? 32 : 0 +- property var iconAndCloseButtonHeight : Math.floor(24 * scaleFactor) +- property var appBorderWidth : Math.floor(4 * scaleFactor) +- property var appRadius : Math.floor(multitaskViewModel.getRadius("Max_Radius") * scaleFactor) +- property var spacingWidth : Math.floor(2 * scaleFactor) +- property var appThumbnailMargin : appBorderWidth + spacingWidth +- property var workspaceBorderWidth : Math.floor(3 * scaleFactor) +- property var workspaceRadius : Math.floor(multitaskViewModel.getRadius("Normal_Radius") * scaleFactor) +- property var thumbRectangleHeight : isVerticalLayout ? Math.floor(screenRect.height * 5 / 22) : Math.floor(screenRect.height * 5 / 23) +- property var previewWindowHeight : thumbRectangleHeight + 2 * appBorderWidth + 3 * spacingWidth + iconAndCloseButtonHeight +- property var previewWindowCount : 0 +- // 工作区窗口缩放比 +- property double desktopScale : isVerticalLayout ? 16 / 135 : 57 / 480 +- // 工作区窗口的高度和宽度 +- property int desktopThumbnailWidth : screenRect.width * desktopScale +- property int desktopThumbnailHeight : screenRect.height * desktopScale +- property ListModel appWindowModel : ListModel{} +- property ListModel desktopWindowModel : ListModel{} +- //水平布局方向 +- property bool isLayoutLeftToRight: multitaskViewManager.isLayoutLeftToRight() +- +- Connections { +- target: multitaskViewModel +- function onAppWindowRemoved(windowId) { +- for (var i = 0; i < appWindowModel.count;i++) { +- var info = appWindowModel.get(i); +- if(info.uuid === windowId) { +- previewWindowCount-- +- appWindowModel.remove(i); +- updateDesktopWindowModel() +- return; +- } +- } +- } +- function onAppWindowDesktopChanged(windowId, oldDesktopIndex, newDesktopIndex) { +- if (highlightDesktop === oldDesktopIndex) { +- // 预览窗口拖动到其他工作区 +- rootWindow.appRemoved(windowId); +- } else { +- // 预览窗口拖动到新建工作区按钮 +- rootWindow.resetAppWindowModel(highlightDesktop) +- } +- } +- function onCurrentDesktopChanged(oldCurrentDesktopIndex, newCurrentDesktopIndex) { +- if (rootWindow.isShowingDesktop) { +- rootWindow.updateDesktopWindowModel() +- } +- rootWindow.isShowingDesktop = multitaskViewModel.isCurrentDesktopShowingDesktop() +- rootWindow.resetAppWindowModel(newCurrentDesktopIndex) +- rootWindow.highlightDesktop = newCurrentDesktopIndex +- } +- function onDesktopRemoved(desktopIndex) { +- // 移除指定虚拟桌面,并更新虚拟桌面索引值 +- console.log("onDesktopRemoved", desktopIndex) +- rootWindow.desktopWindowModel.remove(desktopIndex - 1); +- if(rootWindow.desktopWindowModel.get(rootWindow.desktopWindowModel.count - 1).itemType === "workSpace") { +- rootWindow.desktopWindowModel.insert(rootWindow.desktopWindowModel.count, {value : rootWindow.desktopWindowModel.count, model : [], itemType: "newDesktop" }); +- } +- for(var i = desktopIndex - 1; i < rootWindow.desktopWindowModel.count; ++i) { +- rootWindow.desktopWindowModel.get(i).value = i + 1 +- } +- // 更新小窗口 +- rootWindow.updateDesktopWindowModel() +- if (desktopIndex !== 1) { +- desktopIndex -= 1 +- } +- multitaskViewModel.setCurrentDesktop(desktopIndex); +- rootWindow.highlightDesktop = multitaskViewModel.getCurrentDesktop() +- rootWindow.resetAppWindowModel(multitaskViewModel.getCurrentDesktop()) +- } +- // 交换desktopWindowModel中的指定两项 +- function onDesktopMoved(oldDesktopIndex, newDesktopIndex) { +- rootWindow.desktopWindowModel.move(oldDesktopIndex - 1, newDesktopIndex - 1, 1); +- multitaskViewModel.setCurrentDesktop(newDesktopIndex); +- rootWindow.highlightDesktop = newDesktopIndex +- // 交换后更新索引值 +- for (var i = Math.min(oldDesktopIndex, newDesktopIndex); i <= Math.max(oldDesktopIndex, newDesktopIndex); ++i) { +- rootWindow.desktopWindowModel.get(i-1).value = i +- } +- } +- } +- +- KWin.DesktopBackground { +- id : wholeDesktopBackground +- width : rootWindow.width +- height : rootWindow.height +- blurAlpha : 0.7 +- } +- +- function setItemColor() { +- if (rootWindow.currentTheme === "ukui-default" || rootWindow.currentTheme === "ukui-white" +- || rootWindow.currentTheme === "ukui" || rootWindow.currentTheme === "ukui-light") { +- rootWindow.createDesktopButtonReceiveColor = Qt.rgba(0, 0, 0, 0.25) +- rootWindow.createDesktopButtonDefaultColor = Qt.rgba(0, 0, 0, 0.15) +- rootWindow.desktopMaskReceiveColor = Qt.rgba(0, 0, 0, 0.25) +- rootWindow.desktopCaptionColor = Qt.rgba(0, 0, 0, 1) +- rootWindow.desktopAreaColor = Qt.rgba(245/255, 245/255, 245/255, 0.75) +- rootWindow.scrollDefaultColor = Qt.rgba(0, 0, 0, 0.15) +- rootWindow.scrollHoverColor = Qt.rgba(0, 0, 0, 0.25) +- rootWindow.tabFocusBorderColor = "#2c73c8" +- desktopCloseButtonDefaultColor = Qt.rgba(38/255, 38/255, 38/255, 0.15) +- closeButtonGeneralHoverColor = Qt.rgba(1, 1, 1, 1) +- closeButtonGeneralClickColor = Qt.rgba(1, 1, 1, 0.75) +- closeButtonGeneralImage = "qrc:/images/application-exit-symbolic.svg" +- } else { +- rootWindow.createDesktopButtonReceiveColor = isVerticalLayout ? Qt.rgba(0, 0, 0, 0.1) : Qt.rgba(1, 1, 1, 0.25) +- rootWindow.createDesktopButtonDefaultColor = Qt.rgba(1, 1, 1, 0.15) +- rootWindow.desktopMaskReceiveColor = Qt.rgba(1, 1, 1, 0.25) +- rootWindow.desktopCaptionColor = Qt.rgba(1, 1, 1, 1) +- rootWindow.desktopAreaColor = Qt.rgba(35/255, 36/255, 38/255, 0.75) +- rootWindow.scrollDefaultColor = Qt.rgba(1, 1, 1, 0.15) +- rootWindow.scrollHoverColor = Qt.rgba(1, 1, 1, 0.25) +- rootWindow.tabFocusBorderColor = "#5fa6fb" +- desktopCloseButtonDefaultColor = Qt.rgba(1, 1, 1, 0.15) +- closeButtonGeneralHoverColor = "#37373B" +- closeButtonGeneralClickColor = Qt.rgba(75/255, 75/255, 79/255, 1) +- closeButtonGeneralImage = "qrc:/images/application-exit-symbolic-white.svg" +- } +- } +- +- // 获取指定工作区预览窗口的内容 +- function resetAppWindowModel(deskindex) { +- var windowInfo = multitaskViewModel.getAppWindowList(deskindex, index) +- //发生了工作区切换, 需要清空所有item,会发出大量的itemRemoved信号 +- //将previewWindowCount设为0,通知appArea不必处理之后的itemRemoved信号,也不要执行动画 +- previewWindowCount = 0 +- rootWindow.appWindowModel.clear(); +- previewWindowCount = windowInfo.length +- for (var i in windowInfo) { +- var info = windowInfo[i] +- rootWindow.appWindowModel.append({"x" : info.x, "y" : info.y, +- "width" : info.width, "height" : info.height, +- "id" : info.id,"minimized" : info.minimized, "caption" : info.caption, +- "uuid" : String(info.uuid)}); +- } +- } +- +- //当拖拽窗口切换页面时,调用 +- function appRemoved(wid){ +- for (var i = 0; i < rootWindow.appWindowModel.count; i++) { +- var info = rootWindow.appWindowModel.get(i) +- if(info.uuid === wid) { +- previewWindowCount-- +- rootWindow.appWindowModel.remove(i) +- } +- } +- } +- +- // 重置desktopWindowModel信息,获取所有虚拟桌面的内容 +- function resetDesktopWindowModel(){ +- rootWindow.desktopWindowModel.clear() +- var desktopinfo = multitaskViewModel.getDesktopList(); +- for (var i in desktopinfo) { +- // 获取虚拟桌面上的窗口显示情况 +- var winModel = []; +- var infos = desktopinfo[i] +- if (rootWindow.highlightDesktop === infos.index && rootWindow.isShowingDesktop) { +- rootWindow.desktopWindowModel.append({ value: infos.index, model: [], itemType: "workSpace"}); +- continue; +- } +- var screenlist =infos.screenList +- var appList = screenlist[index].windowList +- for(var j in appList) { +- var info = appList[j] +- winModel.push({"x": info.x, "y": info.y, +- "width": info.width, "height": info.height, +- "id": info.id,"minimized": info.minimized, +- "caption": info.caption, +- "uuid" : String(info.uuid)}); +- } +- rootWindow.desktopWindowModel.append({ value: infos.index, model: winModel, itemType: "workSpace"}); +- } +- if (desktopWindowModel.count < 15) { +- rootWindow.desktopWindowModel.append({ value: desktopinfo.count + 1, model: [], itemType: "newDesktop"}); +- } +- +- } +- +- // 更新全部desktopWindowModel信息,更新某一个虚拟桌面的内容 +- function updateDesktopWindowModel(){ +- var desktopinfo = multitaskViewModel.getDesktopList(); +- // workspaceIndex 为工作区的索引 +- for (var workspaceIndex in desktopinfo) { +- rootWindow.desktopWindowModel.get(workspaceIndex).model.clear(); +- // index 为扩展屏的屏幕索引,单个屏幕时 index 只能为 1 +- var appList = desktopinfo[workspaceIndex].screenList[index].windowList +- for(var j in appList) { +- var info = appList[j] +- rootWindow.desktopWindowModel.get(workspaceIndex).model.append({"x": info.x, "y": info.y, +- "width": info.width, "height": info.height, +- "id": info.id, "minimized":info.minimized, +- "caption": info.caption, +- "uuid" : String(info.uuid)}); +- } +- } +- } +- +- FocusScope { +- id: mainView +- anchors.fill: parent +- focus: true +- property var screenIndex : index +- +- Loader { +- id: viewLoader +- sourceComponent: isVerticalLayout ? verticalLayoutView : horizontalLayoutView +- anchors.fill: parent +- } +- +- Component { +- id: verticalLayoutView +- Rectangle { +- color: "transparent" +- AppArea { +- id : appArea1 +- anchors.left : parent.left +- anchors.right : parent.right +- anchors.top : parent.top +- height : Math.floor(mainView.height * 111 / 135) +- +- Component.onCompleted : { +- console.log("AppArea end! ! !") +- } +- } +- DesktopArea { +- id : desktopArea1 +- anchors.left : parent.left +- anchors.right : parent.right +- anchors.top : appArea1.bottom +- anchors.bottom : parent.bottom +- } +- +- Component.onCompleted : { +- console.log("verticalLayoutView end! ! !") +- } +- } +- } +- +- Component { +- id: horizontalLayoutView +- Rectangle { +- color: "transparent" +- AppArea { +- id : appArea2 +- anchors.left : parent.left +- anchors.bottom : parent.bottom +- anchors.top : parent.top +- width : Math.floor(mainView.width * 410 / 480) +- +- Component.onCompleted : { +- console.log("MasterAppArea end! ! !") +- } +- } +- +- MasterDesktopArea { +- id : desktopArea2 +- anchors.left : appArea2.right +- anchors.right : parent.right +- anchors.top : parent.top +- anchors.bottom : parent.bottom +- } +- +- Component.onCompleted : { +- console.log("horizontalLayoutView end! ! !") +- } +- } +- } +- } +- +- Component.onCompleted : { +- setItemColor() +- resetAppWindowModel(multitaskViewModel.getCurrentDesktop()) +- resetDesktopWindowModel() +- } +- } +-} +diff --git a/windowsview/qml/tabbox.qml b/windowsview/qml/tabbox.qml +deleted file mode 100755 +index d746e60..0000000 +--- a/windowsview/qml/tabbox.qml ++++ /dev/null +@@ -1,303 +0,0 @@ +-/* +- * Copyright 2024 KylinSoft Co., Ltd. +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU Library General Public License as +- * published by the Free Software Foundation; either version 2, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details +- * +- * You should have received a copy of the GNU Library General Public +- * License along with this program; if not, write to the +- * Free Software Foundation, Inc., +- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +- */ +- +-import QtQuick 2.0 +-import QtQuick.Layouts 1.3 +-import QtQuick.Controls 2.5 +-import QtGraphicalEffects 1.0 +-import "Controller.js" as Controller +-import IconTheme 1.0 +-import org.kylin.thumbnail 1.0 as WlcomThumbnail +-//import org.ukui.kwin 2.0 as KWin +- +-// https://techbase.kde.org/Development/Tutorials/KWin/WindowSwitcher +-// https://github.com/KDE/kwin/blob/master/tabbox/switcheritem.h +-Rectangle { +- id : tabbox +- property var controller : new Controller.AppController(multitaskViewModel, tabbox, multitaskViewManager, ["none"]); +- property var currentIndex : thumbnailGridView.currentIndex +- property var screenGeometry : multitaskViewModel.getFullScreenGeometry(multitaskViewModel.getCurrentDesktop(), 0) +- property var theme : multitaskViewModel.getUKUIStyleName() +- property ListModel model : ListModel{} +- property var isOpenGL : true +- property int maxHeight : screenGeometry.height * 0.8 +- property int maxGridColumnsByWidth: Math.floor(screenGeometry.width / thumbnailGridView.cellWidth) +- property var scaleFactor : Math.min(screenGeometry.width, screenGeometry.height) / 1080 +- property int gridColumns : maxGridColumnsByWidth +- property int gridRows : Math.ceil(multitaskViewModel.getAllWindowCount() / gridColumns) +- property int optimalWidth : thumbnailGridView.cellWidth * gridColumns +- property int optimalHeight : thumbnailGridView.cellHeight * gridRows +- property int gridViewMargin : 40 * scaleFactor +- property bool isLayoutLeftToRight: Qt.application.layoutDirection === Qt.LeftToRight +- +- focus : true +- color : (theme === "ukui-white" || theme === "ukui" || theme === "ukui-light")? Qt.rgba(245/255, 245/255, 245/255, 0.45) : Qt.rgba(35/255, 36/255, 38/255, 0.45) +- width : screenGeometry.width +- height : Math.min(optimalHeight + 2 * gridViewMargin, maxHeight) +- clip : true +- Keys.enabled : true +- onActiveFocusChanged : { +- if(!tabbox.activeFocus) { +- multitaskViewManager.close() +- } else { +- /** +- 1. wlcom环境特定情况(快速操作按下alt+tab并松开)下,会出现本界面不隐藏问题,原因如下: +- 由于wlcom合成器与窗口选择器是两个独立的进程,使得窗口选择器被快捷键拉起时,向合成器发出的GrabKeyboard请求未被及时响应 +- 导致在特定情况下窗口选择器无法收到Key_Alt的Released信号,进而无法通过响应alt released事件来关闭此界面 +- 2. 当前实现,此界面显示时可以认为Key_Alt必定处于按下状态,因此针对特定情况处理如下: +- 在此界面显示并获取键盘焦点后,立即查询Key_Alt是否处于按下状态 +- 如果按未处于按下状态,则激活选定窗口并退出;否则,不做特殊处理 +- **/ +- // fix https://gitee.com/openkylin/ukui-window-switch/issues/IAID8L?from=project-issue +- if (!multitaskViewManager.isAltKeyPressed()) { +- activateSelectedWindow(); +- } +- } +- } +- +- GridView { +- id : thumbnailGridView +- anchors.fill : parent +- anchors.bottomMargin : tabbox.gridViewMargin +- anchors.topMargin : tabbox.gridViewMargin +- anchors.leftMargin : count > tabbox.maxGridColumnsByWidth ? (tabbox.width-tabbox.maxGridColumnsByWidth * cellWidth) / 2 : +- (tabbox.width-count * cellWidth) / 2 +- anchors.rightMargin : count > tabbox.maxGridColumnsByWidth ? (tabbox.width-tabbox.maxGridColumnsByWidth * cellWidth) / 2 : +- (tabbox.width-count * cellWidth) / 2 +- LayoutMirroring.enabled: !isLayoutLeftToRight +- model : tabbox.model +- property int iconSize : 24 * tabbox.scaleFactor +- property int captionRowHeight : 33 * tabbox.scaleFactor +- property int thumbnailWidth : (tabbox.screenGeometry.width - 2 * tabbox.gridViewMargin) / 4 +- property int thumbnailHeight : tabbox.screenGeometry.height / 22 * 5 +- property int spaceWidth : 2 * tabbox.scaleFactor +- property int outerBorderWidth : 4 * tabbox.scaleFactor +- property int innerBorderWidth : 2 * tabbox.scaleFactor +- property int appRadius : 8 * tabbox.scaleFactor +- property int thumbnailOuterRadius : tabbox.isOpenGL ? appRadius + outerBorderWidth + innerBorderWidth + 2 * spaceWidth : 0 +- property int thumbnailInterRadius : tabbox.isOpenGL ? appRadius + innerBorderWidth + spaceWidth : 0 +- cellWidth : 2 * (innerBorderWidth + outerBorderWidth) + 4 * spaceWidth + thumbnailWidth +- cellHeight : 2 * (innerBorderWidth + outerBorderWidth) + 5 * spaceWidth + captionRowHeight + thumbnailHeight +- keyNavigationWraps : true +- focus : true +- +- delegate : Rectangle { +- id : thumbnailGridItem +- width : thumbnailGridView.cellWidth +- height : thumbnailGridView.cellHeight +- color : "transparent" +- border.color : (tabbox.theme === "ukui-white" || tabbox.theme === "ukui" || tabbox.theme === "ukui-light") ? "#262626" : "#FFFFFF" +- border.width : index == thumbnailGridView.currentIndex ? thumbnailGridView.outerBorderWidth : 0 +- // highlight在快速绘制的时候会出现绘制的坐标偏移的问题,故不使用 +- radius : thumbnailGridView.thumbnailOuterRadius +- +- MouseArea { +- anchors.fill : parent +- onClicked : { +- thumbnailGridItem.select(); +- } +- hoverEnabled : true +- +- onEntered : { +- thumbnailBorderItem.border.width = thumbnailGridView.innerBorderWidth; +- } +- +- onExited : { +- thumbnailBorderItem.border.width = 0; +- } +- } +- function select() { +- thumbnailGridView.currentIndex = index; +- controller.onWindowClicked(model.uuid); +- } +- +- function getThumbnailSize() +- { +- var thumbHeight = thumbnailGridView.thumbnailHeight +- var max_width = thumbnailGridView.thumbnailWidth +- var clientWidth = model.width +- var clientHeight = model.height +- var thumbWidth = Math.floor(thumbHeight * clientWidth / clientHeight) +- if (thumbWidth > max_width) { +- thumbWidth = max_width +- thumbHeight = Math.floor(thumbWidth * clientHeight / clientWidth) +- } +- return [thumbWidth, thumbHeight] +- } +- +- ColumnLayout { +- spacing : 0 +- anchors.centerIn : parent +- height : parent.height - 2 * (thumbnailGridView.outerBorderWidth + thumbnailGridView.spaceWidth) +- width : parent.width - 2 * (thumbnailGridView.outerBorderWidth + thumbnailGridView.spaceWidth) +- x : thumbnailGridView.outerBorderWidth + thumbnailGridView.spaceWidth +- y : thumbnailGridView.outerBorderWidth + thumbnailGridView.spaceWidth +- RowLayout { +- id : captionRow +- spacing : 2 * thumbnailGridView.spaceWidth +- Layout.fillHeight : true +- layoutDirection: isLayoutLeftToRight ? Qt.LeftToRight : Qt.RightToLeft +- +- IconTheme { +- id : iconItem +- width : thumbnailGridView.iconSize +- height : thumbnailGridView.iconSize +- icon : multitaskViewModel.getWindowIcon(model.uuid) +- } +- +- Label { +- id : label +- verticalAlignment : Qt.AlignVCenter +- Layout.fillWidth : true +- color : (tabbox.theme === "ukui-white" || tabbox.theme === "ukui" || tabbox.theme === "ukui-light") ? "#000000" : "#FFFFFF" +- text : model.caption +- horizontalAlignment: isLayoutLeftToRight ? Qt.AlignLeft : Qt.AlignRight +- elide : isLayoutLeftToRight ? Text.ElideRight : Text.ElideLeft +- } +- +- //label高度受字号控制,此Rectangle起占位作用,防止字号改变时缩略图位置改变 +- Rectangle { +- width : 1 +- height : thumbnailGridView.captionRowHeight +- color : "transparent" +- } +- } +- +- // KWin.ThumbnailItem needs a container +- // otherwise it will be drawn the same size as the parent ColumnLayout +- Rectangle { +- color : "transparent" +- Layout.fillHeight : true +- Layout.fillWidth : true +- Rectangle { +- id : thumbnailBorderItem +- x : (parent.width - thumbnailBorderItem.width) / 2 +- y : thumbnailGridView.spaceWidth +- width : getThumbnailSize()[0] + 2 * (thumbnailGridView.innerBorderWidth + thumbnailGridView.spaceWidth) +- height : thumbnailGridView.thumbnailHeight + 2 * (thumbnailGridView.innerBorderWidth + thumbnailGridView.spaceWidth) +- color : "transparent" +- border.color : (tabbox.theme === "ukui-white" || tabbox.theme === "ukui" || tabbox.theme === "ukui-light") ? "#262626" : "#FFFFFF" +- border.width : 0 +- radius : thumbnailGridView.thumbnailInterRadius +- Rectangle { +- id : thumbnailBackItem +- width : getThumbnailSize()[0] +- height : getThumbnailSize()[1] +- anchors.centerIn : parent +- color : "transparent" +- clip : true +- layer.enabled : tabbox.isOpenGL ? true : false +- layer.effect : OpacityMask { +- maskSource : Rectangle { +- width : thumbnailBackItem.width +- height : thumbnailBackItem.height +- radius : Math.min(thumbnailGridView.appRadius, Math.floor(Math.min(width, height) / 2)) +- } +- } +- +- +- WlcomThumbnail.ThumbnailItem { +- anchors.fill: parent +- windowId: model.uuid +- visible: thumbnailGridView.visible +- } +- } +- } +- } +- } +- } // GridView.delegate +- +- Connections { +- target : tabbox +- function onCurrentIndexChanged() { +- thumbnailGridView.currentIndex = tabbox.currentIndex; +- } +- } +- } // GridView +- +- Keys.onDeletePressed : { +- multitaskViewManager.close() +- } +- +- Keys.onEscapePressed : { +- multitaskViewManager.close() +- } +- +- Keys.onBacktabPressed : { +- if (!multitaskViewManager.isAltKeyPressed()) { +- return; +- } +- if (isLayoutLeftToRight) { +- thumbnailGridView.moveCurrentIndexLeft(); +- } else { +- thumbnailGridView.moveCurrentIndexRight(); +- } +- } +- +- Keys.onTabPressed : { +- if (isLayoutLeftToRight) { +- thumbnailGridView.moveCurrentIndexRight(); +- } else { +- thumbnailGridView.moveCurrentIndexLeft(); +- } +- } +- +- Keys.onPressed : { +- if (event.key === Qt.Key_Left) { +- thumbnailGridView.moveCurrentIndexLeft(); +- } else if (event.key === Qt.Key_Right) { +- thumbnailGridView.moveCurrentIndexRight(); +- } else if (event.key === Qt.Key_Up) { +- thumbnailGridView.moveCurrentIndexUp(); +- } else if (event.key === Qt.Key_Down) { +- thumbnailGridView.moveCurrentIndexDown(); +- } else { +- return; +- } +- } +- +- Keys.onReleased : { +- if (event.key === Qt.Key_Alt) { +- activateSelectedWindow(); +- } else if (event.key === Qt.Key_Shift && !multitaskViewManager.isAltKeyPressed()) { +- activateSelectedWindow(); +- } +- } +- +- function activateSelectedWindow() { +- controller.onWindowClicked(model.get(thumbnailGridView.currentIndex).uuid); +- thumbnailGridView.visible = false; +- } +- +- function resetAppWindowModel(deskindex) { +- var windowInfo = multitaskViewModel.getAllAppWindowList() +- model.clear(); +- for (var i in windowInfo) { +- var info = windowInfo[i] +- model.append({"x" : info.x, "y" : info.y, +- "width" : info.width, "height" : info.height, +- "id" : info.id,"minimized" : info.minimized, "caption" : info.caption, +- "uuid" : String(info.uuid)}); +- } +- } +- +- Component.onCompleted : { +- resetAppWindowModel(multitaskViewModel.getCurrentDesktop()) +- tabbox.currentIndex = model.count > 1 ? 1 : 0 +- } +-} +diff --git a/windowsview/translations/ukui-window-switch_ar.ts b/windowsview/translations/ukui-window-switch_ar.ts +new file mode 100644 +index 0000000..872eb87 +--- /dev/null ++++ b/windowsview/translations/ukui-window-switch_ar.ts +@@ -0,0 +1,34 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="ar" sourcelanguage="en_US"> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="../qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation>سطح مكتب جديد</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="178"/> ++ <source>No recent tasks</source> ++ <translation>لا توجد مهام حديثة</translation> ++ </message> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="354"/> ++ <source>Clear</source> ++ <translation>واضح</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="198"/> ++ <source>Desktop</source> ++ <translation>سطح المكتب</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/translations/ukui-window-switch_bo_CN.ts b/windowsview/translations/ukui-window-switch_bo_CN.ts +new file mode 100644 +index 0000000..784bb50 +--- /dev/null ++++ b/windowsview/translations/ukui-window-switch_bo_CN.ts +@@ -0,0 +1,34 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="bo_CN" sourcelanguage="en_US"> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="../qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">གསར་དུ་བཙུགས་པའི་ལས་དོན་ཁུལ།</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="178"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">ཉེ་ལམ་གྱི་ལས་འགན་གང་ཡང་མེད།</translation> ++ </message> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="354"/> ++ <source>Clear</source> ++ <translation type="unfinished">གསལ་པོར་བཤད་ན།</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="198"/> ++ <source>Desktop</source> ++ <translation type="unfinished">ལས་སྒྲུབ་ཁུལ།</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/translations/ukui-window-switch_de.ts b/windowsview/translations/ukui-window-switch_de.ts +new file mode 100644 +index 0000000..6c91b6e +--- /dev/null ++++ b/windowsview/translations/ukui-window-switch_de.ts +@@ -0,0 +1,34 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="de" sourcelanguage="en_US"> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="../qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">Neuer Desktop</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="178"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">Keine aktuellen Aufgaben</translation> ++ </message> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="354"/> ++ <source>Clear</source> ++ <translation type="unfinished">Klar</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="198"/> ++ <source>Desktop</source> ++ <translation type="unfinished">Desktop</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/translations/ukui-window-switch_es.ts b/windowsview/translations/ukui-window-switch_es.ts +new file mode 100644 +index 0000000..a54c7d7 +--- /dev/null ++++ b/windowsview/translations/ukui-window-switch_es.ts +@@ -0,0 +1,34 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="es" sourcelanguage="en_US"> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="../qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">Nuevo escritorio</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="178"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">No hay tareas recientes</translation> ++ </message> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="354"/> ++ <source>Clear</source> ++ <translation type="unfinished">Claro</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="198"/> ++ <source>Desktop</source> ++ <translation type="unfinished">Escritorio</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/translations/ukui-window-switch_fr.ts b/windowsview/translations/ukui-window-switch_fr.ts +new file mode 100644 +index 0000000..4d739f2 +--- /dev/null ++++ b/windowsview/translations/ukui-window-switch_fr.ts +@@ -0,0 +1,34 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="fr" sourcelanguage="en_US"> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="../qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">Nouveau bureau</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="178"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">Pas de tâches récentes</translation> ++ </message> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="354"/> ++ <source>Clear</source> ++ <translation type="unfinished">Clair</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="198"/> ++ <source>Desktop</source> ++ <translation type="unfinished">Bureau</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/translations/ukui-window-switch_kk.ts b/windowsview/translations/ukui-window-switch_kk.ts +new file mode 100644 +index 0000000..d2411a9 +--- /dev/null ++++ b/windowsview/translations/ukui-window-switch_kk.ts +@@ -0,0 +1,34 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="kk" sourcelanguage="en_US"> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="../qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">Жаңа үстел</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="178"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">Соңғы тапсырмалар жоқ</translation> ++ </message> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="354"/> ++ <source>Clear</source> ++ <translation type="unfinished">Тазалау</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="198"/> ++ <source>Desktop</source> ++ <translation type="unfinished">Жұмыс үстелі</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/translations/ukui-window-switch_ky.ts b/windowsview/translations/ukui-window-switch_ky.ts +new file mode 100644 +index 0000000..52ba01d +--- /dev/null ++++ b/windowsview/translations/ukui-window-switch_ky.ts +@@ -0,0 +1,34 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="ky" sourcelanguage="en_US"> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="../qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">Жаңы иш столу</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="178"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">Акыркы милдеттер жок</translation> ++ </message> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="354"/> ++ <source>Clear</source> ++ <translation type="unfinished">Тазалоо</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="198"/> ++ <source>Desktop</source> ++ <translation type="unfinished">Иш столу</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/translations/ukui-window-switch_mn.ts b/windowsview/translations/ukui-window-switch_mn.ts +new file mode 100644 +index 0000000..72594ff +--- /dev/null ++++ b/windowsview/translations/ukui-window-switch_mn.ts +@@ -0,0 +1,34 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="mn" sourcelanguage="en_US"> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="../qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">ᠱᠢᠨᠡᠪᠡᠷ ᠪᠠᠢᠭᠤᠯᠤᠭ᠍ᠰᠠᠨ ᠠᠵᠢᠯᠯᠠᠬᠤ ᠤᠷᠤᠨ</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="178"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">ᠨᠡᠬᠡᠬᠡᠬᠦ᠌ ᠬᠡᠷᠡᠭᠯᠡᠭᠡ ᠪᠠᠢᠬᠤ ᠦᠬᠡᠢ</translation> ++ </message> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="354"/> ++ <source>Clear</source> ++ <translation type="unfinished">ᠠᠷᠢᠯᠭᠠᠬᠤ</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="198"/> ++ <source>Desktop</source> ++ <translation type="unfinished">ᠠᠵᠢᠯᠯᠠᠬᠤ ᠤᠷᠤᠨ</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/translations/ukui-window-switch_ug.ts b/windowsview/translations/ukui-window-switch_ug.ts +new file mode 100644 +index 0000000..cf49de3 +--- /dev/null ++++ b/windowsview/translations/ukui-window-switch_ug.ts +@@ -0,0 +1,34 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="ug" sourcelanguage="en_US"> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="../qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation>يېڭى ئۈستەلئۈستى</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="178"/> ++ <source>No recent tasks</source> ++ <translation>يېقىنقى ۋەزىپىلەر يوق</translation> ++ </message> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="354"/> ++ <source>Clear</source> ++ <translation>تازىلاش</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="198"/> ++ <source>Desktop</source> ++ <translation>ئۈستەل يۈزى</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/translations/ukui-window-switch_vi.ts b/windowsview/translations/ukui-window-switch_vi.ts +new file mode 100644 +index 0000000..c0b4fbb +--- /dev/null ++++ b/windowsview/translations/ukui-window-switch_vi.ts +@@ -0,0 +1,34 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="vi" sourcelanguage="en_US"> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="../qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation>Máy tính để bàn mới</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="178"/> ++ <source>No recent tasks</source> ++ <translation>Không có nhiệm vụ gần đây</translation> ++ </message> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="354"/> ++ <source>Clear</source> ++ <translation>Trong</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="198"/> ++ <source>Desktop</source> ++ <translation>Bàn làm việc</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/translations/ukui-window-switch_zh_CN.ts b/windowsview/translations/ukui-window-switch_zh_CN.ts +new file mode 100644 +index 0000000..2a6ba66 +--- /dev/null ++++ b/windowsview/translations/ukui-window-switch_zh_CN.ts +@@ -0,0 +1,34 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="zh_CN" sourcelanguage="en_US"> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="../qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">新建工作区</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="178"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">无应用开启</translation> ++ </message> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="354"/> ++ <source>Clear</source> ++ <translation type="unfinished">清除</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="198"/> ++ <source>Desktop</source> ++ <translation type="unfinished">工作区</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/translations/ukui-window-switch_zh_Hant.ts b/windowsview/translations/ukui-window-switch_zh_Hant.ts +new file mode 100644 +index 0000000..67c2770 +--- /dev/null ++++ b/windowsview/translations/ukui-window-switch_zh_Hant.ts +@@ -0,0 +1,34 @@ ++<?xml version="1.0" encoding="utf-8"?> ++<!DOCTYPE TS> ++<TS version="2.1" language="zh_Hant" sourcelanguage="en_US"> ++<context> ++ <name>NewDesktopButton</name> ++ <message> ++ <location filename="../qml/NewDesktopButton.qml" line="104"/> ++ <source>New Desktop</source> ++ <translation type="unfinished">新桌面</translation> ++ </message> ++</context> ++<context> ++ <name>TabletViewMain</name> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="178"/> ++ <source>No recent tasks</source> ++ <translation type="unfinished">無應用開啟</translation> ++ </message> ++ <message> ++ <location filename="../qml/TabletViewMain.qml" line="354"/> ++ <source>Clear</source> ++ <translation type="unfinished">清除</translation> ++ </message> ++</context> ++<context> ++ <name>VirtualDesktopWindow</name> ++ <message> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="189"/> ++ <location filename="../qml/VirtualDesktopWindow.qml" line="198"/> ++ <source>Desktop</source> ++ <translation type="unfinished">桌面</translation> ++ </message> ++</context> ++</TS> +diff --git a/windowsview/ukui-flow.cpp b/windowsview/ukui-flow.cpp +new file mode 100644 +index 0000000..f61d2cc +--- /dev/null ++++ b/windowsview/ukui-flow.cpp +@@ -0,0 +1,913 @@ ++/**************************************************************************** ++** ++** Copyright (C) 2016 The Qt Company Ltd. ++* Copyright (C) 2025, KylinSoft Co., Ltd. ++* ++** Contact: https://www.qt.io/licensing/ ++** ++** This file is part of the QtQml module of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL$ ++** Commercial License Usage ++** Licensees holding valid commercial Qt licenses may use this file in ++** accordance with the commercial license agreement provided with the ++** Software or, alternatively, in accordance with the terms contained in ++** a written agreement between you and The Qt Company. For licensing terms ++** and conditions see https://www.qt.io/terms-conditions. For further ++** information use the contact form at https://www.qt.io/contact-us. ++** ++** GNU Lesser General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU Lesser ++** General Public License version 3 as published by the Free Software ++** Foundation and appearing in the file LICENSE.LGPL3 included in the ++** packaging of this file. Please review the following information to ++** ensure the GNU Lesser General Public License version 3 requirements ++** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU ++** General Public License version 2.0 or (at your option) the GNU General ++** Public license version 3 or any later version approved by the KDE Free ++** Qt Foundation. The licenses are as published by the Free Software ++** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ++** included in the packaging of this file. Please review the following ++** information to ensure the GNU General Public License requirements will ++** be met: https://www.gnu.org/licenses/gpl-2.0.html and ++** https://www.gnu.org/licenses/gpl-3.0.html. ++** ++** $QT_END_LICENSE$ ++** ++** iaom <zhangpengfei@kylinos.cn> ++****************************************************************************/ ++ ++#include "ukui-flow.h" ++ ++#include <libkywc.h> ++#include <qqmlinfo.h> ++static const QQuickItemPrivate::ChangeTypes watchedChanges ++ = QQuickItemPrivate::Geometry ++ | QQuickItemPrivate::SiblingOrder ++ | QQuickItemPrivate::Visibility ++ | QQuickItemPrivate::Destroyed; ++ ++void UkuiBasePositionerPrivate::watchChanges(QQuickItem *other) ++{ ++ QQuickItemPrivate *otherPrivate = QQuickItemPrivate::get(other); ++ otherPrivate->addItemChangeListener(this, watchedChanges); ++} ++ ++void UkuiBasePositionerPrivate::unwatchChanges(QQuickItem* other) ++{ ++ QQuickItemPrivate *otherPrivate = QQuickItemPrivate::get(other); ++ otherPrivate->removeItemChangeListener(this, watchedChanges); ++} ++ ++ ++UkuiBasePositioner::PositionedItem::PositionedItem(QQuickItem *i) ++ : item(i) ++ , transitionableItem(nullptr) ++ , index(-1) ++ , isNew(false) ++ , isVisible(true) ++ , topPadding(0) ++ , leftPadding(0) ++ , rightPadding(0) ++ , bottomPadding(0) ++{ ++} ++ ++UkuiBasePositioner::PositionedItem::~PositionedItem() ++{ ++ delete transitionableItem; ++} ++ ++qreal UkuiBasePositioner::PositionedItem::itemX() const ++{ ++ return transitionableItem ? transitionableItem->itemX() : item->x(); ++} ++ ++qreal UkuiBasePositioner::PositionedItem::itemY() const ++{ ++ return transitionableItem ? transitionableItem->itemY() : item->y(); ++} ++ ++void UkuiBasePositioner::PositionedItem::moveTo(const QPointF &pos) ++{ ++ if (transitionableItem) { ++ transitionableItem->moveTo(pos); ++ } ++ else ++ item->setPosition(pos); ++} ++ ++void UkuiBasePositioner::PositionedItem::transitionNextReposition(QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, bool asTarget) ++{ ++ if (!transitioner) ++ return; ++ if (!transitionableItem) ++ transitionableItem = new QQuickItemViewTransitionableItem(item); ++ transitioner->transitionNextReposition(transitionableItem, type, asTarget); ++} ++ ++bool UkuiBasePositioner::PositionedItem::prepareTransition(QQuickItemViewTransitioner *transitioner, const QRectF &viewBounds) ++{ ++ return transitionableItem ? transitionableItem->prepareTransition(transitioner, index, viewBounds) : false; ++} ++ ++void UkuiBasePositioner::PositionedItem::startTransition(QQuickItemViewTransitioner *transitioner) ++{ ++ if (transitionableItem) ++ transitionableItem->startTransition(transitioner, index); ++} ++ ++void UkuiBasePositioner::PositionedItem::updatePadding(qreal lp, qreal tp, qreal rp, qreal bp) ++{ ++ leftPadding = lp; ++ topPadding = tp; ++ rightPadding = rp; ++ bottomPadding = bp; ++} ++ ++UkuiBasePositioner::UkuiBasePositioner(PositionerType at, QQuickItem *parent) ++ : QQuickImplicitSizeItem(*(new UkuiBasePositionerPrivate), parent) ++{ ++ Q_D(UkuiBasePositioner); ++ d->init(at); ++} ++ ++UkuiBasePositioner::UkuiBasePositioner(UkuiBasePositionerPrivate &dd, PositionerType at, QQuickItem *parent) ++ : QQuickImplicitSizeItem(dd, parent) ++{ ++ Q_D(UkuiBasePositioner); ++ d->init(at); ++} ++ ++UkuiBasePositioner::~UkuiBasePositioner() ++{ ++ Q_D(UkuiBasePositioner); ++ delete d->transitioner; ++ for (int i = 0; i < positionedItems.count(); ++i) ++ d->unwatchChanges(positionedItems.at(i).item); ++ for (int i = 0; i < unpositionedItems.count(); ++i) ++ d->unwatchChanges(unpositionedItems.at(i).item); ++ clearPositionedItems(&positionedItems); ++ clearPositionedItems(&unpositionedItems); ++} ++ ++void UkuiBasePositioner::updatePolish() ++{ ++ Q_D(UkuiBasePositioner); ++ if (d->positioningDirty) ++ prePositioning(); ++} ++ ++qreal UkuiBasePositioner::spacing() const ++{ ++ Q_D(const UkuiBasePositioner); ++ return d->spacing; ++} ++ ++void UkuiBasePositioner::setSpacing(qreal s) ++{ ++ Q_D(UkuiBasePositioner); ++ if (s == d->spacing) ++ return; ++ d->spacing = s; ++ d->setPositioningDirty(); ++ emit spacingChanged(); ++} ++ ++QQuickTransition *UkuiBasePositioner::populate() const ++{ ++ Q_D(const UkuiBasePositioner); ++ return d->transitioner ? d->transitioner->populateTransition : nullptr; ++} ++ ++void UkuiBasePositioner::setPopulate(QQuickTransition *transition) ++{ ++ Q_D(UkuiBasePositioner); ++ if (!d->transitioner) ++ d->transitioner = new QQuickItemViewTransitioner; ++ if (d->transitioner->populateTransition != transition) { ++ d->transitioner->populateTransition = transition; ++ emit populateChanged(); ++ } ++} ++ ++QQuickTransition *UkuiBasePositioner::move() const ++{ ++ Q_D(const UkuiBasePositioner); ++ return d->transitioner ? d->transitioner->displacedTransition : nullptr; ++} ++ ++void UkuiBasePositioner::setMove(QQuickTransition *mt) ++{ ++ Q_D(UkuiBasePositioner); ++ if (!d->transitioner) ++ d->transitioner = new QQuickItemViewTransitioner; ++ if (mt == d->transitioner->displacedTransition) ++ return; ++ ++ d->transitioner->displacedTransition = mt; ++ emit moveChanged(); ++} ++ ++QQuickTransition *UkuiBasePositioner::add() const ++{ ++ Q_D(const UkuiBasePositioner); ++ return d->transitioner ? d->transitioner->addTransition : nullptr; ++} ++ ++void UkuiBasePositioner::setAdd(QQuickTransition *add) ++{ ++ Q_D(UkuiBasePositioner); ++ if (!d->transitioner) ++ d->transitioner = new QQuickItemViewTransitioner; ++ if (add == d->transitioner->addTransition) ++ return; ++ ++ d->transitioner->addTransition = add; ++ emit addChanged(); ++} ++ ++void UkuiBasePositioner::componentComplete() ++{ ++ Q_D(UkuiBasePositioner); ++ QQuickItem::componentComplete(); ++ if (d->transitioner) ++ d->transitioner->setPopulateTransitionEnabled(true); ++ positionedItems.reserve(childItems().count()); ++ prePositioning(); ++ if (d->transitioner) ++ d->transitioner->setPopulateTransitionEnabled(false); ++} ++ ++void UkuiBasePositioner::itemChange(ItemChange change, const ItemChangeData &value) ++{ ++ Q_D(UkuiBasePositioner); ++ if (change == ItemChildAddedChange) { ++ d->setPositioningDirty(); ++ } else if (change == ItemChildRemovedChange) { ++ QQuickItem *child = value.item; ++ UkuiBasePositioner::PositionedItem posItem(child); ++ int idx = positionedItems.find(posItem); ++ if (idx >= 0) { ++ d->unwatchChanges(child); ++ removePositionedItem(&positionedItems, idx); ++ } else if ((idx = unpositionedItems.find(posItem)) >= 0) { ++ d->unwatchChanges(child); ++ removePositionedItem(&unpositionedItems, idx); ++ } ++ d->setPositioningDirty(); ++ } ++ ++ QQuickItem::itemChange(change, value); ++} ++ ++void UkuiBasePositioner::forceLayout() ++{ ++ updatePolish(); ++} ++ ++void UkuiBasePositioner::prePositioning() ++{ ++ Q_D(UkuiBasePositioner); ++ if (!isComponentComplete()) ++ return; ++ ++ if (d->doingPositioning) ++ return; ++ ++ d->positioningDirty = false; ++ d->doingPositioning = true; ++ //Need to order children by creation order modified by stacking order ++ QList<QQuickItem *> children = childItems(); ++ ++ QPODVector<PositionedItem,8> oldItems; ++ positionedItems.copyAndClear(oldItems); ++ for (int ii = 0; ii < unpositionedItems.count(); ii++) ++ oldItems.append(unpositionedItems[ii]); ++ unpositionedItems.clear(); ++ int addedIndex = -1; ++ ++ for (int ii = 0; ii < children.count(); ++ii) { ++ QQuickItem *child = children.at(ii); ++ if (QQuickItemPrivate::get(child)->isTransparentForPositioner()) ++ continue; ++ QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child); ++ PositionedItem posItem(child); ++ int wIdx = oldItems.find(posItem); ++ if (wIdx < 0) { ++ d->watchChanges(child); ++ posItem.isNew = true; ++ if (!childPrivate->explicitVisible || !child->width() || !child->height()) { ++ posItem.isVisible = false; ++ posItem.index = -1; ++ unpositionedItems.append(posItem); ++ } else { ++ posItem.index = positionedItems.count(); ++ positionedItems.append(posItem); ++ ++ if (d->transitioner) { ++ if (addedIndex < 0) ++ addedIndex = posItem.index; ++ PositionedItem *theItem = &positionedItems[positionedItems.count()-1]; ++ if (d->transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) ++ theItem->transitionNextReposition(d->transitioner, QQuickItemViewTransitioner::PopulateTransition, true); ++ else if (!d->transitioner->populateTransitionEnabled()) ++ theItem->transitionNextReposition(d->transitioner, QQuickItemViewTransitioner::AddTransition, true); ++ } ++ } ++ } else { ++ PositionedItem *item = &oldItems[wIdx]; ++ // Items are only omitted from positioning if they are explicitly hidden ++ // i.e. their positioning is not affected if an ancestor is hidden. ++ if (!childPrivate->explicitVisible || !child->width() || !child->height()) { ++ item->isVisible = false; ++ item->index = -1; ++ unpositionedItems.append(*item); ++ } else if (!item->isVisible) { ++ // item changed from non-visible to visible, treat it as a "new" item ++ item->isVisible = true; ++ item->isNew = true; ++ item->index = positionedItems.count(); ++ positionedItems.append(*item); ++ ++ if (d->transitioner) { ++ if (addedIndex < 0) ++ addedIndex = item->index; ++ positionedItems[positionedItems.count()-1].transitionNextReposition(d->transitioner, QQuickItemViewTransitioner::AddTransition, true); ++ } ++ } else { ++ item->isNew = false; ++ item->index = positionedItems.count(); ++ positionedItems.append(*item); ++ } ++ } ++ } ++ ++ if (d->transitioner) { ++ for (int i=0; i<positionedItems.count(); i++) { ++ if (!positionedItems[i].isNew) { ++ if (addedIndex >= 0) { ++ positionedItems[i].transitionNextReposition(d->transitioner, QQuickItemViewTransitioner::AddTransition, false); ++ } else { ++ // just queue the item for a move-type displace - if the item hasn't ++ // moved anywhere, it won't be transitioned anyway ++ positionedItems[i].transitionNextReposition(d->transitioner, QQuickItemViewTransitioner::MoveTransition, false); ++ } ++ } ++ } ++ } ++ ++ QSizeF contentSize(0,0); ++ reportConflictingAnchors(); ++ if (!d->anchorConflict) { ++ doPositioning(&contentSize); ++ updateAttachedProperties(); ++ } ++ ++ if (d->transitioner) { ++ QRectF viewBounds(QPointF(), contentSize); ++ for (int i=0; i<positionedItems.count(); i++) ++ positionedItems[i].prepareTransition(d->transitioner, viewBounds); ++ for (int i=0; i<positionedItems.count(); i++) ++ positionedItems[i].startTransition(d->transitioner); ++ d->transitioner->resetTargetLists(); ++ } ++ ++ d->doingPositioning = false; ++ ++ //Set implicit size to the size of its children ++ setImplicitSize(contentSize.width(), contentSize.height()); ++ ++ emit positioningComplete(); ++} ++ ++void UkuiBasePositioner::positionItem(qreal x, qreal y, PositionedItem *target) ++{ ++ if ( target->itemX() != x || target->itemY() != y ) ++ target->moveTo(QPointF(x, y)); ++} ++ ++void UkuiBasePositioner::positionItemX(qreal x, PositionedItem *target) ++{ ++ Q_D(UkuiBasePositioner); ++ if (target->itemX() != x ++ && (d->type == Horizontal || d->type == Both)) { ++ target->moveTo(QPointF(x, target->itemY())); ++ } ++} ++ ++void UkuiBasePositioner::positionItemY(qreal y, PositionedItem *target) ++{ ++ Q_D(UkuiBasePositioner); ++ if (target->itemY() != y ++ && (d->type == Vertical || d->type == Both)) { ++ target->moveTo(QPointF(target->itemX(), y)); ++ } ++} ++ ++/* ++ Since PositionedItem values are stored by value, their internal transitionableItem pointers ++ must be cleaned up when a PositionedItem is removed from a QPODVector, otherwise the pointer ++ is never deleted since QPODVector doesn't invoke the destructor. ++ */ ++void UkuiBasePositioner::removePositionedItem(QPODVector<PositionedItem,8> *items, int index) ++{ ++ Q_ASSERT(index >= 0 && index < items->count()); ++ delete items->at(index).transitionableItem; ++ items->remove(index); ++} ++void UkuiBasePositioner::clearPositionedItems(QPODVector<PositionedItem,8> *items) ++{ ++ for (int i=0; i<items->count(); i++) ++ delete items->at(i).transitionableItem; ++ items->clear(); ++} ++ ++UkuiPositionerAttached *UkuiBasePositioner::qmlAttachedProperties(QObject *obj) ++{ ++ return new UkuiPositionerAttached(obj); ++} ++ ++void UkuiBasePositioner::updateAttachedProperties(UkuiPositionerAttached *specificProperty, QQuickItem *specificPropertyOwner) const ++{ ++ // If this function is deemed too expensive or shows up in profiles, it could ++ // be changed to run only when there are attached properties present. This ++ // could be a flag in the positioner that is set by the attached property ++ // constructor. ++ UkuiPositionerAttached *prevLastProperty = nullptr; ++ UkuiPositionerAttached *lastProperty = nullptr; ++ ++ for (int ii = 0; ii < positionedItems.count(); ++ii) { ++ const PositionedItem &child = positionedItems.at(ii); ++ if (!child.item) ++ continue; ++ ++ UkuiPositionerAttached *property = nullptr; ++ ++ if (specificProperty) { ++ if (specificPropertyOwner == child.item) { ++ property = specificProperty; ++ } ++ } else { ++ property = static_cast<UkuiPositionerAttached *>(qmlAttachedPropertiesObject<UkuiBasePositioner>(child.item, false)); ++ } ++ ++ if (property) { ++ property->setIndex(ii); ++ property->setIsFirstItem(ii == 0); ++ ++ if (property->isLastItem()) { ++ if (prevLastProperty) ++ prevLastProperty->setIsLastItem(false); // there can be only one last property ++ prevLastProperty = property; ++ } ++ } ++ ++ lastProperty = property; ++ } ++ ++ if (prevLastProperty && prevLastProperty != lastProperty) ++ prevLastProperty->setIsLastItem(false); ++ if (lastProperty) ++ lastProperty->setIsLastItem(true); ++ ++ // clear attached properties for unpositioned items ++ for (int ii = 0; ii < unpositionedItems.count(); ++ii) { ++ const PositionedItem &child = unpositionedItems.at(ii); ++ if (!child.item) ++ continue; ++ ++ UkuiPositionerAttached *property = nullptr; ++ ++ if (specificProperty) { ++ if (specificPropertyOwner == child.item) { ++ property = specificProperty; ++ } ++ } else { ++ property = static_cast<UkuiPositionerAttached *>(qmlAttachedPropertiesObject<UkuiBasePositioner>(child.item, false)); ++ } ++ ++ if (property) { ++ property->setIndex(-1); ++ property->setIsFirstItem(false); ++ property->setIsLastItem(false); ++ } ++ } ++} ++ ++qreal UkuiBasePositioner::padding() const ++{ ++ Q_D(const UkuiBasePositioner); ++ return d->padding(); ++} ++ ++void UkuiBasePositioner::setPadding(qreal padding) ++{ ++ Q_D(UkuiBasePositioner); ++ if (qFuzzyCompare(d->padding(), padding)) ++ return; ++ ++ d->extra.value().padding = padding; ++ d->setPositioningDirty(); ++ emit paddingChanged(); ++ if (!d->extra.isAllocated() || !d->extra->explicitTopPadding) ++ emit topPaddingChanged(); ++ if (!d->extra.isAllocated() || !d->extra->explicitLeftPadding) ++ emit leftPaddingChanged(); ++ if (!d->extra.isAllocated() || !d->extra->explicitRightPadding) ++ emit rightPaddingChanged(); ++ if (!d->extra.isAllocated() || !d->extra->explicitBottomPadding) ++ emit bottomPaddingChanged(); ++} ++ ++void UkuiBasePositioner::resetPadding() ++{ ++ setPadding(0); ++} ++ ++qreal UkuiBasePositioner::topPadding() const ++{ ++ Q_D(const UkuiBasePositioner); ++ if (d->extra.isAllocated() && d->extra->explicitTopPadding) ++ return d->extra->topPadding; ++ return d->padding(); ++} ++ ++void UkuiBasePositioner::setTopPadding(qreal padding) ++{ ++ Q_D(UkuiBasePositioner); ++ d->setTopPadding(padding); ++} ++ ++void UkuiBasePositioner::resetTopPadding() ++{ ++ Q_D(UkuiBasePositioner); ++ d->setTopPadding(0, true); ++} ++ ++qreal UkuiBasePositioner::leftPadding() const ++{ ++ Q_D(const UkuiBasePositioner); ++ if (d->extra.isAllocated() && d->extra->explicitLeftPadding) ++ return d->extra->leftPadding; ++ return d->padding(); ++} ++ ++void UkuiBasePositioner::setLeftPadding(qreal padding) ++{ ++ Q_D(UkuiBasePositioner); ++ d->setLeftPadding(padding); ++} ++ ++void UkuiBasePositioner::resetLeftPadding() ++{ ++ Q_D(UkuiBasePositioner); ++ d->setLeftPadding(0, true); ++} ++ ++qreal UkuiBasePositioner::rightPadding() const ++{ ++ Q_D(const UkuiBasePositioner); ++ if (d->extra.isAllocated() && d->extra->explicitRightPadding) ++ return d->extra->rightPadding; ++ return d->padding(); ++} ++ ++void UkuiBasePositioner::setRightPadding(qreal padding) ++{ ++ Q_D(UkuiBasePositioner); ++ d->setRightPadding(padding); ++} ++ ++void UkuiBasePositioner::resetRightPadding() ++{ ++ Q_D(UkuiBasePositioner); ++ d->setRightPadding(0, true); ++} ++ ++qreal UkuiBasePositioner::bottomPadding() const ++{ ++ Q_D(const UkuiBasePositioner); ++ if (d->extra.isAllocated() && d->extra->explicitBottomPadding) ++ return d->extra->bottomPadding; ++ return d->padding(); ++} ++ ++void UkuiBasePositioner::setBottomPadding(qreal padding) ++{ ++ Q_D(UkuiBasePositioner); ++ d->setBottomPadding(padding); ++} ++ ++void UkuiBasePositioner::resetBottomPadding() ++{ ++ Q_D(UkuiBasePositioner); ++ d->setBottomPadding(0, true); ++} ++ ++UkuiBasePositionerPrivate::ExtraData::ExtraData() ++ : padding(0) ++ , topPadding(0) ++ , leftPadding(0) ++ , rightPadding(0) ++ , bottomPadding(0) ++ , explicitTopPadding(false) ++ , explicitLeftPadding(false) ++ , explicitRightPadding(false) ++ , explicitBottomPadding(false) ++{ ++} ++ ++void UkuiBasePositionerPrivate::setTopPadding(qreal value, bool reset) ++{ ++ Q_Q(UkuiBasePositioner); ++ qreal oldPadding = q->topPadding(); ++ if (!reset || extra.isAllocated()) { ++ extra.value().topPadding = value; ++ extra.value().explicitTopPadding = !reset; ++ } ++ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) { ++ setPositioningDirty(); ++ emit q->topPaddingChanged(); ++ } ++} ++ ++void UkuiBasePositionerPrivate::setLeftPadding(qreal value, bool reset) ++{ ++ Q_Q(UkuiBasePositioner); ++ qreal oldPadding = q->leftPadding(); ++ if (!reset || extra.isAllocated()) { ++ extra.value().leftPadding = value; ++ extra.value().explicitLeftPadding = !reset; ++ } ++ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) { ++ setPositioningDirty(); ++ emit q->leftPaddingChanged(); ++ } ++} ++ ++void UkuiBasePositionerPrivate::setRightPadding(qreal value, bool reset) ++{ ++ Q_Q(UkuiBasePositioner); ++ qreal oldPadding = q->rightPadding(); ++ if (!reset || extra.isAllocated()) { ++ extra.value().rightPadding = value; ++ extra.value().explicitRightPadding = !reset; ++ } ++ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) { ++ setPositioningDirty(); ++ emit q->rightPaddingChanged(); ++ } ++} ++ ++void UkuiBasePositionerPrivate::setBottomPadding(qreal value, bool reset) ++{ ++ Q_Q(UkuiBasePositioner); ++ qreal oldPadding = q->bottomPadding(); ++ if (!reset || extra.isAllocated()) { ++ extra.value().bottomPadding = value; ++ extra.value().explicitBottomPadding = !reset; ++ } ++ if ((!reset && !qFuzzyCompare(oldPadding, value)) || (reset && !qFuzzyCompare(oldPadding, padding()))) { ++ setPositioningDirty(); ++ emit q->bottomPaddingChanged(); ++ } ++} ++ ++UkuiPositionerAttached::UkuiPositionerAttached(QObject *parent) : QObject(parent), m_index(-1), m_isFirstItem(false), m_isLastItem(false) ++{ ++ QQuickItem *attachedItem = qobject_cast<QQuickItem *>(parent); ++ if (attachedItem) { ++ UkuiBasePositioner *positioner = qobject_cast<UkuiBasePositioner *>(attachedItem->parent()); ++ if (positioner) { ++ positioner->updateAttachedProperties(this, attachedItem); ++ } ++ } ++} ++ ++void UkuiPositionerAttached::setIndex(int index) ++{ ++ if (m_index == index) ++ return; ++ m_index = index; ++ emit indexChanged(); ++} ++ ++void UkuiPositionerAttached::setIsFirstItem(bool isFirstItem) ++{ ++ if (m_isFirstItem == isFirstItem) ++ return; ++ m_isFirstItem = isFirstItem; ++ emit isFirstItemChanged(); ++} ++ ++void UkuiPositionerAttached::setIsLastItem(bool isLastItem) ++{ ++ if (m_isLastItem == isLastItem) ++ return; ++ m_isLastItem = isLastItem; ++ emit isLastItemChanged(); ++} ++ ++class UkuiFlowPrivate : public UkuiBasePositionerPrivate ++{ ++ Q_DECLARE_PUBLIC(UkuiFlow) ++ ++public: ++ UkuiFlowPrivate() ++ : UkuiBasePositionerPrivate(), flow(UkuiFlow::LeftToRight), lineHorizontalCenterAlignment(false) ++ {} ++ ++ void effectiveLayoutDirectionChange() override ++ { ++ Q_Q(UkuiFlow); ++ // Don't postpone, as it might be the only trigger for visible changes. ++ q->prePositioning(); ++ emit q->effectiveLayoutDirectionChanged(); ++ } ++ ++ UkuiFlow::Flow flow; ++ bool lineHorizontalCenterAlignment; ++ QHash<int, QPointF> posCache; ++}; ++ ++UkuiFlow::UkuiFlow(QQuickItem *parent) ++: UkuiBasePositioner(*(new UkuiFlowPrivate), Both, parent) ++{ ++ Q_D(UkuiFlow); ++ // Flow layout requires relayout if its own size changes too. ++ d->addItemChangeListener(d, QQuickItemPrivate::Geometry); ++} ++ ++UkuiFlow::Flow UkuiFlow::flow() const ++{ ++ Q_D(const UkuiFlow); ++ return d->flow; ++} ++ ++void UkuiFlow::setFlow(Flow flow) ++{ ++ Q_D(UkuiFlow); ++ if (d->flow != flow) { ++ d->flow = flow; ++ prePositioning(); ++ emit flowChanged(); ++ } ++} ++ ++Qt::LayoutDirection UkuiFlow::layoutDirection() const ++{ ++ Q_D(const UkuiFlow); ++ return d->layoutDirection; ++} ++ ++void UkuiFlow::setLayoutDirection(Qt::LayoutDirection layoutDirection) ++{ ++ Q_D(UkuiFlow); ++ if (d->layoutDirection != layoutDirection) { ++ d->layoutDirection = layoutDirection; ++ emit layoutDirectionChanged(); ++ d->effectiveLayoutDirectionChange(); ++ } ++} ++ ++Qt::LayoutDirection UkuiFlow::effectiveLayoutDirection() const ++{ ++ return UkuiBasePositionerPrivate::getEffectiveLayoutDirection(this); ++} ++ ++bool UkuiFlow::lineHorizontalCenterAlignment() const ++{ ++ Q_D(const UkuiFlow); ++ return d->lineHorizontalCenterAlignment; ++} ++ ++void UkuiFlow::setLineHorizontalCenterAlignment(bool lineHorizontalCenterAlignment) ++{ ++ Q_D(UkuiFlow); ++ if (d->lineHorizontalCenterAlignment != lineHorizontalCenterAlignment) { ++ d->lineHorizontalCenterAlignment = lineHorizontalCenterAlignment; ++ d->setPositioningDirty(); ++ emit lineHorizontalCenterAlignmentChanged(); ++ } ++} ++ ++void UkuiFlow::doPositioning(QSizeF *contentSize) ++{ ++ //Precondition: All items in the positioned list have a valid item pointer and should be positioned ++ Q_D(UkuiFlow); ++ ++ qreal hoffset1 = leftPadding(); ++ qreal hoffset2 = rightPadding(); ++ if (!d->isLeftToRight()) ++ qSwap(hoffset1, hoffset2); ++ qreal hoffset = hoffset1; ++ const qreal voffset1 = topPadding(); ++ qreal voffset = voffset1; ++ qreal linemax = 0; ++ contentSize->setWidth(qMax(contentSize->width(), hoffset1 + hoffset2)); ++ contentSize->setHeight(qMax(contentSize->height(), voffset + bottomPadding())); ++ ++ int lineFirstIndex = 0; ++ for (int i = 0; i < positionedItems.count(); ++i) { ++ PositionedItem &child = positionedItems[i]; ++ ++ if (d->flow == LeftToRight) { ++ if (widthValid() && hoffset != hoffset1 && hoffset + child.item->width() + hoffset2 > width()) { ++ //居中处理 ++ if (d->lineHorizontalCenterAlignment) { ++ PositionedItem &lineLastItem = positionedItems[i - 1]; ++ qreal moveOffSet = (width() - (d->posCache.value(lineLastItem.index).x() + lineLastItem.item->width() - d->posCache.value(lineFirstIndex).x())) / 2; ++ for (int j = lineFirstIndex; j < i; ++j) { ++ PositionedItem &lineChild = positionedItems[j]; ++ qreal posX = d->posCache.value(j).x() + moveOffSet; ++ if (!d->isLeftToRight()) { ++ posX = width() - lineChild.item->width() - posX; ++ } ++ positionItem(posX, d->posCache.value(j).y(), &lineChild); ++ lineChild.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding()); ++ } ++ lineFirstIndex = i; ++ } ++ hoffset = hoffset1; ++ voffset += linemax + spacing(); ++ linemax = 0; ++ } ++ } else { ++ if (heightValid() && voffset != voffset1 && voffset + child.item->height() + bottomPadding() > height()) { ++ voffset = voffset1; ++ hoffset += linemax + spacing(); ++ linemax = 0; ++ } ++ } ++ ++ if (d->isLeftToRight()) { ++ if(d->lineHorizontalCenterAlignment) { ++ d->posCache.insert(child.index, {hoffset, voffset}); ++ } else { ++ positionItem(hoffset, voffset, &child); ++ } ++ } else { ++ if(d->lineHorizontalCenterAlignment) { ++ d->posCache.insert(child.index, {hoffset, voffset}); ++ } else { ++ positionItemY(voffset, &child); ++ child.topPadding = topPadding(); ++ child.bottomPadding = bottomPadding(); ++ } ++ } ++ ++ contentSize->setWidth(qMax(contentSize->width(), hoffset + child.item->width() + hoffset2)); ++ contentSize->setHeight(qMax(contentSize->height(), voffset + child.item->height() + bottomPadding())); ++ ++ if (d->flow == LeftToRight) { ++ hoffset += child.item->width(); ++ hoffset += spacing(); ++ linemax = qMax(linemax, child.item->height()); ++ } else { ++ voffset += child.item->height(); ++ voffset += spacing(); ++ linemax = qMax(linemax, child.item->width()); ++ } ++ } ++ //最后一行 ++ if (widthValid() && d->lineHorizontalCenterAlignment && lineFirstIndex < positionedItems.count()) { ++ PositionedItem &lastItem = positionedItems[positionedItems.count() - 1]; ++ if (d->flow == LeftToRight) { ++ qreal moveOffSet = (width() - (d->posCache.value(lastItem.index).x() + lastItem.item->width() - d->posCache.value(lineFirstIndex).x())) / 2; ++ for (int j = lineFirstIndex; j < positionedItems.count(); ++j) { ++ PositionedItem &lineChild = positionedItems[j]; ++ qreal posX = d->posCache.value(j).x() + moveOffSet; ++ if (!d->isLeftToRight()) { ++ posX = width() - lineChild.item->width() - posX; ++ } ++ positionItem(posX, d->posCache.value(j).y(), &lineChild); ++ lineChild.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding()); ++ } ++ } ++ } ++ if(d->lineHorizontalCenterAlignment && d->flow == LeftToRight) { ++ contentSize->setWidth(width()); ++ } ++ d->posCache.clear(); ++} ++ ++void UkuiFlow::reportConflictingAnchors() ++{ ++ Q_D(UkuiFlow); ++ for (int ii = 0; ii < positionedItems.count(); ++ii) { ++ const PositionedItem &child = positionedItems.at(ii); ++ if (child.item) { ++ QQuickAnchors *anchors = QQuickItemPrivate::get(static_cast<QQuickItem *>(child.item))->_anchors; ++ if (anchors && (anchors->usedAnchors() || anchors->fill() || anchors->centerIn())) { ++ d->anchorConflict = true; ++ break; ++ } ++ } ++ } ++ if (d->anchorConflict) ++ qmlWarning(this) << "Cannot specify anchors for items inside Flow." << " Flow will not function."; ++} +diff --git a/windowsview/ukui-flow.h b/windowsview/ukui-flow.h +new file mode 100644 +index 0000000..3370163 +--- /dev/null ++++ b/windowsview/ukui-flow.h +@@ -0,0 +1,370 @@ ++/**************************************************************************** ++** ++** Copyright (C) 2016 The Qt Company Ltd. ++* Copyright (C) 2025, KylinSoft Co., Ltd. ++** Contact: https://www.qt.io/licensing/ ++** ++** This file is part of the QtQuick module of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL$ ++** Commercial License Usage ++** Licensees holding valid commercial Qt licenses may use this file in ++** accordance with the commercial license agreement provided with the ++** Software or, alternatively, in accordance with the terms contained in ++** a written agreement between you and The Qt Company. For licensing terms ++** and conditions see https://www.qt.io/terms-conditions. For further ++** information use the contact form at https://www.qt.io/contact-us. ++** ++** GNU Lesser General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU Lesser ++** General Public License version 3 as published by the Free Software ++** Foundation and appearing in the file LICENSE.LGPL3 included in the ++** packaging of this file. Please review the following information to ++** ensure the GNU Lesser General Public License version 3 requirements ++** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU ++** General Public License version 2.0 or (at your option) the GNU General ++** Public license version 3 or any later version approved by the KDE Free ++** Qt Foundation. The licenses are as published by the Free Software ++** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ++** included in the packaging of this file. Please review the following ++** information to ensure the GNU General Public License requirements will ++** be met: https://www.gnu.org/licenses/gpl-2.0.html and ++** https://www.gnu.org/licenses/gpl-3.0.html. ++** ++** $QT_END_LICENSE$ ++** ++** iaom <zhangpengfei@kylinos.cn> ++****************************************************************************/ ++ ++#ifndef UKUI_FLOW_H ++#define UKUI_FLOW_H ++ ++#include <private/qquickimplicitsizeitem_p.h> ++#include <private/qquickitemviewtransition_p.h> ++#include <private/qpodvector_p.h> ++#include <private/qquickimplicitsizeitem_p_p.h> ++#include <private/qquickitemchangelistener_p.h> ++ ++#include <QtCore/qobject.h> ++#include <QtCore/qstring.h> ++ ++class UkuiBasePositionerPrivate; ++ ++class UkuiPositionerAttached : public QObject ++{ ++ Q_OBJECT ++ ++public: ++ UkuiPositionerAttached(QObject *parent); ++ ++ Q_PROPERTY(int index READ index NOTIFY indexChanged) ++ Q_PROPERTY(bool isFirstItem READ isFirstItem NOTIFY isFirstItemChanged) ++ Q_PROPERTY(bool isLastItem READ isLastItem NOTIFY isLastItemChanged) ++ ++ int index() const { return m_index; } ++ void setIndex(int index); ++ ++ bool isFirstItem() const { return m_isFirstItem; } ++ void setIsFirstItem(bool isFirstItem); ++ ++ bool isLastItem() const { return m_isLastItem; } ++ void setIsLastItem(bool isLastItem); ++ ++ Q_SIGNALS: ++ void indexChanged(); ++ void isFirstItemChanged(); ++ void isLastItemChanged(); ++ ++private: ++ int m_index; ++ bool m_isFirstItem; ++ bool m_isLastItem; ++}; ++ ++class UkuiBasePositioner : public QQuickImplicitSizeItem ++{ ++ Q_OBJECT ++ ++ Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged) ++ Q_PROPERTY(QQuickTransition *populate READ populate WRITE setPopulate NOTIFY populateChanged) ++ Q_PROPERTY(QQuickTransition *move READ move WRITE setMove NOTIFY moveChanged) ++ Q_PROPERTY(QQuickTransition *add READ add WRITE setAdd NOTIFY addChanged) ++ ++ Q_PROPERTY(qreal padding READ padding WRITE setPadding RESET resetPadding NOTIFY paddingChanged) ++ Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding RESET resetTopPadding NOTIFY topPaddingChanged) ++ Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding RESET resetLeftPadding NOTIFY leftPaddingChanged) ++ Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding RESET resetRightPadding NOTIFY rightPaddingChanged) ++ Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding RESET resetBottomPadding NOTIFY bottomPaddingChanged) ++ ++public: ++ enum PositionerType { None = 0x0, Horizontal = 0x1, Vertical = 0x2, Both = 0x3 }; ++ ++ UkuiBasePositioner(PositionerType, QQuickItem *parent); ++ ~UkuiBasePositioner(); ++ ++ qreal spacing() const; ++ void setSpacing(qreal); ++ ++ QQuickTransition *populate() const; ++ void setPopulate(QQuickTransition *); ++ ++ QQuickTransition *move() const; ++ void setMove(QQuickTransition *); ++ ++ QQuickTransition *add() const; ++ void setAdd(QQuickTransition *); ++ ++ static UkuiPositionerAttached *qmlAttachedProperties(QObject *obj); ++ ++ void updateAttachedProperties(UkuiPositionerAttached *specificProperty = nullptr, QQuickItem *specificPropertyOwner = nullptr) const; ++ ++ qreal padding() const; ++ void setPadding(qreal padding); ++ void resetPadding(); ++ ++ qreal topPadding() const; ++ void setTopPadding(qreal padding); ++ void resetTopPadding(); ++ ++ qreal leftPadding() const; ++ void setLeftPadding(qreal padding); ++ void resetLeftPadding(); ++ ++ qreal rightPadding() const; ++ void setRightPadding(qreal padding); ++ void resetRightPadding(); ++ ++ qreal bottomPadding() const; ++ void setBottomPadding(qreal padding); ++ void resetBottomPadding(); ++ ++ Q_INVOKABLE void forceLayout(); ++ ++protected: ++ UkuiBasePositioner(UkuiBasePositionerPrivate &dd, PositionerType at, QQuickItem *parent); ++ void componentComplete() override; ++ void itemChange(ItemChange, const ItemChangeData &) override; ++ ++ void updatePolish() override; ++ ++Q_SIGNALS: ++ void spacingChanged(); ++ void populateChanged(); ++ void moveChanged(); ++ void addChanged(); ++ void paddingChanged(); ++ void topPaddingChanged(); ++ void leftPaddingChanged(); ++ void rightPaddingChanged(); ++ void bottomPaddingChanged(); ++ void positioningComplete(); ++ ++protected Q_SLOTS: ++ void prePositioning(); ++ ++protected: ++ virtual void doPositioning(QSizeF *contentSize)=0; ++ virtual void reportConflictingAnchors()=0; ++ ++ class PositionedItem ++ { ++ public : ++ PositionedItem(QQuickItem *i); ++ ~PositionedItem(); ++ bool operator==(const PositionedItem &other) const { return other.item == item; } ++ ++ qreal itemX() const; ++ qreal itemY() const; ++ ++ void moveTo(const QPointF &pos); ++ ++ void transitionNextReposition(QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, bool asTarget); ++ bool prepareTransition(QQuickItemViewTransitioner *transitioner, const QRectF &viewBounds); ++ void startTransition(QQuickItemViewTransitioner *transitioner); ++ ++ void updatePadding(qreal lp, qreal tp, qreal rp, qreal bp); ++ ++ QQuickItem *item; ++ QQuickItemViewTransitionableItem *transitionableItem; ++ int index; ++ bool isNew; ++ bool isVisible; ++ ++ qreal topPadding; ++ qreal leftPadding; ++ qreal rightPadding; ++ qreal bottomPadding; ++ }; ++ ++ QPODVector<PositionedItem,8> positionedItems; ++ QPODVector<PositionedItem,8> unpositionedItems;//Still 'in' the positioner, just not positioned ++ ++ void positionItem(qreal x, qreal y, PositionedItem *target); ++ void positionItemX(qreal, PositionedItem *target); ++ void positionItemY(qreal, PositionedItem *target); ++ ++ void removePositionedItem(QPODVector<PositionedItem,8> *items, int index); ++ void clearPositionedItems(QPODVector<PositionedItem,8> *items); ++ ++private: ++ Q_DISABLE_COPY(UkuiBasePositioner) ++ Q_DECLARE_PRIVATE(UkuiBasePositioner) ++}; ++ ++class UkuiBasePositionerPrivate : public QQuickImplicitSizeItemPrivate, public QQuickItemChangeListener ++{ ++ Q_DECLARE_PUBLIC(UkuiBasePositioner) ++ ++public: ++ struct ExtraData { ++ ExtraData(); ++ ++ qreal padding; ++ qreal topPadding; ++ qreal leftPadding; ++ qreal rightPadding; ++ qreal bottomPadding; ++ bool explicitTopPadding : 1; ++ bool explicitLeftPadding : 1; ++ bool explicitRightPadding : 1; ++ bool explicitBottomPadding : 1; ++ }; ++ QLazilyAllocated<ExtraData> extra; ++ ++ UkuiBasePositionerPrivate() ++ : spacing(0), type(UkuiBasePositioner::None) ++ , transitioner(0), positioningDirty(false) ++ , doingPositioning(false), anchorConflict(false), layoutDirection(Qt::LeftToRight) ++ ++ { ++ } ++ ++ void init(UkuiBasePositioner::PositionerType at) ++ { ++ type = at; ++ } ++ ++ qreal spacing; ++ ++ UkuiBasePositioner::PositionerType type; ++ QQuickItemViewTransitioner *transitioner; ++ ++ void watchChanges(QQuickItem *other); ++ void unwatchChanges(QQuickItem* other); ++ void setPositioningDirty() { ++ Q_Q(UkuiBasePositioner); ++ if (!positioningDirty) { ++ positioningDirty = true; ++ q->polish(); ++ } ++ } ++ ++ bool positioningDirty : 1; ++ bool doingPositioning : 1; ++ bool anchorConflict : 1; ++ ++ Qt::LayoutDirection layoutDirection; ++ ++ void mirrorChange() override { ++ effectiveLayoutDirectionChange(); ++ } ++ bool isLeftToRight() const { ++ if (type == UkuiBasePositioner::Vertical) ++ return true; ++ else ++ return effectiveLayoutMirror ? layoutDirection == Qt::RightToLeft : layoutDirection == Qt::LeftToRight; ++ } ++ ++ void itemSiblingOrderChanged(QQuickItem* other) override ++ { ++ Q_UNUSED(other); ++ setPositioningDirty(); ++ } ++ ++ void itemGeometryChanged(QQuickItem *, QQuickGeometryChange change, const QRectF &) override ++ { ++ if (change.sizeChange()) ++ setPositioningDirty(); ++ } ++ ++ void itemVisibilityChanged(QQuickItem *) override ++ { ++ setPositioningDirty(); ++ } ++ ++ void itemDestroyed(QQuickItem *item) override ++ { ++ Q_Q(UkuiBasePositioner); ++ int index = q->positionedItems.find(UkuiBasePositioner::PositionedItem(item)); ++ if (index >= 0) ++ q->removePositionedItem(&q->positionedItems, index); ++ } ++ ++ static Qt::LayoutDirection getLayoutDirection(const UkuiBasePositioner *positioner) ++ { ++ return positioner->d_func()->layoutDirection; ++ } ++ ++ static Qt::LayoutDirection getEffectiveLayoutDirection(const UkuiBasePositioner *positioner) ++ { ++ if (positioner->d_func()->effectiveLayoutMirror) ++ return positioner->d_func()->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft; ++ else ++ return positioner->d_func()->layoutDirection; ++ } ++ ++ virtual void effectiveLayoutDirectionChange() ++ { ++ } ++ ++ inline qreal padding() const { return extra.isAllocated() ? extra->padding : 0.0; } ++ void setTopPadding(qreal value, bool reset = false); ++ void setLeftPadding(qreal value, bool reset = false); ++ void setRightPadding(qreal value, bool reset = false); ++ void setBottomPadding(qreal value, bool reset = false); ++}; ++ ++class UkuiFlowPrivate; ++class UkuiFlow : public UkuiBasePositioner ++{ ++ Q_OBJECT ++ Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged) ++ Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged) ++ Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged) ++ Q_PROPERTY(bool lineHorizontalCenterAlignment READ lineHorizontalCenterAlignment WRITE setLineHorizontalCenterAlignment NOTIFY lineHorizontalCenterAlignmentChanged) ++public: ++ UkuiFlow(QQuickItem *parent=nullptr); ++ ++ enum Flow { LeftToRight, TopToBottom }; ++ Q_ENUM(Flow) ++ Flow flow() const; ++ void setFlow(Flow); ++ ++ Qt::LayoutDirection layoutDirection() const; ++ void setLayoutDirection (Qt::LayoutDirection); ++ Qt::LayoutDirection effectiveLayoutDirection() const; ++ ++ bool lineHorizontalCenterAlignment() const; ++ void setLineHorizontalCenterAlignment(bool); ++ ++Q_SIGNALS: ++ void flowChanged(); ++ void layoutDirectionChanged(); ++ void effectiveLayoutDirectionChanged(); ++ void lineHorizontalCenterAlignmentChanged(); ++ ++protected: ++ UkuiFlow(UkuiFlowPrivate &dd, QQuickItem *parent); ++ void doPositioning(QSizeF *contentSize) override; ++ void reportConflictingAnchors() override; ++private: ++ Q_DISABLE_COPY(UkuiFlow) ++ Q_DECLARE_PRIVATE(UkuiFlow) ++}; ++QML_DECLARE_TYPEINFO(UkuiPositionerAttached, QML_HAS_ATTACHED_PROPERTIES) ++ ++ ++#endif //UKUI_FLOW_H +diff --git a/windowsview/ukui-window-switch b/windowsview/ukui-window-switch +index ee703c1..153c407 100755 +--- a/windowsview/ukui-window-switch ++++ b/windowsview/ukui-window-switch +@@ -13,4 +13,4 @@ else + if [ $process_count -gt 0 ]; then + /usr/bin/ukui-window-switch-wlcom + fi +-fi ++fi +\ No newline at end of file +diff --git a/windowsview/ukui-window-switch-kwineffect/CMakeLists.txt b/windowsview/ukui-window-switch-kwineffect/CMakeLists.txt +index b572c2e..73a73da 100644 +--- a/windowsview/ukui-window-switch-kwineffect/CMakeLists.txt ++++ b/windowsview/ukui-window-switch-kwineffect/CMakeLists.txt +@@ -1,4 +1,4 @@ +-cmake_minimum_required(VERSION 3.5) ++cmake_minimum_required(VERSION 3.16) + + # 调试多任务视图需要取消注释下面 + # add_definitions("-Wall -g") +@@ -6,7 +6,6 @@ set(PLUGIN_NAME "windowsview") + + set(CMAKE_INCLUDE_CURRENT_DIR ON) + set(CMAKE_AUTOMOC ON) +-set(CMAKE_AUTOUIC ON) + set(CMAKE_AUTORCC ON) + + set(CMAKE_CXX_STANDARD 14) +@@ -17,43 +16,14 @@ set(KF5_DEP_VERSION "5.54.0") + find_package(ECM 5.54.0 NO_MODULE) + set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake) + +-find_package(X11 MODULE) +-find_package(XCB MODULE COMPONENTS XCB COMPOSITE DAMAGE SHAPE XFIXES RENDER) +-message("XCB:"${X11_FOUND}, ${XCB_XCB_FOUND}, ${XCB_COMPOSITE_FOUND}, ${XCB_DAMAGE_FOUND}) +-if(X11_FOUND AND XCB_XCB_FOUND) +- set(HAVE_X11 1) +-endif() +-if(HAVE_X11 AND XCB_COMPOSITE_FOUND AND XCB_DAMAGE_FOUND) +- set(HAVE_XCB_COMPOSITE 1) +-endif() +- + find_package(OpenGL) +- + find_package(EGL MODULE) +-message("EGL:"${EGL_FOUND}) +-if (${EGL_FOUND}) +- set(HAVE_EGL 1) +-endif() +- +-message("OPENGL:"${OPENGL_FOUND},${Qt5Gui_OPENGL_IMPLEMENTATION}) +-if(OPENGL_FOUND AND (${Qt5Gui_OPENGL_IMPLEMENTATION} STREQUAL "GL")) +- set(HAVE_GLX ${HAVE_X11}) +-else() +- set(HAVE_GLX 0) +-endif() +- +-message("MACRO:"${HAVE_X11},${HAVE_XCB_COMPOSITE},${HAVE_EGL},${HAVE_GLX}) +- +-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../globalconfig.h.in ${CMAKE_CURRENT_SOURCE_DIR}/../globalconfig.h) +- +-find_package(Qt5Quick REQUIRED) +-find_package(Qt5QuickWidgets REQUIRED) + find_package(KF5Config REQUIRED) + find_package(KF5GlobalAccel REQUIRED) + find_package(KF5I18n REQUIRED) + find_package(PkgConfig REQUIRED) + find_package(Qt5LinguistTools REQUIRED) +-find_package(Qt5 REQUIRED NO_MODULE COMPONENTS X11Extras Concurrent) ++find_package(Qt5 REQUIRED NO_MODULE COMPONENTS X11Extras Concurrent Quick Qml DBus) + + pkg_check_modules(KDK REQUIRED kysdk-sysinfo) + pkg_check_modules(DATACOLLECT REQUIRED kysdk-datacollect) +@@ -61,75 +31,51 @@ pkg_check_modules(DATACOLLECT REQUIRED kysdk-datacollect) + include_directories(${KDK_INCLUDE_DIRS}) + include_directories(${DATACOLLECT_INCLUDE_DIRS}) + +-# 注意要链接到kwin,如果本地安装了kwin的依赖,记得注意区分 +-include_directories(/usr/include/) +- + add_definitions(-DKWINEFFECT=1) + + set(SRCS ../desktopbackground.cpp + ../icontheme.cpp +- ../multitaskviewmodel.cpp ++ ../windowmanagerinterface.cpp + multitaskviewmanager.cpp + dbusservice.cpp + multitaskviewmanagerpluginfactory.cpp +- ../multitaskviewmodelhandler.h ++ ../multitaskviewabstractmodelhandler.h + multitaskviewmodelbycompositehandler.cpp ++ ../desktoplistmodel.h ++ ../desktoplistmodel.cpp ++ ../appwindowlistmodel.h ++ ../appwindowlistmodel.cpp ++ ../appwindowfiltermodel.h ++ ../appwindowfiltermodel.cpp ++ ../ukui-flow.cpp ++ ../ukui-flow.h + ) + +-# translation +-find_package(QT NAMES Qt6 Qt5 COMPONENTS LinguistTools REQUIRED) +-find_package(Qt${QT_VERSION_MAJOR} COMPONENTS LinguistTools REQUIRED) +- +-set(TS_FILES) +-set(QM_FILES) +- +-file(GLOB QML_FILES "../qml/*.qml") +- +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_zh_CN.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_bo_CN.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_zh_Hant.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_ug.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_mn.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_ky.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_kk.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_fr.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_es.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_de.ts) +- +-set_source_files_properties(${TS_FILES} +- PROPERTIES OUTPUT_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/../) +- +-qt5_create_translation(QM_FILES ${TS_FILES} ${QML_FILES}) +- +-add_custom_target(lupdate_task DEPENDS ${TS_FILES}) +- +-add_custom_target(lrelease_task DEPENDS ${QM_FILES}) +- + qt5_add_resources(SRCS ../data.qrc) + add_library( + ${PLUGIN_NAME} MODULE + ${SRCS} +- ${QM_FILES} + ) + + target_link_libraries( +- ${PLUGIN_NAME} +- PUBLIC +- Qt5::Core +- Qt5::Gui +- Qt5::Widgets +- Qt5::Quick +- Qt5::QuickWidgets +- PRIVATE +- KF5::ConfigCore +- KF5::WindowSystem +- KF5::CoreAddons +- KF5::GlobalAccel +- Qt5::X11Extras +- Qt5::Concurrent +- ${QGSettings_LIBRARIES} +- ${KDK_LINK_LIBRARIES} +- ${DATACOLLECT_LINK_LIBRARIES} ++ ${PLUGIN_NAME} ++ PRIVATE ++ Qt5::Core ++ Qt5::Gui ++ Qt5::Quick ++ Qt5::QuickPrivate ++ KF5::ConfigCore ++ KF5::WindowSystem ++ KF5::CoreAddons ++ KF5::GlobalAccel ++ Qt5::X11Extras ++ Qt5::Concurrent ++ Qt5::DBus ++ Qt5::Qml ++ Qt::QmlPrivate ++ ${QGSettings_LIBRARIES} ++ ${KDK_LINK_LIBRARIES} ++ ${DATACOLLECT_LINK_LIBRARIES} + ) +- ++set(INSTALL_PATH ${QT_INSTALL_PLUGINS}/kwin/effects/plugins/) + install(TARGETS ${PLUGIN_NAME} DESTINATION ${INSTALL_PATH}) +diff --git a/windowsview/ukui-window-switch-kwineffect/multitaskviewmanager.cpp b/windowsview/ukui-window-switch-kwineffect/multitaskviewmanager.cpp +index 05810dd..ffb8d4e 100644 +--- a/windowsview/ukui-window-switch-kwineffect/multitaskviewmanager.cpp ++++ b/windowsview/ukui-window-switch-kwineffect/multitaskviewmanager.cpp +@@ -35,6 +35,9 @@ + + #include "../desktopbackground.h" + #include "../icontheme.h" ++#include "../windowmanagerinterface.h" ++#include "../appwindowfiltermodel.h" ++#include "../ukui-flow.h" + + bool MultitaskViewManager::m_isOpenGLBackend = true; + +@@ -216,7 +219,8 @@ void MultitaskViewManager::setShowingDesktop(bool showing) + void MultitaskViewManager::initModel() + { + qDebug() << "创建model数据" << __FUNCTION__; +- m_model.reset(new MultitaskViewModel()); ++ m_desktopListModel.reset(new DesktopListModel()); ++ m_appWindowListModel.reset(new AppWindowListModel()); + } + + void MultitaskViewManager::initializeProjectType() +@@ -238,12 +242,12 @@ void MultitaskViewManager::initializeProjectType() + void MultitaskViewManager::setQmlUrl() + { + if (m_projectType == MultitaskViewManager::TABLET +- || (m_projectType == MultitaskViewManager::TWOINONE && m_model->isTabletMode())) { ++ || (m_projectType == MultitaskViewManager::TWOINONE && WindowManagerInterface::getInstance()->isTabletMode())) { + m_qmlUrl = QUrl("qrc:/qml/TabletViewMain.qml"); + m_isLoadTabletModeQML = true; + } else if (m_projectType == MultitaskViewManager::MASTER +- || m_projectType == MultitaskViewManager::TWOINONE && !m_model->isTabletMode()) { +- m_qmlUrl = QUrl("qrc:/qml/multitaskview.qml"); ++ || (m_projectType == MultitaskViewManager::TWOINONE && !WindowManagerInterface::getInstance()->isTabletMode())) { ++ m_qmlUrl = QUrl("qrc:/qml/MultitaskView.qml"); + m_isLoadTabletModeQML = false; + } + } +@@ -252,6 +256,12 @@ void MultitaskViewManager::registerQmlTypes() + { + qmlRegisterType<DesktopBackground>("org.kylin.background", 3, 0, "DesktopBackground"); + qmlRegisterType<IconTheme>("IconTheme", 1, 0, "IconTheme"); ++ qmlRegisterType<AppWindowFilterModel>("AppWindowFilterModel", 1, 0, "AppWindowFilterModel"); ++ qmlRegisterType<DesktopListModel>("DesktopListModel", 1, 0, "DesktopListModel"); ++ qRegisterMetaType<QList<Window> >("QList<Window>"); ++ qmlRegisterUncreatableType<UkuiPositionerAttached>("org.ukui.positioner", 1, 0, "UkuiPositioner", "UkuiPositioner is an attached property"); ++ qmlRegisterUncreatableType<UkuiBasePositioner>("org.ukui.positioner", 1, 0, "UkuiBasePositioner", "UkuiBasePositioner is an abstract type that is only available as an attached property."); ++ qmlRegisterType<UkuiFlow>("org.ukui.positioner", 1, 0, "UkuiFlow"); + } + + void MultitaskViewManager::registerShortcut() +@@ -275,7 +285,7 @@ void MultitaskViewManager::installTranslator() + { + m_translator = new QTranslator(qApp); + m_translator->load(QLocale::system(), QLatin1String("ukui-window-switch"), +- QLatin1String("_"), QLatin1String(":/")); ++ QLatin1String("_"), TRANSLATION_DIR); + QApplication::installTranslator(m_translator); + } + +@@ -289,11 +299,13 @@ void MultitaskViewManager::initView() + qDebug() << "[DEBUG]: multitask view uses " << m_view->sceneGraphBackend(); + if (m_view->rendererInterface()->graphicsApi() < 2 || !KWin::effects->isOpenGLCompositing()) { + m_isOpenGLBackend = false; +- m_model->setIsOpenGLBackend(m_isOpenGLBackend); ++ WindowManagerInterface::getInstance()->setIsOpenGLBackend(m_isOpenGLBackend); + } + // 通过 QQmlContext::setContextProperty() 注册 C++ 的对象实例到 QML 中 + m_view->rootContext()->setContextProperty("multitaskViewManager", this); +- m_view->rootContext()->setContextProperty("multitaskViewModel", m_model.get()); ++ m_view->rootContext()->setContextProperty("multitaskViewModel", WindowManagerInterface::getInstance()); ++ m_view->rootContext()->setContextProperty("desktopListModel", m_desktopListModel.get()); ++ m_view->rootContext()->setContextProperty("appWindowListModel", m_appWindowListModel.get()); + m_view->show(); + setQmlUrl(); + qDebug() << "加载的qml为 " << m_qmlUrl; +@@ -331,18 +343,17 @@ void MultitaskViewManager::destroyView() + // MultitaskViewManager的析构函数选择直接调用 + // destroyView函数,即采用了延迟销毁的做法。 + m_view.release()->deleteLater(); +- m_model.release()->deleteLater(); ++ m_desktopListModel.release()->deleteLater(); ++ m_appWindowListModel.release()->deleteLater(); + } + + void MultitaskViewManager::connectSignals() + { + qDebug() << "创建信号" << __FUNCTION__; +- const auto* model = m_model.get(); +- const auto* rootObject = m_view->rootObject(); +- connect(model, &MultitaskViewModel::appWindowCreated, this, &MultitaskViewManager::close); +- connect(model, &MultitaskViewModel::screenCountChanged, this, &MultitaskViewManager::close); +- connect(model, &MultitaskViewModel::screenSizeChanged, this, &MultitaskViewManager::close); +- connect(model, &MultitaskViewModel::tabletModeChanged, this, &MultitaskViewManager::close); ++ connect(WindowManagerInterface::getInstance(), &WindowManagerInterface::appWindowCreated, this, &MultitaskViewManager::close); ++ connect(WindowManagerInterface::getInstance(), &WindowManagerInterface::screenCountChanged, this, &MultitaskViewManager::close); ++ connect(WindowManagerInterface::getInstance(), &WindowManagerInterface::screenSizeChanged, this, &MultitaskViewManager::close); ++ connect(WindowManagerInterface::getInstance(), &WindowManagerInterface::tabletModeChanged, this, &MultitaskViewManager::close); + } + + QString MultitaskViewManager::getProjectCodeName() +diff --git a/windowsview/ukui-window-switch-kwineffect/multitaskviewmanager.h b/windowsview/ukui-window-switch-kwineffect/multitaskviewmanager.h +index 9a8fa7d..97f967d 100644 +--- a/windowsview/ukui-window-switch-kwineffect/multitaskviewmanager.h ++++ b/windowsview/ukui-window-switch-kwineffect/multitaskviewmanager.h +@@ -25,7 +25,8 @@ + #include <kwineffects.h> + + #include "dbusservice.h" +-#include "../multitaskviewmodel.h" ++#include "../desktoplistmodel.h" ++#include "../appwindowlistmodel.h" + + class QTranslator; + +@@ -79,9 +80,10 @@ private: + void initGuiLayouDirection(); + + private: +- std::unique_ptr<MultitaskViewModel> m_model = nullptr; + std::unique_ptr<QQuickView> m_view = nullptr; + std::unique_ptr<DBusService> m_dbusService = nullptr; ++ std::unique_ptr<DesktopListModel> m_desktopListModel = nullptr; ++ std::unique_ptr<AppWindowListModel> m_appWindowListModel = nullptr; + bool isOpen = false; + bool m_isKeyboardGrab = false; + ProjectType m_projectType = MultitaskViewManager::MASTER; +diff --git a/windowsview/ukui-window-switch-kwineffect/multitaskviewmodelbycompositehandler.cpp b/windowsview/ukui-window-switch-kwineffect/multitaskviewmodelbycompositehandler.cpp +index c7a92cb..6aa75e5 100644 +--- a/windowsview/ukui-window-switch-kwineffect/multitaskviewmodelbycompositehandler.cpp ++++ b/windowsview/ukui-window-switch-kwineffect/multitaskviewmodelbycompositehandler.cpp +@@ -8,7 +8,7 @@ + #include <QtX11Extras/QX11Info> + #include <QTimer> + +-MultitaskViewModelByCompositeHandler::MultitaskViewModelByCompositeHandler(QObject *parent) : MultitaskViewModelHandler{} ++MultitaskViewModelByCompositeHandler::MultitaskViewModelByCompositeHandler(QObject *parent) : MultitaskViewAbstractModelHandler{} + { + connectSignals(); + } +@@ -77,17 +77,21 @@ int MultitaskViewModelByCompositeHandler::getNumberOfDesktops() + void MultitaskViewModelByCompositeHandler::removeDesktop(int desktopIndex) + { + KWin::desktopManager->removeDesktop(desktopIndex); ++ emit desktopRemoved(desktopIndex); + } + + void MultitaskViewModelByCompositeHandler::moveDesktop(int srcDesktopIndex, int destDesktopIndex) + { + KWin::desktopManager->moveDesktop(srcDesktopIndex, destDesktopIndex); ++ emit desktopMoved(srcDesktopIndex, destDesktopIndex); ++ setCurrentDesktop(destDesktopIndex); + } + + void MultitaskViewModelByCompositeHandler::appendDesktop() + { + auto desktopCount = KWin::effects->numberOfDesktops(); + KWin::effects->setNumberOfDesktops(desktopCount + 1); ++ emit desktopAppended(desktopCount + 1); + } + + int MultitaskViewModelByCompositeHandler::getCurrentDesktop() +@@ -157,10 +161,10 @@ QUuid MultitaskViewModelByCompositeHandler::getUuid(KWin::EffectWindow *window) + return window->parent()->property("internalId").toUuid(); + } + +-QList<QVariant> MultitaskViewModelByCompositeHandler::createWindowList(int desktopIndex, int screenIndex) ++QList<Window> MultitaskViewModelByCompositeHandler::createWindowList(int desktopIndex, int screenIndex) + { + KWin::EffectScreen* screen = KWin::effects->findScreen(screenIndex); +- QList<QVariant> windowList; ++ QList<Window> windowList; + const auto& effectWindowList = KWin::effects->stackingOrder(); + for (auto iter = effectWindowList.cbegin(); iter != effectWindowList.cend(); iter++) { + auto* effectWindow = *iter; +@@ -172,14 +176,14 @@ QList<QVariant> MultitaskViewModelByCompositeHandler::createWindowList(int deskt + continue; + } + Window window(getWindowId(effectWindow), ++ getUuid(effectWindow).toString(), + effectWindow->caption(), + effectWindow->pos().x(), + effectWindow->pos().y(), + effectWindow->frameGeometry().width(), + effectWindow->frameGeometry().height(), +- effectWindow->isMinimized(), +- getUuid(effectWindow).toString()); +- windowList.append(QVariant::fromValue(window)); ++ effectWindow->isMinimized()); ++ windowList.append(window); + } + return windowList; + } +@@ -260,7 +264,7 @@ void MultitaskViewModelByCompositeHandler::connectSignals() + this, &MultitaskViewModelByCompositeHandler::onWindowActivated); + QObject::connect(KWin::effects, &KWin::EffectsHandler::desktopPresenceChanged, + this, &MultitaskViewModelByCompositeHandler::onDesktopPresenceChanged); +- QObject::connect(KWin::effects, SIGNAL(desktopChanged(int, int)), ++ QObject::connect(KWin::effects, SIGNAL(desktopChanged(int, int, KWin::EffectWindow*)), + this, SIGNAL(currentDesktopChanged(int, int))); + QObject::connect(KWin::effects, SIGNAL(numberDesktopsChanged(uint)), + this, SIGNAL(desktopNumberChanged())); +diff --git a/windowsview/ukui-window-switch-kwineffect/multitaskviewmodelbycompositehandler.h b/windowsview/ukui-window-switch-kwineffect/multitaskviewmodelbycompositehandler.h +index 3dad9cc..10fa41b 100644 +--- a/windowsview/ukui-window-switch-kwineffect/multitaskviewmodelbycompositehandler.h ++++ b/windowsview/ukui-window-switch-kwineffect/multitaskviewmodelbycompositehandler.h +@@ -1,7 +1,7 @@ + #ifndef MULTITASKVIEWMODELBYCOMPOSITEHANDLER_H + #define MULTITASKVIEWMODELBYCOMPOSITEHANDLER_H +-#include "../multitaskviewmodelhandler.h" +-#include "../multitaskviewmodel.h" ++#include "../multitaskviewabstractmodelhandler.h" ++#include "../windowmanagerinterface.h" + #include <QObject> + #include <QIcon> + #include <QList> +@@ -11,7 +11,7 @@ + #include <QString> + #include <kwineffects.h> + +-class MultitaskViewModelByCompositeHandler : public MultitaskViewModelHandler ++class MultitaskViewModelByCompositeHandler : public MultitaskViewAbstractModelHandler + { + Q_OBJECT + +@@ -34,7 +34,7 @@ public: + bool hasModalChildWindow(QString windowId) override; + bool isExtensionMode() override; + int logicalScreenCount() override; +- QList<QVariant> createWindowList(int desktopIndex, int screenIndex) override; ++ QList<Window> createWindowList(int desktopIndex, int screenIndex) override; + QString getDesktopUuid(int desktopIndex) override; + QString getOutputUuid(int outputIndex) override; + private: +diff --git a/windowsview/ukui-window-switch-wlcom/CMakeLists.txt b/windowsview/ukui-window-switch-wlcom/CMakeLists.txt +index 3128c93..312fc90 100644 +--- a/windowsview/ukui-window-switch-wlcom/CMakeLists.txt ++++ b/windowsview/ukui-window-switch-wlcom/CMakeLists.txt +@@ -1,4 +1,4 @@ +-cmake_minimum_required(VERSION 3.5) ++cmake_minimum_required(VERSION 3.16) + + # 调试多任务视图需要取消注释下面 + add_definitions("-Wall -g") +@@ -7,7 +7,6 @@ project(ukui-window-switch-wlcom) + + set(CMAKE_INCLUDE_CURRENT_DIR ON) + set(CMAKE_AUTOMOC ON) +-set(CMAKE_AUTOUIC ON) + set(CMAKE_AUTORCC ON) + + set(CMAKE_CXX_STANDARD 14) +@@ -15,102 +14,49 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) + + set(KF5_DEP_VERSION "5.54.0") + +-find_package(ECM 5.54.0 NO_MODULE) +-set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake) +- +-find_package(X11 MODULE) +-find_package(XCB MODULE COMPONENTS XCB COMPOSITE DAMAGE SHAPE XFIXES RENDER) +-message("XCB:"${X11_FOUND}, ${XCB_XCB_FOUND}, ${XCB_COMPOSITE_FOUND}, ${XCB_DAMAGE_FOUND}) +-if(X11_FOUND AND XCB_XCB_FOUND) +- set(HAVE_X11 1) +-endif() +-if(HAVE_X11 AND XCB_COMPOSITE_FOUND AND XCB_DAMAGE_FOUND) +- set(HAVE_XCB_COMPOSITE 1) +-endif() +- +-find_package(OpenGL) +- +-find_package(EGL MODULE) +-message("EGL:"${EGL_FOUND}) +-if (${EGL_FOUND}) +- set(HAVE_EGL 1) +-endif() +- +-message("OPENGL:"${OPENGL_FOUND},${Qt5Gui_OPENGL_IMPLEMENTATION}) +-if(OPENGL_FOUND AND (${Qt5Gui_OPENGL_IMPLEMENTATION} STREQUAL "GL")) +- set(HAVE_GLX ${HAVE_X11}) +-else() +- set(HAVE_GLX 0) +-endif() +- +-message("MACRO:"${HAVE_X11},${HAVE_XCB_COMPOSITE},${HAVE_EGL},${HAVE_GLX}) +- +-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../globalconfig.h.in ${CMAKE_CURRENT_SOURCE_DIR}/../globalconfig.h) +- +-find_package(Qt5Quick REQUIRED) +-find_package(Qt5QuickWidgets REQUIRED) + find_package(KF5Config REQUIRED) + find_package(KF5GlobalAccel REQUIRED) ++find_package(KF5WindowSystem) + find_package(KF5I18n REQUIRED) + find_package(PkgConfig REQUIRED) +-find_package(Qt5LinguistTools REQUIRED) +-find_package(Qt5 REQUIRED NO_MODULE COMPONENTS X11Extras Concurrent) ++find_package(Qt5 REQUIRED NO_MODULE COMPONENTS Concurrent Quick Qml LinguistTools DBus REQUIRED) + + pkg_check_modules(KDK REQUIRED kysdk-sysinfo) + pkg_check_modules(DATACOLLECT REQUIRED kysdk-datacollect) + pkg_check_modules(KYSDKWAYLANDHELPER_PKG kysdk-waylandhelper) ++pkg_check_modules(GL REQUIRED gl) + + include_directories(${KDK_INCLUDE_DIRS}) + include_directories(${DATACOLLECT_INCLUDE_DIRS}) + include_directories(${WAYLANDHELPER_INCLUDE_DIRS}) + include_directories(${OPENGL_INCLUDE_DIR}) ++include_directories(${GL}) + + set(WLCSRCS main.cpp +- log-utils.h log-utils.cpp +- ../desktopbackground.cpp +- ../icontheme.cpp +- multitaskviewmanagerbywlcom.cpp +- dbusservice.cpp +- ../multitaskviewmodel.cpp +- ../multitaskviewmodelhandler.h +- multitaskviewmodelbywlcomhandler.cpp +- context.cpp +- toplevel.cpp +- workspace.cpp +- output.cpp +- thumbnail.cpp +- ThumbnailItem.cpp ++ log-utils.h log-utils.cpp ++ ../desktopbackground.cpp ++ ../icontheme.cpp ++ multitaskviewmanagerbywlcom.cpp ++ dbusservice.cpp ++ ../windowmanagerinterface.cpp ++ ../multitaskviewabstractmodelhandler.h ++ multitaskviewmodelbywlcomhandler.cpp ++ context.cpp ++ toplevel.cpp ++ workspace.cpp ++ output.cpp ++ thumbnail.cpp ++ ThumbnailItem.cpp ++ ../desktoplistmodel.h ++ ../desktoplistmodel.cpp ++ ../appwindowlistmodel.h ++ ../appwindowlistmodel.cpp ++ ../appwindowfiltermodel.h ++ ../appwindowfiltermodel.cpp ++ ../ukui-flow.cpp ++ ../ukui-flow.h + ) + +-# translation +-find_package(QT NAMES Qt6 Qt5 COMPONENTS LinguistTools REQUIRED) +-find_package(Qt${QT_VERSION_MAJOR} COMPONENTS LinguistTools REQUIRED) +- +-set(TS_FILES) +-set(QM_FILES) +- +-file(GLOB QML_FILES "../qml/*.qml") +- +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_zh_CN.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_bo_CN.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_zh_Hant.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_ug.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_mn.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_ky.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_kk.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_fr.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_es.ts) +-list(APPEND TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../ukui-window-switch_de.ts) +- +-set_source_files_properties(${TS_FILES} +- PROPERTIES OUTPUT_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/../) +- +-qt5_create_translation(QM_FILES ${TS_FILES} ${QML_FILES}) +- +-add_custom_target(wlupdate_task DEPENDS ${TS_FILES}) +- +-add_custom_target(wlrelease_task DEPENDS ${QM_FILES}) +- + add_subdirectory(qtsingleapplication) + include_directories(qtsingleapplication/src) + +@@ -118,35 +64,36 @@ qt5_add_resources(WLCSRCS ../data.qrc) + + add_executable(ukui-window-switch-wlcom + ${WLCSRCS} +- ${QM_FILES} + ) +- ++target_include_directories(ukui-window-switch-wlcom PRIVATE ${Qt5Quick_PRIVATE_INCLUDE_DIRS}) + target_include_directories(ukui-window-switch-wlcom PRIVATE ${KYSDKWAYLANDHELPER_PKG_INCLUDE_DIRS}) + target_link_directories(ukui-window-switch-wlcom PRIVATE ${KYSDKWAYLANDHELPER_PKG_LIBRARY_DIRS} KF5::WindowSystem) + ++target_compile_definitions(${PROJECT_NAME} PRIVATE $<$<CONFIG:Debug>:DISABLE_LOG_FILE>) ++target_compile_definitions(${PROJECT_NAME} PRIVATE $<$<CONFIG:Debug>:QT_QML_DEBUG>) ++ + target_link_libraries( +- ukui-window-switch-wlcom +- PUBLIC +- Qt5::Core +- Qt5::GuiPrivate +- Qt5::Widgets +- Qt5::Quick +- Qt5::QuickWidgets +- PRIVATE +- KF5::ConfigCore +- KF5::WindowSystem +- KF5::CoreAddons +- KF5::GlobalAccel +- Qt5::X11Extras +- Qt5::Concurrent +- qtsingleapplication +- kywc +- ${QGSettings_LIBRARIES} +- ${KYSDKWAYLANDHELPER_PKG_LIBRARIES} +- ${KDK_LINK_LIBRARIES} +- ${DATACOLLECT_LINK_LIBRARIES} +- ${OPENGL_gl_LIBRARY} +- ${EGL_LIBRARY} ++ ukui-window-switch-wlcom ++ PRIVATE ++ Qt5::Core ++ Qt5::GuiPrivate ++ Qt5::Quick ++ Qt5::QuickPrivate ++ KF5::WindowSystem ++ KF5::GlobalAccel ++ Qt5::Concurrent ++ Qt5::DBus ++ Qt5::Qml ++ Qt::QmlPrivate ++ qtsingleapplication ++ kywc ++ ${QGSettings_LIBRARIES} ++ ${KYSDKWAYLANDHELPER_PKG_LIBRARIES} ++ ${KDK_LINK_LIBRARIES} ++ ${DATACOLLECT_LINK_LIBRARIES} ++ ${OPENGL_gl_LIBRARY} ++ ${EGL_LIBRARY} ++ ${GL_LIBRARIES} + ) + +-install(TARGETS ukui-window-switch-wlcom ${INSTALL_TARGETS_DEFAULT_ARGS}) ++install(TARGETS ukui-window-switch-wlcom DESTINATION /usr/bin) +diff --git a/windowsview/ukui-window-switch-wlcom/main.cpp b/windowsview/ukui-window-switch-wlcom/main.cpp +index c962097..9950d0c 100644 +--- a/windowsview/ukui-window-switch-wlcom/main.cpp ++++ b/windowsview/ukui-window-switch-wlcom/main.cpp +@@ -28,7 +28,7 @@ + + int main(int argc, char *argv[]) + { +-#ifndef PANEL_DISABLE_LOG_FILE ++#ifndef DISABLE_LOG_FILE + LogUtils::initLogFile("ukui-window-switch-wlcom"); + qInstallMessageHandler(LogUtils::messageOutput); + #endif +@@ -39,15 +39,18 @@ int main(int argc, char *argv[]) + parser.process(a); + if (a.isRunning()) + { +- if (parser.isSet("show-workspace")) { ++ if (parser.isSet(showWorkSpaceOption)) { + a.sendMessage(QApplication::arguments().length() > 1 ? QApplication::arguments().at(1) : a.applicationFilePath()); + } + return EXIT_SUCCESS; + } + + MultitaskViewManagerByWlcom m; ++ if (parser.isSet(showWorkSpaceOption)) { ++ m.open(); ++ } + QObject::connect(&a, &QtSingleApplication::messageReceived, [&m](){ + m.open(); + }); +- return a.exec(); ++ return QtSingleApplication::exec(); + } +diff --git a/windowsview/ukui-window-switch-wlcom/multitaskviewmanagerbywlcom.cpp b/windowsview/ukui-window-switch-wlcom/multitaskviewmanagerbywlcom.cpp +index d4420f1..bbc7f80 100644 +--- a/windowsview/ukui-window-switch-wlcom/multitaskviewmanagerbywlcom.cpp ++++ b/windowsview/ukui-window-switch-wlcom/multitaskviewmanagerbywlcom.cpp +@@ -20,7 +20,6 @@ + + // kf5 + #include <KF5/KGlobalAccel/KGlobalAccel> +-#include <KF5/KWindowSystem/KWindowSystem> + #include <KF5/KWindowSystem/KWindowEffects> + + // kysdk +@@ -41,9 +40,12 @@ + #include <QPainterPath> + #include <QGSettings> + ++#include "../windowmanagerinterface.h" + #include "../desktopbackground.h" + #include "../icontheme.h" + #include "ThumbnailItem.h" ++#include "../appwindowfiltermodel.h" ++#include "../ukui-flow.h" + + bool MultitaskViewManagerByWlcom::m_isOpenGLBackend = true; + bool MultitaskViewManagerByWlcom::isOpen = false; +@@ -147,7 +149,7 @@ void MultitaskViewManagerByWlcom::openTab() + // m_isKeyboardGrab = KWin::effects->grabKeyboard(this); + // KWin::effects->setActiveFullScreenEffect(this); + int currentIndex = m_view->rootObject()->property("currentIndex").toInt(); +- int allcount = m_model->getAllWindowCount(); ++ int allcount = m_appWindowListModel->rowCount(); + if (currentIndex+1 == allcount) { + currentIndex = 0; + } else { +@@ -161,13 +163,13 @@ void MultitaskViewManagerByWlcom::openTab() + setRotationModeStatus(!m_isAutoRotateBeforeShowMultiTask); + } + initModel(); +- if (m_model->getAllWindowCount() == 0) { +- m_model.release()->deleteLater(); ++ if (m_appWindowListModel->rowCount() == 0) { ++ m_appWindowListModel.release()->deleteLater(); + return; + } + m_isShowTabBorder = false; + initView(false); +- ++ m_view->rootObject()->setProperty("currentIndex", m_appWindowListModel->rowCount() > 1 ? 1 : 0); + // if (!m_isKeyboardGrab) { + // m_isKeyboardGrab = KWin::effects->grabKeyboard(this); + // KWin::effects->setActiveFullScreenEffect(this); +@@ -188,7 +190,7 @@ void MultitaskViewManagerByWlcom::openBackTab() + // KWin::effects->setActiveFullScreenEffect(this); + int currentIndex = m_view->rootObject()->property("currentIndex").toInt(); + if (currentIndex == 0) { +- currentIndex = m_model->getAllWindowCount()-1; ++ currentIndex = m_appWindowListModel->rowCount() - 1; + } else { + currentIndex--; + } +@@ -200,13 +202,13 @@ void MultitaskViewManagerByWlcom::openBackTab() + setRotationModeStatus(!m_isAutoRotateBeforeShowMultiTask); + } + initModel(); +- if (m_model->getAllWindowCount() == 0) { +- m_model.release()->deleteLater(); ++ if (m_appWindowListModel->rowCount() == 0) { ++ m_appWindowListModel.release()->deleteLater(); + return; + } + m_isShowTabBorder = false; + initView(false); +- // m_view->rootObject()->setProperty("currentIndex", m_model->getAllWindowCount()-1); ++ m_view->rootObject()->setProperty("currentIndex", m_appWindowListModel->rowCount() - 1); + // if (!m_isKeyboardGrab) { + // m_isKeyboardGrab = KWin::effects->grabKeyboard(this); + // KWin::effects->setActiveFullScreenEffect(this); +@@ -291,7 +293,8 @@ void MultitaskViewManagerByWlcom::setShowingDesktop(bool showing) + void MultitaskViewManagerByWlcom::initModel() + { + qDebug() << "创建model数据" << __FUNCTION__; +- m_model.reset(new MultitaskViewModel()); ++ m_desktopListModel.reset(new DesktopListModel()); ++ m_appWindowListModel.reset(new AppWindowListModel()); + } + + void MultitaskViewManagerByWlcom::initializeProjectType() +@@ -313,12 +316,12 @@ void MultitaskViewManagerByWlcom::initializeProjectType() + void MultitaskViewManagerByWlcom::setQmlUrl() + { + if (m_projectType == MultitaskViewManagerByWlcom::TABLET +- || (m_projectType == MultitaskViewManagerByWlcom::TWOINONE && m_model->isTabletMode())) { ++ || (m_projectType == MultitaskViewManagerByWlcom::TWOINONE && WindowManagerInterface::getInstance()->isTabletMode())) { + m_qmlUrl = QUrl("qrc:/qml/TabletViewMain.qml"); + m_isLoadTabletModeQML = true; + } else if (m_projectType == MultitaskViewManagerByWlcom::MASTER +- || m_projectType == MultitaskViewManagerByWlcom::TWOINONE && !m_model->isTabletMode()) { +- m_qmlUrl = QUrl("qrc:/qml/multitaskview.qml"); ++ || (m_projectType == MultitaskViewManagerByWlcom::TWOINONE && !WindowManagerInterface::getInstance()->isTabletMode())) { ++ m_qmlUrl = QUrl("qrc:/qml/MultitaskView.qml"); + m_isLoadTabletModeQML = false; + } + } +@@ -328,6 +331,12 @@ void MultitaskViewManagerByWlcom::registerQmlTypes() + qmlRegisterType<ThumbnailItem>("org.kylin.thumbnail", 1, 0, "ThumbnailItem"); + qmlRegisterType<DesktopBackground>("org.kylin.background", 3, 0, "DesktopBackground"); + qmlRegisterType<IconTheme>("IconTheme", 1, 0, "IconTheme"); ++ qmlRegisterType<AppWindowFilterModel>("AppWindowFilterModel", 1, 0, "AppWindowFilterModel"); ++ qmlRegisterType<DesktopListModel>("DesktopListModel", 1, 0, "DesktopListModel"); ++ qRegisterMetaType<QList<Window> >("QList<Window>"); ++ qmlRegisterUncreatableType<UkuiPositionerAttached>("org.ukui.positioner", 1, 0, "UkuiPositioner", "UkuiPositioner is an attached property"); ++ qmlRegisterUncreatableType<UkuiBasePositioner>("org.ukui.positioner", 1, 0, "UkuiBasePositioner", "UkuiBasePositioner is an abstract type that is only available as an attached property."); ++ qmlRegisterType<UkuiFlow>("org.ukui.positioner", 1, 0, "UkuiFlow"); + } + + void MultitaskViewManagerByWlcom::registerShortcut() +@@ -369,7 +378,7 @@ void MultitaskViewManagerByWlcom::installTranslator() + { + m_translator = new QTranslator(qApp); + m_translator->load(QLocale::system(), QLatin1String("ukui-window-switch"), +- QLatin1String("_"), QLatin1String(":/")); ++ QLatin1String("_"), TRANSLATION_DIR); + QApplication::installTranslator(m_translator); + } + +@@ -384,11 +393,13 @@ void MultitaskViewManagerByWlcom::initView(bool isShowWindowsView) + qDebug() << "[DEBUG]: multitask view uses " << m_view->sceneGraphBackend(); + if (m_view->rendererInterface()->graphicsApi() < 2) { + m_isOpenGLBackend = false; +- m_model->setIsOpenGLBackend(m_isOpenGLBackend); ++ WindowManagerInterface::getInstance()->setIsOpenGLBackend(m_isOpenGLBackend); + } + // 通过 QQmlContext::setContextProperty() 注册 C++ 的对象实例到 QML 中 + m_view->rootContext()->setContextProperty("multitaskViewManager", this); +- m_view->rootContext()->setContextProperty("multitaskViewModel", m_model.get()); ++ m_view->rootContext()->setContextProperty("multitaskViewModel", WindowManagerInterface::getInstance()); ++ m_view->rootContext()->setContextProperty("desktopListModel", m_desktopListModel.get()); ++ m_view->rootContext()->setContextProperty("appWindowListModel", m_appWindowListModel.get()); + qDebug()<<"isShowWindowsView"<<isShowWindowsView; + if (isShowWindowsView) { + setQmlUrl(); +@@ -467,18 +478,17 @@ void MultitaskViewManagerByWlcom::destroyView() + // MultitaskViewManagerByWlcom的析构函数选择直接调用 + // destroyView函数,即采用了延迟销毁的做法。 + m_view.release()->deleteLater(); +- m_model.release()->deleteLater(); ++ m_desktopListModel.release()->deleteLater(); ++ m_appWindowListModel.release()->deleteLater(); + } + + void MultitaskViewManagerByWlcom::connectSignals() + { + qDebug() << "创建信号" << __FUNCTION__; +- const auto* model = m_model.get(); +- const auto* rootObject = m_view->rootObject(); +- connect(model, &MultitaskViewModel::appWindowCreated, this, &MultitaskViewManagerByWlcom::close); +- connect(model, &MultitaskViewModel::screenCountChanged, this, &MultitaskViewManagerByWlcom::close); +- connect(model, &MultitaskViewModel::screenSizeChanged, this, &MultitaskViewManagerByWlcom::close); +- connect(model, &MultitaskViewModel::tabletModeChanged, this, &MultitaskViewManagerByWlcom::close); ++ connect(WindowManagerInterface::getInstance(), &WindowManagerInterface::appWindowCreated, this, &MultitaskViewManagerByWlcom::close); ++ connect(WindowManagerInterface::getInstance(), &WindowManagerInterface::screenCountChanged, this, &MultitaskViewManagerByWlcom::close); ++ connect(WindowManagerInterface::getInstance(), &WindowManagerInterface::screenSizeChanged, this, &MultitaskViewManagerByWlcom::close); ++ connect(WindowManagerInterface::getInstance(), &WindowManagerInterface::tabletModeChanged, this, &MultitaskViewManagerByWlcom::close); + } + + QString MultitaskViewManagerByWlcom::getProjectCodeName() +diff --git a/windowsview/ukui-window-switch-wlcom/multitaskviewmanagerbywlcom.h b/windowsview/ukui-window-switch-wlcom/multitaskviewmanagerbywlcom.h +index e0260c5..cdd49f7 100644 +--- a/windowsview/ukui-window-switch-wlcom/multitaskviewmanagerbywlcom.h ++++ b/windowsview/ukui-window-switch-wlcom/multitaskviewmanagerbywlcom.h +@@ -24,7 +24,8 @@ + + + #include "dbusservice.h" +-#include "../multitaskviewmodel.h" ++#include "../desktoplistmodel.h" ++#include "../appwindowlistmodel.h" + + class QTranslator; + class MultitaskViewManagerByWlcom : public QObject +@@ -82,13 +83,14 @@ private: + void initGuiLayouDirection(); + + private: +- std::unique_ptr<MultitaskViewModel> m_model = nullptr; + std::unique_ptr<QQuickView> m_view = nullptr; + std::unique_ptr<DBusService> m_dbusService = nullptr; ++ std::unique_ptr<DesktopListModel> m_desktopListModel = nullptr; ++ std::unique_ptr<AppWindowListModel> m_appWindowListModel = nullptr; + bool m_isKeyboardGrab = false; + ProjectType m_projectType = MultitaskViewManagerByWlcom::MASTER; +- QUrl m_qmlUrl = QUrl("qrc:/qml/multitaskview.qml"); +- QUrl m_tabQmlUrl = QUrl("qrc:/qml/tabbox.qml"); ++ QUrl m_qmlUrl = QUrl("qrc:/qml/MultitaskView.qml"); ++ QUrl m_tabQmlUrl = QUrl("qrc:/qml/Tabbox.qml"); + // 记录旋转模式是否打开 + bool m_isAutoRotateBeforeShowMultiTask = false; + // 记录是否加载平板模式的qml +diff --git a/windowsview/ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.cpp b/windowsview/ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.cpp +index 95f354c..5c1b602 100644 +--- a/windowsview/ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.cpp ++++ b/windowsview/ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.cpp +@@ -28,19 +28,21 @@ + #include <QEventLoop> + #include <qpa/qplatformnativeinterface.h> + #include <iostream> ++#include <KWindowSystem> ++ + #include "multitaskviewmanagerbywlcom.h" + using namespace std; + +-MultitaskViewModelByWlcomHandler::MultitaskViewModelByWlcomHandler(QObject *parent) : MultitaskViewModelHandler{} ++MultitaskViewModelByWlcomHandler::MultitaskViewModelByWlcomHandler(QObject *parent) : MultitaskViewAbstractModelHandler{} + { + createContext(); +- context->start(); ++ m_context->start(); + connectSignals(); + } + + MultitaskViewModelByWlcomHandler::~MultitaskViewModelByWlcomHandler() + { +- delete context; ++ delete m_context; + } + + void MultitaskViewModelByWlcomHandler::createContext() +@@ -59,18 +61,18 @@ void MultitaskViewModelByWlcomHandler::createContext() + return; + } + +- context = new Context(nullptr, Context::Capability::Output | Context::Capability::Toplevel | ++ m_context = new Context(nullptr, Context::Capability::Output | Context::Capability::Toplevel | + Context::Capability::Workspace); +- connect(context, &Context::workespaceAdded, this, &MultitaskViewModelByWlcomHandler::onWorkSpaceAdded); +- connect(context, &Context::toplevelAdded, this, &MultitaskViewModelByWlcomHandler::onWindowAdded); +- connect(context, &Context::outputAdded, this, &MultitaskViewModelByWlcomHandler::onOutputAdded); ++ connect(m_context, &Context::workespaceAdded, this, &MultitaskViewModelByWlcomHandler::onWorkSpaceAdded); ++ connect(m_context, &Context::toplevelAdded, this, &MultitaskViewModelByWlcomHandler::onWindowAdded); ++ connect(m_context, &Context::outputAdded, this, &MultitaskViewModelByWlcomHandler::onOutputAdded); + } + + Toplevel *MultitaskViewModelByWlcomHandler::getToplevel(QString windowId) + { + Toplevel *toplevel = NULL; + +- const auto wnds = allWindowList; ++ const auto wnds = m_allWindowList; + for (auto const wnd: wnds) { + if ((QString)wnd->uuid() == windowId) { + toplevel = wnd; +@@ -93,11 +95,11 @@ void MultitaskViewModelByWlcomHandler::moveAppWindowToDesktop(QString windowId, + int destDesktopInex) + { + +- if (destDesktopInex -1 >= workspaceList.size()){ ++ if (destDesktopInex -1 >= m_workspaceList.size()){ + return; + } + Toplevel *toplevel = getToplevel(windowId); +- toplevel->moveToWorkspace(workspaceList[destDesktopInex-1]->uuid()); ++ toplevel->moveToWorkspace(m_workspaceList[destDesktopInex-1]->uuid()); + + } + +@@ -114,24 +116,25 @@ QIcon MultitaskViewModelByWlcomHandler::getWindowIcon(QString windowId) + + int MultitaskViewModelByWlcomHandler::getNumberOfDesktops() + { +- return workspaceList.size(); ++ return m_workspaceList.size(); + } + + void MultitaskViewModelByWlcomHandler::removeDesktop(int desktopIndex) + { +- workspaceList[desktopIndex-1]->remove(); ++ m_workspaceList[desktopIndex-1]->remove(); + } + + void MultitaskViewModelByWlcomHandler::moveDesktop(int srcDesktopIndex, int destDesktopIndex) + { +- workspaceList[srcDesktopIndex-1]->move(destDesktopIndex - 1); +- std::swap(workspaceList[srcDesktopIndex - 1], workspaceList[destDesktopIndex - 1]); ++ m_workspaceList[srcDesktopIndex-1]->move(destDesktopIndex - 1); ++ std::swap(m_workspaceList[srcDesktopIndex - 1], m_workspaceList[destDesktopIndex - 1]); ++ emit desktopMoved(srcDesktopIndex, destDesktopIndex); + } + + void MultitaskViewModelByWlcomHandler::appendDesktop() + { +- int desktopCount = workspaceList.size(); +- context->addWorkspace(desktopCount); ++ int desktopCount = m_workspaceList.size(); ++ m_context->addWorkspace(desktopCount); + QEventLoop loop; + connect(this, &MultitaskViewModelByWlcomHandler::workspaceHasCreated, &loop, &QEventLoop::quit); + loop.exec(); +@@ -139,8 +142,8 @@ void MultitaskViewModelByWlcomHandler::appendDesktop() + + int MultitaskViewModelByWlcomHandler::getCurrentDesktop() + { +- for (int i = 0; i <workspaceList.size(); i++) { +- if (workspaceList[i]->isActivated()) { ++ for (int i = 0; i < m_workspaceList.size(); i++) { ++ if (m_workspaceList[i]->isActivated()) { + return i+1; + } + } +@@ -155,7 +158,7 @@ bool MultitaskViewModelByWlcomHandler::isCurrentDesktopShowingDesktop() + + void MultitaskViewModelByWlcomHandler::setCurrentDesktop(int desktopIndex) + { +- workspaceList[desktopIndex-1]->setActivate(); ++ m_workspaceList[desktopIndex-1]->setActivate(); + } + + QRect MultitaskViewModelByWlcomHandler::getFullScreenGeometry(int desktopIndex, int screenIndex) +@@ -198,11 +201,11 @@ int MultitaskViewModelByWlcomHandler::logicalScreenCount() + } + + +-QList<QVariant> MultitaskViewModelByWlcomHandler::createWindowList(int desktopIndex, int screenIndex) ++QList<Window> MultitaskViewModelByWlcomHandler::createWindowList(int desktopIndex, int screenIndex) + { +- QList<QVariant> windowList; ++ QList<Window> windowList; + +- const auto wnds = allWindowList; ++ const auto wnds = m_allWindowList; + + for (auto const wnd: wnds) { + if (!shouldAcceptWindow(wnd)) { +@@ -210,7 +213,7 @@ QList<QVariant> MultitaskViewModelByWlcomHandler::createWindowList(int desktopIn + } + bool isOnDesktop = false; + for (int i = 0; i < wnd->workspaces().size(); i++) { +- if (wnd->workspaces()[i] == (QString)workspaceList[desktopIndex - 1]->uuid()){ ++ if (wnd->workspaces()[i] == (QString)m_workspaceList[desktopIndex - 1]->uuid()){ + isOnDesktop = true; + break; + } +@@ -227,15 +230,15 @@ QList<QVariant> MultitaskViewModelByWlcomHandler::createWindowList(int desktopIn + } + QString id =wnd->uuid(); + Window window(id.toInt(), ++ wnd->uuid(), + wnd->title(), + wnd->point().x(), + wnd->point().y(), + wnd->size().width(), + wnd->size().height(), +- wnd->isMinimized(), +- wnd->uuid()); ++ wnd->isMinimized()); + +- windowList.append(QVariant::fromValue(window)); ++ windowList.append(window); + + } + return windowList; +@@ -248,12 +251,12 @@ bool MultitaskViewModelByWlcomHandler::shouldAcceptWindow(Toplevel *toplevel) + + QString MultitaskViewModelByWlcomHandler::getDesktopUuid(int desktopIndex) + { +- return workspaceList[desktopIndex - 1]->uuid(); ++ return m_workspaceList[desktopIndex - 1]->uuid(); + } + + QString MultitaskViewModelByWlcomHandler::getOutputUuid(int outputIndex) + { +- return outputList[outputIndex]->uuid(); ++ return m_outputList[outputIndex]->uuid(); + } + + +@@ -263,7 +266,7 @@ void MultitaskViewModelByWlcomHandler::onWindowAdded(Toplevel *toplevel) + if (!shouldAcceptWindow(toplevel)) { + return; + } +- allWindowList.push_back(toplevel); ++ m_allWindowList.push_back(toplevel); + connect(toplevel, &Toplevel::stateUpdated, this, &MultitaskViewModelByWlcomHandler::onWindowUpdate); + connect(toplevel, &Toplevel::deleted, this, &MultitaskViewModelByWlcomHandler::onWindowDeleted); + } else if (toplevel->title() != "ukui-window-switch-wlcom") { +@@ -273,15 +276,15 @@ void MultitaskViewModelByWlcomHandler::onWindowAdded(Toplevel *toplevel) + + void MultitaskViewModelByWlcomHandler::onOutputAdded(Output *output) + { +- outputList.push_back(output); ++ m_outputList.push_back(output); + } + + void MultitaskViewModelByWlcomHandler::onWindowDeleted() + { + Toplevel *toplevel = qobject_cast<Toplevel *>(sender()); +- for (int i = 0; i < allWindowList.size(); i++){ +- if (allWindowList[i]->uuid() == toplevel->uuid()){ +- allWindowList.removeAt(i); ++ for (int i = 0; i < m_allWindowList.size(); i++){ ++ if (m_allWindowList[i]->uuid() == toplevel->uuid()){ ++ m_allWindowList.removeAt(i); + break; + } + } +@@ -305,6 +308,10 @@ void MultitaskViewModelByWlcomHandler::onWindowActivated(Toplevel *toplevel) + return; + } + if (toplevel->isActivated()) { ++ int index = m_allWindowList.indexOf(toplevel); ++ if (index != -1) { ++ m_allWindowList.move(index, m_allWindowList.size() - 1); ++ } + emit appWindowActivated(); + } + } +@@ -320,8 +327,8 @@ void MultitaskViewModelByWlcomHandler::onWindowUpdate(Toplevel::Masks mask) + if (mask & Toplevel::Mask::Workspace) { + QStringList workspaces = toplevel->workspaces(); + if (!workspaces.isEmpty()) { +- for (int i = 0; i <workspaceList.size(); i++) { +- if (workspaceList[i]->uuid() == workspaces.at(0)) { ++ for (int i = 0; i <m_workspaceList.size(); i++) { ++ if (m_workspaceList[i]->uuid() == workspaces.at(0)) { + onDesktopPresenceChanged(toplevel,0,i+1); + break; + } +@@ -336,9 +343,9 @@ void MultitaskViewModelByWlcomHandler::onDesktopPresenceChanged(Toplevel *toplev + if (!shouldAcceptWindow(toplevel)) { + return; + } +- for (int i = 0; i < allWindowList.size(); i++){ +- if (allWindowList[i]->uuid() == toplevel->uuid()){ +- allWindowList[i] = toplevel; ++ for (int i = 0; i < m_allWindowList.size(); i++){ ++ if (m_allWindowList[i]->uuid() == toplevel->uuid()){ ++ m_allWindowList[i] = toplevel; + break; + } + } +@@ -348,18 +355,19 @@ void MultitaskViewModelByWlcomHandler::onDesktopPresenceChanged(Toplevel *toplev + + void MultitaskViewModelByWlcomHandler::onWorkSpaceAdded(Workspace *workspace) + { +- workspaceList.push_back(workspace); ++ m_workspaceList.push_back(workspace); + connect(workspace, &Workspace::stateUpdated, this, &MultitaskViewModelByWlcomHandler::onCurrentDesktopChanged); + connect(workspace, &Workspace::deleted, this, &MultitaskViewModelByWlcomHandler::onWorkSpaceDeleted); + emit workspaceHasCreated(); ++ emit desktopAppended(m_workspaceList.size()); + } + + void MultitaskViewModelByWlcomHandler::onWorkSpaceDeleted() + { + Workspace *workspace = qobject_cast<Workspace *>(sender()); +- for (int i = 0; i < workspaceList.size(); i++) { +- if (workspace->uuid() == (QString)workspaceList[i]->uuid()){ +- workspaceList.removeAt(i); ++ for (int i = 0; i < m_workspaceList.size(); i++) { ++ if (workspace->uuid() == (QString)m_workspaceList[i]->uuid()){ ++ m_workspaceList.removeAt(i); + emit desktopRemoved(i+1); + break; + } +@@ -372,9 +380,10 @@ void MultitaskViewModelByWlcomHandler::onCurrentDesktopChanged(Workspace::Masks + + if (mask & Workspace::Mask::Position) { + if (workspace->isActivated()){ +- for (int i = 0; i < workspaceList.size(); i++) { +- if (workspace->uuid() == workspaceList[i]->uuid()){ +- workspaceList[i] = workspace; ++ for (int i = 0; i < m_workspaceList.size(); i++) { ++ if (workspace->uuid() == m_workspaceList[i]->uuid()){ ++ m_workspaceList[i] = workspace; ++ emit currentDesktopChanged(0,i+1); + break; + } + } +@@ -383,9 +392,9 @@ void MultitaskViewModelByWlcomHandler::onCurrentDesktopChanged(Workspace::Masks + + if (mask & Workspace::Mask::Activated) { + if (workspace->isActivated()){ +- for (int i = 0; i < workspaceList.size(); i++) { +- if (workspace->uuid() == workspaceList[i]->uuid()){ +- workspaceList[i] = workspace; ++ for (int i = 0; i < m_workspaceList.size(); i++) { ++ if (workspace->uuid() == m_workspaceList[i]->uuid()){ ++ m_workspaceList[i] = workspace; + emit currentDesktopChanged(0,i+1); + break; + } +diff --git a/windowsview/ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.h b/windowsview/ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.h +index 6f3417a..574effb 100644 +--- a/windowsview/ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.h ++++ b/windowsview/ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.h +@@ -18,20 +18,16 @@ + + #ifndef MULTITASKVIEWMODELBYWLCOMHANDLER_H + #define MULTITASKVIEWMODELBYWLCOMHANDLER_H +-#include "../multitaskviewmodelhandler.h" +-#include "../multitaskviewmodel.h" ++#include "../multitaskviewabstractmodelhandler.h" + #include <QObject> + #include <QIcon> + #include <QList> + #include <QMap> + #include <QRect> + #include <QVariantList> +-#include <KWindowSystem/KWindowSystem> +-#include <KWindowSystem/KWindowInfo> +-#include <KWindowSystem/NETWM> + #include "context.h" + +-class MultitaskViewModelByWlcomHandler : public MultitaskViewModelHandler ++class MultitaskViewModelByWlcomHandler : public MultitaskViewAbstractModelHandler + { + Q_OBJECT + +@@ -54,7 +50,7 @@ public: + bool hasModalChildWindow(QString windowId) override; + bool isExtensionMode() override; + int logicalScreenCount() override; +- QList<QVariant> createWindowList(int desktopIndex, int screenIndex) override; ++ QList<Window> createWindowList(int desktopIndex, int screenIndex) override; + QString getDesktopUuid(int desktopIndex) override; + QString getOutputUuid(int outputIndex) override; + +@@ -63,10 +59,10 @@ private: + void createContext(); + void connectSignals(); + Toplevel *getToplevel(QString windowId); +- Context *context = nullptr; +- QList<Toplevel *> allWindowList; +- QList<Workspace *> workspaceList; +- QList<Output *> outputList; ++ Context *m_context = nullptr; ++ QList<Toplevel *> m_allWindowList; ++ QList<Workspace *> m_workspaceList; ++ QList<Output *> m_outputList; + + signals: + void workspaceHasCreated(); +diff --git a/windowsview/ukui-window-switch-wlcom/toplevel.cpp b/windowsview/ukui-window-switch-wlcom/toplevel.cpp +index 1a15be3..6e07fd4 100644 +--- a/windowsview/ukui-window-switch-wlcom/toplevel.cpp ++++ b/windowsview/ukui-window-switch-wlcom/toplevel.cpp +@@ -103,8 +103,11 @@ void Toplevel::Private::stateHandle(kywc_toplevel *toplevel, uint32_t mask) + if (mask & KYWC_TOPLEVEL_STATE_PARENT) { + t_mask |= Toplevel::Mask::Parent; + if (toplevel->parent) { +- Toplevel *parent_toplevel = new Toplevel; +- parent_toplevel->setup(toplevel->parent); ++ Toplevel *parent_toplevel = (Toplevel *)kywc_toplevel_get_user_data(toplevel->parent); ++ if (parent_toplevel == nullptr) { ++ parent_toplevel = new Toplevel; ++ parent_toplevel->setup(toplevel->parent); ++ } + t_toplevel->pri->parent = parent_toplevel; + } else + t_toplevel->pri->parent = nullptr; +@@ -130,6 +133,7 @@ void Toplevel::Private::stateHandle(kywc_toplevel *toplevel, uint32_t mask) + void Toplevel::Private::destroyHandle(kywc_toplevel *toplevel) + { + Toplevel *t_toplevel = (Toplevel *)kywc_toplevel_get_user_data(toplevel); ++ + emit t_toplevel->deleted(); + } + +@@ -145,8 +149,11 @@ void Toplevel::Private::setup(kywc_toplevel *toplevel) + icon = QString(toplevel->icon); + app_id = QString(toplevel->app_id); + if (toplevel->parent) { +- Toplevel *parent_toplevel = new Toplevel; +- parent_toplevel->setup(toplevel->parent); ++ Toplevel *parent_toplevel = (Toplevel *)kywc_toplevel_get_user_data(toplevel->parent); ++ if (parent_toplevel == nullptr) { ++ parent_toplevel = new Toplevel; ++ parent_toplevel->setup(toplevel->parent); ++ } + parent = parent_toplevel; + } else + parent = nullptr; +diff --git a/windowsview/ukui-window-switch_ar.ts b/windowsview/ukui-window-switch_ar.ts +deleted file mode 100644 +index bf0b6c9..0000000 +--- a/windowsview/ukui-window-switch_ar.ts ++++ /dev/null +@@ -1,62 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="ar" sourcelanguage="en_US"> +-<context> +- <name>DesktopArea</name> +- <message> +- <source>Desktop</source> +- <translatorcomment>工作区</translatorcomment> +- <translation type="vanished">工作区</translation> +- </message> +- <message> +- <source>New Desktop</source> +- <translatorcomment>新建工作区</translatorcomment> +- <translation type="vanished">新建工作区</translation> +- </message> +-</context> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="qml/NewDesktopButton.qml" line="104"/> +- <source>New Desktop</source> +- <translation>سطح مكتب جديد</translation> +- </message> +-</context> +-<context> +- <name>TabletViewClearAllWindowButton</name> +- <message> +- <source>Clear</source> +- <translatorcomment>清除</translatorcomment> +- <translation type="vanished">清除</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="qml/TabletViewMain.qml" line="174"/> +- <source>No recent tasks</source> +- <translation>لا توجد مهام حديثة</translation> +- </message> +- <message> +- <location filename="qml/TabletViewMain.qml" line="357"/> +- <source>Clear</source> +- <translation>واضح</translation> +- </message> +-</context> +-<context> +- <name>TabletViewRootWindow</name> +- <message> +- <source>No recent tasks</source> +- <translatorcomment>无应用开启</translatorcomment> +- <translation type="vanished">无应用开启</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="qml/VirtualDesktopWindow.qml" line="187"/> +- <source>Desktop</source> +- <translation>سطح المكتب</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/ukui-window-switch_bo_CN.ts b/windowsview/ukui-window-switch_bo_CN.ts +deleted file mode 100644 +index 210d9a1..0000000 +--- a/windowsview/ukui-window-switch_bo_CN.ts ++++ /dev/null +@@ -1,62 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="bo_CN" sourcelanguage="en_US"> +-<context> +- <name>DesktopArea</name> +- <message> +- <source>Desktop</source> +- <translatorcomment>工作区</translatorcomment> +- <translation type="vanished">ལས་སྒྲུབ་ཁུལ།</translation> +- </message> +- <message> +- <source>New Desktop</source> +- <translatorcomment>新建工作区</translatorcomment> +- <translation type="vanished">གསར་དུ་བཙུགས་པའི་ལས་དོན་ཁུལ།</translation> +- </message> +-</context> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="qml/NewDesktopButton.qml" line="104"/> +- <source>New Desktop</source> +- <translation type="unfinished">གསར་དུ་བཙུགས་པའི་ལས་དོན་ཁུལ།</translation> +- </message> +-</context> +-<context> +- <name>TabletViewClearAllWindowButton</name> +- <message> +- <source>Clear</source> +- <translatorcomment>清除</translatorcomment> +- <translation type="vanished">གསལ་པོར་བཤད་ན།</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="qml/TabletViewMain.qml" line="174"/> +- <source>No recent tasks</source> +- <translation type="unfinished">ཉེ་ལམ་གྱི་ལས་འགན་གང་ཡང་མེད།</translation> +- </message> +- <message> +- <location filename="qml/TabletViewMain.qml" line="357"/> +- <source>Clear</source> +- <translation type="unfinished">གསལ་པོར་བཤད་ན།</translation> +- </message> +-</context> +-<context> +- <name>TabletViewRootWindow</name> +- <message> +- <source>No recent tasks</source> +- <translatorcomment>无应用开启</translatorcomment> +- <translation type="vanished">ཉེ་ལམ་གྱི་ལས་འགན་གང་ཡང་མེད།</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="qml/VirtualDesktopWindow.qml" line="187"/> +- <source>Desktop</source> +- <translation type="unfinished">ལས་སྒྲུབ་ཁུལ།</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/ukui-window-switch_de.ts b/windowsview/ukui-window-switch_de.ts +deleted file mode 100644 +index b79eefa..0000000 +--- a/windowsview/ukui-window-switch_de.ts ++++ /dev/null +@@ -1,62 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="de" sourcelanguage="en_US"> +-<context> +- <name>DesktopArea</name> +- <message> +- <source>Desktop</source> +- <translatorcomment>工作区</translatorcomment> +- <translation type="vanished">Desktop</translation> +- </message> +- <message> +- <source>New Desktop</source> +- <translatorcomment>新建工作区</translatorcomment> +- <translation type="vanished">Neuer Desktop</translation> +- </message> +-</context> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="qml/NewDesktopButton.qml" line="104"/> +- <source>New Desktop</source> +- <translation type="unfinished">Neuer Desktop</translation> +- </message> +-</context> +-<context> +- <name>TabletViewClearAllWindowButton</name> +- <message> +- <source>Clear</source> +- <translatorcomment>清除</translatorcomment> +- <translation type="vanished">Klar</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="qml/TabletViewMain.qml" line="174"/> +- <source>No recent tasks</source> +- <translation type="unfinished">Keine aktuellen Aufgaben</translation> +- </message> +- <message> +- <location filename="qml/TabletViewMain.qml" line="357"/> +- <source>Clear</source> +- <translation type="unfinished">Klar</translation> +- </message> +-</context> +-<context> +- <name>TabletViewRootWindow</name> +- <message> +- <source>No recent tasks</source> +- <translatorcomment>无应用开启</translatorcomment> +- <translation type="vanished">Keine aktuellen Aufgaben</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="qml/VirtualDesktopWindow.qml" line="187"/> +- <source>Desktop</source> +- <translation type="unfinished">Desktop</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/ukui-window-switch_es.ts b/windowsview/ukui-window-switch_es.ts +deleted file mode 100644 +index f316292..0000000 +--- a/windowsview/ukui-window-switch_es.ts ++++ /dev/null +@@ -1,62 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="es" sourcelanguage="en_US"> +-<context> +- <name>DesktopArea</name> +- <message> +- <source>Desktop</source> +- <translatorcomment>工作区</translatorcomment> +- <translation type="vanished">Escritorio</translation> +- </message> +- <message> +- <source>New Desktop</source> +- <translatorcomment>新建工作区</translatorcomment> +- <translation type="vanished">Nuevo escritorio</translation> +- </message> +-</context> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="qml/NewDesktopButton.qml" line="104"/> +- <source>New Desktop</source> +- <translation type="unfinished">Nuevo escritorio</translation> +- </message> +-</context> +-<context> +- <name>TabletViewClearAllWindowButton</name> +- <message> +- <source>Clear</source> +- <translatorcomment>清除</translatorcomment> +- <translation type="vanished">Claro</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="qml/TabletViewMain.qml" line="174"/> +- <source>No recent tasks</source> +- <translation type="unfinished">No hay tareas recientes</translation> +- </message> +- <message> +- <location filename="qml/TabletViewMain.qml" line="357"/> +- <source>Clear</source> +- <translation type="unfinished">Claro</translation> +- </message> +-</context> +-<context> +- <name>TabletViewRootWindow</name> +- <message> +- <source>No recent tasks</source> +- <translatorcomment>无应用开启</translatorcomment> +- <translation type="vanished">No hay tareas recientes</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="qml/VirtualDesktopWindow.qml" line="187"/> +- <source>Desktop</source> +- <translation type="unfinished">Escritorio</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/ukui-window-switch_fr.ts b/windowsview/ukui-window-switch_fr.ts +deleted file mode 100644 +index bb4aac9..0000000 +--- a/windowsview/ukui-window-switch_fr.ts ++++ /dev/null +@@ -1,62 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="fr" sourcelanguage="en_US"> +-<context> +- <name>DesktopArea</name> +- <message> +- <source>Desktop</source> +- <translatorcomment>工作区</translatorcomment> +- <translation type="vanished">Bureau</translation> +- </message> +- <message> +- <source>New Desktop</source> +- <translatorcomment>新建工作区</translatorcomment> +- <translation type="vanished">Nouveau bureau</translation> +- </message> +-</context> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="qml/NewDesktopButton.qml" line="104"/> +- <source>New Desktop</source> +- <translation type="unfinished">Nouveau bureau</translation> +- </message> +-</context> +-<context> +- <name>TabletViewClearAllWindowButton</name> +- <message> +- <source>Clear</source> +- <translatorcomment>清除</translatorcomment> +- <translation type="vanished">Clair</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="qml/TabletViewMain.qml" line="174"/> +- <source>No recent tasks</source> +- <translation type="unfinished">Pas de tâches récentes</translation> +- </message> +- <message> +- <location filename="qml/TabletViewMain.qml" line="357"/> +- <source>Clear</source> +- <translation type="unfinished">Clair</translation> +- </message> +-</context> +-<context> +- <name>TabletViewRootWindow</name> +- <message> +- <source>No recent tasks</source> +- <translatorcomment>无应用开启</translatorcomment> +- <translation type="vanished">Pas de tâches récentes</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="qml/VirtualDesktopWindow.qml" line="187"/> +- <source>Desktop</source> +- <translation type="unfinished">Bureau</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/ukui-window-switch_kk.ts b/windowsview/ukui-window-switch_kk.ts +deleted file mode 100644 +index b70f893..0000000 +--- a/windowsview/ukui-window-switch_kk.ts ++++ /dev/null +@@ -1,62 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="kk" sourcelanguage="en_US"> +-<context> +- <name>DesktopArea</name> +- <message> +- <source>Desktop</source> +- <translatorcomment>工作区</translatorcomment> +- <translation type="vanished">Жұмыс үстелі</translation> +- </message> +- <message> +- <source>New Desktop</source> +- <translatorcomment>新建工作区</translatorcomment> +- <translation type="vanished">Жаңа үстел</translation> +- </message> +-</context> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="qml/NewDesktopButton.qml" line="104"/> +- <source>New Desktop</source> +- <translation>جاڭا ئۈستەلئۈستى</translation> +- </message> +-</context> +-<context> +- <name>TabletViewClearAllWindowButton</name> +- <message> +- <source>Clear</source> +- <translatorcomment>清除</translatorcomment> +- <translation type="vanished">Тазалау</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="qml/TabletViewMain.qml" line="174"/> +- <source>No recent tasks</source> +- <translation>جاقىنعى مىندەتتەر جوق</translation> +- </message> +- <message> +- <location filename="qml/TabletViewMain.qml" line="357"/> +- <source>Clear</source> +- <translation>تازالاۋ</translation> +- </message> +-</context> +-<context> +- <name>TabletViewRootWindow</name> +- <message> +- <source>No recent tasks</source> +- <translatorcomment>无应用开启</translatorcomment> +- <translation type="vanished">Соңғы тапсырмалар жоқ</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="qml/VirtualDesktopWindow.qml" line="187"/> +- <source>Desktop</source> +- <translation>ئۈستەلئۈستى</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/ukui-window-switch_ky.ts b/windowsview/ukui-window-switch_ky.ts +deleted file mode 100644 +index 77a2a21..0000000 +--- a/windowsview/ukui-window-switch_ky.ts ++++ /dev/null +@@ -1,62 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="ky" sourcelanguage="en_US"> +-<context> +- <name>DesktopArea</name> +- <message> +- <source>Desktop</source> +- <translatorcomment>工作区</translatorcomment> +- <translation type="vanished">Иш столу</translation> +- </message> +- <message> +- <source>New Desktop</source> +- <translatorcomment>新建工作区</translatorcomment> +- <translation type="vanished">Жаңы иш столу</translation> +- </message> +-</context> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="qml/NewDesktopButton.qml" line="104"/> +- <source>New Desktop</source> +- <translation>جاڭى ئۈستەلئۈستى</translation> +- </message> +-</context> +-<context> +- <name>TabletViewClearAllWindowButton</name> +- <message> +- <source>Clear</source> +- <translatorcomment>清除</translatorcomment> +- <translation type="vanished">Тазалоо</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="qml/TabletViewMain.qml" line="174"/> +- <source>No recent tasks</source> +- <translation>جاقىندا مٸلدەتتەر جوق</translation> +- </message> +- <message> +- <location filename="qml/TabletViewMain.qml" line="357"/> +- <source>Clear</source> +- <translation>تازالوو</translation> +- </message> +-</context> +-<context> +- <name>TabletViewRootWindow</name> +- <message> +- <source>No recent tasks</source> +- <translatorcomment>无应用开启</translatorcomment> +- <translation type="vanished">Акыркы милдеттер жок</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="qml/VirtualDesktopWindow.qml" line="187"/> +- <source>Desktop</source> +- <translation>ئۈستەلئۈستى</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/ukui-window-switch_mn.ts b/windowsview/ukui-window-switch_mn.ts +deleted file mode 100644 +index 179ef7d..0000000 +--- a/windowsview/ukui-window-switch_mn.ts ++++ /dev/null +@@ -1,62 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="mn" sourcelanguage="en_US"> +-<context> +- <name>DesktopArea</name> +- <message> +- <source>Desktop</source> +- <translatorcomment>工作区</translatorcomment> +- <translation type="vanished">ᠠᠵᠢᠯᠯᠠᠬᠤ ᠤᠷᠤᠨ</translation> +- </message> +- <message> +- <source>New Desktop</source> +- <translatorcomment>新建工作区</translatorcomment> +- <translation type="vanished">ᠱᠢᠨᠡᠪᠡᠷ ᠪᠠᠢᠭᠤᠯᠤᠭ᠍ᠰᠠᠨ ᠠᠵᠢᠯᠯᠠᠬᠤ ᠤᠷᠤᠨ</translation> +- </message> +-</context> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="qml/NewDesktopButton.qml" line="104"/> +- <source>New Desktop</source> +- <translation type="unfinished">ᠱᠢᠨᠡᠪᠡᠷ ᠪᠠᠢᠭᠤᠯᠤᠭ᠍ᠰᠠᠨ ᠠᠵᠢᠯᠯᠠᠬᠤ ᠤᠷᠤᠨ</translation> +- </message> +-</context> +-<context> +- <name>TabletViewClearAllWindowButton</name> +- <message> +- <source>Clear</source> +- <translatorcomment>清除</translatorcomment> +- <translation type="vanished">ᠠᠷᠢᠯᠭᠠᠬᠤ</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="qml/TabletViewMain.qml" line="174"/> +- <source>No recent tasks</source> +- <translation type="unfinished">ᠨᠡᠬᠡᠬᠡᠬᠦ᠌ ᠬᠡᠷᠡᠭᠯᠡᠭᠡ ᠪᠠᠢᠬᠤ ᠦᠬᠡᠢ</translation> +- </message> +- <message> +- <location filename="qml/TabletViewMain.qml" line="357"/> +- <source>Clear</source> +- <translation type="unfinished">ᠠᠷᠢᠯᠭᠠᠬᠤ</translation> +- </message> +-</context> +-<context> +- <name>TabletViewRootWindow</name> +- <message> +- <source>No recent tasks</source> +- <translatorcomment>无应用开启</translatorcomment> +- <translation type="vanished">ᠨᠡᠬᠡᠬᠡᠬᠦ᠌ ᠬᠡᠷᠡᠭᠯᠡᠭᠡ ᠪᠠᠢᠬᠤ ᠦᠬᠡᠢ</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="qml/VirtualDesktopWindow.qml" line="187"/> +- <source>Desktop</source> +- <translation type="unfinished">ᠠᠵᠢᠯᠯᠠᠬᠤ ᠤᠷᠤᠨ</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/ukui-window-switch_ug.ts b/windowsview/ukui-window-switch_ug.ts +deleted file mode 100644 +index f9d529f..0000000 +--- a/windowsview/ukui-window-switch_ug.ts ++++ /dev/null +@@ -1,62 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="ug" sourcelanguage="en_US"> +-<context> +- <name>DesktopArea</name> +- <message> +- <source>Desktop</source> +- <translatorcomment>工作区</translatorcomment> +- <translation type="vanished">ئۈستەلئۈستى</translation> +- </message> +- <message> +- <source>New Desktop</source> +- <translatorcomment>新建工作区</translatorcomment> +- <translation type="vanished">يېڭى ئۈستەلئۈستى</translation> +- </message> +-</context> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="qml/NewDesktopButton.qml" line="104"/> +- <source>New Desktop</source> +- <translation>يېڭى ئۈستەلئۈستى</translation> +- </message> +-</context> +-<context> +- <name>TabletViewClearAllWindowButton</name> +- <message> +- <source>Clear</source> +- <translatorcomment>清除</translatorcomment> +- <translation type="vanished">تازىلاش</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="qml/TabletViewMain.qml" line="174"/> +- <source>No recent tasks</source> +- <translation>يېقىنقى ۋەزىپىلەر يوق</translation> +- </message> +- <message> +- <location filename="qml/TabletViewMain.qml" line="357"/> +- <source>Clear</source> +- <translation>تازىلاش</translation> +- </message> +-</context> +-<context> +- <name>TabletViewRootWindow</name> +- <message> +- <source>No recent tasks</source> +- <translatorcomment>无应用开启</translatorcomment> +- <translation type="vanished">يېقىنقى ۋەزىپىلەر يوق</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="qml/VirtualDesktopWindow.qml" line="187"/> +- <source>Desktop</source> +- <translation>ئۈستەل يۈزى</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/ukui-window-switch_vi.ts b/windowsview/ukui-window-switch_vi.ts +deleted file mode 100644 +index d673d4a..0000000 +--- a/windowsview/ukui-window-switch_vi.ts ++++ /dev/null +@@ -1,62 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="vi" sourcelanguage="en_US"> +-<context> +- <name>DesktopArea</name> +- <message> +- <source>Desktop</source> +- <translatorcomment>工作区</translatorcomment> +- <translation type="vanished">工作区</translation> +- </message> +- <message> +- <source>New Desktop</source> +- <translatorcomment>新建工作区</translatorcomment> +- <translation type="vanished">新建工作区</translation> +- </message> +-</context> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="qml/NewDesktopButton.qml" line="104"/> +- <source>New Desktop</source> +- <translation>Máy tính để bàn mới</translation> +- </message> +-</context> +-<context> +- <name>TabletViewClearAllWindowButton</name> +- <message> +- <source>Clear</source> +- <translatorcomment>清除</translatorcomment> +- <translation type="vanished">清除</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="qml/TabletViewMain.qml" line="174"/> +- <source>No recent tasks</source> +- <translation>Không có nhiệm vụ gần đây</translation> +- </message> +- <message> +- <location filename="qml/TabletViewMain.qml" line="357"/> +- <source>Clear</source> +- <translation>Trong</translation> +- </message> +-</context> +-<context> +- <name>TabletViewRootWindow</name> +- <message> +- <source>No recent tasks</source> +- <translatorcomment>无应用开启</translatorcomment> +- <translation type="vanished">无应用开启</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="qml/VirtualDesktopWindow.qml" line="187"/> +- <source>Desktop</source> +- <translation>Bàn làm việc</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/ukui-window-switch_zh_CN.ts b/windowsview/ukui-window-switch_zh_CN.ts +deleted file mode 100644 +index 397f1fe..0000000 +--- a/windowsview/ukui-window-switch_zh_CN.ts ++++ /dev/null +@@ -1,62 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="zh_CN" sourcelanguage="en_US"> +-<context> +- <name>DesktopArea</name> +- <message> +- <source>Desktop</source> +- <translatorcomment>工作区</translatorcomment> +- <translation type="vanished">工作区</translation> +- </message> +- <message> +- <source>New Desktop</source> +- <translatorcomment>新建工作区</translatorcomment> +- <translation type="vanished">新建工作区</translation> +- </message> +-</context> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="qml/NewDesktopButton.qml" line="104"/> +- <source>New Desktop</source> +- <translation type="unfinished">新建工作区</translation> +- </message> +-</context> +-<context> +- <name>TabletViewClearAllWindowButton</name> +- <message> +- <source>Clear</source> +- <translatorcomment>清除</translatorcomment> +- <translation type="vanished">清除</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="qml/TabletViewMain.qml" line="174"/> +- <source>No recent tasks</source> +- <translation type="unfinished">无应用开启</translation> +- </message> +- <message> +- <location filename="qml/TabletViewMain.qml" line="357"/> +- <source>Clear</source> +- <translation type="unfinished">清除</translation> +- </message> +-</context> +-<context> +- <name>TabletViewRootWindow</name> +- <message> +- <source>No recent tasks</source> +- <translatorcomment>无应用开启</translatorcomment> +- <translation type="vanished">无应用开启</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="qml/VirtualDesktopWindow.qml" line="187"/> +- <source>Desktop</source> +- <translation type="unfinished">工作区</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/ukui-window-switch_zh_Hant.ts b/windowsview/ukui-window-switch_zh_Hant.ts +deleted file mode 100644 +index 35f0bda..0000000 +--- a/windowsview/ukui-window-switch_zh_Hant.ts ++++ /dev/null +@@ -1,62 +0,0 @@ +-<?xml version="1.0" encoding="utf-8"?> +-<!DOCTYPE TS> +-<TS version="2.1" language="zh_Hant" sourcelanguage="en_US"> +-<context> +- <name>DesktopArea</name> +- <message> +- <source>Desktop</source> +- <translatorcomment>工作区</translatorcomment> +- <translation type="vanished">桌面</translation> +- </message> +- <message> +- <source>New Desktop</source> +- <translatorcomment>新建工作区</translatorcomment> +- <translation type="vanished">新桌面</translation> +- </message> +-</context> +-<context> +- <name>NewDesktopButton</name> +- <message> +- <location filename="qml/NewDesktopButton.qml" line="104"/> +- <source>New Desktop</source> +- <translation type="unfinished">新桌面</translation> +- </message> +-</context> +-<context> +- <name>TabletViewClearAllWindowButton</name> +- <message> +- <source>Clear</source> +- <translatorcomment>清除</translatorcomment> +- <translation type="vanished">清除</translation> +- </message> +-</context> +-<context> +- <name>TabletViewMain</name> +- <message> +- <location filename="qml/TabletViewMain.qml" line="174"/> +- <source>No recent tasks</source> +- <translation type="unfinished">無應用開啟</translation> +- </message> +- <message> +- <location filename="qml/TabletViewMain.qml" line="357"/> +- <source>Clear</source> +- <translation type="unfinished">清除</translation> +- </message> +-</context> +-<context> +- <name>TabletViewRootWindow</name> +- <message> +- <source>No recent tasks</source> +- <translatorcomment>无应用开启</translatorcomment> +- <translation type="vanished">無應用開啟</translation> +- </message> +-</context> +-<context> +- <name>VirtualDesktopWindow</name> +- <message> +- <location filename="qml/VirtualDesktopWindow.qml" line="187"/> +- <source>Desktop</source> +- <translation type="unfinished">桌面</translation> +- </message> +-</context> +-</TS> +diff --git a/windowsview/windowmanagerinterface.cpp b/windowsview/windowmanagerinterface.cpp +new file mode 100644 +index 0000000..43a45c7 +--- /dev/null ++++ b/windowsview/windowmanagerinterface.cpp +@@ -0,0 +1,383 @@ ++/* ++ * Copyright 2022 KylinSoft Co., Ltd. ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Library General Public License as ++ * published by the Free Software Foundation; either version 2, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details ++ * ++ * You should have received a copy of the GNU Library General Public ++ * License along with this program; if not, write to the ++ * Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ */ ++ ++#include "windowmanagerinterface.h" ++ ++#include <algorithm> ++ ++#include <QGSettings> ++#include <QSettings> ++#include <QGuiApplication> ++#include <QScreen> ++#include <QDBusConnection> ++#include <QDBusMessage> ++#include <QFile> ++#include <QJsonDocument> ++#include <QJsonObject> ++#include <mutex> ++#ifdef KWINEFFECT ++#include "ukui-window-switch-kwineffect/multitaskviewmodelbycompositehandler.h" ++#endif ++#include "ukui-window-switch-wlcom/multitaskviewmodelbywlcomhandler.h" ++ ++static constexpr int MAX_DESKTOP_COUNT = 15; ++static const QString UKUI_STYLE_SCHEMA = "org.ukui.style"; ++static const QString UKUI_STYLE_SCHEMA_STYLENAME = "styleName"; ++static const QString UKUI_STYLE_SCHEMA_FONTSIZE = "systemFontSize"; ++static const QString UKUI_STYLE_SCHEMA_FONT = "systemFont"; ++static const QString UKUI_STYLE_SCHEMA_WIDGETNAME = "widgetThemeName"; ++const QString IGNORE_WINDOW_CONFIG = "/usr/share/ukui/ukui-panel/panel-commission.ini"; ++ ++WindowManagerInterface *WindowManagerInterface::getInstance() ++{ ++ static WindowManagerInterface s_interface; ++ return &s_interface; ++} ++ ++WindowManagerInterface::WindowManagerInterface(QObject *parent) : QObject(parent) ++{ ++ //kwineffect相关接口无法在非effect插件的环境下编译通过,需要通过预编译来进行判断 ++#ifdef KWINEFFECT ++ m_modelhandler = new MultitaskViewModelByCompositeHandler(this); ++#else ++ m_modelhandler = new MultitaskViewModelByWlcomHandler(this); ++#endif ++ ++ updateInputMode(); ++ connectSignals(); ++ if (QGSettings::isSchemaInstalled(UKUI_STYLE_SCHEMA.toUtf8())) { ++ m_settings = new QGSettings(UKUI_STYLE_SCHEMA.toUtf8()); ++ } ++} ++ ++WindowManagerInterface::~WindowManagerInterface() ++{ ++ if (m_modelhandler != nullptr) { ++ delete m_modelhandler; ++ m_modelhandler = nullptr; ++ } ++} ++ ++bool WindowManagerInterface::currentDesktopHasWindow() const ++{ ++ for (int screenIndex = 0; screenIndex < logicalScreenCount(); screenIndex++) { ++ if (m_modelhandler->createWindowList(getCurrentDesktop(), screenIndex).size() > 0) { ++ return true; ++ } ++ } ++ return false; ++} ++ ++QString WindowManagerInterface::getDesktopUuid(int desktopIndex) ++{ ++ if (!validateDesktopIndex(desktopIndex)) { ++ return QString(); ++ } ++ return m_modelhandler->getDesktopUuid(desktopIndex); ++} ++ ++QString WindowManagerInterface::getOutputUuid(int outputIndex) ++{ ++ return m_modelhandler->getOutputUuid(outputIndex); ++} ++ ++ ++void WindowManagerInterface::removeAppWindow(QString windowId) ++{ ++ m_modelhandler->removeAppWindow(windowId); ++} ++ ++void WindowManagerInterface::removeAllAppWindowOnDesktop(int desktopIndex, int screenIndex) ++{ ++ QList<Window> windowList; ++ windowList = m_modelhandler->createWindowList(desktopIndex, screenIndex); ++ for (Window &window : windowList) { ++ m_modelhandler->removeAppWindow(window.uuid()); ++ } ++} ++ ++int WindowManagerInterface::getNumberOfDesktops() const ++{ ++ return m_modelhandler->getNumberOfDesktops(); ++} ++ ++void WindowManagerInterface::moveAppWindowToDesktop(QString windowId, int srcDesktopInex, int destDesktopInex) const ++{ ++ m_modelhandler->moveAppWindowToDesktop(windowId, srcDesktopInex, destDesktopInex); ++} ++ ++void WindowManagerInterface::activateAppWindow(QString windowId) ++{ ++ m_modelhandler->activateAppWindow(windowId); ++} ++ ++QIcon WindowManagerInterface::getWindowIcon(QString windowId) ++{ ++ return m_modelhandler->getWindowIcon(windowId); ++} ++ ++void WindowManagerInterface::removeDesktop(int desktopIndex) ++{ ++ if (m_modelhandler->getNumberOfDesktops() <= 1) { ++ return; ++ } ++ if (!validateDesktopIndex(desktopIndex)) { ++ return; ++ } ++ m_modelhandler->removeDesktop(desktopIndex); ++} ++ ++void WindowManagerInterface::appendDesktop() ++{ ++ if (m_modelhandler->getNumberOfDesktops() >= MAX_DESKTOP_COUNT) { ++ return; ++ } ++ m_modelhandler->appendDesktop(); ++} ++ ++void WindowManagerInterface::moveDesktop(int srcDesktopIndex, int destDesktopIndex) ++{ ++ if (srcDesktopIndex == destDesktopIndex) { ++ return; ++ } ++ m_modelhandler->moveDesktop(srcDesktopIndex, destDesktopIndex); ++} ++ ++QList<Window> WindowManagerInterface::createWindowList(int desktopIndex, int screenIndex) ++{ ++ return m_modelhandler->createWindowList(desktopIndex, screenIndex); ++} ++ ++int WindowManagerInterface::getCurrentDesktop() const ++{ ++ return m_modelhandler->getCurrentDesktop(); ++} ++ ++bool WindowManagerInterface::isCurrentDesktopShowingDesktop() const ++{ ++ return m_modelhandler->isCurrentDesktopShowingDesktop(); ++} ++ ++void WindowManagerInterface::setCurrentDesktop(int desktopIndex) ++{ ++ if (!validateDesktopIndex(desktopIndex)) { ++ return; ++ } ++ m_modelhandler->setCurrentDesktop(desktopIndex); ++} ++ ++QRect WindowManagerInterface::getFullScreenGeometry(int desktopIndex, int screenIndex) const ++{ ++ return m_modelhandler->getFullScreenGeometry(desktopIndex, screenIndex); ++} ++ ++bool WindowManagerInterface::hasModalChildWindow(QString windowId) ++{ ++ return m_modelhandler->hasModalChildWindow(windowId); ++} ++ ++ ++QString WindowManagerInterface::getUKUIStyleName() const ++{ ++ // default to ukui-default ++ QString styleName = "ukui-default"; ++ if (m_settings && m_settings->keys().contains(UKUI_STYLE_SCHEMA_STYLENAME)) { ++ styleName = m_settings->get(UKUI_STYLE_SCHEMA_STYLENAME).toString(); ++ } else { ++ qWarning() << QString("未查询到Gesetting的键值(%1)").arg(UKUI_STYLE_SCHEMA_STYLENAME); ++ } ++ return styleName; ++} ++ ++double WindowManagerInterface::getUKUIFontSize() const ++{ ++ // default to 11 ++ double fontSize = 11; ++ if (m_settings && m_settings->keys().contains(UKUI_STYLE_SCHEMA_FONTSIZE)) { ++ fontSize = m_settings->get(UKUI_STYLE_SCHEMA_FONTSIZE).toDouble(); ++ } else { ++ qWarning() << QString("未查询到Gesetting的键值(%1)").arg(UKUI_STYLE_SCHEMA_FONTSIZE); ++ } ++ return fontSize; ++} ++ ++QString WindowManagerInterface::getUKUIFont() const ++{ ++ // default to 11 ++ QString font = "Noto Sans CJK SC"; ++ if (m_settings && m_settings->keys().contains(UKUI_STYLE_SCHEMA_FONT)) { ++ font = m_settings->get(UKUI_STYLE_SCHEMA_FONT).toString(); ++ } else { ++ qWarning() << QString("未查询到Gesetting的键值(%1)").arg(UKUI_STYLE_SCHEMA_FONT); ++ } ++ return font; ++} ++ ++void WindowManagerInterface::setIsOpenGLBackend(bool isOpenGLBackend) ++{ ++ m_isOpenGLBackend = isOpenGLBackend; ++} ++ ++int WindowManagerInterface::getRadius(QString type) const ++{ ++ return m_isOpenGLBackend ? getUKUIRadius(type) : 0; ++} ++ ++int WindowManagerInterface::getUKUIRadius(QString type) const ++{ ++ // default to 8 ++ QString widgetName = "default"; ++ if (m_settings && m_settings->keys().contains(UKUI_STYLE_SCHEMA_WIDGETNAME)) { ++ widgetName = m_settings->get(UKUI_STYLE_SCHEMA_WIDGETNAME).toString(); ++ } else { ++ qWarning() << QString("未查询到Gesetting的键值(%1)").arg(UKUI_STYLE_SCHEMA_WIDGETNAME); ++ return 8; ++ } ++ ++ QFile file(QString("/usr/share/qt5-ukui-platformtheme/themeconfig/%1.json").arg(widgetName)); ++ if (!file.open(QIODevice::ReadOnly)) { ++ qWarning() << "无法打开JSON文件"; ++ return 8; ++ } ++ ++ QByteArray jsonData = file.readAll(); ++ file.close(); ++ ++ // 将JSON数据转换为QJsonDocument对象 ++ QJsonParseError error; ++ QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &error); ++ if (error.error != QJsonParseError::NoError) { ++ qWarning() << "JSON格式错误:" << error.errorString(); ++ return 8; ++ } ++ ++ // 获取属性 ++ QJsonObject rootObj = jsonDoc.object(); ++ QJsonObject radiusObj = rootObj["Radius"].toObject(); ++ QJsonObject radiusValueObj = radiusObj[type].toObject(); ++ ++ return radiusValueObj["value"].toString().toInt(); ++} ++ ++bool WindowManagerInterface::isExtensionMode() ++{ ++ return m_modelhandler->isExtensionMode(); ++} ++ ++int WindowManagerInterface::logicalScreenCount() const ++{ ++ return m_modelhandler->logicalScreenCount(); ++} ++ ++bool WindowManagerInterface::isTabletMode() const ++{ ++ // default to PC mode. ++ bool tabletMode = false; ++ QDBusMessage message = QDBusMessage::createMethodCall("com.kylin.statusmanager.interface", ++ "/", ++ "com.kylin.statusmanager.interface", ++ "get_current_tabletmode"); ++ QDBusMessage response = QDBusConnection::sessionBus().call(message); ++ if (response.type() == QDBusMessage::ReplyMessage) { ++ tabletMode = response.arguments().takeFirst().toBool(); ++ } else { ++ qDebug() << "get tablet mode failed " << response.type(); ++ } ++ return tabletMode; ++} ++ ++QString WindowManagerInterface::getCurrentLanguage() const ++{ ++ // default to "Chinese". ++ QLocale locale = QLocale::system(); ++ QString language = "Chinese"; ++ if (locale.language() == QLocale::Chinese) { ++ language = "Chinese"; ++ } else if (locale.language() == QLocale::Tibetan) { ++ language = "Tibetan"; ++ } ++ return language; ++} ++ ++void WindowManagerInterface::updateInputMode() ++{ ++ ++ QDBusMessage message = QDBusMessage::createMethodCall("com.kylin.statusmanager.interface", ++ "/", ++ "com.kylin.statusmanager.interface", ++ "get_inputmethod_mode"); ++ QDBusMessage response = QDBusConnection::sessionBus().call(message); ++ if (response.type() == QDBusMessage::ReplyMessage) { ++ m_inputMode = response.arguments().takeFirst().toBool(); ++ qDebug() << "m_inputMode =" << m_inputMode; ++ } else { ++ // invalid response, keep default. ++ } ++} ++ ++bool WindowManagerInterface::validateDesktopIndex(int desktopIndex) const ++{ ++ return desktopIndex >= 1 && desktopIndex <= m_modelhandler->getNumberOfDesktops(); ++} ++ ++bool WindowManagerInterface::validateScreenIndex(int screenIndex) const ++{ ++ return screenIndex >= 0 || screenIndex < logicalScreenCount(); ++} ++ ++void WindowManagerInterface::connectSignals() ++{ ++ QDBusConnection::sessionBus().connect("com.kylin.statusmanager.interface", ++ "/", ++ "com.kylin.statusmanager.interface", ++ "inputmethod_change_signal", ++ this, ++ SLOT(inputModeSlot(bool))); ++ QObject::connect(m_modelhandler, &MultitaskViewAbstractModelHandler::tabletModeChanged, ++ this, &WindowManagerInterface::tabletModeChanged, Qt::QueuedConnection); ++ QObject::connect(m_modelhandler, &MultitaskViewAbstractModelHandler::currentDesktopChanged, ++ this, &WindowManagerInterface::currentDesktopChanged, Qt::QueuedConnection); ++ QObject::connect(m_modelhandler, &MultitaskViewAbstractModelHandler::desktopNumberChanged, ++ this, &WindowManagerInterface::desktopNumberChanged, Qt::QueuedConnection); ++ QObject::connect(m_modelhandler, &MultitaskViewAbstractModelHandler::desktopRemoved, ++ this, &WindowManagerInterface::desktopRemoved, Qt::QueuedConnection); ++ QObject::connect(m_modelhandler, &MultitaskViewAbstractModelHandler::desktopAppended, ++ this, &WindowManagerInterface::desktopAppended, Qt::QueuedConnection); ++ QObject::connect(m_modelhandler, &MultitaskViewAbstractModelHandler::desktopMoved, ++ this, &WindowManagerInterface::desktopMoved, Qt::QueuedConnection); ++ ++ QObject::connect(m_modelhandler, &MultitaskViewAbstractModelHandler::appWindowCreated, ++ this, &WindowManagerInterface::appWindowCreated, Qt::QueuedConnection); ++ QObject::connect(m_modelhandler, &MultitaskViewAbstractModelHandler::appWindowRemoved, ++ this, &WindowManagerInterface::appWindowRemoved, Qt::QueuedConnection); ++ QObject::connect(m_modelhandler, &MultitaskViewAbstractModelHandler::appWindowDesktopChanged, ++ this, &WindowManagerInterface::appWindowDesktopChanged, Qt::QueuedConnection); ++ ++ QObject::connect(m_modelhandler, &MultitaskViewAbstractModelHandler::screenSizeChanged, ++ this, &WindowManagerInterface::screenSizeChanged, Qt::QueuedConnection); ++ QObject::connect(qGuiApp, &QGuiApplication::screenAdded, ++ this, &WindowManagerInterface::screenCountChanged, Qt::QueuedConnection); ++ QObject::connect(qGuiApp, &QGuiApplication::screenRemoved, ++ this, &WindowManagerInterface::screenCountChanged, Qt::QueuedConnection); ++} ++ ++void WindowManagerInterface::inputModeSlot(bool inputMode) ++{ ++ m_inputMode = inputMode; ++ emit inputModeChanged(m_inputMode); ++} +diff --git a/windowsview/windowmanagerinterface.h b/windowsview/windowmanagerinterface.h +new file mode 100644 +index 0000000..10eca1f +--- /dev/null ++++ b/windowsview/windowmanagerinterface.h +@@ -0,0 +1,115 @@ ++/* ++ * Copyright 2022 KylinSoft Co., Ltd. ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Library General Public License as ++ * published by the Free Software Foundation; either version 2, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details ++ * ++ * You should have received a copy of the GNU Library General Public ++ * License along with this program; if not, write to the ++ * Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ */ ++ ++#ifndef WINDOWMANAGERINTERFACE_H ++#define WINDOWMANAGERINTERFACE_H ++ ++#include <QObject> ++#include <QIcon> ++#include <QList> ++#include <QMap> ++#include <QRect> ++#include <QVariantList> ++#include <QString> ++#include "multitaskviewabstractmodelhandler.h" ++ ++class QGSettings; ++class Window; ++ ++class WindowManagerInterface : public QObject ++{ ++ Q_OBJECT ++ Q_PROPERTY(int logicalScreenCount READ logicalScreenCount NOTIFY screenCountChanged) ++ Q_PROPERTY(int highlightDesktop READ getCurrentDesktop WRITE setCurrentDesktop NOTIFY currentDesktopChanged) ++ Q_PROPERTY(bool inputMode READ isInputMode NOTIFY inputModeChanged) ++ Q_PROPERTY(bool isTabletMode READ isTabletMode NOTIFY tabletModeChanged) ++ ++public: ++ static WindowManagerInterface *getInstance(); ++ ~WindowManagerInterface(); ++ ++ Q_INVOKABLE bool isInputMode() const { return m_inputMode; } ++ Q_INVOKABLE QString getCurrentLanguage() const; ++ Q_INVOKABLE QString getUKUIStyleName() const; ++ Q_INVOKABLE double getUKUIFontSize() const; ++ Q_INVOKABLE QString getUKUIFont() const; ++ Q_INVOKABLE int getRadius(QString type) const; ++ void setIsOpenGLBackend(bool isOpenGLBackend); ++ ++ Q_INVOKABLE QRect getFullScreenGeometry(int desktopIndex, int screenIndex) const; ++ ++ // window ++ Q_INVOKABLE void removeAppWindow(QString windowId); ++ Q_INVOKABLE void moveAppWindowToDesktop(QString windowId, int srcDesktopInex, int destDesktopInex) const; ++ Q_INVOKABLE void activateAppWindow(QString windowId); ++ Q_INVOKABLE QIcon getWindowIcon(QString windowId); ++ Q_INVOKABLE bool hasModalChildWindow(QString windowId); ++ ++ // desktop ++ Q_INVOKABLE void removeDesktop(int desktopIndex); ++ Q_INVOKABLE void moveDesktop(int srcDesktopIndex, int destDesktopIndex); ++ Q_INVOKABLE void appendDesktop(); ++ Q_INVOKABLE void setCurrentDesktop(int desktopIndex); ++ Q_INVOKABLE QList<Window> createWindowList(int desktopIndex, int screenIndex); ++ Q_INVOKABLE QString getDesktopUuid(int desktopIndex); ++ Q_INVOKABLE QString getOutputUuid(int outputIndex); ++ Q_INVOKABLE void removeAllAppWindowOnDesktop(int desktopIndex, int screenIndex); ++ Q_INVOKABLE bool isCurrentDesktopShowingDesktop() const; ++ Q_INVOKABLE bool currentDesktopHasWindow() const; ++ ++ int getNumberOfDesktops() const; ++ int getCurrentDesktop() const; ++ ++ int logicalScreenCount() const; ++ bool isTabletMode() const; ++ ++signals: ++ void appWindowCreated(); ++ void appWindowRemoved(QString windowId); ++ void appWindowActivated(); ++ void appWindowDesktopChanged(QString windowId, int oldDesktopIndex,int newDesktopIndex); ++ void desktopRemoved(int desktopIndex); ++ void desktopAppended(int desktopIndex); ++ void desktopMoved(int oldDesktopIndex, int newDesktopIndex); ++ void desktopNumberChanged(); ++ void currentDesktopChanged(int oldCurrentDesktopIndex, int newCurrentDesktopIndex); ++ void screenCountChanged(); ++ void screenSizeChanged(); ++ void tabletModeChanged(bool); ++ void inputModeChanged(bool); ++ ++private slots: ++ void inputModeSlot(bool); ++ ++private: ++ explicit WindowManagerInterface(QObject *parent = nullptr); ++ bool isExtensionMode(); ++ void updateInputMode(); ++ bool validateDesktopIndex(int desktopIndex) const; ++ bool validateScreenIndex(int screenIndex) const; ++ void connectSignals(); ++ int getUKUIRadius(QString type) const; ++ ++private: ++ bool m_inputMode; ++ QGSettings* m_settings = nullptr; ++ bool m_isOpenGLBackend = true; ++ MultitaskViewAbstractModelHandler *m_modelhandler = nullptr; ++}; ++ ++#endif // WINDOWMANAGERINTERFACE_H diff -Nru ukui-window-switch-4.10.1.10/debian/patches/0013-fix-ui.patch ukui-window-switch-4.10.1.10/debian/patches/0013-fix-ui.patch --- ukui-window-switch-4.10.1.10/debian/patches/0013-fix-ui.patch 1970-01-01 08:00:00.000000000 +0800 +++ ukui-window-switch-4.10.1.10/debian/patches/0013-fix-ui.patch 2025-03-07 14:07:48.000000000 +0800 @@ -0,0 +1,67 @@ +From: zhangyuanyuan1 <zhangyuanyuan1@kylinos.cn> +Date: Fri, 14 Mar 2025 14:02:51 +0800 +Subject: =?utf-8?b?Zml4KHVpKTog6YCC6YWN5Li76aKY5ZyG6KeS?= + +--- + windowsview/qml/AppPreviewWindow.qml | 2 +- + windowsview/qml/ArrowButton.qml | 2 +- + windowsview/qml/Tabbox.qml | 6 +++--- + windowsview/qml/VirtualDesktopWindow.qml | 2 +- + 4 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/windowsview/qml/AppPreviewWindow.qml b/windowsview/qml/AppPreviewWindow.qml +index db41c16..72c3cc5 100644 +--- a/windowsview/qml/AppPreviewWindow.qml ++++ b/windowsview/qml/AppPreviewWindow.qml +@@ -152,7 +152,7 @@ Rectangle { + id : previewWindowCloseButton + width : iconAndCloseButtonHeight + height : width +- radius : width / 2 ++ radius : appRadius !== 0 ? width / 2 : 0 + windowType : "app" + onExited: { + previewWindowCloseButton.state = "default" +diff --git a/windowsview/qml/ArrowButton.qml b/windowsview/qml/ArrowButton.qml +index 12183c2..d1d9e1f 100644 +--- a/windowsview/qml/ArrowButton.qml ++++ b/windowsview/qml/ArrowButton.qml +@@ -24,7 +24,7 @@ Rectangle{ + id : arrowButton + width : Math.floor(56 * scaleFactor) + height : width +- radius : Math.floor(8 * scaleFactor) ++ radius : rootWindow.appRadius + color : Qt.rgba(255,255,255,0.4) + property var direction : "right" + Image { +diff --git a/windowsview/qml/Tabbox.qml b/windowsview/qml/Tabbox.qml +index 9883f0f..b0a3cc1 100755 +--- a/windowsview/qml/Tabbox.qml ++++ b/windowsview/qml/Tabbox.qml +@@ -86,9 +86,9 @@ Rectangle { + property int spaceWidth : 2 * tabbox.scaleFactor + property int outerBorderWidth : 4 * tabbox.scaleFactor + property int innerBorderWidth : 2 * tabbox.scaleFactor +- property int appRadius : 8 * tabbox.scaleFactor +- property int thumbnailOuterRadius : tabbox.isOpenGL ? appRadius + outerBorderWidth + innerBorderWidth + 2 * spaceWidth : 0 +- property int thumbnailInterRadius : tabbox.isOpenGL ? appRadius + innerBorderWidth + spaceWidth : 0 ++ property int appRadius : Math.floor(multitaskViewModel.getRadius("Max_Radius") * scaleFactor) ++ property int thumbnailOuterRadius : tabbox.isOpenGL && appRadius !== 0 ? appRadius + outerBorderWidth + innerBorderWidth + 2 * spaceWidth : 0 ++ property int thumbnailInterRadius : tabbox.isOpenGL && appRadius !== 0 ? appRadius + innerBorderWidth + spaceWidth : 0 + cellWidth : 2 * (innerBorderWidth + outerBorderWidth) + 4 * spaceWidth + thumbnailWidth + cellHeight : 2 * (innerBorderWidth + outerBorderWidth) + 5 * spaceWidth + captionRowHeight + thumbnailHeight + keyNavigationWraps : true +diff --git a/windowsview/qml/VirtualDesktopWindow.qml b/windowsview/qml/VirtualDesktopWindow.qml +index 3108dbd..7f8afd5 100644 +--- a/windowsview/qml/VirtualDesktopWindow.qml ++++ b/windowsview/qml/VirtualDesktopWindow.qml +@@ -209,7 +209,7 @@ Item { + id : closeButton + width : iconAndCloseButtonHeight + height : iconAndCloseButtonHeight +- radius : width / 2 ++ radius : appRadius !== 0 ? width / 2 : 0 + windowType : "desktop" + onClicked : { + defaultTextBinding.when = false diff -Nru ukui-window-switch-4.10.1.10/debian/patches/series ukui-window-switch-4.10.1.10/debian/patches/series --- ukui-window-switch-4.10.1.10/debian/patches/series 2025-01-03 17:52:20.000000000 +0800 +++ ukui-window-switch-4.10.1.10/debian/patches/series 2025-03-07 14:07:48.000000000 +0800 @@ -4,3 +4,10 @@ 0004-update-changelog-4.10.1.10-ok1.3.patch 0005-update-changelog-4.10.1.10-ok1.4.patch 0006-update-changelog-4.10.1.10-ok1.5.patch +0007-Added-translation-using-Weblate-Arabic.patch +0008-Added-translation-using-Weblate-Vietnamese.patch +0009-Translated-using-Weblate-Vietnamese.patch +0010-perf-CMakeLists.txt.patch +0011-Revert-perf-CMakeLists.txt.patch +0012-update-changelog-4.10.1.10-ok2.0.patch +0013-fix-ui.patch