init
This commit is contained in:
+65
@@ -0,0 +1,65 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
# Most of the code taken from
|
||||
# https://unix.stackexchange.com/questions/48860/how-to-dump-the-icon-of-a-running-x-program
|
||||
|
||||
|
||||
SIZE=16
|
||||
COLOR="#00000000"
|
||||
|
||||
wid="$2"
|
||||
# wid="$(xdotool selectwindow)"
|
||||
# class="$(bspc query -T -n "$wid" | jq -r '.client.className')"
|
||||
WM_CLASS="$(xprop -id "$wid" WM_CLASS | awk '{print $4}' | tr -d '"')"
|
||||
|
||||
name="$WM_CLASS"
|
||||
|
||||
|
||||
CACHE="$1/$name"
|
||||
|
||||
if [ -f "$CACHE.jpg" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
# Check if there is an icon for us in xprop,
|
||||
# so it won't break the behavior of the script
|
||||
if [ -z "$(xprop -id "$wid" | grep "Icon")" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
# Resize it in advance, so icons will look better, but it's not necessary, so
|
||||
# you can remove "-resize" flag if you prefer it the other way
|
||||
cmd=(convert -resize "$SIZE"x"$SIZE" -set 'filename:w' '%w' - "${name}.png")
|
||||
|
||||
split_icons() {
|
||||
xprop -id "$wid" -notype 32c _NET_WM_ICON |
|
||||
awk -v RS=', | = ' '
|
||||
NR == 1 { h = $1; i++; next }
|
||||
NR == i + 1 { x = $1; printf "%s = %s", h, x; next }
|
||||
NR == i + 2 { s = x * $1 } { printf ", %s", $1 }
|
||||
NR == i + 2 + s { i += s + 2; printf "\n" }
|
||||
'
|
||||
}
|
||||
|
||||
to_pam() {
|
||||
perl -0777 -pe '@_=/\d+/g;
|
||||
printf "P7\nWIDTH %d\nHEIGHT %d\n", splice@_,0,2;
|
||||
printf "DEPTH 4\nMAXVAL 255\nTUPLTYPE RGB_ALPHA\nENDHDR\n";
|
||||
$_=pack "N*", @_;
|
||||
s/(.)(...)/$2$1/gs'
|
||||
}
|
||||
|
||||
|
||||
|
||||
while read -r data; do to_pam <<< "$data" | "${cmd[@]}"; done < <(split_icons)
|
||||
|
||||
convert "$name.png" -background $COLOR -flatten -alpha off "$name.jpg"
|
||||
mv "$name.jpg" "$CACHE.jpg" && rm "$name.png"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+187
@@ -0,0 +1,187 @@
|
||||
#!/bin/bash
|
||||
|
||||
GAP=""
|
||||
|
||||
print_info() {
|
||||
echo -n "$GAP"
|
||||
|
||||
local DESK="$(bspc query --names -D -d focused)"
|
||||
|
||||
case $DESK in
|
||||
1)
|
||||
DESKICON=""
|
||||
;;
|
||||
2)
|
||||
DESKICON=""
|
||||
;;
|
||||
3)
|
||||
DESKICON=""
|
||||
;;
|
||||
4)
|
||||
DESKICON=""
|
||||
;;
|
||||
5)
|
||||
DESKICON=""
|
||||
;;
|
||||
6)
|
||||
DESKICON=""
|
||||
;;
|
||||
7)
|
||||
DESKICON=""
|
||||
;;
|
||||
8)
|
||||
DESKICON=""
|
||||
;;
|
||||
9)
|
||||
DESKICON=""
|
||||
;;
|
||||
*)
|
||||
DESKICON=""
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "$1" = "Empty" ]; then
|
||||
echo "$DESKICON $(whoami)@$(uname -n) - $(uname -r)"
|
||||
else
|
||||
local wid="$1"
|
||||
|
||||
# Doesn't always work, so xprop is more realiable here
|
||||
# WM_CLASS="$(bspc query -T -n "$Node" | jq -r '.client.className')"
|
||||
local WM_CLASS="$(xprop -id "$wid" WM_CLASS | awk '{print $4}' | tr -d '"')"
|
||||
local WM_NAME="$(xprop -id $wid _NET_WM_NAME | awk -F '=' '{print $2}' | tr -d '"')"
|
||||
|
||||
case "$WM_CLASS" in
|
||||
'firefox')
|
||||
echo "$DESKICON ${WM_NAME:0:100}";;
|
||||
'kitty')
|
||||
echo "$DESKICON ${WM_NAME:0:100}";;
|
||||
'code-oss')
|
||||
echo "$DESKICON ${WM_NAME:0:100}";;
|
||||
'Audacious')
|
||||
echo "$DESKICON ﱘ ${WM_NAME:0:100}";;
|
||||
'io.github.celluloid_player.Celluloid')
|
||||
echo "$DESKICON ${WM_NAME:0:100}";;
|
||||
'Lutris')
|
||||
echo "$DESKICON ${WM_NAME:0:100}";;
|
||||
'discord')
|
||||
echo "$DESKICON ﭮ ${WM_NAME:0:100}";;
|
||||
'Nemo')
|
||||
echo "$DESKICON ${WM_NAME:0:100}";;
|
||||
*)
|
||||
# https://stackoverflow.com/questions/1538676/uppercasing-first-letter-of-words-using-sed
|
||||
echo "$DESKICON ${WM_NAME:0:100}" | sed -e "s/\b\(.\)/\u\1/g";;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
exists_fullscreen_node() {
|
||||
local fullscreen_nodes="$(bspc query -N -n .fullscreen.\!hidden -d "$1")"
|
||||
|
||||
if [ -n "$fullscreen_nodes" ]; then
|
||||
echo '1'
|
||||
else
|
||||
echo '0'
|
||||
fi
|
||||
}
|
||||
|
||||
process_window() {
|
||||
local desk="$2"
|
||||
local wid="$1"
|
||||
local WM_CLASS="$(xprop -id "$wid" WM_CLASS | awk '{print $4}' | tr -d '"')"
|
||||
|
||||
# If there is a fullscreen node, don't show anything,
|
||||
# since we shouldn't see it
|
||||
if [ "$(exists_fullscreen_node "$desk")" = "1" ]; then
|
||||
return 0;
|
||||
fi
|
||||
|
||||
|
||||
|
||||
print_info "$wid"
|
||||
}
|
||||
|
||||
|
||||
is_desktop_empty() {
|
||||
local desk="$1"
|
||||
local nodes="$(bspc query -N -n .window.\!hidden -d "$desk")"
|
||||
|
||||
|
||||
if [ -n "$nodes" ]; then
|
||||
echo '0'
|
||||
else
|
||||
echo '1'
|
||||
fi
|
||||
}
|
||||
|
||||
process_desktop() {
|
||||
local desk="$1"
|
||||
local is_empty="$(is_desktop_empty "$desk")"
|
||||
|
||||
if [ "$is_empty" = "1" ]; then
|
||||
|
||||
print_info "Empty"
|
||||
fi
|
||||
}
|
||||
|
||||
bspc subscribe node_focus | while read -r Event Monitor Desktop Node
|
||||
do
|
||||
# For some reason "$Node" and "$Desktop" are not always working
|
||||
# properly with sticky windows
|
||||
Node="$(xdotool getactivewindow)"
|
||||
Desktop="$(bspc query -D -d focused)"
|
||||
|
||||
process_window "$Node" "$Desktop"
|
||||
|
||||
done &
|
||||
|
||||
bspc subscribe node_state | while read -r Event Monitor Desktop Node State Active
|
||||
do
|
||||
Node="$(xdotool getactivewindow)"
|
||||
Desktop="$(bspc query -D -d focused)"
|
||||
|
||||
if [ "$State" != "fullscreen" ]; then
|
||||
continue;
|
||||
fi
|
||||
|
||||
# So, if you will focus on the other windows of the same app,
|
||||
# which are not fullscreen, you will see icon
|
||||
|
||||
|
||||
if ![ "$Active" = "on" ]; then
|
||||
process_window "$Node" "$Desktop"
|
||||
fi
|
||||
|
||||
done &
|
||||
|
||||
bspc subscribe node_add | while read -r Event Monitor Desktop Ip Node
|
||||
do
|
||||
State="$(bspc query -T -n "$Node" | jq -r '.client.state')"
|
||||
done &
|
||||
|
||||
bspc subscribe node_flag | while read -r Event Monitor Desktop Node Flag Active
|
||||
do
|
||||
if [ "$Flag" = "hidden" ] && [ "$Desktop" = "$(bspc query -D -d .focused)" ]; then
|
||||
process_desktop "$Desktop"
|
||||
fi
|
||||
|
||||
done &
|
||||
|
||||
bspc subscribe node_remove | while read -r Event Monitor Desktop Node
|
||||
do
|
||||
process_desktop "$Desktop"
|
||||
|
||||
done &
|
||||
|
||||
bspc subscribe desktop_focus | while read -r Event Monitor Desktop
|
||||
do
|
||||
|
||||
if [ "$(exists_fullscreen_node "$Desktop")" = "1" ]; then
|
||||
|
||||
continue;
|
||||
fi
|
||||
|
||||
process_desktop "$Desktop"
|
||||
|
||||
done
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,148 @@
|
||||
// compilation:
|
||||
// g++ polybar-xwindow-icon.cpp -o polybar-xwindow-icon -I/usr/include/opencv4/ -lopencv_core -lopencv_videoio -lopencv_highgui -lopencv_imgcodecs -lopencv_imgproc -lX11
|
||||
//
|
||||
// Code is mostly copied from
|
||||
// https://stackoverflow.com/questions/54513419/putting-image-into-a-window-in-x11
|
||||
|
||||
// Some parts are taken from
|
||||
// https://stackoverflow.com/questions/57078155/draw-border-frame-using-xlib
|
||||
|
||||
|
||||
|
||||
#include <opencv2/opencv.hpp> // FOR OpenCV
|
||||
#include <opencv2/core/core.hpp> // Basic OpenCV structures (cv::Mat)
|
||||
#include <opencv2/video/video.hpp>
|
||||
#include <opencv2/imgproc/imgproc.hpp>
|
||||
#include <opencv2/highgui/highgui.hpp>
|
||||
|
||||
#include <bits/stdc++.h>
|
||||
#include <X11/Xlib.h> // Every Xlib program must include this
|
||||
#include <assert.h> // I include this to test return values the lazy way
|
||||
#include <unistd.h> // So we got the profile for 10 seconds
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/Xlib.h> // Every Xlib program must include this
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/extensions/Xcomposite.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
#include <X11/extensions/shape.h>
|
||||
#define NIL (0) // A name for the void pointer
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
|
||||
XGCValues gr_values;
|
||||
//GC gc;
|
||||
XColor color, dummy;
|
||||
|
||||
|
||||
Display *dpy = XOpenDisplay(NIL);
|
||||
//assert(dpy);
|
||||
//int screen = DefaultScreen(dpy);
|
||||
// Get some colors
|
||||
|
||||
int blackColor = BlackPixel(dpy, DefaultScreen(dpy));
|
||||
int whiteColor = WhitePixel(dpy, DefaultScreen(dpy));
|
||||
|
||||
// Create the window
|
||||
|
||||
Window w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 270, 6,
|
||||
24, 24, 0, whiteColor, blackColor);
|
||||
|
||||
// We want to get MapNotify events
|
||||
|
||||
XSelectInput(dpy, w, StructureNotifyMask);
|
||||
// XSelectInput(dpy, w, ExposureMask);
|
||||
long value = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
|
||||
|
||||
XChangeProperty(dpy, w, XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False),
|
||||
XA_ATOM, 32, PropModeReplace, (unsigned char *) &value, 1);
|
||||
|
||||
XClassHint *polybar_xwindow_icon;
|
||||
|
||||
//my_struct = malloc(sizeof(t_data));
|
||||
polybar_xwindow_icon = XAllocClassHint();
|
||||
polybar_xwindow_icon->res_name = "polybar-xwindow-icon";
|
||||
polybar_xwindow_icon->res_class = "Polybar-xwindow-icon";
|
||||
|
||||
XSetClassHint(dpy, w, polybar_xwindow_icon);
|
||||
XFree(polybar_xwindow_icon);
|
||||
|
||||
|
||||
XMapWindow(dpy, w);
|
||||
|
||||
// Wait for the MapNotify event
|
||||
|
||||
for(;;) {
|
||||
XEvent e;
|
||||
XNextEvent(dpy, &e);
|
||||
if (e.type == MapNotify)
|
||||
break;
|
||||
}
|
||||
|
||||
Window focal = w;
|
||||
|
||||
XWindowAttributes gwa;
|
||||
XGetWindowAttributes(dpy, w, &gwa);
|
||||
int wd1 = gwa.width;
|
||||
int ht1 = gwa.height;
|
||||
|
||||
|
||||
|
||||
XImage *image = XGetImage(dpy, w, 0, 0 , wd1, ht1, AllPlanes, ZPixmap);
|
||||
unsigned long rm = image->red_mask;
|
||||
unsigned long gm = image->green_mask;
|
||||
unsigned long bm = image->blue_mask;
|
||||
|
||||
Mat img(ht1, wd1, CV_8UC3); // OpenCV Mat object is initilaized
|
||||
Mat scrap = imread(argv[1]);//(wid, ht, CV_8UC3);
|
||||
resize(scrap, img, img.size(), cv::INTER_AREA);
|
||||
|
||||
for (int x = 0; x < wd1; x++)
|
||||
for (int y = 0; y < ht1 ; y++)
|
||||
{
|
||||
unsigned long pixel = XGetPixel(image,x,y);
|
||||
|
||||
Vec3b color = img.at<Vec3b>(Point(x,y));
|
||||
|
||||
|
||||
|
||||
pixel = 65536 * color[2] + 256 * color[1] + color[0];
|
||||
|
||||
XPutPixel(image, x, y, pixel);
|
||||
}
|
||||
|
||||
// namedWindow("QR", CV_WINDOW_NORMAL);
|
||||
// imshow("QR", img);
|
||||
|
||||
|
||||
GC gc = XCreateGC(dpy, w, 0, NIL);
|
||||
XPutImage(dpy, w, gc, image, 0, 0, 0, 0, wd1, ht1);
|
||||
|
||||
int run = 1;
|
||||
|
||||
while(run) {
|
||||
XEvent xe;
|
||||
XNextEvent(dpy, &xe);
|
||||
switch (xe.type) {
|
||||
case Expose:
|
||||
XPutImage(dpy, w, gc, image, 0, 0, 0, 0, wd1, ht1);
|
||||
XSetForeground(dpy, gc, color.pixel);
|
||||
XSync(dpy, False);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
XDestroyWindow(dpy, w);
|
||||
XCloseDisplay(dpy);
|
||||
|
||||
|
||||
// waitKey(0);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user