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