Experimental: Friendly shutdown

Under development: PCMCIA, wireless, etc.

Moderator: Forum moderators

Post Reply
HerrBert
Posts: 329
Joined: Mon Jul 13, 2020 6:14 pm
Location: Germany, NRW
Has thanked: 17 times
Been thanked: 110 times

Experimental: Friendly shutdown

Post by HerrBert »

This is not an application ready to use!

I label this as experimental here!

What it's about:
I saw some desktops providing an icon to shutdown immediately or similar.

What happens to me often is, that i have applications with unsaved changes on different desktops. So when i shutdown, all these unsaved changes are lost due to killing the WM.

Here's something to try out:
A friendly shutdown app that doesn't just kill apps but tries to close programs gracefully when shutting down, rebooting, restarting wm or exiting to prompt.
(Xorg terminate keyboard shortcut ctrl+alt+backspace will not be altered)

What it does:
Move open windows to the current desktop, activate them and send the key code alt+F4.
This will request a 'Close' command by jwm rather than just killing windows with unsaved content.
Closing a window with unsaved changes should bring up a save dialog which then prevents from shutting down.

Problem is to merge this with Puppy installs.
When creating this as ROX application directory it is possible to just drag it to desktop and use its optional rightclick menu.
Implementation into regular shutdown process seems to be more complicated.

Important notes:
· Do not run this from a terminal!!
· Older versions of xdotool do not support command chaining and may cause errors...
· wmexit code verified/tested downwards compatible to slacko 6.3.2 (so i guess it works in woofCE created puppies later than 2016)
· This ROX Application Directory was build with xdotool binaries from slacko(32 and 64bit)14.2 repos used as fallback in case there is no xdotool installed.
· NO WARRANTY - Use at your own risk

Comments, suggestions and/or improvements welcome

EDIT:
attachment removed last but not least due to licensing voilation.

AppRun:

Code: Select all

#!/bin/bash
# close open programs gracefully

# do not run in terminal
[ -t 0 ] && exit 1

[ -z "$(which xdotool)" ] && exit 2

# move open windows to active desktop, activate window and send key alt+F4
PROP="$(xprop -root _NET_CLIENT_LIST_STACKING _NET_CURRENT_DESKTOP)"
STACK="${PROP%$'\n'*}"
STACK="${STACK#*\#}"
DESK="${PROP##* }"

# on slow machine longer sleep needed (tested: Atom N270 ~1s)
for WID in ${STACK//,}; do
	xdotool set_desktop_for_window $WID $DESK sleep .2 windowactivate --sync $WID key alt+F4
	[ $? -ne 0 ] && echo "Your xdotool is too old..." 1>&2 && break
done

# all windows closed?
PROP="$(xprop -root _NET_CLIENT_LIST_STACKING)"
[ "${PROP#*\#}" = " " ] || exit 255

# weird situation here: button ok returns 0, timeout returns 255
Xdialog --title Shutdown --buttons-style text --ok-label 'Oh no!!' --timeout 5 --msgbox 'Shutdown' 200x80
[ $? -eq 0 ] && exit 255

wmpoweroff $@

AppInfo.xml:

Code: Select all

<?xml version="1.0"?>
<AppInfo>
  <Summary>Close apps gracefully and shutdown</Summary>
  <Summary xml:lang="de">Programme "höflich" beenden und herunterfahren</Summary>
  <AppMenu>
    <Item option="wmpoweroff">
      <Label>Shutdown</Label>
      <Label xml:lang="de">Herunterfahren</Label>
    </Item>
    <Item option="wmreboot">
      <Label>Reboot</Label>
      <Label xml:lang="de">Neu starten</Label>
    </Item>
    <Item option="restartwm">
      <Label>Restart WM</Label>
      <Label xml:lang="de">Desktop neu starten</Label>
    </Item>
    <Item option="wmexit">
      <Label>Exit to prompt</Label>
      <Label xml:lang="de">Desktop beenden</Label>
    </Item>
  </AppMenu>
</AppInfo>

.DirIcon:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="100" width="100">

  <circle cx="50" cy="48" r="45" style="fill:#FFF"/>
  <circle cx="50" cy="48" r="45" style="fill:#c52727;opacity:0.8"/>
  <circle cx="50" cy="52" r="45" style="fill:#000;opacity:0.3"/>
  <circle cx="50" cy="50" r="45" style="fill:#c52727"/>
  <g style="fill:none;stroke:#fff;stroke-width:10px;stroke-linecap:round;stroke-linejoin:round;">
    <path d="m 50,16 0,25"/>
    <path d="m 70,26 a 30,30 0 1 1 -40,0"/>
  </g>
</svg>
Last edited by HerrBert on Sun Dec 19, 2021 6:12 pm, edited 2 times in total.
User avatar
MochiMoppel
Posts: 1115
Joined: Mon Jun 15, 2020 6:25 am
Location: Japan
Has thanked: 17 times
Been thanked: 359 times

Re: Experimental: Friendly shutdown

Post by MochiMoppel »

HerrBert wrote: Fri Dec 17, 2021 10:52 pm

What happens to me often is, that i have applications with unsaved changes on different desktops. So when i shutdown, all these unsaved changes are lost due to killing the WM.

I once raised this topic in the old Murga forum (https://oldforum.puppylinux.com/viewtopic.php?t=94371) but couldn't see much enthusiasm to improve the shutdown behavior.

For my own use I prefer wmctrl to do the "friendly shutdown" but I'm sure you can do this with xdotool as well. Good luck :thumbup2:

HerrBert
Posts: 329
Joined: Mon Jul 13, 2020 6:14 pm
Location: Germany, NRW
Has thanked: 17 times
Been thanked: 110 times

Re: Experimental: Friendly shutdown

Post by HerrBert »

MochiMoppel wrote: Sat Dec 18, 2021 2:00 am

I once raised this topic in the old Murga forum (https://oldforum.puppylinux.com/viewtopic.php?t=94371) but couldn't see much enthusiasm to improve the shutdown behavior.

For my own use I prefer wmctrl to do the "friendly shutdown" but I'm sure you can do this with xdotool as well. Good luck :thumbup2:

Thank you.
Very sad i didn't find your post before. It is exactly what i was looking for.

Good to know i'm not the only one feeling uncomfortable with this killing all and everything.

My various searches for gracefully close windows and shutdown did not bring up very many related results at all. But there were a few matches using wmctrl too.

Since wmctrl and xdotool are not included in all Puppies i have at hand here, i decided to give xdotool a try, because i already use it for some other stuff.

HerrBert
Posts: 329
Joined: Mon Jul 13, 2020 6:14 pm
Location: Germany, NRW
Has thanked: 17 times
Been thanked: 110 times

Re: Experimental: Friendly shutdown

Post by HerrBert »

Update:

I've removed the attachment from 1st post so please install
xdotool from ppm if not already in your Puppy...

Tested on
· Slacko64 7.0 -> works
· Slacko 6.3.2 -> doesn't move windows to current desktop, otherwise works
· FossaPup64 9.5 -> fails
· BionicPup64 8.0 -> works
· BusterPup 8.0 -> works
· FocalPup20.12+8 -> works

Issues:

In FossaPup64 9.5 scripts are run with tty when started from rox.
So my test -t 0 will be true and exit.

I tried to overcome the test by getting the PPID of the shell,
just in case the script is started from a terminal.

This works in all afore mentioned Puppies BUT FossaPup64 9.5.
It may also fail on others, where i changed the settings for urxvt.
I didn't test it any further yet.

What i found so far is, that urxvt consists of 2 window ids with
the same _NET_WM_PID. ps -ef returns 2 different pids with the
same ppid.
Searching for the parent pid of the shell with
xdotool search --pid returns 2 window ids but xprop only returns
the window id for the embedded window.

Also there may be an issue with conky, which i actually don't run,
but in FossaPup64 9.5 it starts by default. In my understanding
xdotool windowactivate --sync tries to activate conky, but i guess
this will fail and cause a long delay. Also moving sticky windows
to the current desktop is no good idea (though it seems to work in
case of conky...)

The following is only to close windows - not shutdown:

Code: Select all

#!/bin/bash
# close open programs gracefully
# move open windows to current desktop, activate window and send key alt+F4

# IMPORTANT: do NOT close terminal in case started from!!!
MYPPID=$$
while [ $MYPPID -ne 1 ] ; do
  read MYPPID CMD <<<"$(ps --no-headers --format ppid,cmd --pid $MYPPID)"
  [ "$CMD" = "${SHELL##*/}" ] && break
done

PROP="$(xprop -root _NET_CLIENT_LIST_STACKING _NET_CURRENT_DESKTOP)"
STACK="${PROP%$'\n'*}"
STACK="${STACK#*\#}"
DESK="${PROP##* }"

[ $MYPPID -ne 1 ] && TERMINAL="$(xdotool search --pid $MYPPID)"

for WID in ${STACK//,}; do
	[ "$(echo "$TERMINAL" | grep $((WID)))" ] && continue
	xdotool set_desktop_for_window $WID $DESK sleep .2 windowactivate --sync $WID key alt+F4
done

# all windows closed?
PROP="$(xprop -root _NET_CLIENT_LIST_STACKING)"
PROP="${PROP#*\#}"
if [ "${PROP}" != " " ]; then
	for WID in ${PROP//,}; do
		[ "$(echo "$TERMINAL" | grep $((WID)))" ] && continue
		exit 255
	done
fi

EDIT:
I've downloaded and compiled latest version of xdotool from
https://github.com/jordansissel/xdotool
xdotool 3.20211022.1 has new command windowquit

Close a window gracefully. This action sends a request, allowing the
application to apply close confirmation mechanics. If no window is given, %1
is the default. See WINDOW STACK and COMMAND CHAINING for more details.

This supersedes windowactivate and key in the above code.

Note:
make install installs libs to /usr/lib. At least on Slacko64 7.0 you have
to move libs to /usr/lib64

Post Reply

Return to “Cutting Edge”