From 218212824c3d8f8d1077b3c1da78256991fc320c Mon Sep 17 00:00:00 2001 From: Robert Lv Date: Wed, 17 Jul 2024 11:42:59 +0800 Subject: [PATCH] fix: Can't input Chinese when opening the launcher Create an InputEventItem object to forward the input events of the input method. Issue: https://github.com/linuxdeepin/developer-center/issues/8469 --- CMakeLists.txt | 1 + inputeventitem.cpp | 19 + inputeventitem.h | 25 + qml/FullscreenFrame.qml | 918 +++++++++++++++++---------------- qml/windowed/WindowedFrame.qml | 8 +- 5 files changed, 516 insertions(+), 455 deletions(-) create mode 100644 inputeventitem.cpp create mode 100644 inputeventitem.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d0439b9..a0ccd18a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,7 @@ set(SOURCE_FILES desktopintegration.cpp desktopintegration.h launchercontroller.cpp launchercontroller.h debughelper.cpp debughelper.h + inputeventitem.h inputeventitem.cpp ) set(QML_FILES diff --git a/inputeventitem.cpp b/inputeventitem.cpp new file mode 100644 index 00000000..0cfca76d --- /dev/null +++ b/inputeventitem.cpp @@ -0,0 +1,19 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later +#include "inputeventitem.h" + +InputEventItem::InputEventItem() +{ + qApp->installEventFilter(this); +} + +bool InputEventItem::eventFilter(QObject *obj, QEvent *event) { + if (event->type() == QEvent::InputMethod && (this->children().contains(obj) || obj == this)) { + QInputMethodEvent *inputMethodEvent = static_cast(event); + qDebug() << "InputEventItem::eventFilter: " << inputMethodEvent->commitString(); + if (!inputMethodEvent->commitString().isEmpty()) + Q_EMIT inputReceived(inputMethodEvent->commitString()); + } + return QObject::eventFilter(obj, event); +} diff --git a/inputeventitem.h b/inputeventitem.h new file mode 100644 index 00000000..5bf41e0d --- /dev/null +++ b/inputeventitem.h @@ -0,0 +1,25 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later +#ifndef INPUTEVENTITEM_H +#define INPUTEVENTITEM_H + +#include +#include +#include + +class InputEventItem : public QQuickItem +{ + Q_OBJECT + QML_ELEMENT +public: + InputEventItem(); + +protected: + bool eventFilter(QObject *obj, QEvent *event) override; + +signals: + void inputReceived(const QString &input); +}; + +#endif // INPUTEVENTITEM_H diff --git a/qml/FullscreenFrame.qml b/qml/FullscreenFrame.qml index 8bf5b08f..78d237f4 100644 --- a/qml/FullscreenFrame.qml +++ b/qml/FullscreenFrame.qml @@ -14,573 +14,583 @@ import org.deepin.dtk.style 1.0 as DS import org.deepin.launchpad 1.0 import org.deepin.launchpad.models 1.0 -Control { - id: baseLayer - visible: true +InputEventItem { anchors.fill: parent - focus: true - objectName: "FullscreenFrame-BaseLayer" - - readonly property bool isHorizontalDock: DesktopIntegration.dockPosition === Qt.UpArrow || DesktopIntegration.dockPosition === Qt.DownArrow - readonly property int dockSpacing: (isHorizontalDock ? DesktopIntegration.dockGeometry.height : DesktopIntegration.dockGeometry.width) / Screen.devicePixelRatio - - leftPadding: (DesktopIntegration.dockPosition === Qt.LeftArrow ? dockSpacing : 0) - rightPadding: (DesktopIntegration.dockPosition === Qt.RightArrow ? dockSpacing : 0) - topPadding: (DesktopIntegration.dockPosition === Qt.UpArrow ? dockSpacing : 0) + 20 - bottomPadding: (DesktopIntegration.dockPosition === Qt.DownArrow ? dockSpacing : 0) + 20 - - property Palette textColor: appTextColor - palette.windowText: ColorSelector.textColor - - // ----------- Drag and Drop related functions START ----------- - Label { - property string currentlyDraggedId - - signal dragEnded() - - id: dndItem - visible: DebugHelper.qtDebugEnabled - text: "DnD DEBUG" - - Drag.onActiveChanged: { - if (Drag.active) { - text = "Dragging " + currentlyDraggedId - } else { - currentlyDraggedId = "" - dragEnded() + objectName: "FullscreenFrame-InputEventItem" + Control { + id: baseLayer + visible: true + anchors.fill: parent + focus: true + objectName: "FullscreenFrame-BaseLayer" + + readonly property bool isHorizontalDock: DesktopIntegration.dockPosition === Qt.UpArrow || DesktopIntegration.dockPosition === Qt.DownArrow + readonly property int dockSpacing: (isHorizontalDock ? DesktopIntegration.dockGeometry.height : DesktopIntegration.dockGeometry.width) / Screen.devicePixelRatio + + leftPadding: (DesktopIntegration.dockPosition === Qt.LeftArrow ? dockSpacing : 0) + rightPadding: (DesktopIntegration.dockPosition === Qt.RightArrow ? dockSpacing : 0) + topPadding: (DesktopIntegration.dockPosition === Qt.UpArrow ? dockSpacing : 0) + 20 + bottomPadding: (DesktopIntegration.dockPosition === Qt.DownArrow ? dockSpacing : 0) + 20 + + property Palette textColor: appTextColor + palette.windowText: ColorSelector.textColor + + // ----------- Drag and Drop related functions START ----------- + Label { + property string currentlyDraggedId + + signal dragEnded() + + id: dndItem + visible: DebugHelper.qtDebugEnabled + text: "DnD DEBUG" + + Drag.onActiveChanged: { + if (Drag.active) { + text = "Dragging " + currentlyDraggedId + } else { + currentlyDraggedId = "" + dragEnded() + } } } - } - - function dropOnItem(dragId, dropId, op) { - dndItem.text = "drag " + dragId + " onto " + dropId + " with " + op - ItemArrangementProxyModel.commitDndOperation(dragId, dropId, op) - } - function dropOnPage(dragId, dropFolderId, pageNumber) { - dndItem.text = "drag " + dragId + " into " + dropFolderId + " at page " + pageNumber - ItemArrangementProxyModel.commitDndOperation(dragId, dropFolderId, ItemArrangementProxyModel.DndJoin, pageNumber) - } - // ----------- Drag and Drop related functions END ----------- + function dropOnItem(dragId, dropId, op) { + dndItem.text = "drag " + dragId + " onto " + dropId + " with " + op + ItemArrangementProxyModel.commitDndOperation(dragId, dropId, op) + } - function tryToRemoveEmptyPage() { - ItemArrangementProxyModel.removeEmptyPage() - } + function dropOnPage(dragId, dropFolderId, pageNumber) { + dndItem.text = "drag " + dragId + " into " + dropFolderId + " at page " + pageNumber + ItemArrangementProxyModel.commitDndOperation(dragId, dropFolderId, ItemArrangementProxyModel.DndJoin, pageNumber) + } + // ----------- Drag and Drop related functions END ----------- - Timer { - id: flipPageDelay - interval: 400 - repeat: false - } + function tryToRemoveEmptyPage() { + ItemArrangementProxyModel.removeEmptyPage() + } - background: Image { - source: DesktopIntegration.backgroundUrl + Timer { + id: flipPageDelay + interval: 400 + repeat: false + } - Rectangle { - anchors.fill: parent - color: folderGridViewPopup.visible ? Qt.rgba(0, 0, 0, 0.6) : Qt.rgba(0, 0, 0, 0.5) + background: Image { + source: DesktopIntegration.backgroundUrl - MouseArea { + Rectangle { anchors.fill: parent - scrollGestureEnabled: false - onClicked: { - if (!DebugHelper.avoidHideWindow) { - LauncherController.visible = false - } - } - // TODO: this might not be the correct way to handle wheel - onWheel: { - if (flipPageDelay.running) return - let xDelta = wheel.angleDelta.x / 8 - let yDelta = wheel.angleDelta.y / 8 - let toPage = 0; // -1 prev, +1 next, 0 don't change - if (yDelta !== 0) { - toPage = (yDelta > 0) ? -1 : 1 - } else if (xDelta !== 0) { - toPage = (xDelta > 0) ? 1 : -1 + color: folderGridViewPopup.visible ? Qt.rgba(0, 0, 0, 0.6) : Qt.rgba(0, 0, 0, 0.5) + + MouseArea { + anchors.fill: parent + scrollGestureEnabled: false + onClicked: { + if (!DebugHelper.avoidHideWindow) { + LauncherController.visible = false + } } - if (toPage < 0) { - flipPageDelay.start() - if (!searchEdit.focus) { // reset keyboard focus when using mouse to flip page, but keep searchEdit focus - baseLayer.focus = true + // TODO: this might not be the correct way to handle wheel + onWheel: { + if (flipPageDelay.running) return + let xDelta = wheel.angleDelta.x / 8 + let yDelta = wheel.angleDelta.y / 8 + let toPage = 0; // -1 prev, +1 next, 0 don't change + if (yDelta !== 0) { + toPage = (yDelta > 0) ? -1 : 1 + } else if (xDelta !== 0) { + toPage = (xDelta > 0) ? 1 : -1 } - decrementPageIndex(pages) - } else if (toPage > 0) { - flipPageDelay.start() - if (!searchEdit.focus) { // reset keyboard focus when using mouse to flip page, but keep searchEdit focus - baseLayer.focus = true + if (toPage < 0) { + flipPageDelay.start() + if (!searchEdit.focus) { // reset keyboard focus when using mouse to flip page, but keep searchEdit focus + baseLayer.focus = true + } + decrementPageIndex(pages) + } else if (toPage > 0) { + flipPageDelay.start() + if (!searchEdit.focus) { // reset keyboard focus when using mouse to flip page, but keep searchEdit focus + baseLayer.focus = true + } + incrementPageIndex(pages) } - incrementPageIndex(pages) } } } } - } - contentItem: ColumnLayout { + contentItem: ColumnLayout { - Control { - Layout.fillWidth: true - Layout.fillHeight: false + Control { + Layout.fillWidth: true + Layout.fillHeight: false - leftPadding: 20 - rightPadding: 20 - topPadding: 10 + leftPadding: 20 + rightPadding: 20 + topPadding: 10 - contentItem: Rectangle { - id: fullscreenHeader - implicitHeight: exitFullscreenBtn.height - color: "transparent" + contentItem: Rectangle { + id: fullscreenHeader + implicitHeight: exitFullscreenBtn.height + color: "transparent" - ToolButton { - id: exitFullscreenBtn + ToolButton { + id: exitFullscreenBtn - visible: (DesktopIntegration.environmentVariable("DDE_CURRENT_COMPOSITOR") !== "TreeLand") + visible: (DesktopIntegration.environmentVariable("DDE_CURRENT_COMPOSITOR") !== "TreeLand") - Accessible.name: "Exit fullscreen" + Accessible.name: "Exit fullscreen" - anchors.right: fullscreenHeader.right + anchors.right: fullscreenHeader.right - ColorSelector.family: Palette.CrystalColor + ColorSelector.family: Palette.CrystalColor - icon.name: "launcher_exit_fullscreen" - onClicked: { - searchEdit.text = "" - LauncherController.currentFrame = "WindowedFrame" + icon.name: "launcher_exit_fullscreen" + onClicked: { + searchEdit.text = "" + LauncherController.currentFrame = "WindowedFrame" + } } - } - - PageIndicator { - id: indicator - opacity: folderGridViewPopup.visible ? 0.4 : 1 - anchors.horizontalCenter: parent.horizontalCenter - visible: pages.visible - count: searchResultGridViewContainer.visible ? 1 : pages.count - currentIndex: searchResultGridViewContainer.visible ? 1 : pages.currentIndex - interactive: true - spacing: 10 - delegate: Rectangle { - width: 10 - height: 10 - - radius: width / 2 - color: Qt.rgba(255, 255, 255, index === indicator.currentIndex ? 0.9 : pressed ? 0.5 : 0.2) - OutsideBoxBorder { - anchors.fill: parent - radius: parent.radius - width: 1 - color: Qt.rgba(0, 0, 0, 0.1) + PageIndicator { + id: indicator + + opacity: folderGridViewPopup.visible ? 0.4 : 1 + anchors.horizontalCenter: parent.horizontalCenter + visible: pages.visible + count: searchResultGridViewContainer.visible ? 1 : pages.count + currentIndex: searchResultGridViewContainer.visible ? 1 : pages.currentIndex + interactive: true + spacing: 10 + delegate: Rectangle { + width: 10 + height: 10 + + radius: width / 2 + color: Qt.rgba(255, 255, 255, index === indicator.currentIndex ? 0.9 : pressed ? 0.5 : 0.2) + OutsideBoxBorder { + anchors.fill: parent + radius: parent.radius + width: 1 + color: Qt.rgba(0, 0, 0, 0.1) + } } } } } - } - Item { - Layout.fillWidth: true - Layout.fillHeight: true - - DropArea { - id: dropArea - property int pageIntent: 0 - readonly property real paddingColumns: 0.5 - readonly property int horizontalPadding: searchResultGridViewContainer.cellWidth * paddingColumns - anchors.fill: parent - - property bool createdEmptyPage: false - function checkDragMove() { - if (drag.x < horizontalPadding) { - pageIntent = -1 - } else if (drag.x > (width - searchResultGridViewContainer.cellWidth)) { - let isLastPage = pages.currentIndex === pages.count - 1 - if (isLastPage && dropArea.createdEmptyPage) { - return + Item { + Layout.fillWidth: true + Layout.fillHeight: true + + DropArea { + id: dropArea + property int pageIntent: 0 + readonly property real paddingColumns: 0.5 + readonly property int horizontalPadding: searchResultGridViewContainer.cellWidth * paddingColumns + anchors.fill: parent + + property bool createdEmptyPage: false + function checkDragMove() { + if (drag.x < horizontalPadding) { + pageIntent = -1 + } else if (drag.x > (width - searchResultGridViewContainer.cellWidth)) { + let isLastPage = pages.currentIndex === pages.count - 1 + if (isLastPage && dropArea.createdEmptyPage) { + return + } + pageIntent = 1 + } else { + pageIntent = 0 } - pageIntent = 1 - } else { - pageIntent = 0 } - } - keys: ["text/x-dde-launcher-dnd-desktopId"] - onEntered: { - if (folderGridViewPopup.opened) { - folderGridViewPopup.close() + keys: ["text/x-dde-launcher-dnd-desktopId"] + onEntered: { + if (folderGridViewPopup.opened) { + folderGridViewPopup.close() + } } - } - onPositionChanged: { - checkDragMove() - } - onDropped: (drop) => { - // drop over the left or right boundary of the page, do nothing - if (pageIntent !== 0) { + onPositionChanged: { + checkDragMove() + } + onDropped: (drop) => { + // drop over the left or right boundary of the page, do nothing + if (pageIntent !== 0) { + pageIntent = 0 + return + } + // drop into current page + let dragId = drop.getDataAsString("text/x-dde-launcher-dnd-desktopId") + dropOnPage(dragId, "internal/folders/0", pages.currentIndex) + pageIntent = 0 + } + onExited: { pageIntent = 0 - return } - // drop into current page - let dragId = drop.getDataAsString("text/x-dde-launcher-dnd-desktopId") - dropOnPage(dragId, "internal/folders/0", pages.currentIndex) - pageIntent = 0 - } - onExited: { - pageIntent = 0 - } - onPageIntentChanged: { - if (pageIntent !== 0) { - dndMovePageTimer.restart() - } else { - dndMovePageTimer.stop() + onPageIntentChanged: { + if (pageIntent !== 0) { + dndMovePageTimer.restart() + } else { + dndMovePageTimer.stop() + } } - } - Timer { - id: dndMovePageTimer - interval: 1000 - onTriggered: { - if (parent.pageIntent > 0) { - let isLastPage = pages.currentIndex === pages.count - 1 - if (isLastPage && !dropArea.createdEmptyPage) { - let newPageIndex = ItemArrangementProxyModel.creatEmptyPage() - dropArea.createdEmptyPage = true - pages.setCurrentIndex(newPageIndex) - parent.pageIntent = 0 - return - } else { - incrementPageIndex(pages) + Timer { + id: dndMovePageTimer + interval: 1000 + onTriggered: { + if (parent.pageIntent > 0) { + let isLastPage = pages.currentIndex === pages.count - 1 + if (isLastPage && !dropArea.createdEmptyPage) { + let newPageIndex = ItemArrangementProxyModel.creatEmptyPage() + dropArea.createdEmptyPage = true + pages.setCurrentIndex(newPageIndex) + parent.pageIntent = 0 + return + } else { + incrementPageIndex(pages) + } + } else if (parent.pageIntent < 0) { + decrementPageIndex(pages) } - } else if (parent.pageIntent < 0) { - decrementPageIndex(pages) - } - parent.pageIntent = 0 - if (pages.currentIndex !== 0) { - parent.checkDragMove() + parent.pageIntent = 0 + if (pages.currentIndex !== 0) { + parent.checkDragMove() + } } } - } - Connections { - target: dndItem - function onDragEnded() { - if (dropArea.createdEmptyPage) { - tryToRemoveEmptyPage() - dropArea.createdEmptyPage = false + Connections { + target: dndItem + function onDragEnded() { + if (dropArea.createdEmptyPage) { + tryToRemoveEmptyPage() + dropArea.createdEmptyPage = false + } } } } - } - SwipeView { - id: pages + SwipeView { + id: pages - property int previousIndex: -1 - anchors.fill: parent - visible: searchEdit.text === "" + property int previousIndex: -1 + anchors.fill: parent + visible: searchEdit.text === "" - currentIndex: indicator.currentIndex + currentIndex: indicator.currentIndex - // To ensure toplevelRepeater's model (page count) updated correctly - // Caution! Don't put it directly under a Repeater{}, that will prevent Connections from working - Connections { - target: ItemArrangementProxyModel - function onRowsInserted() { - toplevelRepeater.pageCount = ItemArrangementProxyModel.pageCount(0) - } - function onRowsRemoved() { - toplevelRepeater.pageCount = ItemArrangementProxyModel.pageCount(0) - } + // To ensure toplevelRepeater's model (page count) updated correctly + // Caution! Don't put it directly under a Repeater{}, that will prevent Connections from working + Connections { + target: ItemArrangementProxyModel + function onRowsInserted() { + toplevelRepeater.pageCount = ItemArrangementProxyModel.pageCount(0) + } + function onRowsRemoved() { + toplevelRepeater.pageCount = ItemArrangementProxyModel.pageCount(0) + } - function onTopLevelPageCountChanged() { - toplevelRepeater.pageCount = ItemArrangementProxyModel.pageCount(0) + function onTopLevelPageCountChanged() { + toplevelRepeater.pageCount = ItemArrangementProxyModel.pageCount(0) + } } - } - Repeater { - id: toplevelRepeater - property int pageCount: ItemArrangementProxyModel.pageCount(0) - model: pageCount + Repeater { + id: toplevelRepeater + property int pageCount: ItemArrangementProxyModel.pageCount(0) + model: pageCount - Loader { - active: SwipeView.isCurrentItem || SwipeView.isNextItem || SwipeView.isPreviousItem - id: gridViewLoader - objectName: "Main GridView Loader" + Loader { + active: SwipeView.isCurrentItem || SwipeView.isNextItem || SwipeView.isPreviousItem + id: gridViewLoader + objectName: "Main GridView Loader" - property int viewIndex: index + property int viewIndex: index - sourceComponent: Rectangle { - color: "transparent" + sourceComponent: Rectangle { + color: "transparent" - property var grids: gridViewContainer + property var grids: gridViewContainer - MultipageSortFilterProxyModel { - id: proxyModel - sourceModel: ItemArrangementProxyModel - pageId: modelData - folderId: 0 - } + MultipageSortFilterProxyModel { + id: proxyModel + sourceModel: ItemArrangementProxyModel + pageId: modelData + folderId: 0 + } - MouseArea { - anchors.fill: parent - acceptedButtons: Qt.RightButton - onClicked: { - // FIXME: prevent the bug:https://bugreports.qt.io/browse/QTBUG-125139; - if (mouse.button === Qt.RightButton) { - mouse.accepted = false; + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.RightButton + onClicked: { + // FIXME: prevent the bug:https://bugreports.qt.io/browse/QTBUG-125139; + if (mouse.button === Qt.RightButton) { + mouse.accepted = false; + } } } - } - GridViewContainer { - id: gridViewContainer - objectName: "gridViewContainer" - anchors.fill: parent - rows: 4 - columns: 8 - paddingColumns: 0.5 - model: proxyModel - padding: 10 - interactive: false - focus: true - function checkPageSwitchState() { - if (gridViewLoader.viewIndex !== pages.currentIndex) - return - if (pages.previousIndex === -1) { + GridViewContainer { + id: gridViewContainer + objectName: "gridViewContainer" + anchors.fill: parent + rows: 4 + columns: 8 + paddingColumns: 0.5 + model: proxyModel + padding: 10 + interactive: false + focus: true + function checkPageSwitchState() { + if (gridViewLoader.viewIndex !== pages.currentIndex) + return + if (pages.previousIndex === -1) { + pages.previousIndex = pages.currentIndex + return + } + if (pages.currentIndex + 1 === pages.previousIndex || (pages.previousIndex === 0 && pages.currentIndex === pages.count - 1)) + gridViewContainer.setPreviousPageSwitch(true) + else + gridViewContainer.setPreviousPageSwitch(false) pages.previousIndex = pages.currentIndex - return } - if (pages.currentIndex + 1 === pages.previousIndex || (pages.previousIndex === 0 && pages.currentIndex === pages.count - 1)) - gridViewContainer.setPreviousPageSwitch(true) - else - gridViewContainer.setPreviousPageSwitch(false) - pages.previousIndex = pages.currentIndex - } - Keys.onLeftPressed: function(event) { - if (gridViewLoader.SwipeView.index === 0 && toplevelRepeater.pageCount > 1) { - // is the 1st page, go to last page - pages.setCurrentIndex(toplevelRepeater.pageCount - 1) - } else { - // not the 1st page, simply use SwipeView default behavior - event.accepted = false - } - } - Keys.onRightPressed: function(event) { - if (gridViewLoader.SwipeView.index === (toplevelRepeater.pageCount - 1) && toplevelRepeater.pageCount > 1) { - // is the last page, go to last page - pages.setCurrentIndex(0) - } else { - // not the last page, simply use SwipeView default behavior - event.accepted = false - } - } - opacity: folderGridViewPopup.visible ? 0.4 : 1 - activeGridViewFocusOnTab: gridViewLoader.SwipeView.isCurrentItem - itemMove: Transition { NumberAnimation { properties: "x,y"; duration: 250 } } - delegate: DropArea { - Keys.forwardTo: [iconItemDelegate] - - width: gridViewContainer.cellWidth - height: gridViewContainer.cellHeight - onEntered: { - if (folderGridViewPopup.opened) { - folderGridViewPopup.close() + Keys.onLeftPressed: function(event) { + if (gridViewLoader.SwipeView.index === 0 && toplevelRepeater.pageCount > 1) { + // is the 1st page, go to last page + pages.setCurrentIndex(toplevelRepeater.pageCount - 1) + } else { + // not the 1st page, simply use SwipeView default behavior + event.accepted = false } } - onDropped: { - let dragId = drop.getDataAsString("text/x-dde-launcher-dnd-desktopId") - let op = 0 - let sideOpPadding = width / 4 - if (drop.x < sideOpPadding) { - op = -1 - } else if (drop.x > (width - sideOpPadding)) { - op = 1 + Keys.onRightPressed: function(event) { + if (gridViewLoader.SwipeView.index === (toplevelRepeater.pageCount - 1) && toplevelRepeater.pageCount > 1) { + // is the last page, go to last page + pages.setCurrentIndex(0) + } else { + // not the last page, simply use SwipeView default behavior + event.accepted = false } - dropOnItem(dragId, model.desktopId, op) } - - IconItemDelegate { - id: iconItemDelegate - anchors { - fill: parent - margins: 5 - } - dndEnabled: !folderGridViewPopup.opened - Drag.mimeData: { - "text/x-dde-launcher-dnd-desktopId": model.desktopId + opacity: folderGridViewPopup.visible ? 0.4 : 1 + activeGridViewFocusOnTab: gridViewLoader.SwipeView.isCurrentItem + itemMove: Transition { NumberAnimation { properties: "x,y"; duration: 250 } } + delegate: DropArea { + Keys.forwardTo: [iconItemDelegate] + + width: gridViewContainer.cellWidth + height: gridViewContainer.cellHeight + onEntered: { + if (folderGridViewPopup.opened) { + folderGridViewPopup.close() + } } - visible: dndItem.currentlyDraggedId !== model.desktopId - iconSource: (iconName && iconName !== "") ? iconName : "application-x-desktop" - icons: folderIcons - onItemClicked: { - launchApp(desktopId) + onDropped: { + let dragId = drop.getDataAsString("text/x-dde-launcher-dnd-desktopId") + let op = 0 + let sideOpPadding = width / 4 + if (drop.x < sideOpPadding) { + op = -1 + } else if (drop.x > (width - sideOpPadding)) { + op = 1 + } + dropOnItem(dragId, model.desktopId, op) } - onFolderClicked: { - let idStr = model.desktopId - let idNum = Number(idStr.replace("internal/folders/", "")) - folderGridViewPopup.currentFolderId = idNum - folderGridViewPopup.open() - folderGridViewPopup.folderName = model.display.startsWith("internal/category/") ? getCategoryName(model.display.substring(18)) : model.display - console.log("open folder id:" + idNum) + + IconItemDelegate { + id: iconItemDelegate + anchors { + fill: parent + margins: 5 + } + dndEnabled: !folderGridViewPopup.opened + Drag.mimeData: { + "text/x-dde-launcher-dnd-desktopId": model.desktopId + } + visible: dndItem.currentlyDraggedId !== model.desktopId + iconSource: (iconName && iconName !== "") ? iconName : "application-x-desktop" + icons: folderIcons + onItemClicked: { + launchApp(desktopId) + } + onFolderClicked: { + let idStr = model.desktopId + let idNum = Number(idStr.replace("internal/folders/", "")) + folderGridViewPopup.currentFolderId = idNum + folderGridViewPopup.open() + folderGridViewPopup.folderName = model.display.startsWith("internal/category/") ? getCategoryName(model.display.substring(18)) : model.display + console.log("open folder id:" + idNum) + } + onMenuTriggered: { + if (folderIcons) return; + showContextMenu(this, model) + baseLayer.focus = true + } } - onMenuTriggered: { - if (folderIcons) return; - showContextMenu(this, model) - baseLayer.focus = true + } + Connections { + target: pages + function onCurrentIndexChanged() { + gridViewContainer.checkPageSwitchState() } } - } - Connections { - target: pages - function onCurrentIndexChanged() { - gridViewContainer.checkPageSwitchState() + Connections { + target: dropArea + function onDropped() { + gridViewContainer.checkPageSwitchState() + } } - } - Connections { - target: dropArea - function onDropped() { + Component.onCompleted: { gridViewContainer.checkPageSwitchState() } } - Component.onCompleted: { - gridViewContainer.checkPageSwitchState() - } } - } - // Since SwipeView will catch the mouse click event so we need to also do it here... - MouseArea { - anchors.fill: parent - onClicked: { - if (!DebugHelper.avoidHideWindow) { - LauncherController.visible = false + // Since SwipeView will catch the mouse click event so we need to also do it here... + MouseArea { + anchors.fill: parent + onClicked: { + if (!DebugHelper.avoidHideWindow) { + LauncherController.visible = false + } } } } } } - } - DelegateModel { - id: delegateSearchResultModel - model: SearchFilterProxyModel - delegate: IconItemDelegate { - iconSource: iconName - width: searchResultGridViewContainer.cellWidth - height: searchResultGridViewContainer.cellHeight - padding: 5 - onItemClicked: { - launchApp(desktopId) - } - onMenuTriggered: { - showContextMenu(this, model) + DelegateModel { + id: delegateSearchResultModel + model: SearchFilterProxyModel + delegate: IconItemDelegate { + iconSource: iconName + width: searchResultGridViewContainer.cellWidth + height: searchResultGridViewContainer.cellHeight + padding: 5 + onItemClicked: { + launchApp(desktopId) + } + onMenuTriggered: { + showContextMenu(this, model) + } } } - } - - GridViewContainer { - id: searchResultGridViewContainer - anchors.fill: parent - visible: searchEdit.text !== "" - activeFocusOnTab: visible && gridViewFocus - focus: true - alwaysShowHighlighted: true - - rows: 4 - columns: 8 - paddingColumns: 0.5 - placeholderIcon: "search_no_result" - placeholderText: qsTranslate("SearchResultView", "No search results") - placeholderIconSize: 256 - model: delegateSearchResultModel - padding: 10 - interactive: true - vScrollBar: ScrollBar { - visible: parent.model.count > 4 * 8 - active: parent.model.count > 4 * 8 + GridViewContainer { + id: searchResultGridViewContainer + + anchors.fill: parent + visible: searchEdit.text !== "" + activeFocusOnTab: visible && gridViewFocus + focus: true + alwaysShowHighlighted: true + + rows: 4 + columns: 8 + paddingColumns: 0.5 + placeholderIcon: "search_no_result" + placeholderText: qsTranslate("SearchResultView", "No search results") + placeholderIconSize: 256 + model: delegateSearchResultModel + padding: 10 + interactive: true + vScrollBar: ScrollBar { + visible: parent.model.count > 4 * 8 + active: parent.model.count > 4 * 8 + } } } - } - SearchEdit { - id: searchEdit + SearchEdit { + id: searchEdit - Layout.alignment: Qt.AlignHCenter - implicitWidth: (parent.width / 2) > 280 ? 280 : (parent.width / 2) + Layout.alignment: Qt.AlignHCenter + implicitWidth: (parent.width / 2) > 280 ? 280 : (parent.width / 2) - property Palette iconPalette: Palette { - normal { - crystal: Qt.rgba(0, 0, 0, 1) + property Palette iconPalette: Palette { + normal { + crystal: Qt.rgba(0, 0, 0, 1) + } + normalDark { + crystal: Qt.rgba(1, 1, 1, 1) + } + } + placeholderTextColor: palette.brightText + palette.windowText: ColorSelector.iconPalette + + KeyNavigation.up: searchEdit.text === "" ? pages : searchResultGridViewContainer + KeyNavigation.down: KeyNavigation.up + Keys.onReturnPressed: { + if (searchEdit.text === "") { + pages.focus = true + } else { + searchResultGridViewContainer.currentItem?.itemClicked() + } } - normalDark { - crystal: Qt.rgba(1, 1, 1, 1) + onTextChanged: { + searchEdit.focus = true + SearchFilterProxyModel.setFilterRegularExpression(text.trim()) + // reset highlighted item + if (searchResultGridViewContainer.visible) { + if (delegateSearchResultModel.count > 0) { + searchResultGridViewContainer.currentIndex = 0 + } + } } } - placeholderTextColor: palette.brightText - palette.windowText: ColorSelector.iconPalette + } - KeyNavigation.up: searchEdit.text === "" ? pages : searchResultGridViewContainer - KeyNavigation.down: KeyNavigation.up - Keys.onReturnPressed: { - if (searchEdit.text === "") { + FolderGridViewPopup { + id: folderGridViewPopup + cs: searchResultGridViewContainer.cellHeight + } + + Keys.forwardTo: [searchEdit] + Keys.onPressed: { + if (baseLayer.focus === true) { + // the SearchEdit will catch the key event first, and events that it won't accept will then got here + switch (event.key) { + case Qt.Key_Up: + case Qt.Key_Down: + case Qt.Key_Enter: + case Qt.Key_Return: pages.focus = true - } else { - searchResultGridViewContainer.currentItem?.itemClicked() - } - } - onTextChanged: { - searchEdit.focus = true - SearchFilterProxyModel.setFilterRegularExpression(text.trim()) - // reset highlighted item - if (searchResultGridViewContainer.visible) { - if (delegateSearchResultModel.count > 0) { - searchResultGridViewContainer.currentIndex = 0 - } } } } - } - - FolderGridViewPopup { - id: folderGridViewPopup - cs: searchResultGridViewContainer.cellHeight - } - Keys.forwardTo: [searchEdit] - Keys.onPressed: { - if (baseLayer.focus === true) { - // the SearchEdit will catch the key event first, and events that it won't accept will then got here - switch (event.key) { - case Qt.Key_Up: - case Qt.Key_Down: - case Qt.Key_Enter: - case Qt.Key_Return: - pages.focus = true + Keys.onEscapePressed: { + if (!DebugHelper.avoidHideWindow) { + LauncherController.visible = false; } } - } - Keys.onEscapePressed: { - if (!DebugHelper.avoidHideWindow) { - LauncherController.visible = false; + Connections { + target: LauncherController + function onVisibleChanged() { + // only do these clean-up steps on launcher get hide + if (LauncherController.visible) return + // clear searchEdit text + searchEdit.text = "" + // close folder popup + if (folderGridViewPopup.visible) folderGridViewPopup.close() + // reset(remove) keyboard focus + baseLayer.focus = true + // reset page to the first page + pages.setCurrentIndex(0) + } } } - - Connections { - target: LauncherController - function onVisibleChanged() { - // only do these clean-up steps on launcher get hide - if (LauncherController.visible) return - // clear searchEdit text - searchEdit.text = "" - // close folder popup - if (folderGridViewPopup.visible) folderGridViewPopup.close() - // reset(remove) keyboard focus - baseLayer.focus = true - // reset page to the first page - pages.setCurrentIndex(0) + onInputReceived: function(text){ + if (searchEdit.text !== "" || searchEdit.focus !== true) { + searchEdit.text = text + searchEdit.focus = true } } } diff --git a/qml/windowed/WindowedFrame.qml b/qml/windowed/WindowedFrame.qml index 102d44bf..faf8111f 100644 --- a/qml/windowed/WindowedFrame.qml +++ b/qml/windowed/WindowedFrame.qml @@ -13,7 +13,7 @@ import org.deepin.launchpad 1.0 import org.deepin.launchpad.models 1.0 import "." -Item { +InputEventItem { id: baseLayer objectName: "WindowedFrame-BaseLayer" @@ -206,6 +206,12 @@ Item { LauncherController.visible = false; } } + onInputReceived: function(text){ + if (bottomBar.searchEdit.text !== "" || bottomBar.searchEdit.focus !== true) { + bottomBar.searchEdit.text = text + bottomBar.searchEdit.focus = true + } + } Connections { target: LauncherController