diff --git a/roles/config/files/.config/kwinrc b/roles/config/files/.config/kwinrc index 2d5ee43cf..7605d6768 100644 --- a/roles/config/files/.config/kwinrc +++ b/roles/config/files/.config/kwinrc @@ -3,7 +3,7 @@ update_info=kwin.upd:replace-scalein-with-scale,kwin.upd:port-minimizeanimation- [Activities][LastVirtualDesktop] 2efc56f1-09fa-4490-9706-4dcde3912089=7ee59aa2-5b40-453c-a852-224cbf0d3a0a -64664544-a062-48cf-a713-e4045da575e9=4187c550-f678-4921-a4cc-033af5fba3aa +64664544-a062-48cf-a713-e4045da575e9=7ee59aa2-5b40-453c-a852-224cbf0d3a0a [Desktops] Id_1=7ee59aa2-5b40-453c-a852-224cbf0d3a0a diff --git a/roles/config/files/.local/share/kwin/scripts/krohnkite/contents/code/script.js b/roles/config/files/.local/share/kwin/scripts/krohnkite/contents/code/script.js index 9a3173a5d..f2e3b1208 100644 --- a/roles/config/files/.local/share/kwin/scripts/krohnkite/contents/code/script.js +++ b/roles/config/files/.local/share/kwin/scripts/krohnkite/contents/code/script.js @@ -1,40 +1,979 @@ "use strict"; -var Shortcut; -(function (Shortcut) { - Shortcut[Shortcut["FocusNext"] = 0] = "FocusNext"; - Shortcut[Shortcut["FocusPrev"] = 1] = "FocusPrev"; - Shortcut[Shortcut["DWMLeft"] = 2] = "DWMLeft"; - Shortcut[Shortcut["DWMRight"] = 3] = "DWMRight"; - Shortcut[Shortcut["FocusUp"] = 4] = "FocusUp"; - Shortcut[Shortcut["FocusDown"] = 5] = "FocusDown"; - Shortcut[Shortcut["FocusLeft"] = 6] = "FocusLeft"; - Shortcut[Shortcut["FocusRight"] = 7] = "FocusRight"; - Shortcut[Shortcut["ShiftLeft"] = 8] = "ShiftLeft"; - Shortcut[Shortcut["ShiftRight"] = 9] = "ShiftRight"; - Shortcut[Shortcut["ShiftUp"] = 10] = "ShiftUp"; - Shortcut[Shortcut["ShiftDown"] = 11] = "ShiftDown"; - Shortcut[Shortcut["SwapUp"] = 12] = "SwapUp"; - Shortcut[Shortcut["SwapDown"] = 13] = "SwapDown"; - Shortcut[Shortcut["SwapLeft"] = 14] = "SwapLeft"; - Shortcut[Shortcut["SwapRight"] = 15] = "SwapRight"; - Shortcut[Shortcut["GrowWidth"] = 16] = "GrowWidth"; - Shortcut[Shortcut["GrowHeight"] = 17] = "GrowHeight"; - Shortcut[Shortcut["ShrinkWidth"] = 18] = "ShrinkWidth"; - Shortcut[Shortcut["ShrinkHeight"] = 19] = "ShrinkHeight"; - Shortcut[Shortcut["Increase"] = 20] = "Increase"; - Shortcut[Shortcut["Decrease"] = 21] = "Decrease"; - Shortcut[Shortcut["ShiftIncrease"] = 22] = "ShiftIncrease"; - Shortcut[Shortcut["ShiftDecrease"] = 23] = "ShiftDecrease"; - Shortcut[Shortcut["ToggleFloat"] = 24] = "ToggleFloat"; - Shortcut[Shortcut["ToggleFloatAll"] = 25] = "ToggleFloatAll"; - Shortcut[Shortcut["SetMaster"] = 26] = "SetMaster"; - Shortcut[Shortcut["NextLayout"] = 27] = "NextLayout"; - Shortcut[Shortcut["PreviousLayout"] = 28] = "PreviousLayout"; - Shortcut[Shortcut["SetLayout"] = 29] = "SetLayout"; - Shortcut[Shortcut["Rotate"] = 30] = "Rotate"; - Shortcut[Shortcut["RotatePart"] = 31] = "RotatePart"; -})(Shortcut || (Shortcut = {})); +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +const Shortcut = { + FocusNext: 1, + FocusPrev: 2, + DWMLeft: 3, + DWMRight: 4, + FocusUp: 5, + FocusDown: 6, + FocusLeft: 7, + FocusRight: 8, + ShiftLeft: 9, + ShiftRight: 10, + ShiftUp: 11, + ShiftDown: 12, + SwapUp: 13, + SwapDown: 14, + SwapLeft: 15, + SwapRight: 16, + GrowWidth: 17, + GrowHeight: 18, + ShrinkWidth: 19, + ShrinkHeight: 20, + Increase: 21, + Decrease: 22, + ShiftIncrease: 22, + ShiftDecrease: 23, + ToggleFloat: 24, + ToggleFloatAll: 25, + SetMaster: 26, + NextLayout: 27, + PreviousLayout: 28, + SetLayout: 29, + Rotate: 30, + RotatePart: 31, + ToggleDock: 32, +}; let CONFIG; +class Dock { + constructor(cfg, priority = 0) { + this.renderedOutputId = ""; + this.renderedTime = null; + this.priority = priority; + this.position = null; + this.cfg = Object.assign({}, cfg); + } + clone() { + let dock = new Dock(this.cfg, this.priority); + dock.renderedOutputId = this.renderedOutputId; + dock.renderedTime = this.renderedTime; + dock.position = this.position; + return dock; + } +} +class dockSurfaceCfg { + constructor(outputName, activityId, vDesktopName, cfg) { + this.outputName = outputName; + this.activityId = activityId; + this.vDesktopName = vDesktopName; + this.cfg = cfg; + } + isFit(srf) { + return ((this.outputName === "" || this.outputName === srf.output.name) && + (this.vDesktopName === "" || this.vDesktopName === srf.desktop.name) && + (this.activityId === "" || this.activityId === srf.activity)); + } + toString() { + return `dockSurface: Output Name: ${this.outputName}, Activity ID: ${this.activityId}, Virtual Desktop Name: ${this.vDesktopName} cfg: ${this.cfg}`; + } +} +const DockPosition = { + left: 1, + right: 2, + top: 3, + bottom: 4, +}; +const HDockAlignment = { + center: 1, + left: 2, + right: 3, +}; +const VDockAlignment = { + center: 1, + top: 2, + bottom: 3, +}; +const EdgeAlignment = { + outside: 1, + middle: 2, + inside: 3, +}; +var _a, _DefaultDockCfg_instance; +class DefaultDockCfg { + constructor() { + let hHeight = validateNumber(CONFIG.dockHHeight, 1, 50); + if (hHeight instanceof Err) { + warning(`getDefaultCfg: hHeight: ${hHeight}`); + this.hHeight = 25; + } + else + this.hHeight = hHeight; + let hWide = validateNumber(CONFIG.dockHWide, 1, 100); + if (hWide instanceof Err) { + warning(`getDefaultCfg: hWide: ${hWide}`); + this.hWide = 100; + } + else + this.hWide = hWide; + let vHeight = validateNumber(CONFIG.dockVHeight, 1, 100); + if (vHeight instanceof Err) { + warning(`getDefaultCfg: vHeight: ${vHeight}`); + this.vHeight = 100; + } + else + this.vHeight = vHeight; + let vWide = validateNumber(CONFIG.dockVWide, 1, 50); + if (vWide instanceof Err) { + warning(`getDefaultCfg: vWide: ${vWide}`); + this.vWide = 25; + } + else + this.vWide = vWide; + let hGap = validateNumber(CONFIG.dockHGap); + if (hGap instanceof Err) { + warning(`getDefaultCfg: hGap: ${hGap}`); + this.hGap = 0; + } + else + this.hGap = hGap; + let hEdgeGap = validateNumber(CONFIG.dockHEdgeGap); + if (hEdgeGap instanceof Err) { + warning(`getDefaultCfg: hEdgeGap: ${hEdgeGap}`); + this.hEdgeGap = 0; + } + else + this.hEdgeGap = hEdgeGap; + let vGap = validateNumber(CONFIG.dockVGap); + if (vGap instanceof Err) { + warning(`getDefaultCfg: vGap: ${vGap}`); + this.vGap = 0; + } + else + this.vGap = vGap; + let vEdgeGap = validateNumber(CONFIG.dockVEdgeGap); + if (vEdgeGap instanceof Err) { + warning(`getDefaultCfg: vEdgeGap: ${vEdgeGap}`); + this.vEdgeGap = 0; + } + else + this.vEdgeGap = vEdgeGap; + let hAlignmentNumber = validateNumber(CONFIG.dockHAlignment); + if (hAlignmentNumber instanceof Err) { + warning(`getDefaultCfg: hAlignment: ${hAlignmentNumber}`); + this.hAlignment = HDockAlignment.center; + } + else { + switch (hAlignmentNumber) { + case 0: + this.hAlignment = HDockAlignment.center; + break; + case 1: + this.hAlignment = HDockAlignment.left; + break; + case 2: + this.hAlignment = HDockAlignment.right; + break; + default: + warning(`getDefaultCfg: hAlignment:${hAlignmentNumber} is not a valid alignment`); + this.hAlignment = HDockAlignment.center; + break; + } + } + let hEdgeAlignmentNumber = validateNumber(CONFIG.dockHEdgeAlignment); + if (hEdgeAlignmentNumber instanceof Err) { + warning(`getDefaultCfg: hEdgeAlignment: ${hEdgeAlignmentNumber}`); + this.hEdgeAlignment = EdgeAlignment.outside; + } + else { + switch (hEdgeAlignmentNumber) { + case 0: + this.hEdgeAlignment = EdgeAlignment.outside; + break; + case 1: + this.hEdgeAlignment = EdgeAlignment.middle; + break; + case 2: + this.hEdgeAlignment = EdgeAlignment.inside; + break; + default: + warning(`getDefaultCfg: hEdgeAlignment:${hEdgeAlignmentNumber} is not a valid alignment`); + this.hEdgeAlignment = EdgeAlignment.outside; + break; + } + } + let vAlignmentNumber = validateNumber(CONFIG.dockVAlignment); + if (vAlignmentNumber instanceof Err) { + warning(`getDefaultCfg: vAlignment: ${vAlignmentNumber}`); + this.vAlignment = VDockAlignment.center; + } + else { + switch (vAlignmentNumber) { + case 0: + this.vAlignment = VDockAlignment.center; + break; + case 1: + this.vAlignment = VDockAlignment.top; + break; + case 2: + this.vAlignment = VDockAlignment.bottom; + break; + default: + warning(`getDefaultCfg: vAlignment: ${vAlignmentNumber} is not valid alignment`); + this.vAlignment = VDockAlignment.center; + break; + } + } + let vEdgeAlignmentNumber = validateNumber(CONFIG.dockVEdgeAlignment); + if (vEdgeAlignmentNumber instanceof Err) { + warning(`getDefaultCfg: vEdgeAlignment: ${vEdgeAlignmentNumber}`); + this.vEdgeAlignment = EdgeAlignment.outside; + } + else { + switch (vEdgeAlignmentNumber) { + case 0: + this.vEdgeAlignment = EdgeAlignment.outside; + break; + case 1: + this.vEdgeAlignment = EdgeAlignment.middle; + break; + case 2: + this.vEdgeAlignment = EdgeAlignment.inside; + break; + default: + warning(`getDefaultCfg: vEdgeAlignment:${vEdgeAlignmentNumber} is not a valid alignment`); + this.vEdgeAlignment = EdgeAlignment.outside; + break; + } + } + } + static get instance() { + if (!__classPrivateFieldGet(_a, _a, "f", _DefaultDockCfg_instance)) { + __classPrivateFieldSet(_a, _a, new _a(), "f", _DefaultDockCfg_instance); + } + return __classPrivateFieldGet(_a, _a, "f", _DefaultDockCfg_instance); + } + cloneAndUpdate(cfg) { + return Object.assign({}, _a.instance, cfg); + } +} +_a = DefaultDockCfg; +_DefaultDockCfg_instance = { value: void 0 }; +class DockEntry { + constructor(cfg, id) { + this.surfaceCfg = cfg; + this._slots = this.parseSlots(); + this._id = id; + } + get id() { + return this._id; + } + get slots() { + return this._slots; + } + remove(window) { + for (let slot of this.slots) { + if (slot.window === window) { + slot.window = null; + break; + } + } + } + arrange(dockedWindows, workingArea) { + const IS_WIDE = workingArea.width > workingArea.height; + let dockCfg; + let renderedTime = new Date().getTime(); + let renderedOutputId = this.id; + this.arrangeSlots(dockedWindows); + this.assignSizes(workingArea); + const leftSlot = this.getSlot(DockPosition.left); + const rightSlot = this.getSlot(DockPosition.right); + const topSlot = this.getSlot(DockPosition.top); + const bottomSlot = this.getSlot(DockPosition.bottom); + let leftBorder = workingArea.x; + let width = workingArea.width; + let topBorder = workingArea.y; + let height = workingArea.height; + function leftSlotArrange() { + if (leftSlot !== null) { + dockCfg = leftSlot.window.dock.cfg; + let leftSlotHeight = Math.min((workingArea.height * dockCfg.vHeight) / 100, height); + let initRect = new Rect(leftBorder, topBorder, (workingArea.width * dockCfg.vWide) / 100, leftSlotHeight); + leftBorder = leftBorder + initRect.width; + width = width - initRect.width; + leftSlot.window.geometry = DockEntry.align(initRect, leftSlot.position, dockCfg, height); + leftSlot.window.dock.renderedTime = renderedTime; + leftSlot.window.dock.renderedOutputId = renderedOutputId; + } + } + function rightSlotArrange() { + if (rightSlot !== null) { + dockCfg = rightSlot.window.dock.cfg; + let rightSlotHeight = Math.min((workingArea.height * dockCfg.vHeight) / 100, height); + let initRect = new Rect(workingArea.x + + workingArea.width - + (workingArea.width * dockCfg.vWide) / 100, topBorder, (workingArea.width * dockCfg.vWide) / 100, rightSlotHeight); + width = width - initRect.width; + rightSlot.window.geometry = DockEntry.align(initRect, rightSlot.position, dockCfg, height); + rightSlot.window.dock.renderedTime = renderedTime; + rightSlot.window.dock.renderedOutputId = renderedOutputId; + } + } + function topSlotArrange() { + if (topSlot !== null) { + dockCfg = topSlot.window.dock.cfg; + let topSlotWidth = Math.min((workingArea.width * dockCfg.hWide) / 100, width); + let initRect = new Rect(leftBorder, topBorder, topSlotWidth, (workingArea.height * dockCfg.hHeight) / 100); + topBorder = topBorder + initRect.height; + height = height - initRect.height; + topSlot.window.geometry = DockEntry.align(initRect, topSlot.position, dockCfg, width); + topSlot.window.dock.renderedTime = renderedTime; + topSlot.window.dock.renderedOutputId = renderedOutputId; + } + } + function bottomSlotArrange() { + if (bottomSlot !== null) { + dockCfg = bottomSlot.window.dock.cfg; + let bottomSlotWidth = Math.min((workingArea.width * dockCfg.hWide) / 100, width); + let initRect = new Rect(leftBorder, workingArea.y + + workingArea.height - + (workingArea.height * dockCfg.hHeight) / 100, bottomSlotWidth, (workingArea.height * dockCfg.hHeight) / 100); + height = height - initRect.height; + bottomSlot.window.geometry = DockEntry.align(initRect, bottomSlot.position, dockCfg, width); + bottomSlot.window.dock.renderedTime = renderedTime; + bottomSlot.window.dock.renderedOutputId = renderedOutputId; + } + } + if (IS_WIDE) { + leftSlotArrange(); + rightSlotArrange(); + topSlotArrange(); + bottomSlotArrange(); + } + else { + topSlotArrange(); + bottomSlotArrange(); + leftSlotArrange(); + rightSlotArrange(); + } + return new Rect(leftBorder, topBorder, width, height); + } + handleShortcut(window, shortcut) { + const slot = this.getSlotByWindow(window); + let desiredPosition; + if (!slot || !window.dock) { + return false; + } + switch (shortcut) { + case Shortcut.SwapLeft: + desiredPosition = DockPosition.left; + break; + case Shortcut.SwapUp: + desiredPosition = DockPosition.top; + break; + case Shortcut.SwapRight: + desiredPosition = DockPosition.right; + break; + case Shortcut.SwapDown: + desiredPosition = DockPosition.bottom; + break; + default: + return false; + } + if (slot.position !== desiredPosition) { + const desiredSlot = this.getSlotByPosition(desiredPosition); + if (desiredSlot !== null && desiredSlot.window === null) { + window.dock.position = desiredPosition; + return true; + } + } + return false; + } + static align(initRect, position, cfg, wholeSize) { + let leftBorder = initRect.x; + let topBorder = initRect.y; + let width = initRect.width; + let height = initRect.height; + switch (position) { + case DockPosition.left: + case DockPosition.right: + [width, leftBorder] = DockEntry.alignEdge(width, leftBorder, cfg.vEdgeGap, position, cfg.vEdgeAlignment); + if (2 * cfg.vGap < height) { + if (wholeSize - height < 2 * cfg.vGap) { + topBorder = topBorder + cfg.vGap; + height = height - 2 * cfg.vGap; + } + else if (cfg.vAlignment === VDockAlignment.top) { + topBorder = topBorder + cfg.vGap; + } + else if (cfg.vAlignment === VDockAlignment.center) { + topBorder = topBorder + (wholeSize - height) / 2; + } + else if (cfg.vAlignment === VDockAlignment.bottom) { + topBorder = topBorder + (wholeSize - height - cfg.vGap); + } + } + return new Rect(leftBorder, topBorder, width, height); + case DockPosition.top: + case DockPosition.bottom: + [height, topBorder] = DockEntry.alignEdge(height, topBorder, cfg.hEdgeGap, position, cfg.hEdgeAlignment); + if (2 * cfg.hGap < width) { + if (wholeSize - width < 2 * cfg.hGap) { + leftBorder = leftBorder + cfg.hGap; + width = width - 2 * cfg.hGap; + } + else if (cfg.hAlignment === HDockAlignment.left) { + leftBorder = leftBorder + cfg.hGap; + } + else if (cfg.hAlignment === HDockAlignment.center) { + leftBorder = leftBorder + (wholeSize - width) / 2; + } + else if (cfg.hAlignment === HDockAlignment.right) { + leftBorder = leftBorder + (wholeSize - width - cfg.hGap); + } + } + return new Rect(leftBorder, topBorder, width, height); + } + } + static alignEdge(dimension, sideBorder, gap, position, alignment) { + if (2 * gap > dimension) + return [dimension, sideBorder]; + switch (alignment) { + case EdgeAlignment.outside: + if (position === DockPosition.right || position === DockPosition.bottom) + sideBorder = sideBorder + gap; + return [dimension - gap, sideBorder]; + case EdgeAlignment.middle: + return [dimension - 2 * gap, sideBorder + gap]; + case EdgeAlignment.inside: + if (position === DockPosition.left || position === DockPosition.top) + sideBorder = sideBorder + gap; + return [dimension - gap, sideBorder]; + } + } + getSlot(position) { + let slot = this.slots.find((slot) => slot.position === position) || null; + if (slot === null || slot.window === null) { + return null; + } + else if (slot.window.state !== WindowState.Docked || + slot.window.dock.position !== position) { + slot.window = null; + return null; + } + else { + return slot; + } + } + getSlotByPosition(position) { + return this.slots.find((slot) => slot.position === position) || null; + } + getSlotByWindow(window) { + let slot = this.slots.find((slot) => slot.window === window) || null; + if (slot === null || slot.window === null) { + return null; + } + else if (slot.window.state !== WindowState.Docked) { + slot.window = null; + return null; + } + else { + return slot; + } + } + arrangeSlots(dockedWindows) { + let contenders = []; + for (const slot of this.slots) { + if (dockedWindows.length === 0 && contenders.length === 0) { + slot.window = null; + continue; + } + let tempDockedWindows = []; + contenders.push(...dockedWindows.filter((w) => { + if (w.dock === null) { + w.dock = new Dock(this.surfaceCfg.cfg); + return true; + } + if (w.dock.position === slot.position) { + return true; + } + if (w.dock.position === null) + return true; + tempDockedWindows.push(w); + })); + dockedWindows = tempDockedWindows; + if (contenders.length !== 0) { + this.contendersSort(contenders, slot.position, this.id); + slot.window = contenders.pop(); + slot.window.dock.position = slot.position; + } + else { + slot.window = null; + } + } + contenders.forEach((w) => { + w.state = WindowState.Tiled; + }); + } + assignSizes(workingArea) { + const MAX_SIZE = 50; + const MIN_SIZE = 5; + const MAX_V_GAPS = workingArea.width * 0.05; + const MAX_H_GAPS = workingArea.height * 0.05; + let oppositeSlot = null; + let donePositions = []; + let dockCfg; + let oppositeDockCfg; + for (const slot of this.slots) { + if (slot.window === null) + continue; + dockCfg = slot.window.dock.cfg; + if (donePositions.indexOf(slot.position) >= 0) + continue; + switch (slot.position) { + case DockPosition.top: + oppositeSlot = this.getSlot(DockPosition.bottom); + break; + case DockPosition.bottom: + oppositeSlot = this.getSlot(DockPosition.top); + break; + case DockPosition.left: + oppositeSlot = this.getSlot(DockPosition.right); + break; + case DockPosition.right: + oppositeSlot = this.getSlot(DockPosition.left); + break; + default: + warning("DockEntry assignSizes - invalid position"); + break; + } + switch (slot.position) { + case DockPosition.left: + case DockPosition.right: + if (dockCfg.vWide < MIN_SIZE) + dockCfg.vWide = MIN_SIZE; + if (dockCfg.vGap > MAX_V_GAPS) + dockCfg.vGap = MAX_V_GAPS; + if (oppositeSlot !== null) { + oppositeDockCfg = oppositeSlot.window.dock.cfg; + if (oppositeDockCfg.vWide < MIN_SIZE) + oppositeDockCfg.vWide = MIN_SIZE; + if (oppositeDockCfg.vGap > MAX_V_GAPS) + oppositeDockCfg.vGap = MAX_V_GAPS; + if (dockCfg.vWide + oppositeDockCfg.vWide > MAX_SIZE) { + if (dockCfg.vWide > MAX_SIZE / 2 && + oppositeDockCfg.vWide > MAX_SIZE / 2) { + dockCfg.vWide = MAX_SIZE / 2; + oppositeDockCfg.vWide = MAX_SIZE / 2; + } + else if (dockCfg.vWide > MAX_SIZE / 2) { + dockCfg.vWide = MAX_SIZE - oppositeDockCfg.vWide; + } + else { + oppositeDockCfg.vWide = MAX_SIZE - dockCfg.vWide; + } + } + if (oppositeDockCfg.vHeight > 100) + oppositeDockCfg.vHeight = 100; + if (oppositeDockCfg.vHeight < MIN_SIZE) + oppositeDockCfg.vHeight = MIN_SIZE; + donePositions.push(oppositeSlot.position); + } + else { + if (dockCfg.vWide > MAX_SIZE) { + dockCfg.vWide = MAX_SIZE; + } + } + if (dockCfg.vHeight > 100) + dockCfg.vHeight = 100; + if (dockCfg.vHeight < MIN_SIZE) + dockCfg.vHeight = MIN_SIZE; + break; + case DockPosition.top: + case DockPosition.bottom: + if (dockCfg.hWide < MIN_SIZE) + dockCfg.hWide = MIN_SIZE; + if (dockCfg.hGap > MAX_H_GAPS) + dockCfg.hGap = MAX_H_GAPS; + if (oppositeSlot !== null) { + oppositeDockCfg = oppositeSlot.window.dock.cfg; + if (oppositeDockCfg.hHeight < MIN_SIZE) + oppositeDockCfg.hHeight = MIN_SIZE; + if (oppositeDockCfg.hGap > MAX_H_GAPS) + oppositeDockCfg.hGap = MAX_H_GAPS; + if (dockCfg.hHeight + oppositeDockCfg.hHeight > MAX_SIZE) { + if (dockCfg.hHeight > MAX_SIZE / 2 && + oppositeDockCfg.hHeight > MAX_SIZE / 2) { + dockCfg.hHeight = MAX_SIZE / 2; + oppositeDockCfg.hHeight = MAX_SIZE / 2; + } + else if (dockCfg.hHeight > MAX_SIZE / 2) { + dockCfg.hHeight = MAX_SIZE - oppositeDockCfg.hHeight; + } + else { + oppositeDockCfg.hHeight = MAX_SIZE - dockCfg.hHeight; + } + } + if (oppositeDockCfg.hWide > 100) + oppositeDockCfg.hWide = 100; + if (oppositeDockCfg.hWide < 5) + oppositeDockCfg.hWide = 5; + donePositions.push(oppositeSlot.position); + } + else { + if (dockCfg.hHeight > MAX_SIZE) { + dockCfg.hHeight = MAX_SIZE; + } + } + if (dockCfg.hWide > 100) + dockCfg.hWide = 100; + if (dockCfg.hWide < MIN_SIZE) + dockCfg.hWide = MIN_SIZE; + break; + } + } + } + contendersSort(contenders, position, id) { + function compare(a, b) { + if (a.dock === null && b.dock === null) + return 0; + else if (a.dock === null) + return -1; + else if (b.dock === null) + return 1; + else if (a.dock.position === position && b.dock.position !== position) + return 1; + else if (b.dock.position === position && a.dock.position !== position) + return -1; + else if (a.dock.priority > b.dock.priority) + return 1; + else if (b.dock.priority > a.dock.priority) + return -1; + else if (a.dock.renderedTime === null && b.dock.renderedTime === null) + return 0; + else if (a.dock.renderedTime === null) + return -1; + else if (b.dock.renderedTime === null) + return 1; + else if (a.dock.renderedOutputId === id && b.dock.renderedOutputId !== id) + return 1; + else if (b.dock.renderedOutputId === id && a.dock.renderedOutputId !== id) + return -1; + else if (a.dock.renderedTime > b.dock.renderedTime) + return 1; + else if (b.dock.renderedTime > a.dock.renderedTime) + return -1; + else + return 0; + } + contenders.sort(compare); + } + parseSlots() { + const slots = []; + if (CONFIG.dockOrder[0] !== 0) + slots.push(new DockSlot(DockPosition.left, CONFIG.dockOrder[0])); + if (CONFIG.dockOrder[1] !== 0) + slots.push(new DockSlot(DockPosition.top, CONFIG.dockOrder[1])); + if (CONFIG.dockOrder[2] !== 0) + slots.push(new DockSlot(DockPosition.right, CONFIG.dockOrder[2])); + if (CONFIG.dockOrder[3] !== 0) + slots.push(new DockSlot(DockPosition.bottom, CONFIG.dockOrder[3])); + slots.sort((a, b) => a.order - b.order); + return slots; + } +} +function parseDockUserSurfacesCfg() { + let surfacesCfg = []; + if (CONFIG.dockSurfacesConfig.length === 0) + return surfacesCfg; + CONFIG.dockSurfacesConfig.forEach((cfg) => { + let surfaceCfgString = cfg.split(":").map((part) => part.trim()); + if (surfaceCfgString.length !== 4) { + warning(`Invalid User surface config: ${cfg}, config must have three colons`); + return; + } + let splittedUserCfg = surfaceCfgString[3] + .split(",") + .map((part) => part.trim().toLowerCase()); + let partialDockCfg = parseSplittedUserCfg(splittedUserCfg); + if (partialDockCfg instanceof Err) { + warning(`Invalid User surface config: ${cfg}. ${partialDockCfg}`); + return; + } + if (Object.keys(partialDockCfg).length > 0) { + surfacesCfg.push(new dockSurfaceCfg(surfaceCfgString[0], surfaceCfgString[1], surfaceCfgString[2], DefaultDockCfg.instance.cloneAndUpdate(partialDockCfg))); + } + }); + return surfacesCfg; +} +function parseDockUserWindowClassesCfg() { + let userWindowClassesCfg = {}; + if (CONFIG.dockWindowClassConfig.length === 0) + return userWindowClassesCfg; + CONFIG.dockWindowClassConfig.forEach((cfg) => { + let windowCfgString = cfg.split(":").map((part) => part.trim()); + if (windowCfgString.length !== 3) { + warning(`Invalid window class config: "${cfg}" should have two colons`); + return; + } + let splittedUserCfg = windowCfgString[2] + .split(",") + .map((part) => part.trim().toLowerCase()); + let partialDockCfg = parseSplittedUserCfg(splittedUserCfg); + if (partialDockCfg instanceof Err) { + warning(`Invalid User window class config: ${cfg}. ${partialDockCfg}`); + return; + } + let splittedSpecialFlags = windowCfgString[1] + .split(",") + .map((part) => part.trim().toLowerCase()); + let dock = parseSpecialFlags(splittedSpecialFlags, partialDockCfg); + if (dock instanceof Err) { + warning(`Invalid User window class config: ${cfg}. ${dock}`); + return; + } + userWindowClassesCfg[windowCfgString[0]] = dock; + }); + return userWindowClassesCfg; +} +function parseSpecialFlags(splittedSpecialFlags, partialDockCfg) { + let dock = new Dock(DefaultDockCfg.instance.cloneAndUpdate(partialDockCfg)); + splittedSpecialFlags.forEach((flag) => { + switch (flag) { + case "pin": + case "p": + dock.priority = 5; + break; + case "left": + case "l": + dock.position = DockPosition.left; + break; + case "right": + case "r": + dock.position = DockPosition.right; + break; + case "top": + case "t": + dock.position = DockPosition.top; + break; + case "bottom": + case "b": + dock.position = DockPosition.bottom; + break; + default: + warning(`parse Special Flags: ${splittedSpecialFlags}.Unknown special flag: ${flag}`); + } + }); + return dock; +} +function parseSplittedUserCfg(splittedUserCfg) { + let errors = []; + const shortNames = { + hh: "hHeight", + hw: "hWide", + hgv: "hEdgeGap", + hgh: "hGap", + ha: "hAlignment", + he: "hEdgeAlignment", + vh: "vHeight", + vw: "vWide", + vgh: "vEdgeGap", + vgv: "vGap", + ve: "vEdgeAlignment", + va: "vAlignment", + }; + let dockCfg = {}; + splittedUserCfg.forEach((part) => { + let splittedPart = part.split("=").map((part) => part.trim()); + if (splittedPart.length !== 2) { + errors.push(`"${part}" can have only one equal sign`); + return; + } + if (splittedPart[0].length === 0 || splittedPart[1].length === 0) { + errors.push(`"${part}" can not have empty shortname or value`); + return; + } + if (shortNames[splittedPart[0]] in dockCfg) { + errors.push(`"${part}" has duplicate shortname`); + return; + } + if (!(splittedPart[0] in shortNames)) { + errors.push(`"${part}" has unknown shortname`); + return; + } + if (["he", "ve"].indexOf(splittedPart[0]) >= 0) { + switch (splittedPart[1]) { + case "outside": + case "o": + case "0": + dockCfg[shortNames[splittedPart[0]]] = EdgeAlignment.outside; + break; + case "middle": + case "m": + case "1": + dockCfg[shortNames[splittedPart[0]]] = EdgeAlignment.middle; + break; + case "inside": + case "i": + case "2": + dockCfg[shortNames[splittedPart[0]]] = EdgeAlignment.inside; + break; + default: + errors.push(` "${part}" value can be o,m or i or output,middle,input or 0,1,2`); + return; + } + } + else if (splittedPart[0] === "va") { + switch (splittedPart[1]) { + case "center": + case "c": + case "0": + dockCfg[shortNames[splittedPart[0]]] = VDockAlignment.center; + break; + case "1": + case "top": + case "t": + dockCfg[shortNames[splittedPart[0]]] = VDockAlignment.top; + break; + case "2": + case "bottom": + case "b": + dockCfg[shortNames[splittedPart[0]]] = VDockAlignment.bottom; + break; + default: + errors.push(` "${part}" value can be c,t or b or center,top,bottom or 0,1,2`); + return; + } + } + else if (splittedPart[0] === "ha") { + switch (splittedPart[1]) { + case "center": + case "c": + case "0": + dockCfg[shortNames[splittedPart[0]]] = HDockAlignment.center; + break; + case "1": + case "left": + case "l": + dockCfg[shortNames[splittedPart[0]]] = HDockAlignment.left; + break; + case "2": + case "right": + case "r": + dockCfg[shortNames[splittedPart[0]]] = HDockAlignment.right; + break; + default: + errors.push(`"${part}" value can be c,l or r or center,left,right or 0,1,2`); + return; + } + } + else { + let value; + switch (splittedPart[0]) { + case "hw": + case "vh": + value = validateNumber(splittedPart[1], 1, 100); + break; + case "hh": + case "vw": + value = validateNumber(splittedPart[1], 1, 50); + break; + case "hgh": + case "vgv": + case "vgh": + case "vgv": + value = validateNumber(splittedPart[1]); + break; + default: + errors.push(`unknown shortname ${splittedPart[0]}`); + return; + } + if (value instanceof Err) + errors.push(`splittedPart[0]: ${value}`); + else + dockCfg[shortNames[splittedPart[0]]] = value; + } + }); + if (errors.length > 0) { + return new Err(errors.join("\n")); + } + return dockCfg; +} +class DockSlot { + get position() { + return this._position; + } + get order() { + return this._order; + } + constructor(position, order) { + this._position = position; + this._order = order; + this.window = null; + } +} +class DockStore { + constructor() { + this.store = {}; + this.defaultCfg = null; + this.surfacesCfg = []; + this.windowClassesCfg = {}; + } + render(srf, visibles, workingArea) { + if (this.defaultCfg === null) { + this.defaultCfg = DefaultDockCfg.instance; + this.surfacesCfg = parseDockUserSurfacesCfg(); + this.windowClassesCfg = parseDockUserWindowClassesCfg(); + } + if (!this.store[srf.id]) { + this.store[srf.id] = new DockEntry(this.getSurfaceCfg(srf), srf.id); + } + let dockedWindows = visibles.filter((w) => { + if (w.state === WindowState.Docked) { + if (w.dock === null && w.windowClassName in this.windowClassesCfg) { + w.dock = this.windowClassesCfg[w.windowClassName].clone(); + } + return true; + } + }); + if (dockedWindows.length === 0) + return workingArea; + return this.store[srf.id].arrange(dockedWindows, workingArea); + } + remove(window) { + for (let key in this.store) { + this.store[key].remove(window); + } + } + handleShortcut(ctx, window, shortcut) { + switch (shortcut) { + case Shortcut.SwapLeft: + case Shortcut.SwapUp: + case Shortcut.SwapRight: + case Shortcut.SwapDown: + const srf = ctx.currentSurface; + if (this.store[srf.id]) { + return this.store[srf.id].handleShortcut(window, shortcut); + } + return false; + default: + return false; + } + } + getSurfaceCfg(srf) { + let dockCfg = null; + for (let surfaceCfg of this.surfacesCfg) { + if (surfaceCfg.isFit(srf)) { + dockCfg = Object.assign({}, surfaceCfg.cfg); + break; + } + } + if (dockCfg === null) + dockCfg = this.defaultCfg.cloneAndUpdate({}); + let [outputName, activityId, vDesktopName] = srf.getParams(); + return new dockSurfaceCfg(outputName, activityId, vDesktopName, dockCfg); + } +} class KWinConfig { constructor() { function commaSeparate(str) { @@ -45,6 +984,14 @@ class KWinConfig { .map((part) => part.trim()) .filter((part) => part != ""); } + function newLineSeparate(str) { + if (!str || typeof str !== "string") + return []; + return str + .split("\n") + .map((part) => part.trim()) + .filter((part) => part != ""); + } DEBUG.enabled = DEBUG.enabled || KWIN.readConfig("debug", false); this.layoutOrder = []; this.layoutFactories = {}; @@ -66,13 +1013,37 @@ class KWinConfig { this.layoutOrder.push(layoutClass.id); this.layoutFactories[layoutClass.id] = () => new layoutClass(); }); - this.maximizeSoleTile = KWIN.readConfig("maximizeSoleTile", false); + this.dockOrder = [ + KWIN.readConfig("dockOrderLeft", 1), + KWIN.readConfig("dockOrderTop", 2), + KWIN.readConfig("dockOrderRight", 3), + KWIN.readConfig("dockOrderBottom", 4), + ]; + this.dockHHeight = KWIN.readConfig("dockHHeight", 15); + this.dockHWide = KWIN.readConfig("dockHWide", 100); + this.dockHGap = KWIN.readConfig("dockHGap", 0); + this.dockHEdgeGap = KWIN.readConfig("dockHEdgeGap", 0); + this.dockHAlignment = KWIN.readConfig("dockHAlignment", 0); + this.dockHEdgeAlignment = KWIN.readConfig("dockHEdgeAlignment", 0); + this.dockVHeight = KWIN.readConfig("dockVHeight", 100); + this.dockVWide = KWIN.readConfig("dockVWide", 15); + this.dockVEdgeGap = KWIN.readConfig("dockVEdgeGap", 0); + this.dockVGap = KWIN.readConfig("dockVGap", 0); + this.dockVAlignment = KWIN.readConfig("dockVAlignment", 0); + this.dockVEdgeAlignment = KWIN.readConfig("dockVEdgeAlignment", 0); + this.dockSurfacesConfig = newLineSeparate(KWIN.readConfig("dockSurfacesConfig", "")); + this.dockWindowClassConfig = newLineSeparate(KWIN.readConfig("dockWindowClassConfig", "")); + this.soleWindowWidth = KWIN.readConfig("soleWindowWidth", 100); + this.soleWindowHeight = KWIN.readConfig("soleWindowHeight", 100); + this.soleWindowNoBorders = KWIN.readConfig("soleWindowNoBorders", false); + this.soleWindowNoGaps = KWIN.readConfig("soleWindowNoGaps", false); this.tileLayoutInitialAngle = KWIN.readConfig("tileLayoutInitialRotationAngle", "0"); this.columnsLayoutInitialAngle = KWIN.readConfig("columnsLayoutInitialRotationAngle", "0"); this.columnsBalanced = KWIN.readConfig("columnsBalanced", false); this.columnsLayerConf = commaSeparate(KWIN.readConfig("columnsLayerConf", "")); this.tiledWindowsLayer = getWindowLayer(KWIN.readConfig("tiledWindowsLayer", 0)); this.floatedWindowsLayer = getWindowLayer(KWIN.readConfig("floatedWindowsLayer", 1)); + this.quarterLayoutReset = KWIN.readConfig("quarterLayoutReset", false); this.monocleMaximize = KWIN.readConfig("monocleMaximize", true); this.monocleMinimizeRest = KWIN.readConfig("monocleMinimizeRest", false); this.stairReverse = KWIN.readConfig("stairReverse", false); @@ -97,11 +1068,12 @@ class KWinConfig { this.floatUtility = KWIN.readConfig("floatUtility", true); this.preventMinimize = KWIN.readConfig("preventMinimize", false); this.preventProtrusion = KWIN.readConfig("preventProtrusion", true); + this.notificationDuration = KWIN.readConfig("notificationDuration", 1000); this.pollMouseXdotool = KWIN.readConfig("pollMouseXdotool", false); this.floatingClass = commaSeparate(KWIN.readConfig("floatingClass", "")); this.floatingTitle = commaSeparate(KWIN.readConfig("floatingTitle", "")); this.ignoreActivity = commaSeparate(KWIN.readConfig("ignoreActivity", "")); - this.ignoreClass = commaSeparate(KWIN.readConfig("ignoreClass", "krunner,yakuake,spectacle,kded5,xwaylandvideobridge,plasmashell,ksplashqml")); + this.ignoreClass = commaSeparate(KWIN.readConfig("ignoreClass", "krunner,yakuake,spectacle,kded5,xwaylandvideobridge,plasmashell,ksplashqml,org.kde.plasmashell,org.kde.polkit-kde-authentication-agent-1,org.kde.kruler,kruler,kwin_wayland,ksmserver-logout-greeter")); this.ignoreRole = commaSeparate(KWIN.readConfig("ignoreRole", "quake")); this.ignoreScreen = commaSeparate(KWIN.readConfig("ignoreScreen", "")); this.ignoreVDesktop = commaSeparate(KWIN.readConfig("ignoreVDesktop", "")); @@ -131,7 +1103,7 @@ class KWinDriver { } set currentSurface(value) { const ksrf = value; - if (this.workspace.currentDesktop.name !== ksrf.desktop.name) + if (this.workspace.currentDesktop.id !== ksrf.desktop.id) this.workspace.currentDesktop = ksrf.desktop; if (this.workspace.currentActivity !== ksrf.activity) this.workspace.currentActivity = ksrf.activity; @@ -141,8 +1113,10 @@ class KWinDriver { return client ? this.windowMap.get(client) : null; } set currentWindow(window) { - if (window !== null) + if (window !== null) { + window.timestamp = new Date().getTime(); this.workspace.activeWindow = window.window.window; + } } get screens() { const screens = []; @@ -205,7 +1179,8 @@ class KWinDriver { KWinSetTimeout(() => this.enter(func), timeout); } showNotification(text) { - popupDialog.show(text); + if (CONFIG.notificationDuration > 0) + popupDialog.show(text, CONFIG.notificationDuration); } bindShortcut() { const callbackShortcut = (shortcut) => { @@ -213,6 +1188,9 @@ class KWinDriver { this.enter(() => this.control.onShortcut(this, shortcut)); }; }; + this.shortcuts + .getToggleDock() + .activated.connect(callbackShortcut(Shortcut.ToggleDock)); this.shortcuts .getFocusNext() .activated.connect(callbackShortcut(Shortcut.FocusNext)); @@ -522,16 +1500,27 @@ function KWinSetTimeout(func, timeout) { KWinTimerPool.instance.setTimeout(func, timeout); } class KWinSurface { + static getHash(s) { + let hash = 0; + if (s.length == 0) + return `0`; + for (let i = 0; i < s.length; i++) { + let charCode = s.charCodeAt(i); + hash = (hash << 5) - hash + charCode; + hash = hash & hash; + } + return `${hash}`; + } static generateId(screenName, activity, desktopName) { let path = screenName; if (KWINCONFIG.layoutPerActivity) path += "@" + activity; if (KWINCONFIG.layoutPerDesktop) path += "#" + desktopName; - return path; + return KWinSurface.getHash(path); } constructor(output, activity, desktop, workspace) { - this.id = KWinSurface.generateId(output.name, activity, desktop.name); + this.id = KWinSurface.generateId(output.name, activity, desktop.id); this.ignore = KWINCONFIG.ignoreActivity.indexOf(activity) >= 0 || KWINCONFIG.ignoreScreen.indexOf(output.name) >= 0 || @@ -541,6 +1530,9 @@ class KWinSurface { this.activity = activity; this.desktop = desktop; } + getParams() { + return [this.output.name, this.activity, this.desktop.name]; + } next() { return null; } @@ -560,6 +1552,9 @@ class KWinWindow { get geometry() { return toRect(this.window.frameGeometry); } + get windowClassName() { + return this.window.resourceClass; + } get shouldIgnore() { if (this.window.deleted) return true; @@ -568,10 +1563,7 @@ class KWinWindow { this.isIgnoredByConfig); } get shouldFloat() { - const moreOneDesktop = this.window.desktops.length !== 1; return (this.isFloatByConfig || - moreOneDesktop || - this.window.onAllDesktops || this.window.modal || this.window.transient || !this.window.resizeable || @@ -583,13 +1575,25 @@ class KWinWindow { } get surface() { let activity; + let desktop; if (this.window.activities.length === 0) activity = this.workspace.currentActivity; else if (this.window.activities.indexOf(this.workspace.currentActivity) >= 0) activity = this.workspace.currentActivity; else activity = this.window.activities[0]; - const desktop = this.window.desktops[0]; + if (this.window.desktops.length === 1) { + desktop = this.window.desktops[0]; + } + else if (this.window.desktops.length === 0) { + desktop = this.workspace.currentDesktop; + } + else { + if (this.window.desktops.indexOf(this.workspace.currentDesktop) >= 0) + desktop = this.workspace.currentDesktop; + else + desktop = this.window.desktops[0]; + } return new KWinSurface(this.window.output, activity, desktop, this.workspace); } set surface(srf) { @@ -771,97 +1775,6 @@ function debugWin(win) { }); return s; } -class TestDriver { - constructor() { - this.currentScreen = 0; - this.currentWindow = 0; - this.numScreen = 1; - this.screenSize = new Rect(0, 0, 10000, 10000); - this.windows = []; - } - forEachScreen(func) { - for (let screen = 0; screen < this.numScreen; screen++) - func(new TestSurface(this, screen)); - } - getCurrentContext() { - const window = this.getCurrentWindow(); - if (window) - return window.surface; - return new TestSurface(this, 0); - } - getCurrentWindow() { - return this.windows.length !== 0 ? this.windows[this.currentWindow] : null; - } - getWorkingArea(srf) { - return this.screenSize; - } - setCurrentWindow(window) { - const idx = this.windows.indexOf(window); - if (idx !== -1) - this.currentWindow = idx; - } - setTimeout(func, timeout) { - setTimeout(func, timeout); - } -} -class TestSurface { - get id() { - return String(this.screen); - } - get ignore() { - return false; - } - get workingArea() { - return this.driver.screenSize; - } - constructor(driver, screen) { - this.driver = driver; - this.screen = screen; - } - next() { - return new TestSurface(this.driver, this.screen + 1); - } -} -class TestWindow { - constructor(srf, geometry, ignore, float) { - this.id = String(TestWindow.windowCount); - TestWindow.windowCount += 1; - this.shouldFloat = float !== undefined ? float : false; - this.shouldIgnore = ignore !== undefined ? ignore : false; - this.surface = srf; - this.fullScreen = false; - this.geometry = geometry || new Rect(0, 0, 100, 100); - this.keepAbove = false; - this.keepBelow = false; - this.maximized = false; - this.minimized = false; - this.noBorder = false; - } - commit(geometry, noBorder, windowLayer) { - if (geometry) - this.geometry = geometry; - if (noBorder !== undefined) - this.noBorder = noBorder; - if (windowLayer !== undefined) { - if (windowLayer === 2) - this.keepAbove = true; - else if (windowLayer === 0) - this.keepBelow = true; - } - } - focus() { - } - visible(srf) { - const tctx = srf; - return this.surface.screen === tctx.screen; - } -} -TestWindow.windowCount = 0; -function setTestConfig(name, value) { - if (!CONFIG) - CONFIG = {}; - CONFIG[name] = value; -} class TilingController { constructor(engine) { this.engine = engine; @@ -960,11 +1873,15 @@ class TilingController { } onWindowResize(ctx, window) { debugObj(() => ["onWindowResize", { window }]); - if (CONFIG.adjustLayout && CONFIG.adjustLayoutLive) { - if (window.state === WindowState.Tiled) { - this.engine.adjustLayout(window); - this.engine.arrange(ctx); - } + if (CONFIG.adjustLayout && + CONFIG.adjustLayoutLive && + window.state === WindowState.Tiled) { + this.engine.adjustLayout(window); + this.engine.arrange(ctx); + } + else if (window.state === WindowState.Docked) { + this.engine.adjustDock(window); + this.engine.arrange(ctx); } } onWindowResizeOver(ctx, window) { @@ -973,6 +1890,10 @@ class TilingController { this.engine.adjustLayout(window); this.engine.arrange(ctx); } + else if (window.state === WindowState.Docked) { + this.engine.adjustDock(window); + this.engine.arrange(ctx); + } else if (!CONFIG.adjustLayout) this.engine.enforceSize(ctx, window); } @@ -995,7 +1916,8 @@ class TilingController { window.timestamp = new Date().getTime(); } onDesktopsChanged(ctx, window) { - window.state = WindowState.Undecided; + if (window.state !== WindowState.Docked) + window.state = WindowState.Undecided; } onShortcut(ctx, input, data) { if (CONFIG.directionalKeyMode === "dwm") { @@ -1030,11 +1952,17 @@ class TilingController { break; } } - if (this.engine.handleLayoutShortcut(ctx, input, data)) { + const window = ctx.currentWindow; + if (window !== null && + window.state === WindowState.Docked && + this.engine.handleDockShortcut(ctx, window, input)) { + this.engine.arrange(ctx); + return; + } + else if (this.engine.handleLayoutShortcut(ctx, input, data)) { this.engine.arrange(ctx); return; } - const window = ctx.currentWindow; switch (input) { case Shortcut.FocusNext: this.engine.focusOrder(ctx, -1); @@ -1113,6 +2041,10 @@ class TilingController { if (typeof data === "string") this.engine.setLayout(ctx, data); break; + case Shortcut.ToggleDock: + if (window) + this.engine.toggleDock(window); + break; } this.engine.arrange(ctx); } @@ -1121,6 +2053,7 @@ class TilingEngine { constructor() { this.layouts = new LayoutStore(); this.windows = new WindowStore(); + this.docks = new DockStore(); } adjustLayout(basis) { let delta = basis.geometryDelta; @@ -1134,6 +2067,28 @@ class TilingEngine { layout.adjust(area, tiles, basis, delta); } } + adjustDock(basis) { + if (basis.actualGeometry === basis.geometry) + return; + let widthDiff = basis.actualGeometry.width - basis.geometry.width; + let heightDiff = basis.actualGeometry.height - basis.geometry.height; + let dockCfg = basis.dock.cfg; + const workingArea = basis.surface.workingArea; + switch (basis.dock.position) { + case DockPosition.left: + case DockPosition.right: + dockCfg.vHeight = + dockCfg.vHeight + (100 * heightDiff) / workingArea.height; + dockCfg.vWide = dockCfg.vWide + (100 * widthDiff) / workingArea.width; + break; + case DockPosition.top: + case DockPosition.bottom: + dockCfg.hHeight = + dockCfg.hHeight + (100 * heightDiff) / workingArea.height; + dockCfg.hWide = dockCfg.hWide + (100 * widthDiff) / workingArea.width; + break; + } + } resizeFloat(window, dir, step) { const srf = window.surface; const hStepSize = srf.workingArea.width * 0.05; @@ -1219,12 +2174,6 @@ class TilingEngine { } arrangeScreen(ctx, srf) { const layout = this.layouts.getCurrentLayout(srf); - const workingArea = srf.workingArea; - let tilingArea; - if (CONFIG.monocleMaximize && layout instanceof MonocleLayout) - tilingArea = workingArea; - else - tilingArea = workingArea.gap(CONFIG.screenGapLeft, CONFIG.screenGapRight, CONFIG.screenGapTop, CONFIG.screenGapBottom); const visibles = this.windows.getVisibleWindows(srf); debugObj(() => [ "arrangeScreen", @@ -1234,6 +2183,7 @@ class TilingEngine { visibles: visibles.length, }, ]); + const workingArea = this.docks.render(srf, visibles, srf.workingArea.clone()); visibles.forEach((window) => { if (window.state === WindowState.Undecided) { window.state = window.shouldFloat @@ -1242,11 +2192,24 @@ class TilingEngine { } }); const tileables = this.windows.getVisibleTileables(srf); - if (CONFIG.maximizeSoleTile && tileables.length === 1) { - tileables[0].state = WindowState.Maximized; - tileables[0].geometry = workingArea; + let tilingArea; + if ((CONFIG.monocleMaximize && layout instanceof MonocleLayout) || + (tileables.length === 1 && CONFIG.soleWindowNoGaps)) + tilingArea = workingArea; + else if (tileables.length === 1 && + ((CONFIG.soleWindowWidth < 100 && CONFIG.soleWindowWidth > 0) || + (CONFIG.soleWindowHeight < 100 && CONFIG.soleWindowHeight > 0))) { + const h_gap = (workingArea.height - + workingArea.height * (CONFIG.soleWindowHeight / 100)) / + 2; + const v_gap = (workingArea.width - + workingArea.width * (CONFIG.soleWindowWidth / 100)) / + 2; + tilingArea = workingArea.gap(v_gap, v_gap, h_gap, h_gap); } - else if (tileables.length > 0) + else + tilingArea = workingArea.gap(CONFIG.screenGapLeft, CONFIG.screenGapRight, CONFIG.screenGapTop, CONFIG.screenGapBottom); + if (tileables.length > 0) layout.apply(new EngineContext(ctx, this), tileables, tilingArea); if (CONFIG.limitTileWidthRatio > 0 && !(layout instanceof MonocleLayout)) { const maxWidth = Math.floor(workingArea.height * CONFIG.limitTileWidthRatio); @@ -1257,7 +2220,14 @@ class TilingEngine { tile.geometry = new Rect(g.x + Math.floor((g.width - maxWidth) / 2), g.y, maxWidth, g.height); }); } - visibles.forEach((window) => window.commit()); + if (CONFIG.soleWindowNoBorders && + visibles.length === 1 && + visibles[0].state !== WindowState.Docked) { + visibles[0].commit(CONFIG.soleWindowNoBorders); + } + else { + visibles.forEach((window) => window.commit()); + } debugObj(() => ["arrangeScreen/finished", { srf }]); } enforceSize(ctx, window) { @@ -1280,6 +2250,9 @@ class TilingEngine { } } unmanage(window) { + if (window.state === WindowState.Docked) { + this.docks.remove(window); + } this.windows.remove(window); } focusOrder(ctx, step) { @@ -1370,6 +2343,12 @@ class TilingEngine { else if (WindowClass.isTiledState(state)) this.swapDirection(ctx, dir); } + toggleDock(window) { + window.state = + window.state !== WindowState.Docked + ? WindowState.Docked + : WindowState.Tiled; + } toggleFloat(window) { window.state = !window.tileable ? WindowState.Tiled : WindowState.Floating; } @@ -1411,6 +2390,9 @@ class TilingEngine { return layout.handleShortcut(new EngineContext(ctx, this), input, data); return false; } + handleDockShortcut(ctx, window, input) { + return this.docks.handleShortcut(ctx, window, input); + } getNeighborByDirection(ctx, basis, dir) { let vertical; let sign; @@ -1464,8 +2446,9 @@ class EngineContext { set currentWindow(window) { this.drvctx.currentWindow = window; } - get currentSurfaceId() { - return this.drvctx.currentSurface.id; + get surfaceParams() { + let srf = this.drvctx.currentSurface; + return srf.output.name, srf.activity, srf.desktop.name; } constructor(drvctx, engine) { this.drvctx = drvctx; @@ -1590,31 +2573,30 @@ class LayoutStore { getCurrentLayout(srf) { return srf.ignore ? FloatingLayout.instance - : this.getEntry(srf.id).currentLayout; + : this.getEntry(srf).currentLayout; } cycleLayout(srf, step) { if (srf.ignore) return null; - return this.getEntry(srf.id).cycleLayout(step); + return this.getEntry(srf).cycleLayout(step); } setLayout(srf, layoutClassID) { if (srf.ignore) return null; - return this.getEntry(srf.id).setLayout(layoutClassID); + return this.getEntry(srf).setLayout(layoutClassID); } - getEntry(key) { - if (!this.store[key]) { - let [output_name, activity, desktop_name] = surfaceIdParse(key); - let key_without_activity = output_name + "@#" + desktop_name; + getEntry(srf) { + if (!this.store[srf.id]) { + let key_without_activity = KWinSurface.generateId(srf.output.name, "", srf.desktop.id); if (this.store[key_without_activity]) { - this.store[key] = this.store[key_without_activity]; + this.store[srf.id] = this.store[key_without_activity]; delete this.store[key_without_activity]; } else { - this.store[key] = new LayoutStoreEntry(output_name, desktop_name, activity); + this.store[srf.id] = new LayoutStoreEntry(srf.output.name, srf.desktop.name, srf.activity); } } - return this.store[key]; + return this.store[srf.id]; } } var WindowState; @@ -1628,6 +2610,7 @@ var WindowState; WindowState[WindowState["TiledAfloat"] = 6] = "TiledAfloat"; WindowState[WindowState["Undecided"] = 7] = "Undecided"; WindowState[WindowState["Dragging"] = 8] = "Dragging"; + WindowState[WindowState["Docked"] = 9] = "Docked"; })(WindowState || (WindowState = {})); class WindowClass { static isTileableState(state) { @@ -1709,6 +2692,9 @@ class WindowClass { const srfID = this.window.surface.id; this.weightMap[srfID] = value; } + get windowClassName() { + return this.window.windowClassName; + } constructor(window) { this.id = window.id; this.window = window; @@ -1718,8 +2704,10 @@ class WindowClass { this.internalState = WindowState.Unmanaged; this.shouldCommitFloat = this.shouldFloat; this.weightMap = {}; + this.isDocked = false; + this.dock = null; } - commit() { + commit(noBorders) { const state = this.state; debugObj(() => ["Window#commit", { state: WindowState[state] }]); switch (state) { @@ -1741,7 +2729,7 @@ class WindowClass { this.window.commit(this.geometry, true, 1); break; case WindowState.Tiled: - this.window.commit(this.geometry, CONFIG.noTileBorder, CONFIG.tiledWindowsLayer); + this.window.commit(this.geometry, CONFIG.noTileBorder || Boolean(noBorders), CONFIG.tiledWindowsLayer); break; case WindowState.TiledAfloat: if (!this.shouldCommitFloat) @@ -1749,6 +2737,12 @@ class WindowClass { this.window.commit(this.floatGeometry, false, CONFIG.floatedWindowsLayer); this.shouldCommitFloat = false; break; + case WindowState.Floating: + this.window.commit(this.geometry, CONFIG.noTileBorder || Boolean(noBorders), CONFIG.floatedWindowsLayer); + break; + case WindowState.Docked: + this.window.commit(this.geometry, CONFIG.noTileBorder, CONFIG.tiledWindowsLayer); + break; } } forceSetGeometry(geometry) { @@ -2539,7 +3533,7 @@ class ColumnsLayout { } getDefaultConfig(ctx) { let returnValue = []; - let [outputName, activityId, vDesktopName] = surfaceIdParse(ctx.currentSurfaceId); + let [outputName, activityId, vDesktopName] = ctx.surfaceParams; for (let conf of CONFIG.columnsLayerConf) { if (!conf || typeof conf !== "string") continue; @@ -2914,6 +3908,12 @@ class QuarterLayout { this.lhsplit = 0.5; this.rhsplit = 0.5; this.vsplit = 0.5; + this.prevTileCount = 0; + } + resetSplits() { + this.lhsplit = 0.5; + this.rhsplit = 0.5; + this.vsplit = 0.5; } adjust(area, tiles, basis, delta) { if (tiles.length <= 1 || tiles.length > 4) @@ -2922,26 +3922,20 @@ class QuarterLayout { if (idx < 0) return; if ((idx === 0 || idx === 3) && delta.east !== 0) - this.vsplit = - (Math.floor(area.width * this.vsplit) + delta.east) / area.width; + this.vsplit = (area.width * this.vsplit + delta.east) / area.width; else if ((idx === 1 || idx === 2) && delta.west !== 0) - this.vsplit = - (Math.floor(area.width * this.vsplit) - delta.west) / area.width; + this.vsplit = (area.width * this.vsplit - delta.west) / area.width; if (tiles.length === 4) { if (idx === 0 && delta.south !== 0) - this.lhsplit = - (Math.floor(area.height * this.lhsplit) + delta.south) / area.height; + this.lhsplit = (area.height * this.lhsplit + delta.south) / area.height; if (idx === 3 && delta.north !== 0) - this.lhsplit = - (Math.floor(area.height * this.lhsplit) - delta.north) / area.height; + this.lhsplit = (area.height * this.lhsplit - delta.north) / area.height; } if (tiles.length >= 3) { if (idx === 1 && delta.south !== 0) - this.rhsplit = - (Math.floor(area.height * this.rhsplit) + delta.south) / area.height; + this.rhsplit = (area.height * this.rhsplit + delta.south) / area.height; if (idx === 2 && delta.north !== 0) - this.rhsplit = - (Math.floor(area.height * this.rhsplit) - delta.north) / area.height; + this.rhsplit = (area.height * this.rhsplit - delta.north) / area.height; } this.vsplit = clip(this.vsplit, 1 - QuarterLayout.MAX_PROPORTION, QuarterLayout.MAX_PROPORTION); this.lhsplit = clip(this.lhsplit, 1 - QuarterLayout.MAX_PROPORTION, QuarterLayout.MAX_PROPORTION); @@ -2952,9 +3946,16 @@ class QuarterLayout { other.lhsplit = this.lhsplit; other.rhsplit = this.rhsplit; other.vsplit = this.vsplit; + other.prevTileCount = this.prevTileCount; return other; } apply(ctx, tileables, area) { + if (CONFIG.quarterLayoutReset) { + if (tileables.length < this.prevTileCount) { + this.resetSplits(); + } + this.prevTileCount = tileables.length; + } for (let i = 0; i < 4 && i < tileables.length; i++) tileables[i].state = WindowState.Tiled; if (tileables.length > 4) @@ -2965,9 +3966,9 @@ class QuarterLayout { tileables[0].geometry = area; return; } - const gap1 = Math.floor(CONFIG.tileLayoutGap / 2); + const gap1 = CONFIG.tileLayoutGap / 2; const gap2 = CONFIG.tileLayoutGap - gap1; - const leftWidth = Math.floor(area.width * this.vsplit); + const leftWidth = area.width * this.vsplit; const rightWidth = area.width - leftWidth; const rightX = area.x + leftWidth; if (tileables.length === 2) { @@ -2975,7 +3976,7 @@ class QuarterLayout { tileables[1].geometry = new Rect(rightX, area.y, rightWidth, area.height).gap(gap2, 0, 0, 0); return; } - const rightTopHeight = Math.floor(area.height * this.rhsplit); + const rightTopHeight = area.height * this.rhsplit; const rightBottomHeight = area.height - rightTopHeight; const rightBottomY = area.y + rightTopHeight; if (tileables.length === 3) { @@ -2984,7 +3985,7 @@ class QuarterLayout { tileables[2].geometry = new Rect(rightX, rightBottomY, rightWidth, rightBottomHeight).gap(gap2, 0, gap2, 0); return; } - const leftTopHeight = Math.floor(area.height * this.lhsplit); + const leftTopHeight = area.height * this.lhsplit; const leftBottomHeight = area.height - leftTopHeight; const leftBottomY = area.y + leftTopHeight; if (tileables.length >= 4) { @@ -3392,6 +4393,14 @@ function debugObj(f) { console.log("[" + timestamp + "]", name + ": " + buf.join(" ")); } } +class Err { + constructor(s) { + this.error = s; + } + toString() { + return `${this.error}`; + } +} function warning(s) { print(`Krohnkite warn: ${s}`); } @@ -3584,6 +4593,41 @@ class RectDelta { ")"); } } +function isNumeric(s) { + if (typeof s != "string") + return false; + return !isNaN(s) && !isNaN(parseFloat(s)); +} +function parseNumber(value, float = false) { + if (!isNumeric(value)) { + return new Err("Invalid number"); + } + if (float) { + return parseFloat(value); + } + else { + return parseInt(value); + } +} +function validateNumber(value, from, to, float = false) { + let num; + if (typeof value === "number") { + num = value; + } + else { + num = parseNumber(value, float); + if (num instanceof Err) { + return num; + } + } + if (from !== undefined && num < from) { + return new Err(`Number must be greater than or equal to ${from}`); + } + else if (to !== undefined && num > to) { + return new Err(`Number must be less than or equal to ${to}`); + } + return num; +} class windRose { constructor(direction) { switch (direction) { diff --git a/roles/config/files/.local/share/kwin/scripts/krohnkite/contents/config/main.xml b/roles/config/files/.local/share/kwin/scripts/krohnkite/contents/config/main.xml index dc5a30790..72079622a 100644 --- a/roles/config/files/.local/share/kwin/scripts/krohnkite/contents/config/main.xml +++ b/roles/config/files/.local/share/kwin/scripts/krohnkite/contents/config/main.xml @@ -6,6 +6,96 @@ <kcfgfile name=""/> <group name=""> + <entry name="dockOrderLeft" type="Int"> + <label>The order of the docked window in the dock</label> + <default>1</default> + </entry> + + <entry name="dockOrderTop" type="Int"> + <label>The order of the docked window in the dock</label> + <default>2</default> + </entry> + + <entry name="dockOrderRight" type="Int"> + <label>The order of the docked window in the dock</label> + <default>3</default> + </entry> + + <entry name="dockOrderBottom" type="Int"> + <label>The order of the docked window in the dock</label> + <default>4</default> + </entry> + + <entry name="dockHHeight" type="Int"> + <label>The default height of a horizontal docked window in percent</label> + <default>15</default> + </entry> + + <entry name="dockHWide" type="Int"> + <label>The default width of a horizontal docked window in percent</label> + <default>100</default> + </entry> + + <entry name="dockHGap" type="Int"> + <label>The default Gap of a horizontal docked window in pixels</label> + <default>0</default> + </entry> + + <entry name="dockHEdgeGap" type="Int"> + <label>The default Vertical Gap of a horizontal docked window in pixels</label> + <default>0</default> + </entry> + + <entry name="dockHAlignment" type="Int"> + <label>The default Alignment of a horizontal docked window which can be Center , Left, Right</label> + <default>0</default> + </entry> + + <entry name="dockHEdgeAlignment" type="Int"> + <label>The default vertical Alignment of a horizontal docked window which can be Edge Screen, Middle, Center Screen</label> + <default>0</default> + </entry> + + <entry name="dockVHeight" type="Int"> + <label>The default height of a vertical docked window in percent</label> + <default>100</default> + </entry> + + <entry name="dockVWide" type="Int"> + <label>The default width of a vertical docked window in percent</label> + <default>15</default> + </entry> + + <entry name="dockVEdgeGap" type="Int"> + <label>The default horizontal Gap of a vertical docked window in pixels</label> + <default>0</default> + </entry> + + <entry name="dockVGap" type="Int"> + <label>The default Gap of a vertical docked window in pixels</label> + <default>0</default> + </entry> + + <entry name="dockVEdgeAlignment" type="Int"> + <label>The default horizontal Alignment of a vertical docked window which can be Edge Screen, Middle or Center Screen</label> + <default>0</default> + </entry> + + <entry name="dockVAlignment" type="Int"> + <label>The default vertical Alignment of a vertical docked window which can be Center, Top, Bottom</label> + <default>0</default> + </entry> + + <entry name="dockSurfacesConfig" type="String"> + <label>Dock settings change the default parameters for the surface</label> + <default></default> + </entry> + + <entry name="dockWindowClassConfig" type="String"> + <label>Dock default settings for WindowClass which with high priority.</label> + <default></default> + </entry> + <entry name="debug" type="Bool"> <label>Print debug messages</label> <default>false</default> @@ -60,6 +150,11 @@ <default>false</default> </entry> + <entry name="quarterLayoutReset" type="Bool"> + <label>Reset Quarter layout after closing a window</label> + <default>false</default> + </entry> + <entry name="enableColumnsLayout" type="Bool"> <label>Enable/disable Columns layout</label> <default>true</default> @@ -102,7 +197,7 @@ <entry name="ignoreClass" type="String"> <label>Ignore windows with certain classes(comma-separated list)</label> - <default>krunner,yakuake,spectacle,kded5,xwaylandvideobridge,plasmashell,ksplashqml,org.kde.plasmashell,org.kde.polkit-kde-authentication-agent-1,org.kde.kruler,kruler</default> + <default>krunner,yakuake,spectacle,kded5,xwaylandvideobridge,plasmashell,ksplashqml,org.kde.plasmashell,org.kde.polkit-kde-authentication-agent-1,org.kde.kruler,kruler,kwin_wayland,ksmserver-logout-greeter</default> </entry> <entry name="ignoreRole" type="String"> @@ -114,6 +209,7 @@ <label>Do not apply tiling on some screens(comma-separated list of screen names)</label> <default></default> </entry> + <entry name="ignoreVDesktop" type="String"> <label>Do not apply tiling on some virtual desktops(comma-separated list of virtual desktops names)</label> <default></default> @@ -174,8 +270,23 @@ <default>1</default> </entry> - <entry name="maximizeSoleTile" type="Bool"> - <label>If there is only one tile on the screen, remove screen gap and its borde, making it appear almost fullscreen.</label> + <entry name="soleWindowWidth" type="Int"> + <label>The sole window width in percent.</label> + <default>100</default> + </entry> + + <entry name="soleWindowHeight" type="Int"> + <label>The sole window height in percent.</label> + <default>100</default> + </entry> + + <entry name="soleWindowNoBorders" type="Bool"> + <label>Do not draw borders around sole window</label> + <default>false</default> + </entry> + + <entry name="soleWindowNoGaps" type="Bool"> + <label>Do not draw gaps around sole window</label> <default>false</default> </entry> @@ -219,6 +330,11 @@ <default>true</default> </entry> + <entry name="notificationDuration" type="Int"> + <label>Duration of pop-up notifications</label> + <default>1000</default> + </entry> + <entry name="screenGapLeft" type="Int"> <label>Gap between tiles and screen borders (Left)</label> <default>0</default> diff --git a/roles/config/files/.local/share/kwin/scripts/krohnkite/contents/ui/config.ui b/roles/config/files/.local/share/kwin/scripts/krohnkite/contents/ui/config.ui index adc038276..0c1958b3d 100644 --- a/roles/config/files/.local/share/kwin/scripts/krohnkite/contents/ui/config.ui +++ b/roles/config/files/.local/share/kwin/scripts/krohnkite/contents/ui/config.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>440</width> - <height>1109</height> + <width>817</width> + <height>1157</height> </rect> </property> <property name="minimumSize"> @@ -22,6 +22,9 @@ <layout class="QGridLayout" name="gridLayout"> <item row="0" column="0"> <widget class="QTabWidget" name="configTabs"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> <property name="currentIndex"> <number>0</number> </property> @@ -224,6 +227,26 @@ </property> </widget> </item> + <item> + <layout class="QVBoxLayout" name="quarterLayoutConfigLayout"> + <property name="leftMargin"> + <number>20</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>20</number> + </property> + <item> + <widget class="QCheckBox" name="kcfg_quarterLayoutReset"> + <property name="text"> + <string>Reset Quarter layout after closing a window</string> + </property> + </widget> + </item> + </layout> + </item> <item> <widget class="QCheckBox" name="kcfg_enableStackedLayout"> <property name="toolTip"> @@ -334,7 +357,7 @@ <item> <widget class="QLineEdit" name="kcfg_columnsLayerConf"> <property name="toolTip"> - <string><html><head/><body><p>Comma-separated list OutputName:VirtualDesktopName:ActivityName:ColumnWeight:ColumnWeight:... OutputName value you will see if run KSystemLog and type krohnkite in filter string. The data will right under Krohenkite start string.If all weights are equal they will not be taken into account </p><p> Example: Any monitors 3 columns without weights:</p><p> :::1:1:1</p><p>Example with desktop name and activity id 3 columns the third one is twice as big as the first two:</p><p> HDMI-A-1:Desktop 1:99e10d31-e8f3-44aa-bbed-2a543f13fa54:1:1:2</p></body></html></string> + <string><html><head/><body><p>Comma-separated list OutputName:VirtualDesktopName:ActivityId:ColumnWeight:ColumnWeight:... OutputName value you will see if run KSystemLog and type krohnkite in filter string. The data will right under Krohenkite start string.If all weights are equal they will not be taken into account </p><p>Example: Any monitors 3 columns without weights:</p><p>:::1:1:1</p><p>Example with desktop name and activity id 3 columns the third one is twice as big as the first two:</p><p>HDMI-A-1:Desktop 1:99e10d31-e8f3-44aa-bbed-2a543f13fa54:1:1:2</p></body></html></string> </property> </widget> </item> @@ -976,14 +999,14 @@ <item row="0" column="1"> <widget class="QLineEdit" name="kcfg_ignoreActivity"> <property name="toolTip"> - <string>Comma-separated list of activity names. Windows in corresponding activities will not be tiled.</string> + <string><html><head/><body><p>Comma-separated list of activity IDs. See Readme or Issue #125 to know IDs. Windows in corresponding activities will not be tiled.</p></body></html></string> </property> </widget> </item> <item row="0" column="0"> <widget class="QLabel" name="ignoreActivityLabel"> <property name="text"> - <string>On Activity (name)</string> + <string>On Activity (activityId)</string> </property> </widget> </item> @@ -1073,6 +1096,996 @@ </item> </layout> </widget> + <widget class="QWidget" name="dockTab"> + <attribute name="title"> + <string>Dock</string> + </attribute> + <layout class="QGridLayout" name="gridLayout_12"> + <item row="2" column="0" alignment="Qt::AlignmentFlag::AlignHCenter"> + <widget class="QLabel" name="label_27"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="text"> + <string>Surfaces configuration</string> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QGroupBox" name="groupBox_16"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="title"> + <string>Order of docked windows</string> + </property> + <property name="flat"> + <bool>true</bool> + </property> + <layout class="QGridLayout" name="gridLayout_16"> + <item row="0" column="0" alignment="Qt::AlignmentFlag::AlignHCenter"> + <widget class="QLabel" name="label_17"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="text"> + <string>Left</string> + </property> + </widget> + </item> + <item row="0" column="2" alignment="Qt::AlignmentFlag::AlignHCenter"> + <widget class="QLabel" name="label_29"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="text"> + <string>Right</string> + </property> + </widget> + </item> + <item row="0" column="1" alignment="Qt::AlignmentFlag::AlignHCenter"> + <widget class="QLabel" name="label_18"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="text"> + <string>Top</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QComboBox" name="kcfg_dockOrderLeft"> + <property name="focusPolicy"> + <enum>Qt::FocusPolicy::ClickFocus</enum> + </property> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="currentIndex"> + <number>1</number> + </property> + <item> + <property name="text"> + <string>Off</string> + </property> + </item> + <item> + <property name="text"> + <string>First</string> + </property> + </item> + <item> + <property name="text"> + <string>Second</string> + </property> + </item> + <item> + <property name="text"> + <string>Third</string> + </property> + </item> + <item> + <property name="text"> + <string>Fourth</string> + </property> + </item> + </widget> + </item> + <item row="0" column="3" alignment="Qt::AlignmentFlag::AlignHCenter"> + <widget class="QLabel" name="label_30"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="text"> + <string>Bottom</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QComboBox" name="kcfg_dockOrderTop"> + <property name="focusPolicy"> + <enum>Qt::FocusPolicy::ClickFocus</enum> + </property> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="currentIndex"> + <number>2</number> + </property> + <item> + <property name="text"> + <string>Off</string> + </property> + </item> + <item> + <property name="text"> + <string>First</string> + </property> + </item> + <item> + <property name="text"> + <string>Second</string> + </property> + </item> + <item> + <property name="text"> + <string>Third</string> + </property> + </item> + <item> + <property name="text"> + <string>Fourth</string> + </property> + </item> + </widget> + </item> + <item row="1" column="2"> + <widget class="QComboBox" name="kcfg_dockOrderRight"> + <property name="focusPolicy"> + <enum>Qt::FocusPolicy::ClickFocus</enum> + </property> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="layoutDirection"> + <enum>Qt::LayoutDirection::LeftToRight</enum> + </property> + <property name="currentIndex"> + <number>3</number> + </property> + <item> + <property name="text"> + <string>Off</string> + </property> + </item> + <item> + <property name="text"> + <string>First</string> + </property> + </item> + <item> + <property name="text"> + <string>Second</string> + </property> + </item> + <item> + <property name="text"> + <string>Third</string> + </property> + </item> + <item> + <property name="text"> + <string>Fourth</string> + </property> + </item> + </widget> + </item> + <item row="1" column="3"> + <widget class="QComboBox" name="kcfg_dockOrderBottom"> + <property name="focusPolicy"> + <enum>Qt::FocusPolicy::ClickFocus</enum> + </property> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="currentIndex"> + <number>4</number> + </property> + <item> + <property name="text"> + <string>Off</string> + </property> + </item> + <item> + <property name="text"> + <string>First</string> + </property> + </item> + <item> + <property name="text"> + <string>Second</string> + </property> + </item> + <item> + <property name="text"> + <string>Third</string> + </property> + </item> + <item> + <property name="text"> + <string>Fourth</string> + </property> + </item> + </widget> + </item> + </layout> + </widget> + </item> + <item row="6" column="0"> + <spacer name="verticalSpacer_6"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="orientation"> + <enum>Qt::Orientation::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item row="3" column="0"> + <widget class="QPlainTextEdit" name="kcfg_dockSurfacesConfig"> + <property name="toolTip"> + <string><html><head/><body><p><span style=" font-size:12pt;">Overriding default parameters for every surface. Format: </span><span style=" font-size:12pt; font-weight:700;">OuputName:ActivityId:VirtualDesktopName:shortname=value,shortname=value... &lt;Enter&gt;</span></p><p><span style=" font-size:12pt;">You can only write down parameters you want to change. You can see the short name of the parameter if you hover over any default parameter above.</span></p><p><span style=" font-size:12pt;">Next example override three params on all surfaces with OutputName=HDMI-A-1 </span></p><p><span style=" font-size:12pt; font-weight:700;">HDMI-A-1:::hh=80,vw=80,ha=left</span></p><p><span style=" font-size:12pt;">this one, will override two params only for defined display, virtual desktop and activity</span></p><p><span style=" font-size:12pt; font-weight:700;">HDMI-A-1:99e10d31-e8f3-44aa-bbed-2a543f13fa54:Desktop 1:vg=5,va=2</span></p></body></html></string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QGroupBox" name="groupBox_15"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="title"> + <string>Default settings for a docked window</string> + </property> + <property name="flat"> + <bool>true</bool> + </property> + <layout class="QGridLayout" name="gridLayout_15"> + <item row="0" column="2"> + <widget class="QGroupBox" name="groupBox_20"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="title"> + <string>Up/Bottom Dock</string> + </property> + <property name="flat"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout_13"> + <item> + <widget class="QGroupBox" name="groupBox_24"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="title"> + <string/> + </property> + <property name="flat"> + <bool>false</bool> + </property> + <layout class="QGridLayout" name="gridLayout_22"> + <item row="0" column="3"> + <spacer name="horizontalSpacer_6"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="orientation"> + <enum>Qt::Orientation::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="0"> + <spacer name="horizontalSpacer_5"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="orientation"> + <enum>Qt::Orientation::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="2"> + <widget class="mySpinBox" name="kcfg_dockHHeight"> + <property name="toolTip"> + <string><html><head/><body><p><span style=" font-size:12pt;">short name:</span><span style=" font-weight:700;">hh</span></p></body></html></string> + </property> + <property name="alignment"> + <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set> + </property> + <property name="suffix"> + <string> %</string> + </property> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>50</number> + </property> + <property name="value"> + <number>15</number> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="label_19"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="text"> + <string>Height</string> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="mySpinBox" name="kcfg_dockHWide"> + <property name="toolTip"> + <string><html><head/><body><p><span style=" font-size:12pt;">short name: </span><span style=" font-weight:700;">hw</span></p></body></html></string> + </property> + <property name="alignment"> + <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set> + </property> + <property name="suffix"> + <string> %</string> + </property> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="value"> + <number>100</number> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLabel" name="label_22"> + <property name="toolTip"> + <string><html><head/><body><p>vw - short name</p></body></html></string> + </property> + <property name="text"> + <string>Wide</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_22"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="title"> + <string>Gaps</string> + </property> + <property name="flat"> + <bool>false</bool> + </property> + <layout class="QGridLayout" name="gridLayout_20"> + <item row="1" column="1"> + <widget class="QLabel" name="label_24"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="text"> + <string>Horizontal </string> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="mySpinBox" name="kcfg_dockHEdgeGap"> + <property name="toolTip"> + <string><html><head/><body><p><span style=" font-size:12pt;">short name: </span><span style=" font-weight:700;">hgv</span></p></body></html></string> + </property> + <property name="alignment"> + <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set> + </property> + <property name="suffix"> + <string> px</string> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>9999</number> + </property> + <property name="value"> + <number>0</number> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="mySpinBox" name="kcfg_dockHGap"> + <property name="toolTip"> + <string><html><head/><body><p><span style=" font-size:12pt;">short name:</span><span style=" font-weight:700;">hgh</span></p></body></html></string> + </property> + <property name="alignment"> + <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set> + </property> + <property name="suffix"> + <string> px</string> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>9999</number> + </property> + <property name="value"> + <number>0</number> + </property> + </widget> + </item> + <item row="1" column="0"> + <spacer name="horizontalSpacer_14"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="orientation"> + <enum>Qt::Orientation::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="3"> + <spacer name="horizontalSpacer_15"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="orientation"> + <enum>Qt::Orientation::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="1"> + <widget class="QLabel" name="label_34"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="text"> + <string>Vertical</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_18"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="title"> + <string>Alignment</string> + </property> + <property name="flat"> + <bool>false</bool> + </property> + <layout class="QGridLayout" name="gridLayout_18"> + <item row="0" column="0"> + <spacer name="horizontalSpacer_10"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="orientation"> + <enum>Qt::Orientation::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="label_26"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="text"> + <string>Horizontal</string> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QComboBox" name="kcfg_dockHEdgeAlignment"> + <property name="toolTip"> + <string><html><head/><body><p><span style=" font-size:12pt;">short name: </span><span style=" font-weight:700;">he</span></p></body></html></string> + </property> + <item> + <property name="text"> + <string>Outside</string> + </property> + </item> + <item> + <property name="text"> + <string>Middle</string> + </property> + </item> + <item> + <property name="text"> + <string>Inside</string> + </property> + </item> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLabel" name="label_31"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="text"> + <string>Vertical</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QComboBox" name="kcfg_dockHAlignment"> + <property name="toolTip"> + <string><html><head/><body><p><span style=" font-size:12pt;">short name:</span><span style=" font-weight:700;">ha</span></p></body></html></string> + </property> + <item> + <property name="text"> + <string>Center</string> + </property> + </item> + <item> + <property name="text"> + <string>Left</string> + </property> + </item> + <item> + <property name="text"> + <string>Right</string> + </property> + </item> + </widget> + </item> + <item row="0" column="3"> + <spacer name="horizontalSpacer_11"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="orientation"> + <enum>Qt::Orientation::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </item> + <item row="0" column="0"> + <widget class="QGroupBox" name="groupBox_19"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="title"> + <string>Left/Right Dock</string> + </property> + <property name="flat"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout_12"> + <item> + <widget class="QGroupBox" name="groupBox_23"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="title"> + <string/> + </property> + <property name="flat"> + <bool>false</bool> + </property> + <layout class="QGridLayout" name="gridLayout_21"> + <item row="0" column="1"> + <widget class="QLabel" name="label_20"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="text"> + <string>Height</string> + </property> + </widget> + </item> + <item row="0" column="0"> + <spacer name="horizontalSpacer_7"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="orientation"> + <enum>Qt::Orientation::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="2"> + <widget class="mySpinBox" name="kcfg_dockVHeight"> + <property name="toolTip"> + <string><html><head/><body><p><span style=" font-size:12pt;">short name: </span><span style=" font-weight:700;">vh</span></p></body></html></string> + </property> + <property name="alignment"> + <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set> + </property> + <property name="suffix"> + <string> %</string> + </property> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="value"> + <number>100</number> + </property> + </widget> + </item> + <item row="0" column="3"> + <spacer name="horizontalSpacer_4"> + <property name="toolTip"> + <string>Horizontal Spacer 'horizontalSpacer_4', 40 x 20</string> + </property> + <property name="orientation"> + <enum>Qt::Orientation::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="2"> + <widget class="mySpinBox" name="kcfg_dockVWide"> + <property name="toolTip"> + <string><html><head/><body><p><span style=" font-size:12pt;">short name: </span><span style=" font-weight:700;">vw</span></p></body></html></string> + </property> + <property name="alignment"> + <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set> + </property> + <property name="suffix"> + <string> %</string> + </property> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>50</number> + </property> + <property name="value"> + <number>15</number> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLabel" name="label_21"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="text"> + <string>Wide</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_21"> + <property name="baseSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="font"> + <font> + <italic>false</italic> + <bold>false</bold> + </font> + </property> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="title"> + <string>Gaps</string> + </property> + <property name="flat"> + <bool>false</bool> + </property> + <layout class="QGridLayout" name="gridLayout_19"> + <item row="1" column="1"> + <widget class="QLabel" name="label_33"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="text"> + <string>Vertical</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="label_23"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="text"> + <string>Horizontal </string> + </property> + </widget> + </item> + <item row="0" column="3"> + <spacer name="horizontalSpacer_13"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="orientation"> + <enum>Qt::Orientation::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="0"> + <spacer name="horizontalSpacer_12"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="orientation"> + <enum>Qt::Orientation::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="2"> + <widget class="mySpinBox" name="kcfg_dockVEdgeGap"> + <property name="toolTip"> + <string><html><head/><body><p><span style=" font-size:12pt;">short name:</span><span style=" font-weight:700;">vgh</span></p></body></html></string> + </property> + <property name="alignment"> + <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set> + </property> + <property name="suffix"> + <string> px</string> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>9999</number> + </property> + <property name="value"> + <number>0</number> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="mySpinBox" name="kcfg_dockVGap"> + <property name="toolTip"> + <string><html><head/><body><p><span style=" font-size:12pt;">short name:</span><span style=" font-weight:700;">vgv</span></p></body></html></string> + </property> + <property name="alignment"> + <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set> + </property> + <property name="suffix"> + <string> px</string> + </property> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>9999</number> + </property> + <property name="value"> + <number>0</number> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_17"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="title"> + <string>Alignment</string> + </property> + <property name="flat"> + <bool>false</bool> + </property> + <layout class="QGridLayout" name="gridLayout_17"> + <item row="0" column="3"> + <spacer name="horizontalSpacer_9"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="orientation"> + <enum>Qt::Orientation::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="0"> + <spacer name="horizontalSpacer_8"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="orientation"> + <enum>Qt::Orientation::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="2"> + <widget class="QComboBox" name="kcfg_dockVAlignment"> + <property name="toolTip"> + <string><html><head/><body><p><span style=" font-size:12pt;">short name: </span><span style=" font-weight:700;">va</span></p></body></html></string> + </property> + <item> + <property name="text"> + <string>Center</string> + </property> + </item> + <item> + <property name="text"> + <string>Top</string> + </property> + </item> + <item> + <property name="text"> + <string>Bottom</string> + </property> + </item> + </widget> + </item> + <item row="0" column="2"> + <widget class="QComboBox" name="kcfg_dockVEdgeAlignment"> + <property name="toolTip"> + <string><html><head/><body><p><span style=" font-size:12pt;">short name: </span><span style=" font-weight:700;">ve</span></p></body></html></string> + </property> + <item> + <property name="text"> + <string>Outside</string> + </property> + </item> + <item> + <property name="text"> + <string>Middle</string> + </property> + </item> + <item> + <property name="text"> + <string>Inside</string> + </property> + </item> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLabel" name="label_25"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="text"> + <string>Vertical</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="label_32"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="text"> + <string>Horizontal </string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </item> + <item row="4" column="0" alignment="Qt::AlignmentFlag::AlignHCenter"> + <widget class="QLabel" name="label_28"> + <property name="toolTip"> + <string><html><head/><body><p>hv - short name</p></body></html></string> + </property> + <property name="text"> + <string>Window class configuration</string> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QPlainTextEdit" name="kcfg_dockWindowClassConfig"> + <property name="toolTip"> + <string><html><head/><body><p><span style=" font-size:12pt;">Overriding default parameters for the specified WindowClass. Format:</span></p><p><span style=" font-size:12pt; font-weight:700;">WindowClass:SpecialFlag,SpecialFlag...:shortname=value,shortname=value...</span></p><p><span style=" font-size:12pt; font-weight:700;">pin - </span><span style=" font-size:12pt;">docked window with this flag will displace another if their positions are equal.</span></p><p><span style=" font-size:12pt; font-weight:700;">left,right,top,bottom</span><span style=" font-size:12pt;"> - you can use one them to explicitly set the initial position.</span></p><p><span style=" font-size:12pt;">You can only write down the parameters you want to change. You can see the short name of the parameter if you hover over any default parameter above.</span></p><p><span style=" font-size:12pt;">Examples:</span></p><p><span style=" font-size:12pt;">org.kde.elisa</span><span style=" font-size:12pt; font-weight:700;">:pin,top:hh=10</span></p><p><span style=" font-size:12pt;">if Elisa switches to dock it will have higher priority, top dock position and 10% of screen height</span></p></body></html></string> + </property> + </widget> + </item> + </layout> + </widget> <widget class="QWidget" name="optionsTab"> <attribute name="title"> <string>Options</string> @@ -1153,13 +2166,140 @@ </widget> </item> <item> - <widget class="QCheckBox" name="kcfg_maximizeSoleTile"> - <property name="toolTip"> - <string><p>If there's only one window to be tiled, the window will be maximized with its borders removed to maximize usable screen space.</p><p>When using this option it's advisable to enable the &quot;Allow resizing maximized windows from window edges&quot; in &quot;Breeze Window Decoration&quot; settings, as this will often leave windows maximized, preventing borders from returning when windows are no longer sole otherwise.</p></string> + <widget class="QGroupBox" name="groupBox_12"> + <property name="title"> + <string>Window Size</string> </property> - <property name="text"> - <string>Maximize the sole window</string> + <layout class="QGridLayout" name="gridLayout_10"> + <item row="0" column="2"> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Orientation::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="1"> + <widget class="QSpinBox" name="kcfg_soleWindowHeight"> + <property name="suffix"> + <string>%</string> + </property> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="value"> + <number>100</number> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_16"> + <property name="text"> + <string>The sole window height</string> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label_15"> + <property name="text"> + <string>The sole window width </string> + </property> + </widget> + </item> + <item row="0" column="1" alignment="Qt::AlignmentFlag::AlignHCenter|Qt::AlignmentFlag::AlignVCenter"> + <widget class="QSpinBox" name="kcfg_soleWindowWidth"> + <property name="suffix"> + <string>%</string> + </property> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="value"> + <number>100</number> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QCheckBox" name="kcfg_soleWindowNoBorders"> + <property name="text"> + <string>No Borders</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QCheckBox" name="kcfg_soleWindowNoGaps"> + <property name="text"> + <string>No Gaps</string> + </property> + </widget> + </item> + </layout> + <zorder>kcfg_soleWindowWidth</zorder> + <zorder>label_15</zorder> + <zorder>horizontalSpacer_3</zorder> + <zorder>label_16</zorder> + <zorder>kcfg_soleWindowHeight</zorder> + <zorder>kcfg_soleWindowNoBorders</zorder> + <zorder>kcfg_soleWindowNoGaps</zorder> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_13"> + <property name="title"> + <string>Notifications</string> </property> + <layout class="QGridLayout" name="gridLayout_12"> + <item row="1" column="1"> + <widget class="QSpinBox" name="kcfg_notificationDuration"> + <property name="toolTip"> + <string><html><head/><body><p>Set the time (in milliseconds) for how long a pop-up notification will remain visible before it automatically disappears. A value of 0 will disable notifications.</p></body></html></string> + </property> + <property name="suffix"> + <string> ms</string> + </property> + <property name="maximum"> + <number>9999</number> + </property> + <property name="singleStep"> + <number>100</number> + </property> + <property name="value"> + <number>1000</number> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_18"> + <property name="text"> + <string>Duration </string> + </property> + </widget> + </item> + <item row="1" column="2"> + <spacer name="horizontalSpacer_4"> + <property name="orientation"> + <enum>Qt::Orientation::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> </widget> </item> <item> @@ -1258,6 +2398,13 @@ </item> </layout> </widget> + <customwidgets> + <customwidget> + <class>mySpinBox</class> + <extends>QSpinBox</extends> + <header>myspinbox.h</header> + </customwidget> + </customwidgets> <resources/> <connections/> <buttongroups> diff --git a/roles/config/files/.local/share/kwin/scripts/krohnkite/contents/ui/main.qml b/roles/config/files/.local/share/kwin/scripts/krohnkite/contents/ui/main.qml index 7089c8929..e91d68a12 100644 --- a/roles/config/files/.local/share/kwin/scripts/krohnkite/contents/ui/main.qml +++ b/roles/config/files/.local/share/kwin/scripts/krohnkite/contents/ui/main.qml @@ -42,9 +42,9 @@ Item { id: popupDialog source: "popup.qml" - function show(text) { + function show(text, duration) { var area = Workspace.clientArea(KWin.FullScreenArea, Workspace.activeScreen, Workspace.currentDesktop); - this.item.show(text, area, 1000); + this.item.show(text, area, duration); } } diff --git a/roles/config/files/.local/share/kwin/scripts/krohnkite/contents/ui/shortcuts.qml b/roles/config/files/.local/share/kwin/scripts/krohnkite/contents/ui/shortcuts.qml index 643a3470e..8838961d0 100644 --- a/roles/config/files/.local/share/kwin/scripts/krohnkite/contents/ui/shortcuts.qml +++ b/roles/config/files/.local/share/kwin/scripts/krohnkite/contents/ui/shortcuts.qml @@ -3,6 +3,16 @@ import org.kde.kwin; Item { id: dbus; + function getToggleDock() { + return toggleDock; + } + ShortcutHandler { + id: toggleDock; + + name: "KrohnkitetoggleDock"; + text: "Krohnkite: Toggle Dock"; + sequence: ""; + } function getFocusNext() { return focusNext; diff --git a/roles/config/files/.local/share/kwin/scripts/krohnkite/metadata.json b/roles/config/files/.local/share/kwin/scripts/krohnkite/metadata.json index e0443c595..c3eed55d7 100644 --- a/roles/config/files/.local/share/kwin/scripts/krohnkite/metadata.json +++ b/roles/config/files/.local/share/kwin/scripts/krohnkite/metadata.json @@ -2,7 +2,7 @@ "KPackageStructure": "KWin/Script", "KPlugin": { "Name": "Krohnkite", - "Description": "A dynamic tiling script for KWin (83dd1ab)", + "Description": "A dynamic tiling script for KWin (dbd6f2a)", "Icon": "dialog-tile-clones", "Authors": [ @@ -12,7 +12,7 @@ } ], "Id": "krohnkite", - "Version": "0.9.8.5", + "Version": "0.9.9.0", "License": "MIT", "Website": "https://github.com/anametologin/krohnkite#readme" },