ScreenRecorder: check for availability
This commit is contained in:
parent
94d64a91b8
commit
3c9ce6f8b5
5 changed files with 107 additions and 28 deletions
|
|
@ -22,7 +22,9 @@ Item {
|
||||||
IpcHandler {
|
IpcHandler {
|
||||||
target: "screenRecorder"
|
target: "screenRecorder"
|
||||||
function toggle() {
|
function toggle() {
|
||||||
ScreenRecorderService.toggleRecording()
|
if (ScreenRecorderService.isAvailable) {
|
||||||
|
ScreenRecorderService.toggleRecording()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -735,12 +735,28 @@ Loader {
|
||||||
color: powerButtonArea.containsMouse ? Color.mOnError : Color.mError
|
color: powerButtonArea.containsMouse ? Color.mOnError : Color.mError
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tooltip
|
// Tooltip (inline rectangle to avoid separate Window during lock)
|
||||||
NTooltip {
|
Rectangle {
|
||||||
id: tooltipShutdown
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
target: parent
|
anchors.bottom: parent.top
|
||||||
positionAbove: true
|
anchors.bottomMargin: 12 * scaling
|
||||||
text: "Shut down"
|
radius: Style.radiusM * scaling
|
||||||
|
color: Color.mSurface
|
||||||
|
border.color: Color.mOutline
|
||||||
|
border.width: Math.max(1, Style.borderS * scaling)
|
||||||
|
visible: powerButtonArea.containsMouse
|
||||||
|
z: 1
|
||||||
|
NText {
|
||||||
|
id: shutdownTooltipText
|
||||||
|
anchors.margins: Style.marginM * scaling
|
||||||
|
anchors.fill: parent
|
||||||
|
text: "Shut down the computer."
|
||||||
|
font.pointSize: Style.fontSizeM * scaling
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
implicitWidth: shutdownTooltipText.implicitWidth + Style.marginM * 2 * scaling
|
||||||
|
implicitHeight: shutdownTooltipText.implicitHeight + Style.marginM * 2 * scaling
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
|
@ -750,8 +766,6 @@ Loader {
|
||||||
onClicked: {
|
onClicked: {
|
||||||
CompositorService.shutdown()
|
CompositorService.shutdown()
|
||||||
}
|
}
|
||||||
onEntered: tooltipShutdown.show()
|
|
||||||
onExited: tooltipShutdown.hide()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -773,11 +787,27 @@ Loader {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tooltip
|
// Tooltip
|
||||||
NTooltip {
|
Rectangle {
|
||||||
id: tooltipRestart
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
target: parent
|
anchors.bottom: parent.top
|
||||||
positionAbove: true
|
anchors.bottomMargin: 12 * scaling
|
||||||
text: "Restart"
|
radius: Style.radiusM * scaling
|
||||||
|
color: Color.mSurface
|
||||||
|
border.color: Color.mOutline
|
||||||
|
border.width: Math.max(1, Style.borderS * scaling)
|
||||||
|
visible: restartButtonArea.containsMouse
|
||||||
|
z: 1
|
||||||
|
NText {
|
||||||
|
id: restartTooltipText
|
||||||
|
anchors.margins: Style.marginM * scaling
|
||||||
|
anchors.fill: parent
|
||||||
|
text: "Restart the computer."
|
||||||
|
font.pointSize: Style.fontSizeM * scaling
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
implicitWidth: restartTooltipText.implicitWidth + Style.marginM * 2 * scaling
|
||||||
|
implicitHeight: restartTooltipText.implicitHeight + Style.marginM * 2 * scaling
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
|
@ -787,8 +817,7 @@ Loader {
|
||||||
onClicked: {
|
onClicked: {
|
||||||
CompositorService.reboot()
|
CompositorService.reboot()
|
||||||
}
|
}
|
||||||
onEntered: tooltipRestart.show()
|
// Tooltip handled via inline rectangle visibility
|
||||||
onExited: tooltipRestart.hide()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -810,11 +839,27 @@ Loader {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tooltip
|
// Tooltip
|
||||||
NTooltip {
|
Rectangle {
|
||||||
id: tooltipSuspend
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
target: parent
|
anchors.bottom: parent.top
|
||||||
positionAbove: true
|
anchors.bottomMargin: 12 * scaling
|
||||||
text: "Suspend"
|
radius: Style.radiusM * scaling
|
||||||
|
color: Color.mSurface
|
||||||
|
border.color: Color.mOutline
|
||||||
|
border.width: Math.max(1, Style.borderS * scaling)
|
||||||
|
visible: suspendButtonArea.containsMouse
|
||||||
|
z: 1
|
||||||
|
NText {
|
||||||
|
id: suspendTooltipText
|
||||||
|
anchors.margins: Style.marginM * scaling
|
||||||
|
anchors.fill: parent
|
||||||
|
text: "Suspend the system."
|
||||||
|
font.pointSize: Style.fontSizeM * scaling
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
implicitWidth: suspendTooltipText.implicitWidth + Style.marginM * 2 * scaling
|
||||||
|
implicitHeight: suspendTooltipText.implicitHeight + Style.marginM * 2 * scaling
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
|
@ -824,8 +869,7 @@ Loader {
|
||||||
onClicked: {
|
onClicked: {
|
||||||
CompositorService.suspend()
|
CompositorService.suspend()
|
||||||
}
|
}
|
||||||
onEntered: tooltipSuspend.show()
|
// Tooltip handled via inline rectangle visibility
|
||||||
onExited: tooltipSuspend.hide()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,13 @@ NBox {
|
||||||
// Screen Recorder
|
// Screen Recorder
|
||||||
NIconButton {
|
NIconButton {
|
||||||
icon: "camera-video"
|
icon: "camera-video"
|
||||||
tooltipText: ScreenRecorderService.isRecording ? "Stop screen recording." : "Start screen recording."
|
enabled: ScreenRecorderService.isAvailable
|
||||||
|
tooltipText: ScreenRecorderService.isAvailable ? (ScreenRecorderService.isRecording ? "Stop screen recording." : "Start screen recording.") : "Screen recorder not installed."
|
||||||
colorBg: ScreenRecorderService.isRecording ? Color.mPrimary : Color.mSurfaceVariant
|
colorBg: ScreenRecorderService.isRecording ? Color.mPrimary : Color.mSurfaceVariant
|
||||||
colorFg: ScreenRecorderService.isRecording ? Color.mOnPrimary : Color.mPrimary
|
colorFg: ScreenRecorderService.isRecording ? Color.mOnPrimary : Color.mPrimary
|
||||||
onClicked: {
|
onClicked: {
|
||||||
|
if (!ScreenRecorderService.isAvailable)
|
||||||
|
return
|
||||||
ScreenRecorderService.toggleRecording()
|
ScreenRecorderService.toggleRecording()
|
||||||
// If we were not recording and we just initiated a start, close the panel
|
// If we were not recording and we just initiated a start, close the panel
|
||||||
if (!ScreenRecorderService.isRecording) {
|
if (!ScreenRecorderService.isRecording) {
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,17 @@ Singleton {
|
||||||
property bool isRecording: false
|
property bool isRecording: false
|
||||||
property bool isPending: false
|
property bool isPending: false
|
||||||
property string outputPath: ""
|
property string outputPath: ""
|
||||||
|
property bool isAvailable: false
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
checkAvailability()
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkAvailability() {
|
||||||
|
// Detect native or Flatpak gpu-screen-recorder
|
||||||
|
availabilityCheckProcess.command = ["sh", "-c", "command -v gpu-screen-recorder >/dev/null 2>&1 || (command -v flatpak >/dev/null 2>&1 && flatpak list --app | grep -q 'com.dec05eba.gpu_screen_recorder')"]
|
||||||
|
availabilityCheckProcess.running = true
|
||||||
|
}
|
||||||
|
|
||||||
// Start or Stop recording
|
// Start or Stop recording
|
||||||
function toggleRecording() {
|
function toggleRecording() {
|
||||||
|
|
@ -21,6 +32,9 @@ Singleton {
|
||||||
|
|
||||||
// Start screen recording using Quickshell.execDetached
|
// Start screen recording using Quickshell.execDetached
|
||||||
function startRecording() {
|
function startRecording() {
|
||||||
|
if (!isAvailable) {
|
||||||
|
return
|
||||||
|
}
|
||||||
if (isRecording || isPending) {
|
if (isRecording || isPending) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -88,6 +102,18 @@ Singleton {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Availability check process
|
||||||
|
Process {
|
||||||
|
id: availabilityCheckProcess
|
||||||
|
command: ["sh", "-c", "true"]
|
||||||
|
onExited: function (exitCode, exitStatus) {
|
||||||
|
// exitCode 0 means available, non-zero means unavailable
|
||||||
|
root.isAvailable = (exitCode === 0)
|
||||||
|
}
|
||||||
|
stdout: StdioCollector {}
|
||||||
|
stderr: StdioCollector {}
|
||||||
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: pendingTimer
|
id: pendingTimer
|
||||||
interval: 2000 // Wait 2 seconds to see if process stays alive
|
interval: 2000 // Wait 2 seconds to see if process stays alive
|
||||||
|
|
|
||||||
|
|
@ -35,13 +35,13 @@ Rectangle {
|
||||||
opacity: root.enabled ? Style.opacityFull : Style.opacityMedium
|
opacity: root.enabled ? Style.opacityFull : Style.opacityMedium
|
||||||
color: root.enabled && root.hovering ? colorBgHover : colorBg
|
color: root.enabled && root.hovering ? colorBgHover : colorBg
|
||||||
radius: width * 0.5
|
radius: width * 0.5
|
||||||
border.color: root.hovering ? colorBorderHover : colorBorder
|
border.color: root.enabled && root.hovering ? colorBorderHover : colorBorder
|
||||||
border.width: Math.max(1, Style.borderS * scaling)
|
border.width: Math.max(1, Style.borderS * scaling)
|
||||||
|
|
||||||
NIcon {
|
NIcon {
|
||||||
icon: root.icon
|
icon: root.icon
|
||||||
font.pointSize: Style.fontSizeM * scaling
|
font.pointSize: Style.fontSizeM * scaling
|
||||||
color: root.hovering ? colorFgHover : colorFg
|
color: root.enabled && root.hovering ? colorFgHover : colorFg
|
||||||
// Center horizontally
|
// Center horizontally
|
||||||
x: (root.width - width) / 2
|
x: (root.width - width) / 2
|
||||||
// Center vertically accounting for font metrics
|
// Center vertically accounting for font metrics
|
||||||
|
|
@ -56,13 +56,14 @@ Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
enabled: root.enabled
|
// Always enabled to allow hover/tooltip even when the button is disabled
|
||||||
|
enabled: true
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
cursorShape: root.enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
cursorShape: root.enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onEntered: {
|
onEntered: {
|
||||||
hovering = true
|
hovering = root.enabled ? true : false
|
||||||
if (tooltipText) {
|
if (tooltipText) {
|
||||||
tooltip.show()
|
tooltip.show()
|
||||||
}
|
}
|
||||||
|
|
@ -79,6 +80,9 @@ Rectangle {
|
||||||
if (tooltipText) {
|
if (tooltipText) {
|
||||||
tooltip.hide()
|
tooltip.hide()
|
||||||
}
|
}
|
||||||
|
if (!root.enabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
if (mouse.button === Qt.LeftButton) {
|
if (mouse.button === Qt.LeftButton) {
|
||||||
root.clicked()
|
root.clicked()
|
||||||
} else if (mouse.button === Qt.RightButton) {
|
} else if (mouse.button === Qt.RightButton) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue