mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-06-11 00:47:22 +00:00
kwin: add Shift Aurorae decoration
Add a KWin decoration package under kwin/decorations and install it into share/kwin/decorations. The QML theme defines Shift titlebar colors, button rendering, and maximized border geometry. Wire the new decorations subdirectory from kwin/CMakeLists.txt.
This commit is contained in:
parent
c2f4c8ad88
commit
92e7b78b5e
4 changed files with 229 additions and 0 deletions
|
|
@ -2,4 +2,5 @@
|
|||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
add_subdirectory(scripts)
|
||||
add_subdirectory(decorations)
|
||||
add_subdirectory(mobiletaskswitcher)
|
||||
7
kwin/decorations/CMakeLists.txt
Normal file
7
kwin/decorations/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# SPDX-FileCopyrightText: 2025 SHIFT Contributors
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
install(
|
||||
DIRECTORY org.shift.decoration
|
||||
DESTINATION ${KDE_INSTALL_DATADIR}/kwin/decorations
|
||||
)
|
||||
207
kwin/decorations/org.shift.decoration/contents/ui/main.qml
Normal file
207
kwin/decorations/org.shift.decoration/contents/ui/main.qml
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
// SPDX-FileCopyrightText: 2025 SHIFT Contributors
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import QtQuick
|
||||
import org.kde.kwin.decoration
|
||||
|
||||
Decoration {
|
||||
id: root
|
||||
alpha: true
|
||||
|
||||
// ── Palette ─────────────────────────────────────────────────────────────
|
||||
readonly property color activeBar: "#1a1d2e"
|
||||
readonly property color inactiveBar: "#141620"
|
||||
readonly property color activeText: "#f0f0f8"
|
||||
readonly property color inactiveText: "#505570"
|
||||
|
||||
readonly property int barHeight: 30
|
||||
readonly property int btnSize: 16
|
||||
readonly property int btnSpacing: 8
|
||||
readonly property int btnSideMargin: 12
|
||||
readonly property int cornerRadius: decoration.client.maximized ? 0 : 8
|
||||
|
||||
Component.onCompleted: {
|
||||
borders.top = barHeight;
|
||||
borders.left = 0;
|
||||
borders.right = 0;
|
||||
borders.bottom = 0;
|
||||
|
||||
// Keep titlebar controls available for maximized windows in desktop
|
||||
// convergence mode. Mobile mode uses noBorder=true and bypasses this.
|
||||
maximizedBorders.top = barHeight;
|
||||
maximizedBorders.left = 0;
|
||||
maximizedBorders.right = 0;
|
||||
maximizedBorders.bottom = 0;
|
||||
}
|
||||
|
||||
DecorationOptions {
|
||||
id: options
|
||||
deco: decoration
|
||||
}
|
||||
|
||||
// ── Faint window outline ─────────────────────────────────────────────────
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
radius: root.cornerRadius
|
||||
border.width: decoration.client.maximized ? 0 : 1
|
||||
border.color: Qt.rgba(1, 1, 1, 0.08)
|
||||
}
|
||||
|
||||
// ── Title bar ────────────────────────────────────────────────────────────
|
||||
Rectangle {
|
||||
id: bar
|
||||
anchors { left: parent.left; right: parent.right; top: parent.top }
|
||||
height: root.barHeight
|
||||
radius: root.cornerRadius
|
||||
color: decoration.client.active ? root.activeBar : root.inactiveBar
|
||||
Behavior on color { ColorAnimation { duration: 120 } }
|
||||
|
||||
// Square off bottom half — only top corners are rounded
|
||||
Rectangle {
|
||||
anchors { left: parent.left; right: parent.right; bottom: parent.bottom }
|
||||
height: root.cornerRadius
|
||||
color: parent.color
|
||||
visible: !decoration.client.maximized
|
||||
}
|
||||
|
||||
// ── Title row ────────────────────────────────────────────────────────
|
||||
Item {
|
||||
id: titleRow
|
||||
anchors.fill: parent
|
||||
|
||||
Row {
|
||||
id: leftRow
|
||||
spacing: root.btnSpacing
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: root.btnSideMargin
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
Repeater {
|
||||
model: options.titleButtonsLeft
|
||||
delegate: ShiftButton { btnType: modelData }
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors {
|
||||
left: leftRow.right; leftMargin: 6
|
||||
right: rightRow.left; rightMargin: 6
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
text: decoration.client.caption
|
||||
color: decoration.client.active ? root.activeText : root.inactiveText
|
||||
font: options.titleFont
|
||||
elide: Text.ElideMiddle
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
renderType: Text.NativeRendering
|
||||
Behavior on color { ColorAnimation { duration: 120 } }
|
||||
}
|
||||
|
||||
Row {
|
||||
id: rightRow
|
||||
spacing: root.btnSpacing
|
||||
anchors {
|
||||
right: parent.right
|
||||
rightMargin: root.btnSideMargin
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
Repeater {
|
||||
model: options.titleButtonsRight
|
||||
delegate: ShiftButton { btnType: modelData }
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: decoration.installTitleItem(titleRow)
|
||||
}
|
||||
}
|
||||
|
||||
// ── Button component ─────────────────────────────────────────────────────
|
||||
component ShiftButton: DecorationButton {
|
||||
property int btnType: DecorationOptions.DecorationButtonNone
|
||||
readonly property bool isSpacer: btnType === DecorationOptions.DecorationButtonExplicitSpacer
|
||||
readonly property bool supported: {
|
||||
switch (btnType) {
|
||||
case DecorationOptions.DecorationButtonExplicitSpacer:
|
||||
case DecorationOptions.DecorationButtonClose:
|
||||
case DecorationOptions.DecorationButtonMinimize:
|
||||
case DecorationOptions.DecorationButtonMaximizeRestore:
|
||||
case DecorationOptions.DecorationButtonMenu:
|
||||
case DecorationOptions.DecorationButtonApplicationMenu:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
buttonType: btnType
|
||||
width: isSpacer ? root.btnSpacing * 2 : (supported ? root.btnSize : 0)
|
||||
height: isSpacer ? 1 : (supported ? root.btnSize : 0)
|
||||
visible: supported
|
||||
|
||||
readonly property color normalColor: {
|
||||
switch (btnType) {
|
||||
case DecorationOptions.DecorationButtonClose: return "#C4455D";
|
||||
case DecorationOptions.DecorationButtonMenu:
|
||||
case DecorationOptions.DecorationButtonApplicationMenu:
|
||||
case DecorationOptions.DecorationButtonMinimize:
|
||||
case DecorationOptions.DecorationButtonMaximizeRestore: return "#2b3246";
|
||||
default: return "#2b3246";
|
||||
}
|
||||
}
|
||||
readonly property color hoverColor: {
|
||||
switch (btnType) {
|
||||
case DecorationOptions.DecorationButtonClose: return "#E05D76";
|
||||
case DecorationOptions.DecorationButtonMinimize:
|
||||
case DecorationOptions.DecorationButtonMaximizeRestore:
|
||||
case DecorationOptions.DecorationButtonMenu:
|
||||
case DecorationOptions.DecorationButtonApplicationMenu: return "#3b435c";
|
||||
default: return "#3b435c";
|
||||
}
|
||||
}
|
||||
readonly property color symbolColor: {
|
||||
switch (btnType) {
|
||||
case DecorationOptions.DecorationButtonClose: return "#ffffff";
|
||||
case DecorationOptions.DecorationButtonMenu:
|
||||
case DecorationOptions.DecorationButtonApplicationMenu:
|
||||
case DecorationOptions.DecorationButtonMinimize:
|
||||
case DecorationOptions.DecorationButtonMaximizeRestore: return "#eaf2ff";
|
||||
default: return "#eaf2ff";
|
||||
}
|
||||
}
|
||||
readonly property string symbol: {
|
||||
switch (btnType) {
|
||||
case DecorationOptions.DecorationButtonClose: return "\u00d7";
|
||||
case DecorationOptions.DecorationButtonMinimize: return "\u2212";
|
||||
case DecorationOptions.DecorationButtonMaximizeRestore:
|
||||
return decoration.client.maximized ? "\u25a3" : "\u25a1";
|
||||
case DecorationOptions.DecorationButtonMenu:
|
||||
case DecorationOptions.DecorationButtonApplicationMenu: return "\u2261";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: !isSpacer
|
||||
anchors.fill: parent
|
||||
radius: width / 2
|
||||
antialiasing: true
|
||||
border.width: 1
|
||||
border.color: Qt.rgba(1, 1, 1, 0.18)
|
||||
color: parent.pressed ? Qt.darker(parent.hoverColor, 1.3)
|
||||
: parent.hovered ? parent.hoverColor
|
||||
: parent.normalColor
|
||||
Behavior on color { ColorAnimation { duration: 100 } }
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: parent.parent.symbol
|
||||
color: parent.parent.symbolColor
|
||||
font.pixelSize: Math.round(parent.width * 0.66)
|
||||
font.weight: Font.Bold
|
||||
opacity: 1.0
|
||||
Behavior on opacity { NumberAnimation { duration: 100 } }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
14
kwin/decorations/org.shift.decoration/metadata.json
Normal file
14
kwin/decorations/org.shift.decoration/metadata.json
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"KPackageStructure": "KWin/Decoration",
|
||||
"KPlugin": {
|
||||
"Authors": [
|
||||
{
|
||||
"Name": "SHIFT Contributors"
|
||||
}
|
||||
],
|
||||
"Description": "Shift window decoration",
|
||||
"Id": "org.shift.decoration",
|
||||
"License": "GPL-2.0-or-later",
|
||||
"Name": "Shift"
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue