How to make a single window vnc session with x11vnc? - vnc

I want to create a VNC session to expose a single application that I start on a virtual display. And I want to do it with x11vnc because after that I can expose it through noVNC.
The problem is that x11vnc allows me to create a virtual display:
x11vnc -create
... or to expose a single window of an already launched application
x11vnc -id 0x200002
but I did not find any option to start a new application in a new virtual display (like xstartup for vncserver).

So far the only solution I found is to do all the procedure manually
# create a virtual display on the compute node
Xvnc :33 &
# launch the application on this virtual display
export DISPLAY=:33
glxgears &
# find out its window id
xwininfo -root -children
# -> xwininfo: Window id: 0xdc (the root window) (has no name)
#
# Root window id: 0xdc (the root window) (has no name)
# Parent window id: 0x0 (none)
# 1 child:
# 0x200002 "glxgears": () 300x300+0+0 +0+0
# start the vnc server with this specifix xid
x11vnc -id 0x200002 &
It works but it is a bit complex and I still have to write a small command to get the xid automatically.

I don't have enough "reputation" to write a comment, so I have to write my own answer despite this being just a modification to Michael's answer, which TBH I have yet to test. I came up with a quick hack to get the window ID since I won't be able to input it manually. Try this to find out the Window ID:
window_id=$(xwininfo -root -tree | grep glxgears | tail -n1 | sed "s/^[ \t]*//" | cut -d ' ' -f1)
So you're getting the tree, filtering for the program you're looking for, getting the last option, removing trailing whitespace, then getting only the first column, and saving it. Then you can run...
x11vnc -id $window_id &
...to the same effect as Michael's answer. Hopefully. Like I said, it's a hack.

Nice one for sharing windows at the office !
echo "Select Window...";x11vnc -id $(xwininfo|grep -oP '(?<=id: ).*(?= ")') -viewonly -forever
Or a shorter one:
x11vnc -id pick -viewonly -forever

x11vnc supports sharing a window based on it’s id. Here you can take simulator as window and share it.
Below is steps:
Run xwininfo from a terminal. Click on the window you want to
share. xwininfo will print out the window id.
Run `x11vnc -id win_id take win_id from above steps.
Example command:
x11vnc -id 0x2800005

Related

Retrieving active window from Mutter on Gnome/Wayland session

I'm trying to write an application that sends different dBus signals to different applications depending on what application is active. The idea is to pair it with Libinput-gestures, and allow per application gesture response. Problem is, it's impossible to tell which application is active on the client side.
I've been doing some research into detecting if an application has focus on any particular window manager under Wayland. Consensus is, Wayland doesn't know if an application has focus, and will not give that information. However the window manager itself does know.
So is there a way of creating an entirely server side routine for gnome, to send the title of the active window client side, to a select number of applications. In other words, we still have the "security" of not letting arbitrary applications know everything about the environment, but still allow some accessibility minded software retrieve that information and use it.
Almost 2 years old, but here it goes!! I don't know for sure if Mutter may have a way to do this as well, or if there is a better way to do the following. I suspect with better knowledge of gdbus and further research you can also convert this into some sort of official gdbus monitoring that can communicate with other apps so you do not have to ping for the status.
This is specific to Gnome and I suspect works on at least 3.15+. Tested on Ubuntu 19.10 Wayland. (Gnome 3.34.2)
# Single Command, runs 2 calls to gdbus to get the currently active Window from Gnome 3.x
# Escaped so you can copy and paste into terminal directly
gdbus call -e -d org.gnome.Shell -o /org/gnome/Shell -m org.gnome.Shell.Eval global.get_window_actors\(\)[`gdbus call -e -d org.gnome.Shell -o /org/gnome/Shell -m org.gnome.Shell.Eval global.get_window_actors\(\).findIndex\(a\=\>a.meta_window.has_focus\(\)===true\) | cut -d"'" -f 2`].get_meta_window\(\).get_wm_class\(\) | cut -d'"' -f 2
# Unescaped version, will not run
# Broken down into 2 commands.
# Call to Gnome to get the array location of the active Application
gdbus call -e -d org.gnome.Shell -o /org/gnome/Shell -m org.gnome.Shell.Eval \
global.get_window_actors().findIndex(a=>a.meta_window.has_focus()===true) \
| cut -d"'" -f 2
# Replace the array number 2 with the one from the previous command and you will get the App Name of the actively focused Window
gdbus call -e -d org.gnome.Shell -o /org/gnome/Shell -m org.gnome.Shell.Eval \
global.get_window_actors()[2].get_meta_window().get_wm_class() \
| cut -d'"' -f 2
And here is a gist I made as a note to myself, same as the code above. https://gist.github.com/rbreaves/257c3edfa301786e66e964d7ac036269
I also have a non-gdbus method on how to do something similar for KDE5 Plasma under Wayland up on my github for anyone interested. (added some code to an existing Plasmoid that was retrieving the class names already.)
The following works with Gnome 43:
Install https://extensions.gnome.org/extension/4974/window-calls-extended/
Run gdbus call --session --dest org.gnome.Shell --object-path /org/gnome/Shell/Extensions/WindowsExt --method org.gnome.Shell.Extensions.WindowsExt.FocusPID | sed -E "s/\\('(.*)',\\)/\\1/g" to get the PID of the focussed window or use a different method.

How to write bash script to re-attach to a existing linux screen?

I want to write a bash script to re-attach to the existing linux screen, perform some commands and then detach from that screen. I know to create a new linux screen in detached mode and perform some commands. But I haven't found a way to re-attach to a existing linux screen.
You can give a name to a screen session by using the -S option.
Example : screen -dS NAME <command>
Then you can reattach to that session using screen -r NAME
try this;
user#host:/screen -ls
There are screens on:
29229558.pts-5.host (Detached)
46661728.pts-22.host (Detached)
user#host:/screen -r 46661728.pts-22.host
If you see (attached) as below;
user#host:/screen -ls
There are screens on:
29229558.pts-5.host (Detached)
46661728.pts-22.host (Atached)
screen -D -r 46661728.pts-22.host
To re-attach to the screen you have to follow this steps:
Before de-attaching from the screen, execute:
STDOUTTERM=$(who -m|awk '{print $2}')
Then you can attach stdout to whatever you want. When you finish, to reattach to stdout, execute this:
exec > /dev/$STDOUTTERM
You can send a command to a running screen using screen -X exec. See the man page for redirection options.
screen -X exec ls
Alternatively you can send text to a running screen's stdin buffer using screen -X paste, as if the user had typed it. This can be a way of running commands inside an interactive shell.
screen -X register a "ls\n"
screen -X paste a

Access SSH client IP address, within a screen session

Accessing the IP address of a connecting SSH client is possible via environment variables (such as SSH_CONNECTION), as described in
Find the IP address of the client in an SSH session
In a GNU screen session though, those environment variables are defined by whoever started the screen to begin with. Is there any way to also get hold of the SSH connection information, for someone who enters an already-existing screen session later, like from another host?
I can't think of a way to determine this, but this can be useful in cases where screen sessions are shared between different people, for example.
If the screen session is launched as root, you can but it won't be perfectly reliable
If two users type in the same screen window, they will both interact within the same shell. One can write a command. The other can press the <enter> key.
You have to get access to the environment variable SSH_CONNECTION (or better SSH_CLIENT) which is only possible if you are root, or if you use the same user inside the screen session.
Supposing you are root inside the screen session, you can know the last user active in a screen session by using the ps command and finding the last active session.
ps h -C screen katime -o pid,user
By using the pid, and accessing the /proc/<pid>/environ file, you can get the SSH_CLIENT variable.
sed -z '/SSH_CLIENT/p;d' /proc/`ps h -C screen katime -o pid |head -1`/environ
--> SSH_CLIENT=257.31.120.12
All of this suppose that your screen is executed as root
You can also chose to log all the active connections.
For such need, I would suggest you to store both the full list of connections and their last activity.
ps eh -C screen kstime -o pid,atime | while read pid stime; do echo -n "$stime: ";\
gawk -v 'RS=\0' -F= '$1=="SSH_CLIENT" {print $2}' /proc/$pid/environ; done
Result:
00:00:00: 257.31.120.12 61608 22
00:07:11: 258.1.2.3.4 49947 22
Note that you can also parse the result of the ps eh -C screen kstime -o args command if you find it easier.
EDIT:
This is a working Debian command to get all users currently connected to the same screen session:
find /var/run/screen/
-name $(pstree -sp $$ |sed 's/.*screen(\([0-9]*\)).*/\1/;q').*
-printf "%h\n"
| cut -f2 -d-
You can check the output of the last command that would list of all IP addresses or hostnames of all connection made if sshd is the only way to connect to server.
ec2-user]# last
ec2-user pts/0 115.250.185.183 Sun May 29 13:49 still logged in
ec2-user pts/0 115.250.140.241 Sat May 28 07:26 - 10:15 (02:48)
root pts/4 113.21.68.105 Tue May 3 10:15 - 10:15 (00:00)
Alternatively (on Linux), you can check /var/log/secure where sshd will usually log all details of all the connections made even if they don't result in successful logins.
If you're trying to support the multi-display mode ('screen -x'), then as someone said above you are likely out of luck.
One the other hand, if you could assume single-user mode, then you could create a wrapper/alias for the screen command that carries along an environment variable into screen (see 'screen -X stuff ...'); in this case you are just passing along SSH_CLIENT that will have the appropriate value.
If you can assume a given username comes from a single location (or, if more than one location, then simply choose most recent), then you can do some grep/sed on output of 'last' command.
client_ip=`last -ai | grep "still logged in" | grep "$USER " | grep -v '0.0.0.0' | tail -n 1 | sed 's/.* //g'`
echo "Hello $client_ip"
If your screen is starting usually in detached mode, then in your .screenrc, add the the following:
shell -$SHELL
Then your screen will have all the the variables.
For currently running screens that you are stuck with, simply run.
source ~/.bash_profile
Replace the path and the file name to match your environment.

Bash tool to put an icon on taskbar?

I am trying to create a tiny application on my Ubuntu machine. What I want to do is put to an icon on my taskbar beside the volume, and internet connectivity options. I understand that there is a notify-send command in bash that I can use, or even switch to Qt but that seems to be an overkill for the problem. Concretely, is there a way to create an icon on Ubuntu taskbar with bash, and change its color or text periodically?
For a very shell friendly way to quickly get tray apps working use yad (specifically yad --notification). It allows you to dynamically change icons, set click event handlers and build a custom context menu. For example:
yad --notification --command='echo hello world' --image=myicon.png
Will echo 'hello world' on click. Or:
yad --notification --command='echo hello world' --image=myicon.png --listen
Will read it's standard input waiting for commands to change icons, change visibility, open menu, trigger action and more.
More advanced example using yad.
Shows how to handle click in the same script and how to change the icon on the click. Also shows how to create a simple update loop and exit cleanly.
# stop on error (always good practice)
set -e
# create a FIFO file, used to manage the I/O redirection from shell
PIPE=$(mktemp -u --tmpdir ${0##*/}.XXXXXXXX)
mkfifo $PIPE
export PIPE
# attach a file descriptor to the file
exec 3<> $PIPE
# add handler to manage process shutdown
function on_exit() {
# send command to yad through pipe
echo "quit" >&3
rm -f $PIPE
}
trap on_exit EXIT
function update_icon() {
exec 3<> $PIPE # just in case
echo "icon:/path/to/some/icon" >&3
}
export -f update_icon
# add handler for tray icon left click
function on_click() {
exec 3<> $PIPE # required
echo "clicked"
echo "icon:/path/to/icon" >&3
update_icon
}
export -f on_click
# add handler for right click menu Quit entry function
on_quit() {
# signal to the script that it should end when this file is created
echo "quit" > ./quit.txt
exec 3<> $PIPE # required
echo "quit" >&3
}
export -f on_quit
# Use a file to indicate a quit command to the script
# Make sure it is gone before we start the program to avoid immediate exit
rm -f quit.txt
# create the notification icon with right click menu and Quit option
yad --notification \
--listen \
--image="/path/to/icon" \
--text="demo tray icon" \
--menu="Quit!bash -c on_quit" \
--no-middle \
--command="bash -c on_click" <&3 &
# allow user to end the loop from icon right click Quit menu option
while [ ! -f "quit.txt" ]; do
#echo "Press [CTRL+C] to stop.."
update_icon
sleep 60
done
# clean up after quit
rm quit.txt
Based on:
https://code.google.com/archive/p/yad/wikis/NotificationIcon.wiki
https://sourceforge.net/p/yad-dialog/wiki/NotificationIcon/
https://groups.google.com/g/yad-common/c/DT8q1vJ-yOQ
I'm not a bash expert, so fixes are welcome.
yad is available for many distros as a standard package. On Debian for example it can be installed by apt install yad.
Take a look at alltray; maybe it's your solution.
From its website:
Description
With AllTray you can dock any application with no native tray icon (like Evolution, Thunderbird, Terminals) into the system tray. A high-light feature is that a click on the "close" button will minimize back to system tray. It works well with Gnome, KDE, XFCE 4*, Fluxbox* and WindowMaker*. Xmms is supported in particular.
Options
These programs follow the usual GNU command line syntax, with long
options starting with two dashes ('-'). A summary of options is
included below.
-h --help | Show summary of options.
-v --version | Show version of program.
-d --debug | Show debug messages.
-s --show | Do not hide window after start.
-i --icon | Use a PNG image as an icon.
-l --large_icons | allow large icons (> 24x24).
-st --sticky | visible on all workspaces.
-x --borderless | Remove windows decorations border, title, frame... from parent.
-m --menu | Add entry "menu text:command" to popdown menu.
-t --title | Show title change for seconds. Probably most usefull for xmms.
-g --geometry | initial position. see man X.
Installation (command in a terminal)
- in Ubuntu:
sudo apt-get install alltray
- in Fedora:
sudo dnf install alltray
Cheers

Is there any way to run an application as a screensaver in Linux

I want to run a full-screen application as a screen saver. Is it possible in Linux?
It seems that XScreenSaver is not capable of doing this and GnomeScreenSaver has this in their wish list.
An (untested) trick that might work would be to run your program under Xnest.
something like this pseudo shellcode may work:
#get root window id
RWINID=$(xwininfo -root |sed -n -e 's/.*Window.*id: \(0x[a-f0-9]\+\).*/\1/p')
#start Xnest on the root window
Xnest -parent $RWINID :5
DISPLAY=":5" myapp

Resources