#!/bin/bash

# dde-launchpad 全屏模式主屏修复脚本
# 修复启动器全屏模式在多屏环境下始终显示在主屏

QML_FILE="/usr/share/dde-shell/org.deepin.ds.dock.launcherapplet/launcheritem.qml"
BACKUP_FILE="/home/tts/launcheritem.qml.fixed"

echo "正在安装 dde-launchpad 全屏主屏修复..."

# 创建修复后的 QML 文件
cat > "$BACKUP_FILE" << 'EOF'
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15

import org.deepin.dtk 1.0
import org.deepin.dtk.style 1.0 as DStyle

import org.deepin.ds 1.0
import org.deepin.dtk 1.0 as D
import org.deepin.ds.dock 1.0

import org.deepin.launchpad 1.0
import org.deepin.launchpad.models 1.0
import org.deepin.launchpad.windowed 1.0

AppletItem {
    id: launcher
    property bool useColumnLayout: Panel.position % 2
    property int dockOrder: 12
    // 1:4 the distance between app : dock height; get width/height≈0.8
    implicitWidth: useColumnLayout ? Panel.rootObject.dockSize : Panel.rootObject.dockItemMaxSize * 0.8
    implicitHeight: useColumnLayout ? Panel.rootObject.dockItemMaxSize * 0.8 : Panel.rootObject.dockSize

    Connections {
        target: Panel.rootObject
        function onDockCenterPartPosChanged()
        {
            updateLaunchpadPos()
        }
        function onViewDeactivated() {
            if (LauncherController.currentFrame === "FullscreenFrame" && LauncherController.visible) {
                LauncherController.hideWithTimer()
            }
        }
    }

    property point itemPos: Qt.point(0, 0)
    function updateItemPos()
    {
        var lX = icon.mapToItem(null, 0, 0).x
        var lY = icon.mapToItem(null, 0, 0).y
        launcher.itemPos = Qt.point(lX, lY)
    }
    function updateLaunchpadPos()
    {
        updateItemPos()
        var launchpad = DS.applet("org.deepin.ds.launchpad")
        if (!launchpad || !launchpad.rootObject)
            return

        launchpad.rootObject.windowedPos = launcher.itemPos
    }
    Component.onCompleted: {
        updateLaunchpadPos()
        assignFullscreenFrameScreen()
    }

    function decrementPageIndex(pages) {
        if (pages.currentIndex === 0 && pages.count > 1) {
            // pages.setCurrentIndex(pages.count - 1)
        } else {
            pages.decrementCurrentIndex()
        }

        closeContextMenu()
    }

    function incrementPageIndex(pages) {
        if (pages.currentIndex === pages.count - 1 && pages.count > 1) {
            // pages.setCurrentIndex(0)
        } else {
            pages.incrementCurrentIndex()
        }

        closeContextMenu()
    }

    property var activeMenu: null
    property Component appContextMenuCom: AppItemMenu { }
    function showContextMenu(obj, model, additionalProps = {}) {
        if (!obj || !obj.Window.window) {
            console.log("obj or obj.Window.window is null")
            return
        }
        closeContextMenu()

        const menu = appContextMenuCom.createObject(obj.Window.window.contentItem, Object.assign({
            display: model.display,
            desktopId: model.desktopId,
            iconName: model.iconName,
            isFavoriteItem: false,
            hideFavoriteMenu: true,
            hideDisplayScalingMenu: Math.abs(DesktopIntegration.scaleFactor - 1.0) < 0.0001,
            hideMoveToTopMenu: true
        }, additionalProps));
        menu.closed.connect(menu.destroy)
        menu.popup();

        activeMenu = menu
    }

    function closeContextMenu() {
        if (activeMenu) {
            activeMenu.close()
            activeMenu = null
        }
    }

    function getCategoryName(section) {
        switch (Number(section)) {
        case AppItem.Internet:
            return qsTr("Internet");
        case AppItem.Chat:
            return qsTr("Chat");
        case AppItem.Music:
            return qsTr("Music");
        case AppItem.Video:
            return qsTr("Video");
        case AppItem.Graphics:
            return qsTr("Graphics");
        case AppItem.Game:
            return qsTr("Games");
        case AppItem.Office:
            return qsTr("Office");
        case AppItem.Reading:
            return qsTr("Reading");
        case AppItem.Development:
            return qsTr("Development");
        case AppItem.System:
            return qsTr("System");
        default:
            return qsTr("Others");
        }
    }

    function launchApp(desktopId) {
        LauncherController.visible = false;
        DesktopIntegration.launchByDesktopId(desktopId);
    }

    function assignFullscreenFrameScreen() {
        // 查找主屏幕（geometry 起点为 0,0 的屏幕）
        const screens = Qt.application.screens
        console.log("[Launchpad] assignFullscreenFrameScreen called, screens count:", screens ? screens.length : 0)
        if (screens && screens.length > 0) {
            let primaryScreen = null
            let primaryScreenName = ""
            
            // 打印所有屏幕信息
            for (let i = 0; i < screens.length; i++) {
                const screen = screens[i]
                console.log("[Launchpad] Screen", i, "name:", screen.name, "geometry:", JSON.stringify(screen.geometry))
            }
            
            // 方法1：通过 geometry (0,0) 查找主屏幕
            for (let i = 0; i < screens.length; i++) {
                const screen = screens[i]
                if (screen.geometry && screen.geometry.x === 0 && screen.geometry.y === 0) {
                    primaryScreen = screen
                    primaryScreenName = screen.name
                    console.log("[Launchpad] Found primary screen by geometry(0,0):", screen.name)
                    break
                }
            }
            
            // 方法2：如果没找到，尝试通过 DP 开头的名称（通常是主屏）
            if (!primaryScreen) {
                for (let i = 0; i < screens.length; i++) {
                    const screen = screens[i]
                    if (screen.name && screen.name.indexOf("DP-") === 0) {
                        primaryScreen = screen
                        primaryScreenName = screen.name
                        console.log("[Launchpad] Found primary screen by DP name:", screen.name)
                        break
                    }
                }
            }
            
            // 设置屏幕 - 尝试多种方式
            if (primaryScreen) {
                console.log("[Launchpad] Setting screen to:", primaryScreenName)
                // 方法1：设置 LauncherController.currentScreen 属性
                LauncherController.currentScreen = primaryScreenName
                // 方法2：设置窗口的 screen 属性
                launcher.fullscreenFrame.screen = primaryScreen
                console.log("[Launchpad] LauncherController.currentScreen:", LauncherController.currentScreen)
                console.log("[Launchpad] fullscreenFrame.screen:", launcher.fullscreenFrame.screen ? launcher.fullscreenFrame.screen.name : "null")
            }
        }
    }

    // A singleshot timer
    Timer {
        id: reassignFullscreenFrameScreenTimer
        interval: 100
        repeat: false
        onTriggered: {
            assignFullscreenFrameScreen()
        }
    }

    PanelToolTip {
        id: toolTip
        text: qsTr("launchpad")
        toolTipX: DockPanelPositioner.x
        toolTipY: DockPanelPositioner.y
    }

    property var fullscreenFrame: ApplicationWindow {
        objectName: "FullscreenFrameApplicationWindow"
        title: "org.deepin.ds.launchpad.fullscreen"
        visible: LauncherController.visible && (LauncherController.currentFrame !== "WindowedFrame")
        // Set transparent on kwin will cause abnormal rounded corners in FolderPopup, Bug: 10219
        color: DesktopIntegration.isTreeLand() ? "transparent" : palette.window
        transientParent: null
        
        // 强制设置窗口在主屏幕上
        screen: {
            const screens = Qt.application.screens
            if (screens && screens.length > 0) {
                for (let i = 0; i < screens.length; i++) {
                    const s = screens[i]
                    if (s.geometry && s.geometry.x === 0 && s.geometry.y === 0) {
                        return s
                    }
                }
            }
            return Qt.application.screens[0]
        }

        Connections {
            target: DS.applet("org.deepin.ds.dock")
            function onScreenNameChanged() {
                LauncherController.visible = false
                reassignFullscreenFrameScreenTimer.start()
            }
        }

        DLayerShellWindow.anchors: DLayerShellWindow.AnchorBottom | DLayerShellWindow.AnchorTop | DLayerShellWindow.AnchorLeft | DLayerShellWindow.AnchorRight
        DLayerShellWindow.layer: DLayerShellWindow.LayerTop
        DLayerShellWindow.keyboardInteractivity: DLayerShellWindow.KeyboardInteractivityOnDemand
        DLayerShellWindow.exclusionZone: -1
        DLayerShellWindow.scope: "dde-shell/launchpad"

        // visibility: Window.FullScreen
        flags: {
            if (DebugHelper.useRegularWindow) return Qt.Window
            return (Qt.FramelessWindowHint | Qt.Tool)
        }

        DWindow.enabled: !DebugHelper.useRegularWindow
        DWindow.windowRadius: 0
        DWindow.enableSystemResize: false
        DWindow.enableSystemMove: false
        // Fullscreen mode: always assume dark theme
        DWindow.themeType: ApplicationHelper.DarkType
        DWindow.windowStartUpEffect: PlatformHandle.EffectOut

        onVisibleChanged: {
            if (visible) {
                // 强制重新设置屏幕，确保在主屏显示
                assignFullscreenFrameScreen()
                requestActivate()
                LauncherController.closeAllPopups()
            }
        }

        onActiveChanged: {
            if (LauncherController.currentFrame !== "FullscreenFrame") {
                return
            }
            if (active) {
                LauncherController.cancelHide()
                return;
            }
            if (!active && !DebugHelper.avoidHideWindow) {
                LauncherController.hideWithTimer()
            }
        }

        Loader {
            anchors.fill: parent
            focus: true
            sourceComponent: FullscreenFrame {}

            Label {
                visible: DebugHelper.qtDebugEnabled
                z: 999

                anchors.right: parent.right
                anchors.bottom: parent.bottom
                text: "/ / Under Construction / /"

                background: Rectangle {
                    color: Qt.rgba(1, 1, 0, 0.5)
                }

                MouseArea {
                    anchors.fill: parent
                    onClicked: { debugDialog.open() }
                }
            }
        }
    }

    PanelPopup {
        id: windowedModeLauncher

        property bool visibility: LauncherController.visible && (LauncherController.currentFrame === "WindowedFrame")

        width: 516
        height: 430
        popupX: DockPanelPositioner.x
        popupY: DockPanelPositioner.y
        DockPanelPositioner.bounding: Qt.rect(launcher.itemPos.x + width / 2 * ((Panel.position + 1) % 2),
                                              launcher.itemPos.y + height / 2 * (Panel.position % 2),
                                              width, height)

        WindowedFrame {
            anchors.fill: parent
        }

        onVisibilityChanged: function() {
            if (visibility) {
                if (!windowedModeLauncher.visible) {
                    windowedModeLauncher.open()
                }
            } else {
                windowedModeLauncher.close()
            }
        }
        onPopupVisibleChanged: function() {
            if (LauncherController.currentFrame !== "WindowedFrame") return
            if (popupVisible !== visibility) {
                LauncherController.visible = popupVisible
            }
        }
    }

    DialogWindow {
        id: confirmUninstallDlg

        property string appId: ""
        property string appName: ""

        DLayerShellWindow.anchors: DLayerShellWindow.AnchorNone

        minimumWidth: layout.implicitWidth + 2 * DStyle.Style.dialogWindow.contentHMargin
        minimumHeight: layout.implicitHeight + DStyle.Style.dialogWindow.titleBarHeight
        maximumWidth: minimumWidth
        maximumHeight: minimumHeight

        onVisibleChanged: {
            if (!visible) {
                LauncherController.setAvoidHide(true)
                if (LauncherController.currentFrame === "FullscreenFrame") {
                    fullscreenFrame.requestActivate() 
                } 
            }
        }

        ColumnLayout {
            id: layout
            spacing: 0
            Label {
                font: DTK.fontManager.t5
                text: qsTr("Are you sure you want to uninstall \"%1\"?").arg(confirmUninstallDlg.appName)
                wrapMode: Text.Wrap
                horizontalAlignment: Text.AlignHCenter
                Layout.preferredWidth: 400
                Layout.alignment: Qt.AlignCenter
                Layout.margins: 10
            }
            RowLayout {
                spacing: 10
                Layout.fillWidth: true
                Layout.topMargin: 20
                Layout.bottomMargin: 10
                
                Button {
                    id: cancelButton
                    Layout.fillWidth: true
                    text: qsTr("Cancel")
                    onClicked: {
                        confirmUninstallDlg.close()
                    }
                }               
                WarningButton {
                    id: confirmButton
                    Layout.fillWidth: true
                    text: qsTr("Confirm")
                    onClicked: {
                        DesktopIntegration.uninstallApp(confirmUninstallDlg.appId)
                        confirmUninstallDlg.close()
                    }
                }
            }
        }
    }

    D.DciIcon {
        id: icon
        anchors.centerIn: parent
        name: Applet.iconName
        scale: Panel.rootObject.dockItemMaxSize * 9 / 14 / Dock.MAX_DOCK_TASKMANAGER_ICON_SIZE
        // 9:14 (iconSize/dockHeight)
        sourceSize: Qt.size(Dock.MAX_DOCK_TASKMANAGER_ICON_SIZE, Dock.MAX_DOCK_TASKMANAGER_ICON_SIZE)
        onXChanged: updateLaunchpadPos()
        onYChanged: updateLaunchpadPos()
    }
    Timer {
        id: toolTipShowTimer
        interval: 50
        onTriggered: {
            var point = Applet.rootObject.mapToItem(null, Applet.rootObject.width / 2, Applet.rootObject.height / 2)
            toolTip.DockPanelPositioner.bounding = Qt.rect(point.x, point.y, toolTip.width, toolTip.height)
            toolTip.open()
        }
    }

    // FIXME: The TapHandler receives the event after visibleChange, which causes the state to be inverted after synchronization,
    // causing the launchpad to be displayed again. However, the MouseArea receives the event before visibleChange.
    MouseArea {
        id: mouseHandler
        anchors.fill: parent
        onClicked: function (mouse) {
            if (mouse.button === Qt.LeftButton) {
                // 在切换可见性之前设置屏幕
                assignFullscreenFrameScreen()
                LauncherController.visible = !LauncherController.visible
                toolTip.close()
            }
        }
    }
    HoverHandler {
        onHoveredChanged: {
            if (hovered) {
                toolTipShowTimer.start()
            } else {
                if (toolTipShowTimer.running) {
                    toolTipShowTimer.stop()
                }

                toolTip.close()
            }
        }
    }
}


'
EOF

# 安装文件
if [ -f "$BACKUP_FILE" ]; then
    pkexec cp "$BACKUP_FILE" "$QML_FILE"
    rm -rf ~/.cache/dde-shell/qmlcache/*
    
    # 重启 dde-shell
    pkill -f "dde-shell"
    sleep 2
    nohup dde-shell -p org.deepin.ds.desktop > /dev/null 2>&1 &
    
    echo "修复完成！请按 Super 键测试启动器全屏模式。"
else
    echo "修复文件不存在，无法安装。"
fi
