File indexing completed on 2025-01-26 05:06:18

0001 /*
0002     SPDX-FileCopyrightText: 2012-2016 Eike Hein <hein@kde.org>
0003     SPDX-FileCopyrightText: 2020 Nate Graham <nate@kde.org>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 .pragma library
0009 
0010 .import org.kde.taskmanager 0.1 as TaskManager
0011 .import org.kde.plasma.core as PlasmaCore // Needed by TaskManager
0012 
0013 var windowViewAvailable = false;
0014 var taskManagerInstanceCount = 0;
0015 
0016 function activateNextPrevTask(anchor, next, wheelSkipMinimized, tasks) {
0017     // FIXME TODO: Unnecessarily convoluted and costly; optimize.
0018 
0019     var taskIndexList = [];
0020     var activeTaskIndex = tasks.tasksModel.activeTask;
0021 
0022     for (var i = 0; i < tasks.taskList.children.length - 1; ++i) {
0023         var task = tasks.taskList.children[i];
0024         var modelIndex = task.modelIndex(i);
0025 
0026         if (!task.model.IsLauncher && !task.model.IsStartup) {
0027             if (task.model.IsGroupParent) {
0028                 if (task == anchor) { // If the anchor is a group parent, collect only windows within the group.
0029                     taskIndexList = [];
0030                 }
0031 
0032                 for (var j = 0; j < tasks.tasksModel.rowCount(modelIndex); ++j) {
0033                     const childModelIndex = tasks.tasksModel.makeModelIndex(i, j);
0034                     const childHidden = tasks.tasksModel.data(childModelIndex, TaskManager.AbstractTasksModel.IsHidden);
0035                     if (!wheelSkipMinimized || !childHidden) {
0036                         taskIndexList.push(childModelIndex);
0037                     }
0038                 }
0039 
0040                 if (task == anchor) { // See above.
0041                     break;
0042                 }
0043             } else {
0044                 if (!wheelSkipMinimized || !task.model.IsHidden) {
0045                     taskIndexList.push(modelIndex);
0046                 }
0047             }
0048         }
0049     }
0050 
0051     if (!taskIndexList.length) {
0052         return;
0053     }
0054 
0055     var target = taskIndexList[0];
0056 
0057     for (var i = 0; i < taskIndexList.length; ++i) {
0058         if (taskIndexList[i] === activeTaskIndex)
0059         {
0060             if (next && i < (taskIndexList.length - 1)) {
0061                 target = taskIndexList[i + 1];
0062             } else if (!next) {
0063                 if (i) {
0064                     target = taskIndexList[i - 1];
0065                 } else {
0066                     target = taskIndexList[taskIndexList.length - 1];
0067                 }
0068             }
0069 
0070             break;
0071         }
0072     }
0073 
0074     tasks.tasksModel.requestActivate(target);
0075 }
0076 
0077 function activateTask(index, model, modifiers, task, plasmoid, tasks) {
0078     if (modifiers & Qt.ShiftModifier) {
0079         tasks.tasksModel.requestNewInstance(index);
0080         return;
0081     }
0082     // Publish delegate geometry again if there are more than one task manager instance
0083     if (taskManagerInstanceCount >= 2) {
0084         tasks.tasksModel.requestPublishDelegateGeometry(task.modelIndex(), tasks.backend.globalRect(task), task);
0085     }
0086 
0087     if (model.IsGroupParent) {
0088         // Option 1 (default): Cycle through this group's tasks
0089         // ====================================================
0090         // If the grouped task does not include the currently active task, bring
0091         // forward the most recently used task in the group according to the
0092         // Stacking order.
0093         // Otherwise cycle through all tasks in the group without paying attention
0094         // to the stacking order, which otherwise would change with every click
0095         if (plasmoid.configuration.groupedTaskVisualization === 0) {
0096             let childTaskList = [];
0097             let highestStacking = -1;
0098             let lastUsedTask = undefined;
0099 
0100             // Build list of child tasks and get stacking order data for them
0101             for (let i = 0; i < tasks.tasksModel.rowCount(task.modelIndex(index)); ++i) {
0102                 const childTaskModelIndex = tasks.tasksModel.makeModelIndex(task.index, i);
0103                 childTaskList.push(childTaskModelIndex);
0104                 const stacking = tasks.tasksModel.data(childTaskModelIndex, TaskManager.AbstractTasksModel.StackingOrder);
0105                 if (stacking > highestStacking) {
0106                     highestStacking = stacking;
0107                     lastUsedTask = childTaskModelIndex;
0108                 }
0109             }
0110 
0111             // If the active task is from a different app from the group that
0112             // was clicked on switch to the last-used task from that app.
0113             if (!childTaskList.some(index => tasks.tasksModel.data(index, TaskManager.AbstractTasksModel.IsActive))) {
0114                 tasks.tasksModel.requestActivate(lastUsedTask);
0115             } else {
0116                 // If the active task is already among in the group that was
0117                 // activated, cycle through all tasks according to the order of
0118                 // the immutable model index so the order doesn't change with
0119                 // every click.
0120                 for (let j = 0; j < childTaskList.length; ++j) {
0121                     const childTask = childTaskList[j];
0122                         if (tasks.tasksModel.data(childTask, TaskManager.AbstractTasksModel.IsActive)) {
0123                             // Found the current task. Activate the next one
0124                             let nextTask = j + 1;
0125                             if (nextTask >= childTaskList.length) {
0126                                 nextTask = 0;
0127                             }
0128                             tasks.tasksModel.requestActivate(childTaskList[nextTask]);
0129                             break;
0130                         }
0131                 }
0132             }
0133         }
0134 
0135         // Option 2: show tooltips for all child tasks
0136         // ===========================================
0137         else if (plasmoid.configuration.groupedTaskVisualization === 1) {
0138             if (tasks.toolTipOpenedByClick) {
0139                 task.hideImmediately();
0140             } else {
0141                 tasks.toolTipOpenedByClick = task;
0142                 task.updateMainItemBindings(); // BUG 452187
0143                 task.showToolTip();
0144             }
0145         }
0146 
0147         // Option 3: show Window View for all child tasks
0148         // ==================================================
0149         // Make sure the Window View effect is  are actually enabled though;
0150         // if not, fall through to the next option.
0151         else if (plasmoid.configuration.groupedTaskVisualization === 2 && windowViewAvailable) {
0152             task.hideToolTip();
0153             tasks.activateWindowView(model.WinIdList);
0154         }
0155 
0156         // Option 4: show group dialog/textual list
0157         // ========================================
0158         // This is also the final fallback option if Window View
0159         // is chosen but not actually available
0160         else {
0161             if (!!tasks.groupDialog) {
0162                 task.hideToolTip();
0163                 tasks.groupDialog.visible = false;
0164             } else {
0165                 createGroupDialog(task, tasks);
0166             }
0167         }
0168     } else {
0169         if (model.IsMinimized) {
0170             tasks.tasksModel.requestToggleMinimized(index);
0171             tasks.tasksModel.requestActivate(index);
0172         } else if (model.IsActive && plasmoid.configuration.minimizeActiveTaskOnClick) {
0173             tasks.tasksModel.requestToggleMinimized(index);
0174         } else {
0175             tasks.tasksModel.requestActivate(index);
0176         }
0177     }
0178 }
0179 
0180 function taskPrefix(prefix, location) {
0181     var effectivePrefix;
0182 
0183     switch (location) {
0184     case PlasmaCore.Types.LeftEdge:
0185         effectivePrefix = "west-" + prefix;
0186         break;
0187     case PlasmaCore.Types.TopEdge:
0188         effectivePrefix = "north-" + prefix;
0189         break;
0190     case PlasmaCore.Types.RightEdge:
0191         effectivePrefix = "east-" + prefix;
0192         break;
0193     default:
0194         effectivePrefix = "south-" + prefix;
0195     }
0196     return [effectivePrefix, prefix];
0197 }
0198 
0199 function taskPrefixHovered(prefix, location) {
0200     return [
0201         ...taskPrefix((prefix || "launcher") + "-hover", location),
0202         ...prefix ? taskPrefix("hover", location) : [],
0203         ...taskPrefix(prefix, location)
0204     ];
0205 }
0206 
0207 function createGroupDialog(visualParent, tasks) {
0208     if (!visualParent) {
0209         return;
0210     }
0211 
0212     if (!!tasks.groupDialog) {
0213         tasks.groupDialog.visualParent = visualParent;
0214         return;
0215     }
0216 
0217     tasks.groupDialog = tasks.groupDialogComponent.createObject(tasks,
0218         {
0219             visualParent: visualParent,
0220         }
0221     );
0222 }