From 17dcb0322d0984fa0f86ecd4ee73baa8d4ab7bc3 Mon Sep 17 00:00:00 2001 From: itdominator <1itdominator@gmail.com> Date: Mon, 24 Jan 2022 00:06:11 -0600 Subject: [PATCH] Major refactor --- README.md | 1 + bin/gwinwrap-0-0-2-x64.deb | Bin 0 -> 36088 bytes .../0.0.1}/GWinWrap/GWinWrap.desktop | 0 src/{ => versions/0.0.1}/GWinWrap/__init__.py | 0 src/{ => versions/0.0.1}/GWinWrap/__main__.py | 0 .../GWinWrap/resources/Main_Window.glade | 1 + .../GWinWrap/resources/icons/GWinWrap.png | Bin .../GWinWrap/resources/icons/folder.png | Bin .../GWinWrap/resources/icons/picture.png | Bin .../GWinWrap/resources/icons/player.png | Bin .../0.0.1}/GWinWrap/resources/stylesheet.css | 0 .../signal_classes/CrossClassSignals.py | 75 +- .../GWinWrap/signal_classes/__init__.py | 0 .../GWinWrap/utils/SaveGWinWrapSettings.py | 0 .../GWinWrap/utils/SaveStateToXWinWarp.py | 26 +- .../0.0.1}/GWinWrap/utils/Settings.py | 2 +- .../0.0.1}/GWinWrap/utils/__init__.py | 0 src/{ => versions/0.0.1}/XWinWrap/Makefile | 0 src/{ => versions/0.0.1}/XWinWrap/xwinwrap.c | 0 src/{ => versions/0.0.1}/compileBin.sh | 0 .../0.0.1}/gwinwrap_exec_bin.cpp | 0 src/versions/0.0.2/GWinWrap/__builtins__.py | 73 ++ src/versions/0.0.2/GWinWrap/__init__.py | 50 + src/versions/0.0.2/GWinWrap/__main__.py | 39 + .../GWinWrap/signal_classes/Controller.py | 151 +++ .../signal_classes/Controller_Data.py | 102 ++ .../GWinWrap/signal_classes/IPCServerMixin.py | 64 ++ .../signal_classes/SaveGWinWrapSettings.py | 49 + .../signal_classes/SaveStateToXWinWarp.py | 68 ++ .../0.0.2/GWinWrap/signal_classes/__init__.py | 9 + .../signal_classes/mixins/DrawAreaMixin.py | 59 ++ .../signal_classes/mixins/GridMixin.py | 116 +++ .../signal_classes/mixins/ImageViewerMixin.py | 34 + .../signal_classes/mixins/ThumbnailMixin.py | 56 ++ .../signal_classes/mixins/__init__.py | 4 + src/versions/0.0.2/GWinWrap/utils/Logger.py | 56 ++ src/versions/0.0.2/GWinWrap/utils/Settings.py | 112 +++ src/versions/0.0.2/GWinWrap/utils/__init__.py | 6 + src/versions/0.0.2/XWinWrap/Makefile | 20 + src/versions/0.0.2/XWinWrap/xwinwrap.c | 459 +++++++++ src/versions/0.0.2/compileBin.sh | 6 + src/versions/0.0.2/gwinwrap_exec_bin.cpp | 10 + .../usr/share/gwinwrap/Main_Window.glade | 882 ++++++++++++++++++ user_config/usr/share/gwinwrap/icons/dir.png | Bin 0 -> 850 bytes .../usr/share/gwinwrap/icons/gwinwrap.png | Bin 0 -> 9278 bytes .../usr/share/gwinwrap/icons/picture.png | Bin 0 -> 6591 bytes .../usr/share/gwinwrap/icons/video.png | Bin 0 -> 1313 bytes user_config/usr/share/gwinwrap/settings.json | 9 + user_config/usr/share/gwinwrap/stylesheet.css | 86 ++ 49 files changed, 2580 insertions(+), 45 deletions(-) create mode 100644 bin/gwinwrap-0-0-2-x64.deb rename src/{ => versions/0.0.1}/GWinWrap/GWinWrap.desktop (100%) rename src/{ => versions/0.0.1}/GWinWrap/__init__.py (100%) rename src/{ => versions/0.0.1}/GWinWrap/__main__.py (100%) rename src/{ => versions/0.0.1}/GWinWrap/resources/Main_Window.glade (99%) rename src/{ => versions/0.0.1}/GWinWrap/resources/icons/GWinWrap.png (100%) rename src/{ => versions/0.0.1}/GWinWrap/resources/icons/folder.png (100%) rename src/{ => versions/0.0.1}/GWinWrap/resources/icons/picture.png (100%) rename src/{ => versions/0.0.1}/GWinWrap/resources/icons/player.png (100%) rename src/{ => versions/0.0.1}/GWinWrap/resources/stylesheet.css (100%) rename src/{ => versions/0.0.1}/GWinWrap/signal_classes/CrossClassSignals.py (87%) rename src/{ => versions/0.0.1}/GWinWrap/signal_classes/__init__.py (100%) rename src/{ => versions/0.0.1}/GWinWrap/utils/SaveGWinWrapSettings.py (100%) rename src/{ => versions/0.0.1}/GWinWrap/utils/SaveStateToXWinWarp.py (73%) rename src/{ => versions/0.0.1}/GWinWrap/utils/Settings.py (95%) rename src/{ => versions/0.0.1}/GWinWrap/utils/__init__.py (100%) rename src/{ => versions/0.0.1}/XWinWrap/Makefile (100%) rename src/{ => versions/0.0.1}/XWinWrap/xwinwrap.c (100%) rename src/{ => versions/0.0.1}/compileBin.sh (100%) rename src/{ => versions/0.0.1}/gwinwrap_exec_bin.cpp (100%) create mode 100644 src/versions/0.0.2/GWinWrap/__builtins__.py create mode 100644 src/versions/0.0.2/GWinWrap/__init__.py create mode 100644 src/versions/0.0.2/GWinWrap/__main__.py create mode 100644 src/versions/0.0.2/GWinWrap/signal_classes/Controller.py create mode 100644 src/versions/0.0.2/GWinWrap/signal_classes/Controller_Data.py create mode 100644 src/versions/0.0.2/GWinWrap/signal_classes/IPCServerMixin.py create mode 100644 src/versions/0.0.2/GWinWrap/signal_classes/SaveGWinWrapSettings.py create mode 100644 src/versions/0.0.2/GWinWrap/signal_classes/SaveStateToXWinWarp.py create mode 100644 src/versions/0.0.2/GWinWrap/signal_classes/__init__.py create mode 100644 src/versions/0.0.2/GWinWrap/signal_classes/mixins/DrawAreaMixin.py create mode 100644 src/versions/0.0.2/GWinWrap/signal_classes/mixins/GridMixin.py create mode 100644 src/versions/0.0.2/GWinWrap/signal_classes/mixins/ImageViewerMixin.py create mode 100644 src/versions/0.0.2/GWinWrap/signal_classes/mixins/ThumbnailMixin.py create mode 100644 src/versions/0.0.2/GWinWrap/signal_classes/mixins/__init__.py create mode 100644 src/versions/0.0.2/GWinWrap/utils/Logger.py create mode 100644 src/versions/0.0.2/GWinWrap/utils/Settings.py create mode 100644 src/versions/0.0.2/GWinWrap/utils/__init__.py create mode 100644 src/versions/0.0.2/XWinWrap/Makefile create mode 100644 src/versions/0.0.2/XWinWrap/xwinwrap.c create mode 100755 src/versions/0.0.2/compileBin.sh create mode 100644 src/versions/0.0.2/gwinwrap_exec_bin.cpp create mode 100644 user_config/usr/share/gwinwrap/Main_Window.glade create mode 100644 user_config/usr/share/gwinwrap/icons/dir.png create mode 100644 user_config/usr/share/gwinwrap/icons/gwinwrap.png create mode 100644 user_config/usr/share/gwinwrap/icons/picture.png create mode 100644 user_config/usr/share/gwinwrap/icons/video.png create mode 100644 user_config/usr/share/gwinwrap/settings.json create mode 100644 user_config/usr/share/gwinwrap/stylesheet.css diff --git a/README.md b/README.md index cce5bf5..f75c6bf 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ It includes the XWinWrap binary and source code for Shantanu Goel's version of X # Notes * Need python 2+ +* Need PyGObject * When you first run the application and save settings for a screen, you need to chmod 744 the new file(s) in your $HOME directory. * A settings file per screen is generated. diff --git a/bin/gwinwrap-0-0-2-x64.deb b/bin/gwinwrap-0-0-2-x64.deb new file mode 100644 index 0000000000000000000000000000000000000000..0bb7b17ee04e26cd9776bfdbe004b8b3ee6bc16b GIT binary patch literal 36088 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 literal 0 HcmV?d00001 diff --git a/src/GWinWrap/GWinWrap.desktop b/src/versions/0.0.1/GWinWrap/GWinWrap.desktop similarity index 100% rename from src/GWinWrap/GWinWrap.desktop rename to src/versions/0.0.1/GWinWrap/GWinWrap.desktop diff --git a/src/GWinWrap/__init__.py b/src/versions/0.0.1/GWinWrap/__init__.py similarity index 100% rename from src/GWinWrap/__init__.py rename to src/versions/0.0.1/GWinWrap/__init__.py diff --git a/src/GWinWrap/__main__.py b/src/versions/0.0.1/GWinWrap/__main__.py similarity index 100% rename from src/GWinWrap/__main__.py rename to src/versions/0.0.1/GWinWrap/__main__.py diff --git a/src/GWinWrap/resources/Main_Window.glade b/src/versions/0.0.1/GWinWrap/resources/Main_Window.glade similarity index 99% rename from src/GWinWrap/resources/Main_Window.glade rename to src/versions/0.0.1/GWinWrap/resources/Main_Window.glade index e0d1930..495ebfe 100644 --- a/src/GWinWrap/resources/Main_Window.glade +++ b/src/versions/0.0.1/GWinWrap/resources/Main_Window.glade @@ -435,6 +435,7 @@ .animatedBGstarter.sh .animatedBGstarter2.sh + .animatedBGstarter3.sh diff --git a/src/GWinWrap/resources/icons/GWinWrap.png b/src/versions/0.0.1/GWinWrap/resources/icons/GWinWrap.png similarity index 100% rename from src/GWinWrap/resources/icons/GWinWrap.png rename to src/versions/0.0.1/GWinWrap/resources/icons/GWinWrap.png diff --git a/src/GWinWrap/resources/icons/folder.png b/src/versions/0.0.1/GWinWrap/resources/icons/folder.png similarity index 100% rename from src/GWinWrap/resources/icons/folder.png rename to src/versions/0.0.1/GWinWrap/resources/icons/folder.png diff --git a/src/GWinWrap/resources/icons/picture.png b/src/versions/0.0.1/GWinWrap/resources/icons/picture.png similarity index 100% rename from src/GWinWrap/resources/icons/picture.png rename to src/versions/0.0.1/GWinWrap/resources/icons/picture.png diff --git a/src/GWinWrap/resources/icons/player.png b/src/versions/0.0.1/GWinWrap/resources/icons/player.png similarity index 100% rename from src/GWinWrap/resources/icons/player.png rename to src/versions/0.0.1/GWinWrap/resources/icons/player.png diff --git a/src/GWinWrap/resources/stylesheet.css b/src/versions/0.0.1/GWinWrap/resources/stylesheet.css similarity index 100% rename from src/GWinWrap/resources/stylesheet.css rename to src/versions/0.0.1/GWinWrap/resources/stylesheet.css diff --git a/src/GWinWrap/signal_classes/CrossClassSignals.py b/src/versions/0.0.1/GWinWrap/signal_classes/CrossClassSignals.py similarity index 87% rename from src/GWinWrap/signal_classes/CrossClassSignals.py rename to src/versions/0.0.1/GWinWrap/signal_classes/CrossClassSignals.py index 2654eb9..6cbbb7e 100644 --- a/src/GWinWrap/signal_classes/CrossClassSignals.py +++ b/src/versions/0.0.1/GWinWrap/signal_classes/CrossClassSignals.py @@ -84,7 +84,6 @@ class CrossClassSignals: dir = widget.get_filename() threading.Thread(target=self.newDir, args=(dir,)).start() - @threaded def newDir(self, dir): imageGrid = self.builder.get_object("imageGrid") dirPath = dir @@ -97,41 +96,15 @@ class CrossClassSignals: if file.lower().endswith(('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm', '.png', '.jpg', '.jpeg', '.gif')): files.append(file) - fractionTick = 1.0 / 1.0 if len(files) == 0 else len(files) - tickCount = 0.0 + # fractionTick = 1.0 / 1.0 if len(files) == 0 else len(files) + # tickCount = 0.0 self.clear() imageGrid.remove_column(0) self.loadProgress.set_text("Loading...") self.loadProgress.set_fraction(0.0) self.helpLabel.set_markup("" + dirPath.strip(self.usrHome) + "") for file in files: - fullPathFile = dirPath + "/" + file - eveBox = gtk.EventBox() - thumbnl = gtk.Image() - - if file.lower().endswith(('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm')): - fileHash = hashlib.sha256(str.encode(fullPathFile)).hexdigest() - hashImgpth = self.usrHome + "/.thumbnails/normal/" + fileHash + ".png" - if isfile(hashImgpth) == False: - self.generateThumbnail(fullPathFile, hashImgpth) - - thumbnl = self.createGtkImage(hashImgpth, [310, 310]) - eveBox.connect("button_press_event", self.runMplayerProcess, (fullPathFile, file, eveBox,)) - eveBox.connect("enter_notify_event", self.mouseOver, ()) - eveBox.connect("leave_notify_event", self.mouseOut, ()) - elif file.lower().endswith(('.png', '.jpg', '.jpeg', '.gif')): - thumbnl = self.createGtkImage(fullPathFile, [310, 310]) - eveBox.connect("button_press_event", self.runImageViewerProcess, (fullPathFile, file, eveBox,)) - eveBox.connect("enter_notify_event", self.mouseOver, ()) - eveBox.connect("leave_notify_event", self.mouseOut, ()) - else: - print("Not a video or image file.") - continue - - glib.idle_add(self.preGridSetup, (eveBox, thumbnl, )) - glib.idle_add(self.addToGrid, (imageGrid, eveBox, col, row,)) - tickCount = tickCount + fractionTick - self.loadProgress.set_fraction(tickCount) + self.porocess_file(imageGrid, dirPath, file, col, row) col += 1 if col == 2: @@ -140,6 +113,39 @@ class CrossClassSignals: self.loadProgress.set_text("Finished...") + @threaded + def porocess_file(self, imageGrid, dirPath, file, col, row): + fullPathFile = dirPath + "/" + file + eveBox = gtk.EventBox() + thumbnl = gtk.Image() + + if file.lower().endswith(('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm')): + fileHash = hashlib.sha256(str.encode(fullPathFile)).hexdigest() + hashImgpth = self.usrHome + "/.thumbnails/normal/" + fileHash + ".png" + if isfile(hashImgpth) == False: + self.generateThumbnail(fullPathFile, hashImgpth) + + thumbnl = self.createGtkImage(hashImgpth, [310, 310]) + eveBox.connect("button_press_event", self.runMplayerProcess, (fullPathFile, file, eveBox,)) + eveBox.connect("enter_notify_event", self.mouseOver, ()) + eveBox.connect("leave_notify_event", self.mouseOut, ()) + elif file.lower().endswith(('.png', '.jpg', '.jpeg', '.gif')): + thumbnl = self.createGtkImage(fullPathFile, [310, 310]) + eveBox.connect("button_press_event", self.runImageViewerProcess, (fullPathFile, file, eveBox,)) + eveBox.connect("enter_notify_event", self.mouseOver, ()) + eveBox.connect("leave_notify_event", self.mouseOut, ()) + else: + print("Not a video or image file.") + return + + glib.idle_add(self.preGridSetup, (eveBox, thumbnl, )) + glib.idle_add(self.addToGrid, (imageGrid, eveBox, col, row,)) + # tickCount = tickCount + fractionTick + # self.loadProgress.set_fraction(tickCount) + + + + def preGridSetup(self, args): args[0].show() args[1].show() @@ -267,7 +273,7 @@ class CrossClassSignals: offset4Res = self.builder.get_object("posOffset") resolution = plyBckRes.get_active_text() + offset4Res.get_active_text() self.applyType = self.stateSaver.saveToFile(self.toSavePath, resolution, - saveLoc, useXscreenSaver, self.xScreenVal) + saveLoc, useXscreenSaver, self.xScreenVal, self.player) if self.applyType == -1: self.helpLabel.set_markup("Nothing saved...") return @@ -277,8 +283,11 @@ class CrossClassSignals: def applySttngs(self, widget, data=None): os.system("killall xwinwrap &") if self.applyType == 1: - os.system("bash -c '~/.animatedBGstarter.sh' &") - os.system("bash -c '~/.animatedBGstarter2.sh' &") + files = os.listdir(self.usrHome) + for file in files: + fPath = self.usrHome + "/" + file + if os.path.isfile(fPath) and "animatedBGstarter" in file: + os.system("bash -c '~/" + file + "' &") elif self.applyType == 2: os.system("nitrogen --restore &") else: diff --git a/src/GWinWrap/signal_classes/__init__.py b/src/versions/0.0.1/GWinWrap/signal_classes/__init__.py similarity index 100% rename from src/GWinWrap/signal_classes/__init__.py rename to src/versions/0.0.1/GWinWrap/signal_classes/__init__.py diff --git a/src/GWinWrap/utils/SaveGWinWrapSettings.py b/src/versions/0.0.1/GWinWrap/utils/SaveGWinWrapSettings.py similarity index 100% rename from src/GWinWrap/utils/SaveGWinWrapSettings.py rename to src/versions/0.0.1/GWinWrap/utils/SaveGWinWrapSettings.py diff --git a/src/GWinWrap/utils/SaveStateToXWinWarp.py b/src/versions/0.0.1/GWinWrap/utils/SaveStateToXWinWarp.py similarity index 73% rename from src/GWinWrap/utils/SaveStateToXWinWarp.py rename to src/versions/0.0.1/GWinWrap/utils/SaveStateToXWinWarp.py index ee0045d..1e086be 100644 --- a/src/GWinWrap/utils/SaveStateToXWinWarp.py +++ b/src/versions/0.0.1/GWinWrap/utils/SaveStateToXWinWarp.py @@ -5,24 +5,27 @@ import os class SaveStateToXWinWarp: def __init__(self): self.fileWriter = None - self.toSavePath = None + self.toSavePath = None self.useXSvrn = None self.xScreenVal = None self.sveFileLoc = None self.resolution = None + self.player = None + def saveToFile(self, toSavePath, resolution, - saveLoc, useXSvrn, xScreenVal): + saveLoc, useXSvrn, xScreenVal, player): self.toSavePath = toSavePath self.useXSvrn = useXSvrn self.xScreenVal = xScreenVal self.resolution = resolution + self.player = player userPth = os.path.expanduser('~') # Saves to file with selected and needed settings if toSavePath: - if toSavePath.lower().endswith(('.png', '.jpg', '.jpeg', '.gif')): + if toSavePath.lower().endswith(('.png', '.jpg', '.jpeg')): self.sveFileLoc = userPth + "/" + ".config/nitrogen/bg-saved.cfg" else: self.sveFileLoc = userPth + "/" + saveLoc @@ -40,9 +43,6 @@ class SaveStateToXWinWarp: applyType = 1 output = None - print("XScreen: " + str(self.useXSvrn)) - print(self.fileWriter) - # XSCREENSAVER if self.useXSvrn: output = "xwinwrap -ov -g " + self.resolution + " -st -sp -b -nf -s -ni -- /usr/lib/xscreensaver/" + self.xScreenVal + " -window-id WID -root"; @@ -51,15 +51,19 @@ class SaveStateToXWinWarp: output = "xwinwrap -ov -g " + self.resolution + " -st -sp -b -nf -s -ni -- gifview -a -w WID " + self.toSavePath; # Standard images using nitrogen elif self.toSavePath.lower().endswith(('.png', 'jpg', '.jpeg')): - output = "[xin_0] \n file=" + self.toSavePath + "\nmode=0 \nbgcolor=#000000\n[xin_1] \nfile=" + self.toSavePath + "\nmode=0 \nbgcolor=#000000"; + output = "[xin_0] \nfile=" + self.toSavePath + "\nmode=0 \nbgcolor=#000000\n\n[xin_1] \nfile=" + self.toSavePath + "\nmode=0 \nbgcolor=#000000"; applyType = 2; # VIDEO else: - output = "xwinwrap -ov -g " + self.resolution + " -st -sp -b -nf -s -ni -- mplayer -wid WID -really-quiet -ao null -loop 0 '" + self.toSavePath + "'"; + output = "xwinwrap -ov -g " + self.resolution + " -st -sp -b -nf -s -ni -- " + self.player + " -wid WID -really-quiet -ao null -loop 0 '" + self.toSavePath + "'"; pass - if self.fileWriter: - self.fileWriter.write(output) - self.fileWriter.close() + try: + if self.fileWriter: + self.fileWriter.write(output) + self.fileWriter.close() + except Exception as e: + print(":: Write failed! ::") + print(e) return applyType; diff --git a/src/GWinWrap/utils/Settings.py b/src/versions/0.0.1/GWinWrap/utils/Settings.py similarity index 95% rename from src/GWinWrap/utils/Settings.py rename to src/versions/0.0.1/GWinWrap/utils/Settings.py index 1f5479f..8ffc52a 100644 --- a/src/GWinWrap/utils/Settings.py +++ b/src/versions/0.0.1/GWinWrap/utils/Settings.py @@ -58,7 +58,7 @@ class Settings: monitors.append(screen.get_monitor_geometry(m)) for monitor in monitors: - print(str(monitor.width) + "x" + str(monitor.height) + "+" + str(monitor.x) + "+" + str(monitor.y)) + print("{}x{}+{}+{}".format(monitor.width, monitor.height, monitor.x, monitor.y)) return monitors diff --git a/src/GWinWrap/utils/__init__.py b/src/versions/0.0.1/GWinWrap/utils/__init__.py similarity index 100% rename from src/GWinWrap/utils/__init__.py rename to src/versions/0.0.1/GWinWrap/utils/__init__.py diff --git a/src/XWinWrap/Makefile b/src/versions/0.0.1/XWinWrap/Makefile similarity index 100% rename from src/XWinWrap/Makefile rename to src/versions/0.0.1/XWinWrap/Makefile diff --git a/src/XWinWrap/xwinwrap.c b/src/versions/0.0.1/XWinWrap/xwinwrap.c similarity index 100% rename from src/XWinWrap/xwinwrap.c rename to src/versions/0.0.1/XWinWrap/xwinwrap.c diff --git a/src/compileBin.sh b/src/versions/0.0.1/compileBin.sh similarity index 100% rename from src/compileBin.sh rename to src/versions/0.0.1/compileBin.sh diff --git a/src/gwinwrap_exec_bin.cpp b/src/versions/0.0.1/gwinwrap_exec_bin.cpp similarity index 100% rename from src/gwinwrap_exec_bin.cpp rename to src/versions/0.0.1/gwinwrap_exec_bin.cpp diff --git a/src/versions/0.0.2/GWinWrap/__builtins__.py b/src/versions/0.0.2/GWinWrap/__builtins__.py new file mode 100644 index 0000000..287a5fb --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/__builtins__.py @@ -0,0 +1,73 @@ +import builtins + +# Python imports +import builtins + +# Lib imports + +# Application imports +from signal_classes import IPCServerMixin + + + +class Builtins(IPCServerMixin): + """Docstring for __builtins__ extender""" + + def __init__(self): + # NOTE: The format used is list of [type, target, data] + # Where data may be any kind of data + self._gui_events = [] + self._fm_events = [] + self.is_ipc_alive = False + self.ipc_authkey = b'GWinWrap-ipc' + self.ipc_address = '127.0.0.1' + self.ipc_port = 8888 + self.ipc_timeout = 15.0 + + # Makeshift fake "events" type system FIFO + def _pop_gui_event(self): + if len(self._gui_events) > 0: + return self._gui_events.pop(0) + return None + + def _pop_fm_event(self): + if len(self._fm_events) > 0: + return self._fm_events.pop(0) + return None + + + def push_gui_event(self, event): + if len(event) == 3: + self._gui_events.append(event) + return None + + raise Exception("Invald event format! Please do: [type, target, data]") + + def push_fm_event(self, event): + if len(event) == 3: + self._fm_events.append(event) + return None + + raise Exception("Invald event format! Please do: [type, target, data]") + + def read_gui_event(self): + return self._gui_events[0] + + def read_fm_event(self): + return self._fm_events[0] + + def consume_gui_event(self): + return self._pop_gui_event() + + def consume_fm_event(self): + return self._pop_fm_event() + + + +# NOTE: Just reminding myself we can add to builtins two different ways... +# __builtins__.update({"event_system": Builtins()}) +builtins.app_name = "GWinWrap" +builtins.event_system = Builtins() +builtins.event_sleep_time = 0.2 +builtins.debug = False +builtins.trace_debug = False diff --git a/src/versions/0.0.2/GWinWrap/__init__.py b/src/versions/0.0.2/GWinWrap/__init__.py new file mode 100644 index 0000000..56356ba --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/__init__.py @@ -0,0 +1,50 @@ +# Python imports +import os, inspect, time + +# Lib imports + +# Application imports +from utils import Settings +from signal_classes import Controller +from __builtins__ import Builtins + + + + +class Main(Builtins): + def __init__(self, args, unknownargs): + if not debug: + event_system.create_ipc_server() + + time.sleep(0.2) + if not trace_debug: + if not event_system.is_ipc_alive: + if unknownargs: + for arg in unknownargs: + if os.path.isdir(arg): + message = f"FILE|{arg}" + event_system.send_ipc_message(message) + + raise Exception("IPC Server Exists: Will send data to it and close...") + + + settings = Settings() + settings.create_window() + + controller = Controller(settings, args, unknownargs) + if not controller: + raise Exception("Controller exited and doesn't exist...") + + # Gets the methods from the classes and sets to handler. + # Then, builder from settings will connect to any signals it needs. + classes = [controller] + handlers = {} + for c in classes: + methods = None + try: + methods = inspect.getmembers(c, predicate=inspect.ismethod) + handlers.update(methods) + except Exception as e: + print(repr(e)) + + settings.get_builder().connect_signals(handlers) diff --git a/src/versions/0.0.2/GWinWrap/__main__.py b/src/versions/0.0.2/GWinWrap/__main__.py new file mode 100644 index 0000000..dc06b1a --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/__main__.py @@ -0,0 +1,39 @@ +#!/usr/bin/python3 + + +# Python imports +import argparse, faulthandler, traceback +from setproctitle import setproctitle + +import tracemalloc +tracemalloc.start() + + +# Lib imports +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk + +# Application imports +from __init__ import Main + + +if __name__ == "__main__": + try: + # import web_pdb + # web_pdb.set_trace() + + setproctitle('GWinWrap') + faulthandler.enable() # For better debug info + parser = argparse.ArgumentParser() + # Add long and short arguments + parser.add_argument("--file", "-f", default="default", help="JUST SOME FILE ARG.") + + # Read arguments (If any...) + args, unknownargs = parser.parse_known_args() + + Main(args, unknownargs) + Gtk.main() + except Exception as e: + traceback.print_exc() + quit() diff --git a/src/versions/0.0.2/GWinWrap/signal_classes/Controller.py b/src/versions/0.0.2/GWinWrap/signal_classes/Controller.py new file mode 100644 index 0000000..adcb743 --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/signal_classes/Controller.py @@ -0,0 +1,151 @@ +# Python imports +import threading, signal, subprocess, inspect, os, time + +# Gtk imports +import gi +gi.require_version('Gtk', '3.0') +gi.require_version('Gdk', '3.0') +from gi.repository import Gtk, GLib, Gdk + +# Application imports +from .mixins import * +from . import Controller_Data + + +def threaded(fn): + def wrapper(*args, **kwargs): + threading.Thread(target=fn, args=args, kwargs=kwargs).start() + + return wrapper + + +class Controller(ThumbnailMixin, ImageViewerMixin, DrawAreaMixin, GridMixin, Controller_Data): + def __init__(self, _settings, args, unknownargs): + self.setup_controller_data(_settings) + self.window.show() + self.retrieve_settings() + + + def tear_down(self, widget=None, eve=None): + event_system.send_ipc_message("close server") + if self.demo_area_pid: + self.close_demo_popup() + + self.close_image_popup() + time.sleep(event_sleep_time) + Gtk.main_quit() + + def close_program(self, widget, data=None): + self.tear_down() + + + @threaded + def gui_event_observer(self): + while True: + time.sleep(event_sleep_time) + event = event_system.consume_gui_event() + if event: + try: + type, target, data = event + method = getattr(self.__class__, type) + GLib.idle_add(method, (self, data,)) + except Exception as e: + print(repr(e)) + + + + def apply_settings(self, widget, data=None): + os.system("killall xwinwrap &") + user_home = self.settings.get_home_path() + + if self.apply_type == 1: + files = os.listdir(user_home) + for file in files: + fPath = f"{user_home}/{file}" + if os.path.isfile(fPath) and "animatedBGstarter" in file: + os.system(f"bash -c '~/{file}' &") + elif self.apply_type == 2: + os.system("nitrogen --restore &") + else: + os.system("nitrogen --restore &") + + self.help_label.set_markup(self.appliedLabel) + + def save_to_settings_file(self, widget): + self.start_path = self.builder.get_object("customStartPath").get_text().strip() + self.default_player = self.builder.get_object("customVideoPlayer").get_text().strip() + self.default_img_viewer = self.builder.get_object("customImgViewer").get_text().strip() + + self.settings_saver.save_settings(self.start_path, self.default_player, self.default_img_viewer) + + def save_to_file(self, widget, data=None): + save_location = self.builder.get_object("saveLoc").get_active_text() + use_xscreensvr = self.builder.get_object("useXScrnList").get_active() + playBackRes = self.builder.get_object("playbackResolution") + monitorOffset = self.builder.get_object("monitorOffsetData") + resolution = playBackRes.get_active_text() + monitorOffset.get_active_text() + self.apply_type = self.state_saver.save_to_file(self.to_be_background, resolution, save_location, use_xscreensvr, self.xscreen_value, self.default_player) + + if self.apply_type == -1: + self.help_label.set_markup("Nothing saved...") + return + + self.help_label.set_markup(self.savedLabel) + + + def toggle_xscreen_list(self, widget, data=None): + use_xscreensvr = self.builder.get_object("useXScrnList") + if use_xscreensvr.get_active(): + self.builder.get_object("xScreenSvrList").set_sensitive(True) + else: + self.builder.get_object("xScreenSvrList").set_sensitive(False) + + def show_settings_popup(self, widget): + self.builder.get_object("settingsWindow").popup() + + + def preview_xscreensaver(self, widget, eve): + if eve.type == Gdk.EventType.DOUBLE_BUTTON_PRESS: + demoXscrnSaver = self.xscreensavers + self.xscreen_value + xid = self.getXID() + command = [demoXscrnSaver, "-window-id", str(xid)] + self.run_demo_in_draw_area(command) + + def pass_xscreen_value(self, widget): + row = widget.get_cursor() + path = Gtk.TreePath(row.path) + treeiter = self.xscreen_store.get_iter(path[0]) + self.xscreen_value = self.xscreen_store.get_value(treeiter, 0) + + def kill_xwinwrap(self, widget, data=None): + os.system("killall xwinwrap &") + self.help_label.set_markup(self.stoppedLabel) + + def set_selected_eve_box(self, eveBox): + if self.selected_eve_box: + color = Gdk.RGBA(0.0, 0.0, 0.0, 0.0) + self.selected_eve_box.override_background_color(Gtk.StateType.NORMAL, color) + + color = Gdk.RGBA(0.9, 0.7, 0.4, 0.74) + eveBox.override_background_color(Gtk.StateType.NORMAL, color) + self.selected_eve_box = eveBox + + def mouse_over(self, widget, eve, args): + hand_cursor = Gdk.Cursor(Gdk.CursorType.HAND2) + self.window.get_window().set_cursor(hand_cursor) + + def mouse_out(self, widget, eve, args): + watch_cursor = Gdk.Cursor(Gdk.CursorType.LEFT_PTR) + self.window.get_window().set_cursor(watch_cursor) + + def get_clipboard_data(self): + proc = subprocess.Popen(['xclip','-selection', 'clipboard', '-o'], stdout=subprocess.PIPE) + retcode = proc.wait() + data = proc.stdout.read() + return data.decode("utf-8").strip() + + def set_clipboard_data(self, data): + proc = subprocess.Popen(['xclip','-selection','clipboard'], stdin=subprocess.PIPE) + proc.stdin.write(data) + proc.stdin.close() + retcode = proc.wait() diff --git a/src/versions/0.0.2/GWinWrap/signal_classes/Controller_Data.py b/src/versions/0.0.2/GWinWrap/signal_classes/Controller_Data.py new file mode 100644 index 0000000..e651a46 --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/signal_classes/Controller_Data.py @@ -0,0 +1,102 @@ +# Python imports +import signal +from os import listdir +from os.path import isfile, join + +# Lib imports +from gi.repository import GLib + +# Application imports +from . import SaveStateToXWinWarp, SaveGWinWrapSettings + + + +class Controller_Data: + def has_method(self, obj, name): + return callable(getattr(obj, name, None)) + + def setup_controller_data(self, _settings): + self.settings = _settings + self.state_saver = SaveStateToXWinWarp(_settings) + self.settings_saver = SaveGWinWrapSettings(_settings) + + + self.builder = self.settings.get_builder() + self.window = self.settings.get_main_window() + self.logger = self.settings.get_logger() + + self.home_path = self.settings.get_home_path() + self.success_color = self.settings.get_success_color() + self.warning_color = self.settings.get_warning_color() + self.error_color = self.settings.get_error_color() + + + self.image_grid = self.builder.get_object("imageGrid") + self.grid_label = self.builder.get_object("gridLabel") + self.help_label = self.builder.get_object("helpLabel") + self.xscreen_store = self.builder.get_object("XScreensaverStore") + + self.defaultLabel = "Note: Double click an image to view the video or image." + self.savedLabel = f"Saved settings..." + self.appliedLabel = f"Running xwinwrap..." + self.stoppedLabel = f"Stopped xwinwrap..." + + # Add filter to allow only folders to be selected + dialog = self.builder.get_object("selectedDirDialog") + file_filter = self.builder.get_object("Folders") + dialog.add_filter(file_filter) + + self.xscreensavers = self.settings.get_xscreensavers() + list = [f for f in listdir(self.xscreensavers) if isfile(join(self.xscreensavers , f))] + list.sort() + for file in list: + self.xscreen_store.append((file,)) + + + self.selected_eve_box = None + self.start_path = None + self.default_player = None + self.default_img_viewer = None + self.demo_area_pid = None + + self.apply_type = 1 # 1 is XWinWrap and 2 is Nitrogen + self.xscreen_value = None + self.to_be_background = None # Global file path and type for saving to file + + + self.window.connect("delete-event", self.tear_down) + GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, self.tear_down) + + self.set_monitor_offset_data() + self.retrieve_settings() + + + def set_monitor_offset_data(self): + monitors = self.settings.get_monitor_data() + monitorOffsetData = self.builder.get_object("monitorOffsetData") + + for monitor in monitors: + if monitor.x >= 0 and monitor.y >= 0: + monitorOffsetData.append_text("+" + str(monitor.x) + "+" + str(monitor.y)) + elif monitor.x <= 0 and monitor.y <= 0: + monitorOffsetData.append_text(str(monitor.x) + str(monitor.y)) + elif monitor.x >= 0 and monitor.y <= 0: + monitorOffsetData.append_text("+" + str(monitor.x) + str(monitor.y)) + elif monitor.x <= 0 and monitor.y >= 0: + monitorOffsetData.append_text(str(monitor.x) + "+" + str(monitor.y)) + + monitorOffsetData.set_active(0) + + def retrieve_settings(self): + data = self.settings_saver.retrieve_settings() + self.start_path = data[0] + self.default_player = data[1] + self.default_img_viewer = data[2] + + self.builder.get_object("customStartPath").set_text(self.start_path) + self.builder.get_object("customVideoPlayer").set_text(self.default_player) + self.builder.get_object("customImgViewer").set_text(self.default_img_viewer) + self.builder.get_object("selectedDirDialog").set_filename(self.start_path) + + if self.start_path: + self.load_path(None, self.start_path) diff --git a/src/versions/0.0.2/GWinWrap/signal_classes/IPCServerMixin.py b/src/versions/0.0.2/GWinWrap/signal_classes/IPCServerMixin.py new file mode 100644 index 0000000..be92ace --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/signal_classes/IPCServerMixin.py @@ -0,0 +1,64 @@ +# Python imports +import threading, socket, time +from multiprocessing.connection import Listener, Client + +# Lib imports + +# Application imports + + +def threaded(fn): + def wrapper(*args, **kwargs): + threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start() + return wrapper + + + + +class IPCServerMixin: + + @threaded + def create_ipc_server(self): + listener = Listener((self.ipc_address, self.ipc_port), authkey=self.ipc_authkey) + self.is_ipc_alive = True + while True: + conn = listener.accept() + start_time = time.time() + + print(f"New Connection: {listener.last_accepted}") + while True: + msg = conn.recv() + if debug: + print(msg) + + if "FILE|" in msg: + file = msg.split("FILE|")[1].strip() + if file: + event_system.push_gui_event(["create_tab_from_ipc", None, file]) + + conn.close() + break + + + if msg == 'close connection': + conn.close() + break + if msg == 'close server': + conn.close() + break + + # NOTE: Not perfect but insures we don't lockup the connection for too long. + end_time = time.time() + if (end - start) > self.ipc_timeout: + conn.close() + + listener.close() + + + def send_ipc_message(self, message="Empty Data..."): + try: + conn = Client((self.ipc_address, self.ipc_port), authkey=self.ipc_authkey) + conn.send(message) + conn.send('close connection') + except Exception as e: + print(repr(e)) diff --git a/src/versions/0.0.2/GWinWrap/signal_classes/SaveGWinWrapSettings.py b/src/versions/0.0.2/GWinWrap/signal_classes/SaveGWinWrapSettings.py new file mode 100644 index 0000000..38025a1 --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/signal_classes/SaveGWinWrapSettings.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +import os, json + +class SaveGWinWrapSettings: + def __init__(self, settings): + self.config_file = settings.get_config_file() + + if os.path.isfile(self.config_file) == False: + open(self.config_file, 'a').close() + + + def save_settings(self, start_path, default_player, default_img_viewer): + data = {} + data['settings'] = [] + + data['settings'].append({ + 'start_path': start_path, + 'default_player': default_player, + 'default_img_viewer': default_img_viewer + }) + + with open(self.config_file, 'w') as outfile: + json.dump(data, outfile, separators=(',', ':'), indent=4) + + + def retrieve_settings(self): + data = [] + + with open(self.config_file) as infile: + try: + _data = json.load(infile) + for obj in _data['settings']: + data = [obj['start_path'], obj['default_player'], obj['default_img_viewer']] + except Exception as e: + print(repr(e)) + data = ['', 'mplayer', 'xdg-open'] + + + if data[0] == '': + data[0] = '' + + if data[1] == '': + data[1] = 'mplayer' + + if data[2] == '': + data[2] = 'xdg-open' + + return data diff --git a/src/versions/0.0.2/GWinWrap/signal_classes/SaveStateToXWinWarp.py b/src/versions/0.0.2/GWinWrap/signal_classes/SaveStateToXWinWarp.py new file mode 100644 index 0000000..14ff763 --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/signal_classes/SaveStateToXWinWarp.py @@ -0,0 +1,68 @@ + +class SaveStateToXWinWarp: + def __init__(self, _settings): + self.settings = _settings + self.user_home = self.settings.get_home_path() + + self._file_writer = None + self._to_be_background = None + self._use_xscreensvr = None + self._xscreen_value = None + self._save_file_target = None + self._resolution = None + self._player = None + + + def save_to_file(self, to_be_background, resolution, save_location, + use_xscreensvr, xscreen_value, player): + + self._to_be_background = to_be_background + self._use_xscreensvr = use_xscreensvr + self._xscreen_value = xscreen_value + self._resolution = resolution + self._player = player + + # Saves to file with selected and needed settings + if to_be_background: + if to_be_background.lower().endswith(self.settings.get_images_filter()): + self._save_file_target = f"{self.user_home}/.config/nitrogen/bg-saved.cfg" + else: + self._save_file_target = f"{self.user_home}/{save_location}" + elif use_xscreensvr and xscreen_value: + self._save_file_target = f"{self.user_home}/{save_location}" + else: + return -1 + + if self._save_file_target: + self._file_writer = open(self._save_file_target, "w") + + return self.save() + + def save(self): + applyType = 1 + output = None + + # XSCREENSAVER + if self._use_xscreensvr: + output = f"xwinwrap -ov -g {self._resolution} -st -sp -b -nf -s -ni -- /usr/lib/xscreensaver/{self._xscreen_value} -window-id WID -root"; + # GIF + elif self._to_be_background.lower().endswith(('.gif')): + output = f"xwinwrap -ov -g {self._resolution} -st -sp -b -nf -s -ni -- gifview -a -w WID {self._to_be_background}"; + # Standard images using nitrogen + elif self._to_be_background.lower().endswith(('.png', 'jpg', '.jpeg')): + output = f"[xin_0] \nfile={self._to_be_background}\nmode=0 \nbgcolor=#000000\n\n[xin_1] \nfile={self._to_be_background}\nmode=0 \nbgcolor=#000000"; + applyType = 2; + # VIDEO + else: + output = f"xwinwrap -ov -g {self._resolution} -st -sp -b -nf -s -ni -- {self._player} -wid WID -really-quiet -ao null -loop 0 '{self._to_be_background}'"; + pass + + try: + if self._file_writer: + self._file_writer.write(output) + self._file_writer.close() + except Exception as e: + print(":: Write failed! ::") + print(e) + + return applyType; diff --git a/src/versions/0.0.2/GWinWrap/signal_classes/__init__.py b/src/versions/0.0.2/GWinWrap/signal_classes/__init__.py new file mode 100644 index 0000000..97a8b3b --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/signal_classes/__init__.py @@ -0,0 +1,9 @@ +""" + Gtk Bound Signal Module +""" +from .mixins import * +from .SaveStateToXWinWarp import SaveStateToXWinWarp +from .SaveGWinWrapSettings import SaveGWinWrapSettings +from .IPCServerMixin import IPCServerMixin +from .Controller_Data import Controller_Data +from .Controller import Controller diff --git a/src/versions/0.0.2/GWinWrap/signal_classes/mixins/DrawAreaMixin.py b/src/versions/0.0.2/GWinWrap/signal_classes/mixins/DrawAreaMixin.py new file mode 100644 index 0000000..833d3ae --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/signal_classes/mixins/DrawAreaMixin.py @@ -0,0 +1,59 @@ +# Python imports +import os, subprocess, signal, time + +# Gtk imports +import gi +gi.require_version('Gdk', '3.0') +from gi.repository import Gdk + +# Application imports + + +class DrawAreaMixin: + """docstring for DrawAreaMixin""" + + def close_demo_popup(self, widget=None, data=None): + os.kill(self.demo_area_pid, signal.SIGTERM) #or signal.SIGKILL + self.demo_area_pid = None + time.sleep(.200) + self.builder.get_object("demoPreviewPopWindow").popdown() + + def run_mplayer_process(self, widget, eve, params): + video, file, eveBox = params + self.set_selected_eve_box(eveBox) + + if eve.type == Gdk.EventType.DOUBLE_BUTTON_PRESS: + if self.default_player == "mplayer": + xid = self.getXID() + command = [self.default_player, video, "-slave", "-wid", str(xid), "-really-quiet", "-ao", "null", "-loop", "0"] + self.run_demo_in_draw_area(command) + else: + subprocess.call([self.default_player, video, "-really-quiet", "-ao", "null", "-loop", "0"]) + + + self.to_be_background = video + self.applyType = 1 + self.help_label.set_markup(f"{file}") + + def run_demo_in_draw_area(self, command): + self.help_label.set_markup("") + + if self.demo_area_pid: + os.kill(self.demo_area_pid, signal.SIGTERM) #or signal.SIGKILL + self.demo_area_pid = None + time.sleep(.800) # 800 mili-seconds to ensure first process dead + + process = subprocess.Popen(command) + self.demo_area_pid = process.pid + + def getXID(self): + # Must be actualized before getting window + popup = self.builder.get_object("demoPreviewPopWindow") + + if popup.get_visible() == False: + popup.show_all() + popup.popup() + + preview = self.builder.get_object("demoPreview") + window = preview.get_window() + return window.get_xid() diff --git a/src/versions/0.0.2/GWinWrap/signal_classes/mixins/GridMixin.py b/src/versions/0.0.2/GWinWrap/signal_classes/mixins/GridMixin.py new file mode 100644 index 0000000..513d7b1 --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/signal_classes/mixins/GridMixin.py @@ -0,0 +1,116 @@ +# Python imports +import threading, hashlib +from os import listdir +from os.path import isfile, join + +# Gtk imports +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk, GLib + +# Application imports + + + + + +def threaded(fn): + def wrapper(*args, **kwargs): + threading.Thread(target=fn, args=args, kwargs=kwargs).start() + + return wrapper + + +class GridMixin: + """docstring for GridMixin.""" + + def set_new_path(self, widget, data=None): + dir = widget.get_filename() + self.load_path(None, dir) + + def load_path(self, widget=None, dir=''): + path = dir + list = [f for f in listdir(path) if isfile(join(path, f))] + files = [] + row = 0 + col = 0 + + for file in list: + if file.lower().endswith(self.settings.get_vids_filter() + \ + self.settings.get_images_filter()): + files.append(file) + + # fractionTick = 1.0 / 1.0 if len(files) == 0 else len(files) + # tickCount = 0.0 + self.clear() + self.image_grid.remove_column(0) + # self.loadProgress.set_text("Loading...") + # self.loadProgress.set_fraction(0.0) + self.help_label.set_markup(f"{path.strip(self.settings.get_home_path())}") + for file in files: + self.porocess_file(path, file, col, row) + + col += 1 + if col == 2: + col = 0 + row += 1 + + # self.loadProgress.set_text("Finished...") + + @threaded + def porocess_file(self, path, file, col, row): + fPath = f"{path}/{file}" + eveBox = Gtk.EventBox() + thumbnl = Gtk.Image() + + if file.lower().endswith(self.settings.get_vids_filter()): + fileHash = hashlib.sha256(str.encode(fPath)).hexdigest() + hashImgPath = f"{self.settings.get_home_path()}/.thumbnails/normal/{fileHash}.png" + if isfile(hashImgPath) == False: + self.generate_thumbnail(fPath, hashImgPath) + + thumbnl = self.create_gtk_image(hashImgPath, [310, 310]) + eveBox.connect("button_press_event", self.run_mplayer_process, (fPath, file, eveBox,)) + eveBox.connect("enter_notify_event", self.mouse_over, ()) + eveBox.connect("leave_notify_event", self.mouse_out, ()) + elif file.lower().endswith(self.settings.get_images_filter()): + thumbnl = self.create_gtk_image(fPath, [310, 310]) + eveBox.connect("button_press_event", self.run_image_viewer_process, (fPath, file, eveBox,)) + eveBox.connect("enter_notify_event", self.mouse_over, ()) + eveBox.connect("leave_notify_event", self.mouse_out, ()) + else: + print("Not a video or image file.") + return + + GLib.idle_add(self.pre_grid_setup, (eveBox, thumbnl, )) + GLib.idle_add(self.add_to_grid, (self.image_grid, eveBox, col, row,)) + # tickCount = tickCount + fractionTick + # self.loadProgress.set_fraction(tickCount) + + def pre_grid_setup(self, args): + args[0].show() + args[1].show() + args[0].add(args[1]) + + def add_to_grid(self, args): + args[0].attach(args[1], args[2], args[3], 1, 1) + + def clear_selection(self, widget, data=None): + self.clear() + + def clear(self): + while True: + if self.image_grid.get_child_at(0,0)!= None: + self.image_grid.remove_row(0) + else: + break + + self.image_grid.attach(self.grid_label, 0, 0, 1, 1) + self.builder.get_object("xScreenSvrList").set_sensitive(False) + self.builder.get_object("useXScrnList").set_active(False) + self.help_label.set_markup(self.defaultLabel) + # self.loadProgress.set_text("") + # self.loadProgress.set_fraction(0.0) + self.xscreen_value = None + self.to_be_background = None + self.apply_type = 1 diff --git a/src/versions/0.0.2/GWinWrap/signal_classes/mixins/ImageViewerMixin.py b/src/versions/0.0.2/GWinWrap/signal_classes/mixins/ImageViewerMixin.py new file mode 100644 index 0000000..e4dd1b6 --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/signal_classes/mixins/ImageViewerMixin.py @@ -0,0 +1,34 @@ +# Python imports +import subprocess + +# Gtk imports +import gi +gi.require_version('Gdk', '3.0') +from gi.repository import Gdk + +# Application imports + + +class ImageViewerMixin: + """docstring for ImageViewerMixin""" + + def close_image_popup(self, widget=None): + self.builder.get_object("previewWindow").popdown() + + def open_main_image_viewer(self, widget): + subprocess.call([self.default_img_viewer, self.to_be_background]) + + def run_image_viewer_process(self, widget, eve, params): + image, file, eveBox = params + self.set_selected(eveBox) + + if eve.type == Gdk.EventType.DOUBLE_BUTTON_PRESS: + previewWindow = self.builder.get_object("previewWindow") + previewImg = self.builder.get_object("previewImg") + previewImg.set_from_file(image) + previewWindow.show_all() + previewWindow.popup() + + self.to_be_background = image + self.apply_type = 2 + self.help_label.set_markup(f"{file}") diff --git a/src/versions/0.0.2/GWinWrap/signal_classes/mixins/ThumbnailMixin.py b/src/versions/0.0.2/GWinWrap/signal_classes/mixins/ThumbnailMixin.py new file mode 100644 index 0000000..e067732 --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/signal_classes/mixins/ThumbnailMixin.py @@ -0,0 +1,56 @@ +# Python imports +import subprocess + +# Gtk imports +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk +from gi.repository import GdkPixbuf + +# Application imports + + +class ThumbnailMixin: + """docstring for ThumbnailMixin""" + + def create_gtk_image(self, path, wxh): + try: + pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale( + filename = path, + width = wxh[0], + height = wxh[1], + preserve_aspect_ratio = True) + return Gtk.Image.new_from_pixbuf(pixbuf) + except Exception as e: + print(repr(e)) + + return Gtk.Image() + + def generate_thumbnail(self, fullPathFile, hashImgpth): + # Stream duration + command = ["ffprobe", "-v", "error", "-select_streams", "v:0", "-show_entries", "stream=duration", "-of", "default=noprint_wrappers=1:nokey=1", fullPathFile] + data = subprocess.run(command, stdout=subprocess.PIPE) + duration = data.stdout.decode('utf-8') + + # Format (container) duration + if "N/A" in duration: + command = ["ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", fullPathFile] + data = subprocess.run(command , stdout=subprocess.PIPE) + duration = data.stdout.decode('utf-8') + + # Stream duration type: image2 + if "N/A" in duration: + command = ["ffprobe", "-v", "error", "-select_streams", "v:0", "-f", "image2", "-show_entries", "stream=duration", "-of", "default=noprint_wrappers=1:nokey=1", fullPathFile] + data = subprocess.run(command, stdout=subprocess.PIPE) + duration = data.stdout.decode('utf-8') + + # Format (container) duration type: image2 + if "N/A" in duration: + command = ["ffprobe", "-v", "error", "-f", "image2", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", fullPathFile] + data = subprocess.run(command , stdout=subprocess.PIPE) + duration = data.stdout.decode('utf-8') + + # Get frame roughly 35% through video + grabTime = str( int( float( duration.split(".")[0] ) * 0.35) ) + command = ["ffmpeg", "-ss", grabTime, "-i", fullPathFile, "-an", "-vframes", "1", "-s", "320x180", "-q:v", "2", hashImgpth] + subprocess.call(command) diff --git a/src/versions/0.0.2/GWinWrap/signal_classes/mixins/__init__.py b/src/versions/0.0.2/GWinWrap/signal_classes/mixins/__init__.py new file mode 100644 index 0000000..f482286 --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/signal_classes/mixins/__init__.py @@ -0,0 +1,4 @@ +from .ThumbnailMixin import ThumbnailMixin +from .DrawAreaMixin import DrawAreaMixin +from .ImageViewerMixin import ImageViewerMixin +from .GridMixin import GridMixin diff --git a/src/versions/0.0.2/GWinWrap/utils/Logger.py b/src/versions/0.0.2/GWinWrap/utils/Logger.py new file mode 100644 index 0000000..c7f294e --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/utils/Logger.py @@ -0,0 +1,56 @@ +# Python imports +import os, logging + +# Application imports + + +class Logger: + def __init__(self): + pass + + def get_logger(self, loggerName = "NO_LOGGER_NAME_PASSED", createFile = True): + """ + Create a new logging object and return it. + :note: + NOSET # Don't know the actual log level of this... (defaulting or literally none?) + Log Levels (From least to most) + Type Value + CRITICAL 50 + ERROR 40 + WARNING 30 + INFO 20 + DEBUG 10 + :param loggerName: Sets the name of the logger object. (Used in log lines) + :param createFile: Whether we create a log file or just pump to terminal + + :return: the logging object we created + """ + + globalLogLvl = logging.DEBUG # Keep this at highest so that handlers can filter to their desired levels + chLogLevel = logging.CRITICAL # Prety musch the only one we change ever + fhLogLevel = logging.DEBUG + log = logging.getLogger(loggerName) + log.setLevel(globalLogLvl) + + # Set our log output styles + fFormatter = logging.Formatter('[%(asctime)s] %(pathname)s:%(lineno)d %(levelname)s - %(message)s', '%m-%d %H:%M:%S') + cFormatter = logging.Formatter('%(pathname)s:%(lineno)d] %(levelname)s - %(message)s') + + ch = logging.StreamHandler() + ch.setLevel(level=chLogLevel) + ch.setFormatter(cFormatter) + log.addHandler(ch) + + if createFile: + folder = "logs" + file = folder + "/application.log" + + if not os.path.exists(folder): + os.mkdir(folder) + + fh = logging.FileHandler(file) + fh.setLevel(level=fhLogLevel) + fh.setFormatter(fFormatter) + log.addHandler(fh) + + return log diff --git a/src/versions/0.0.2/GWinWrap/utils/Settings.py b/src/versions/0.0.2/GWinWrap/utils/Settings.py new file mode 100644 index 0000000..e729ee4 --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/utils/Settings.py @@ -0,0 +1,112 @@ +# Python imports +import os + +# Gtk imports +import gi, cairo +gi.require_version('Gtk', '3.0') +gi.require_version('Gdk', '3.0') + +from gi.repository import Gtk +from gi.repository import Gdk + + +# Application imports +from . import Logger + + + +class Settings: + def __init__(self): + self._SCRIPT_PTH = os.path.dirname(os.path.realpath(__file__)) + self._USER_HOME = os.path.expanduser('~') + self._CONFIG_PATH = f"{self._USER_HOME}/.config/{app_name.lower()}" + self._GLADE_FILE = f"{self._CONFIG_PATH}/Main_Window.glade" + self._CSS_FILE = f"{self._CONFIG_PATH}/stylesheet.css" + self._DEFAULT_ICONS = f"{self._CONFIG_PATH}/icons" + self._WINDOW_ICON = f"{self._DEFAULT_ICONS}/{app_name.lower()}.png" + self._USR_PATH = f"/usr/share/{app_name.lower()}" + self._CONFIG_FILE = f"{self._CONFIG_PATH}/settings.json" + self._XSCREEN_SAVERS = "/usr/lib/xscreensaver/" + + + self._logger = Logger().get_logger() + self._builder = Gtk.Builder() + self._main_window = None + + # '_filters' + self._vids_filter = ('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm') + self._images_filter = ('.png', '.jpg', '.jpeg', '.gif') + + self._success_color = "#88cc27" + self._warning_color = "#ffa800" + self._error_color = "#ff0000" + + if not os.path.exists(self._GLADE_FILE): + self._GLADE_FILE = f"{self._USR_PATH}/Main_Window.glade" + if not os.path.exists(self._CSS_FILE): + self._CSS_FILE = f"{self._USR_PATH}/stylesheet.css" + if not os.path.exists(self._WINDOW_ICON): + self._WINDOW_ICON = f"{self._USR_PATH}/icons/{app_name.lower()}.png" + if not os.path.exists(self._DEFAULT_ICONS): + self.DEFAULT_ICONS = f"{self._USR_PATH}/icons" + + self._builder.add_from_file(self._GLADE_FILE) + + + + def create_window(self): + # Get window and connect signals + self._main_window = self._builder.get_object("Main_Window") + self.set_window_data() + + def set_window_data(self): + self._main_window.set_icon_from_file(self._WINDOW_ICON) + screen = self._main_window.get_screen() + visual = screen.get_rgba_visual() + + if visual != None and screen.is_composited(): + self._main_window.set_visual(visual) + self._main_window.set_app_paintable(True) + self._main_window.connect("draw", self.draw_area) + + # bind css file + cssProvider = Gtk.CssProvider() + cssProvider.load_from_path(self._CSS_FILE) + screen = Gdk.Screen.get_default() + styleContext = Gtk.StyleContext() + styleContext.add_provider_for_screen(screen, cssProvider, Gtk.STYLE_PROVIDER_PRIORITY_USER) + + def get_monitor_data(self): + screen = self._builder.get_object("Main_Window").get_screen() + monitors = [] + for m in range(screen.get_n_monitors()): + monitors.append(screen.get_monitor_geometry(m)) + + for monitor in monitors: + print("{}x{}|{}+{}".format(monitor.width, monitor.height, monitor.x, monitor.y)) + + return monitors + + def draw_area(self, widget, cr): + cr.set_source_rgba(0, 0, 0, 0.54) + cr.set_operator(cairo.OPERATOR_SOURCE) + cr.paint() + cr.set_operator(cairo.OPERATOR_OVER) + + + + + def get_builder(self): return self._builder + def get_logger(self): return self._logger + def get_main_window(self): return self._main_window + def get_home_path(self): return self._USER_HOME + def get_config_file(self): return self._CONFIG_FILE + def get_xscreensavers(self): return self._XSCREEN_SAVERS + + # Filter returns + def get_vids_filter(self): return self._vids_filter + def get_images_filter(self): return self._images_filter + + def get_success_color(self): return self._success_color + def get_warning_color(self): return self._warning_color + def get_error_color(self): return self._error_color diff --git a/src/versions/0.0.2/GWinWrap/utils/__init__.py b/src/versions/0.0.2/GWinWrap/utils/__init__.py new file mode 100644 index 0000000..415301e --- /dev/null +++ b/src/versions/0.0.2/GWinWrap/utils/__init__.py @@ -0,0 +1,6 @@ +""" + Utils module +""" + +from .Logger import Logger +from .Settings import Settings diff --git a/src/versions/0.0.2/XWinWrap/Makefile b/src/versions/0.0.2/XWinWrap/Makefile new file mode 100644 index 0000000..4a67078 --- /dev/null +++ b/src/versions/0.0.2/XWinWrap/Makefile @@ -0,0 +1,20 @@ +all: all64 all32 + +all64: + gcc -Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -lX11 -lXext -lXrender xwinwrap.c -o xwinwrap + -mkdir x86_64 + mv ./xwinwrap ./x86_64 + +all32: + gcc -m32 -Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -lX11 -lXext -lXrender xwinwrap.c -o xwinwrap + -mkdir i386 + mv ./xwinwrap ./i386 + +install64: + cp x86_64/xwinwrap /usr/bin + +install32: + cp i386/xwinwrap /usr/bin + +clean: + -rm -rf x86_64/ i386/ diff --git a/src/versions/0.0.2/XWinWrap/xwinwrap.c b/src/versions/0.0.2/XWinWrap/xwinwrap.c new file mode 100644 index 0000000..a2daa04 --- /dev/null +++ b/src/versions/0.0.2/XWinWrap/xwinwrap.c @@ -0,0 +1,459 @@ +/* + * Copyright © 2005 Novell, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * Novell, Inc. not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * Novell, Inc. makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: David Reveman + */ + +/* + * Modified by: Shantanu Goel + * Tech Blog: http://tech.shantanugoel.com + * Blog: http://blog.shantanugoel.com + * Home Page: http://tech.shantanugoel.com/projects/linux/shantz-xwinwrap + * + * Changelog: + * 15-Jan-09: 1. Fixed the bug where XFetchName returning a NULL for "name" + * resulted in a crash. + * 2. Provided an option to specify the desktop window name. + * 3. Added debug messages + * + * 24-Aug-08: 1. Fixed the geometry option (-g) so that it works + * 2. Added override option (-ov), for seamless integration with + * desktop like a background in non-fullscreen modes + * 3. Added shape option (-sh), to create non-rectangular windows. + * Currently supporting circlular and triangular windows + */ + + /* + * Modified by: Maxim Stewart + * Tech Blog: https://www.itdominator.com/ + * + * Changelog: + * 3-March-19: 1. Cleaned up code formatting. + * 2. Removed unused DEBUG_MSG reference. + * 3. Moved functions to a more reasonable order. + * 4. Compile dev library list 32 & 64 bit: + * # 32 + * sudo apt install libxext-dev:i386 libxrender-dev:i386 libc6-dev-i386 + * + * # 64 + * sudo apt install libxext-dev libxrender-dev libc6-dev + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define WIDTH 512 +#define HEIGHT 384 +#define OPAQUE 0xffffffff +#define NAME "xwinwrap" +#define VERSION "0.3" +#define DESKTOP_WINDOW_NAME_MAX_SIZE 25 +#define DEFAULT_DESKTOP_WINDOW_NAME "Desktop" +#define DEBUG_MSG(x) if(debug) { fprintf(stderr, x); } + +typedef enum { + SHAPE_RECT = 0, + SHAPE_CIRCLE, + SHAPE_TRIG, +} win_shape; + +static pid_t pid = 0; +static char **childArgv = 0; +static int nChildArgv = 0; +int debug = 0; +char desktop_window_name[DESKTOP_WINDOW_NAME_MAX_SIZE]; + +static int addArguments(char **argv, int n) { + char **newArgv; + int i; + + newArgv = realloc (childArgv, sizeof (char *) * (nChildArgv + n)); + if (!newArgv) + return 0; + + for (i = 0; i < n; i++) + newArgv[nChildArgv + i] = argv[i]; + + childArgv = newArgv; + nChildArgv += n; + + return n; +} + +static void setWindowOpacity(Display *dpy, Window win, unsigned int opacity) { + CARD32 o; + o = opacity; + XChangeProperty (dpy, win, XInternAtom (dpy, "_NET_WM_WINDOW_OPACITY", 0), + XA_CARDINAL, 32, PropModeReplace, + (unsigned char *) &o, 1); +} + +static Visual * findArgbVisual(Display *dpy, int scr) { + XVisualInfo *xvi; + XVisualInfo template; + int nvi; + int i; + XRenderPictFormat *format; + Visual *visual; + + template.screen = scr; + template.depth = 32; + template.class = TrueColor; + + xvi = XGetVisualInfo (dpy, + VisualScreenMask | + VisualDepthMask | + VisualClassMask, + &template, + &nvi); + + if (!xvi) + return 0; + + visual = 0; + for (i = 0; i < nvi; i++) { + format = XRenderFindVisualFormat (dpy, xvi[i].visual); + if (format->type == PictTypeDirect && format->direct.alphaMask) { + visual = xvi[i].visual; + break; + } + } + + XFree (xvi); + return visual; +} + +static Window find_desktop_window(Display *display, int screen, + Window *root, Window *p_desktop) { + int i; + unsigned int n; + Window win = *root; + Window troot, parent, *children; + char *name; + int status; + int width = DisplayWidth(display, screen); + int height = DisplayHeight(display, screen); + XWindowAttributes attrs; + + XQueryTree(display, *root, &troot, &parent, &children, &n); + for (i = 0; i < (int) n; i++) { + status = XFetchName(display, children[i], &name); + status |= XGetWindowAttributes(display, children[i], &attrs); + + if ((status != 0) && (NULL != name)) { + if( (attrs.map_state != 0) && (attrs.width == width) && + (attrs.height == height) && (!strcmp(name, desktop_window_name)) ) { + win = children[i]; + XFree(children); + XFree(name); + *p_desktop = win; + return win; + } + + if(name) + XFree(name); + } + } + + DEBUG_MSG("Desktop Window Not found\n"); + return 0; +} + +static void usage (void) { + fprintf(stderr, "%s v%s- Modified by Shantanu Goel. Visit http://tech.shantanugoel.com for updates, queries and feature requests\n", NAME, VERSION); + fprintf (stderr, "\nUsage: %s [-g {w}x{h}+{x}+{y}] [-ni] [-argb] [-fs] [-s] [-st] [-sp] [-a] " + "[-b] [-nf] [-o OPACITY] [-sh SHAPE] [-ov]-- COMMAND ARG1...\n", NAME); + fprintf (stderr, "Options:\n \ + -g - Specify Geometry (w=width, h=height, x=x-coord, y=y-coord. ex: -g 640x480+100+100)\n \ + -ni - Ignore Input\n \ + -d - Desktop Window Hack. Provide name of the \"Desktop\" window as parameter \ + -argb - RGB\n \ + -fs - Full Screen\n \ + -s - Sticky\n \ + -st - Skip Taskbar\n \ + -sp - Skip Pager\n \ + -a - Above\n \ + -b - Below\n \ + -nf - No Focus\n \ + -o - Opacity value between 0 to 1 (ex: -o 0.20)\n \ + -sh - Shape of window (choose between rectangle, circle or triangle. Default is rectangle)\n \ + -ov - Set override_redirect flag (For seamless desktop background integration in non-fullscreenmode)\n \ + -debug - Enable debug messages\n"); +} + +static void sigHandler (int sig) { kill(pid, sig); } + +int main (int argc, char **argv) { + Display *dpy; + Window win; + Window root; + Window p_desktop = 0; + int screen; + XSizeHints xsh; + XWMHints xwmh; + char widArg[256]; + char *widArgv[] = { widArg }; + char *endArg = NULL; + int i; + int status = 0; + unsigned int opacity = OPAQUE; + int x = 0; + int y = 0; + unsigned int width = WIDTH; + unsigned int height = HEIGHT; + int argb = 0; + int fullscreen = 0; + int noInput = 0; + int noFocus = 0; + Atom state[256]; + int nState = 0; + int override = 0; + win_shape shape = SHAPE_RECT; + Pixmap mask; + GC mask_gc; + XGCValues xgcv; + + + dpy = XOpenDisplay (NULL); + if (!dpy) { + fprintf (stderr, "%s: Error: couldn't open display\n", argv[0]); + return 1; + } + + screen = DefaultScreen (dpy); + root = RootWindow (dpy, screen); + strcpy(desktop_window_name, DEFAULT_DESKTOP_WINDOW_NAME); + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-g") == 0) { + if (++i < argc) + XParseGeometry (argv[i], &x, &y, &width, &height); + } else if (strcmp(argv[i], "-ni") == 0) { + noInput = 1; + } else if (strcmp(argv[i], "-d") == 0) { + ++i; + strcpy(desktop_window_name, argv[i]); + } else if (strcmp(argv[i], "-argb") == 0) { + argb = 1; + } else if (strcmp(argv[i], "-fs") == 0) { + state[nState++] = XInternAtom (dpy, "_NET_WM_STATE_FULLSCREEN", 0); + fullscreen = 1; + } else if (strcmp(argv[i], "-s") == 0) { + state[nState++] = XInternAtom (dpy, "_NET_WM_STATE_STICKY", 0); + } else if (strcmp(argv[i], "-st") == 0) { + state[nState++] = XInternAtom (dpy, "_NET_WM_STATE_SKIP_TASKBAR", 0); + } else if (strcmp(argv[i], "-sp") == 0) { + state[nState++] = XInternAtom (dpy, "_NET_WM_STATE_SKIP_PAGER", 0); + } else if (strcmp(argv[i], "-a") == 0) { + state[nState++] = XInternAtom (dpy, "_NET_WM_STATE_ABOVE", 0); + } else if (strcmp(argv[i], "-b") == 0) { + state[nState++] = XInternAtom (dpy, "_NET_WM_STATE_BELOW", 0); + } else if (strcmp(argv[i], "-nf") == 0) { + noFocus = 1; + } else if (strcmp(argv[i], "-o") == 0) { + if (++i < argc) + opacity = (unsigned int) (atof (argv[i]) * OPAQUE); + } else if (strcmp(argv[i], "-sh") == 0) { + if (++i < argc) { + if(strcasecmp(argv[i], "circle") == 0) { + shape = SHAPE_CIRCLE; + } else if(strcasecmp(argv[i], "triangle") == 0) { + shape = SHAPE_TRIG; + } + } + } else if (strcmp(argv[i], "-ov") == 0) { + override = 1; + } else if (strcmp(argv[i], "-debug") == 0) { + debug = 1; + } else if (strcmp(argv[i], "--") == 0) { + break; + } else { + usage (); + return 1; + } + } + + for (i = i + 1; i < argc; i++) { + if (strcmp(argv[i], "WID") == 0) + addArguments (widArgv, 1); + else + addArguments (&argv[i], 1); + } + + if (!nChildArgv) { + fprintf (stderr, "%s: Error: couldn't create command line\n", argv[0]); + usage (); + return 1; + } + + addArguments (&endArg, 1); + + if (fullscreen) { + xsh.flags = PSize | PPosition; + xsh.width = DisplayWidth (dpy, screen); + xsh.height = DisplayHeight (dpy, screen); + } else { + xsh.flags = PSize; + xsh.width = width; + xsh.height = height; + } + + xwmh.flags = InputHint; + xwmh.input = !noFocus; + + if (argb) { + XSetWindowAttributes attr; + Visual *visual; + + visual = findArgbVisual (dpy, screen); + if (!visual) { + fprintf (stderr, "%s: Error: couldn't find argb visual\n", argv[0]); + return 1; + } + + attr.background_pixel = 0; + attr.border_pixel = 0; + attr.colormap = XCreateColormap (dpy, root, visual, AllocNone); + + win = XCreateWindow (dpy, root, 0, 0, xsh.width, xsh.height, 0, 32, + InputOutput, visual, + CWBackPixel | CWBorderPixel | CWColormap, &attr); + } else { + XSetWindowAttributes attr; + attr.override_redirect = override; + + if( override && find_desktop_window(dpy, screen, &root, &p_desktop) ) { + win = XCreateWindow (dpy, p_desktop, x, y, xsh.width, xsh.height, 0, + CopyFromParent, InputOutput, CopyFromParent, + CWOverrideRedirect, &attr); + } else { + win = XCreateWindow (dpy, root, x, y, xsh.width, xsh.height, 0, + CopyFromParent, InputOutput, CopyFromParent, + CWOverrideRedirect, &attr); + } + } + + XSetWMProperties (dpy, win, NULL, NULL, argv, argc, &xsh, &xwmh, NULL); + + if (opacity != OPAQUE) + setWindowOpacity (dpy, win, opacity); + + if (noInput) { + Region region; + + region = XCreateRegion (); + if (region) { + XShapeCombineRegion (dpy, win, ShapeInput, 0, 0, region, ShapeSet); + XDestroyRegion (region); + } + } + + if (nState) + XChangeProperty (dpy, win, XInternAtom (dpy, "_NET_WM_STATE", 0), + XA_ATOM, 32, PropModeReplace, (unsigned char *) state, nState); + + if (shape) { + mask = XCreatePixmap(dpy, win, width, height, 1); + mask_gc = XCreateGC(dpy, mask, 0, &xgcv); + + switch(shape) { + //Nothing special to be done if it's a rectangle + case SHAPE_CIRCLE: + /* fill mask */ + XSetForeground(dpy, mask_gc, 0); + XFillRectangle(dpy, mask, mask_gc, 0, 0, width, height); + + XSetForeground(dpy, mask_gc, 1); + XFillArc(dpy, mask, mask_gc, 0, 0, width, height, 0, 23040); + break; + + case SHAPE_TRIG: + { + XPoint points[3] = { {0, height}, + {width/2, 0}, + {width, height} }; + + XSetForeground(dpy, mask_gc, 0); + XFillRectangle(dpy, mask, mask_gc, 0, 0, width, height); + + XSetForeground(dpy, mask_gc, 1); + XFillPolygon(dpy, mask, mask_gc, points, 3, Complex, CoordModeOrigin); + } + break; + default: + break; + } + /* combine */ + XShapeCombineMask(dpy, win, ShapeBounding, 0, 0, mask, ShapeSet); + } + + XMapWindow (dpy, win); + + if(p_desktop == 0) + XLowerWindow(dpy, win); + + XSync (dpy, win); + sprintf (widArg, "0x%x", (int) win); + pid = fork (); + + switch (pid) { + case -1: + perror ("fork"); + return 1; + case 0: + execvp (childArgv[0], childArgv); + perror (childArgv[0]); + exit (2); + break; + default: + break; + } + + signal (SIGTERM, sigHandler); + signal (SIGINT, sigHandler); + + for (;;) { + if (waitpid (pid, &status, 0) != -1) { + if (WIFEXITED (status)) + fprintf (stderr, "%s died, exit status %d\n", childArgv[0], + WEXITSTATUS (status)); + break; + } + } + + XDestroyWindow (dpy, win); + XCloseDisplay (dpy); + return 0; +} diff --git a/src/versions/0.0.2/compileBin.sh b/src/versions/0.0.2/compileBin.sh new file mode 100755 index 0000000..fdd8222 --- /dev/null +++ b/src/versions/0.0.2/compileBin.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +function main() { + gcc -no-pie -s gwinwrap_exec_bin.cpp -o gwinwrap +} +main; diff --git a/src/versions/0.0.2/gwinwrap_exec_bin.cpp b/src/versions/0.0.2/gwinwrap_exec_bin.cpp new file mode 100644 index 0000000..81978ec --- /dev/null +++ b/src/versions/0.0.2/gwinwrap_exec_bin.cpp @@ -0,0 +1,10 @@ +#include +#include +#include +using namespace std; + +int main() { + chdir("/opt/GWinWrap/"); + system("python3 ."); +return 0; +} diff --git a/user_config/usr/share/gwinwrap/Main_Window.glade b/user_config/usr/share/gwinwrap/Main_Window.glade new file mode 100644 index 0000000..41e0e23 --- /dev/null +++ b/user_config/usr/share/gwinwrap/Main_Window.glade @@ -0,0 +1,882 @@ + + + + + + + inode/directory + + + + + + + + + + True + False + gtk-clear + 3 + + + True + False + gtk-quit + 3 + + + True + False + gtk-cancel + 3 + + + True + False + gtk-jump-to + 3 + + + True + False + gtk-save + 3 + + + True + False + gtk-save + 3 + + + True + False + Settings.... + gtk-properties + 3 + + + True + False + gtk-media-play + 3 + + + True + False + gtk-media-stop + 3 + + + 950 + 600 + False + GWinWrap + center + 950 + 600 + icons/GWinWrap.png + center + + + True + False + + + True + False + 15 + 15 + 15 + vertical + + + True + False + 5 + + + True + False + 15 + Note: Double click an image to view the video or image. + + + True + True + 0 + + + + + True + False + Chose Dream Scene / Image Directory + select-folder + False + Folders + Dream Scene / Image Dir + + + + False + True + 1 + + + + + True + True + True + settingsImage + True + + + + False + True + 2 + + + + + False + True + 0 + + + + + True + False + True + + + False + True + 1 + + + + + True + True + in + + + True + False + + + + True + False + vertical + 10 + 10 + True + True + + + 640 + 525 + True + False + Choose Image/Video Directory... + + + + + + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + 2 + + + + + Clear + True + True + True + clearImage + True + + + + False + True + 3 + + + + + True + True + 0 + + + + + 300 + True + False + 10 + 15 + 15 + 15 + False + vertical + + + True + False + vertical + + + Use XScreenSaver + True + True + False + center + 5 + True + + + + False + True + 0 + + + + + True + True + in + + + True + False + True + XScreensaverStore + False + + + + + + + + XScreensaves + + + + 0 + + + + + + + + + True + True + 1 + + + + + True + True + 0 + + + + + True + False + False + vertical + + + True + False + vertical + + + True + False + + + True + False + 10 + 10 + Playback Resolutions + + + True + True + 0 + + + + + True + False + 10 + 10 + Position Offset + + + True + True + 1 + + + + + False + True + 0 + + + + + True + False + + + True + False + 3 + + 7680x4320 + 3840x2160 + 2048x1080 + 1920x1080 + 1440x720 + 1600x900 + 1280x720 + 800x600 + + + + True + True + 0 + + + + + True + False + + + True + True + 1 + + + + + False + True + 1 + + + + + False + True + 0 + + + + + True + False + vertical + + + True + False + 10 + 5 + Save Path + + + True + True + 0 + + + + + True + False + 0 + + .animatedBGstarter.sh + .animatedBGstarter2.sh + .animatedBGstarter3.sh + + + + True + True + 1 + + + + + False + True + 1 + + + + + + True + False + + + Save + True + True + True + True + True + saveImage + True + + + + 1 + 0 + + + + + (Re)Start + True + True + True + True + True + startImage + True + + + + 0 + 0 + + + + + Stop + True + True + True + True + True + stopImage + True + + + + 0 + 1 + + + + + Close + True + True + True + True + True + closeImage + True + + + + 1 + 1 + + + + + + + + + + + + + + + + + + + + False + True + 2 + + + + + False + False + end + 1 + + + + + False + True + 1 + 1 + + + + + + + 640 + 525 + False + 350 + True + True + helpLabel + bottom + False + + + True + False + vertical + + + True + False + + + True + True + True + Close Demo Window + closePopupImage + True + + + + False + True + end + 0 + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + + + + + True + True + 1 + + + + + + + 640 + 525 + False + True + True + helpLabel + bottom + + + True + False + vertical + + + True + False + bottom + + + Main Image Viewer + True + True + True + openProgImage + True + + + + False + True + 0 + + + + + True + True + True + True + + + + False + True + 1 + + + + + False + True + 0 + + + + + True + True + in + False + + + True + False + + + True + False + gtk-missing-image + 6 + + + + + + + True + True + 1 + + + + + + + 250 + False + button1 + + + True + False + vertical + + + True + False + + + True + False + folder + + + False + True + 0 + + + + + 330 + 26 + True + True + Set Custom Default Path + Set Custom Start Path + + + True + True + 1 + + + + + False + True + 0 + + + + + True + False + + + True + False + video-x-generic + + + False + True + 0 + + + + + 330 + 26 + True + True + Set Custom Video Player + Set Custom Video Player + + + True + True + 1 + + + + + False + True + 1 + + + + + True + False + + + True + False + image-x-generic + + + False + True + 0 + + + + + 330 + 26 + True + True + Set Custom Image Viewer + Set Custom Image Viewer + + + False + True + 1 + + + + + False + True + 2 + + + + + Save + True + True + True + saveImag + True + + + + False + True + 3 + + + + + + diff --git a/user_config/usr/share/gwinwrap/icons/dir.png b/user_config/usr/share/gwinwrap/icons/dir.png new file mode 100644 index 0000000000000000000000000000000000000000..a9b5e9f90847d5afe34fec63651ffebcd6c5b6e3 GIT binary patch literal 850 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD3?#3*wSy#>i=8|}I5;?NKlFb92xL>4nJ z$hLzpWB=2SsX#%=64!{5;QX|b^2DN4hVt@qz0ADq;^f4FRK5J7^x5xhq=1UVK#D># zOL9^f0)R3_3ZBXNc?uyJsky1DHrHsBfZYpno_di4|!2nE;;ZdJgpSz-K{;CN})=gZxe$uiHlb3Cnx_r~r6&t6n*feeBrs*p;&sep2 z#_G*8S8tiQdMnTtp!q-(xF)ho0G+E>666=mz{teP#m&ttEFvl4>6lif#XQ z8W13Ilv$zc>xRv19^Jh6-?ox*^G&|HnMr59#~t{-#It^DV2glL{i@!-kE4TcEV%OT z-p;}>w+z1?PA#6E70US!LfC%He;CD4G5_F<15KQ|YZz6wZP-1z`D{=_^8Ki6{avaJ zN7k*_@#bs#uBW^^zIST;wfe&9^4sO*Om&4j>bpKNANjrI3)7R|Q=T#KpZwhZ_*dum zPKyse-tD=U{igWAzqi#}eLQv9Y-+XEJ!hQx&W=4!!(c)y8wWhvU6w0CUnUvw{_K};>3gl1wceg9u(=*FzrTHMS*!j2>yL7`K8m_0?z;72 ikl~}S#Zrnb|3dd~^!AY~RX+CuWU8mDpUXO@geCx;cxYb$ literal 0 HcmV?d00001 diff --git a/user_config/usr/share/gwinwrap/icons/gwinwrap.png b/user_config/usr/share/gwinwrap/icons/gwinwrap.png new file mode 100644 index 0000000000000000000000000000000000000000..cdd708d16faef991c910643670ab5cc4abfc605b GIT binary patch literal 9278 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 literal 0 HcmV?d00001 diff --git a/user_config/usr/share/gwinwrap/icons/video.png b/user_config/usr/share/gwinwrap/icons/video.png new file mode 100644 index 0000000000000000000000000000000000000000..55afa98662c7439702c4391be32151b59c65e253 GIT binary patch literal 1313 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGoEX7WqAsj$Z!;#Vf4nJ zNUsNB#yF{oGC)De64!{5;QX|b^2DN4hVt@qz0ADq;^f4FRK5J7^x5xhq=1UVK#D># zOL9^f0)R3_3ZBXNc?uyJsky1DHrHsBf%ipdZ&9wFl@+Mo$;Vkcv5P@A_uQq{heETG?y0yzC9fraSuz>xc-iKB^S-C2j9}#|+2Trc2JzJRTnfTzEQIH^v=t-uh~( zxc^nT;G^AFyj-F_E#k~I^^GcclIec6N$|KDEZ^HL2yRXD%)^JLrNU0ZK4B(tA;`e?y7+bL3Cv<0)SasI_CAaj~N#c(YL7*x>s=RUEzB;@PrBh& zH)D%og8`esF@{4D4id~9$qb1+3OxwHP0QHrcBOO2*;w_|95lANuJ3MPXxI5(O|0kK zRl|QgH_Ue({_&96Vc&zq|1bC+7nk<1Yuu@Ae>qY6-K)v7Yqj^V-D!HvaJ2dMZM$~H zu!p<&;w*k~%)4!W;alV}{X=v0Uhk~<**mx5&CKevXN-+f=bm`FyWqv#SP7|{IXP;~ zcdqPSDZPH*cNRIBH>Ot885zEOeQr=yWB#r(Ve!YC*VuRDXUi=Ow$PzK?rCL+Fg2guB&_nRD$dv!BcjdVIbiOV!A>s5L(B z_M7webFwb`{Y$Vp;Qn~>iWvW|`+K5R742;lemwcu^H&o81xx0 uulP@kQGh{%aR*z&{2E6WF!;j1pYh0Ho3#3@qwc_>hQZU-&t;ucLK6Tg{6(q& literal 0 HcmV?d00001 diff --git a/user_config/usr/share/gwinwrap/settings.json b/user_config/usr/share/gwinwrap/settings.json new file mode 100644 index 0000000..596ddd2 --- /dev/null +++ b/user_config/usr/share/gwinwrap/settings.json @@ -0,0 +1,9 @@ +{ + "settings":[ + { + "start_path":"/home/abaddon/LazyShare/Movies-TV-Music/Dream Scenes/Games/Halo", + "default_player":"mpv", + "default_img_viewer":"mirage" + } + ] +} \ No newline at end of file diff --git a/user_config/usr/share/gwinwrap/stylesheet.css b/user_config/usr/share/gwinwrap/stylesheet.css new file mode 100644 index 0000000..c0383f6 --- /dev/null +++ b/user_config/usr/share/gwinwrap/stylesheet.css @@ -0,0 +1,86 @@ +/* Set fm to have transparent window */ +box, +iconview, +notebook, +paned, +stack, +scrolledwindow, +treeview.view, +.content-view, +.view { + background: rgba(19, 21, 25, 0.14); + color: rgba(255, 255, 255, 1); +} + +notebook > header > tabs > tab:checked { + /* Neon Blue 00e8ff */ + background-color: rgba(0, 232, 255, 0.2); + /* Dark Bergundy */ + /* background-color: rgba(116, 0, 0, 0.25); */ + + color: rgba(255, 255, 255, 0.8); +} + +#message_view { + font: 16px "Monospace"; +} + +.view:selected, +.view:selected:hover { + box-shadow: inset 0 0 0 9999px rgba(21, 158, 167, 0.34); + color: rgba(255, 255, 255, 0.5); +} + +.alert-border { + border: 2px solid rgba(116, 0, 0, 0.64); +} + +.search-border { + border: 2px solid rgba(136, 204, 39, 1); +} + +.notebook-selected-focus { + /* Neon Blue 00e8ff border */ + border: 2px solid rgba(0, 232, 255, 0.34); + /* Dark Bergundy */ + /* border: 2px solid rgba(116, 0, 0, 0.64); */ +} + +.notebook-unselected-focus { + /* Neon Blue 00e8ff border */ + /* border: 2px solid rgba(0, 232, 255, 0.25); */ + /* Dark Bergundy */ + /* border: 2px solid rgba(116, 0, 0, 0.64); */ + /* Snow White */ + border: 2px solid rgba(255, 255, 255, 0.24); +} + + + + + +/* * { + background: rgba(0, 0, 0, 0.14); + color: rgba(255, 255, 255, 1); +} */ + +/* * selection { + background-color: rgba(116, 0, 0, 0.65); + color: rgba(255, 255, 255, 0.5); +} */ + +/* Rubberband coloring */ +/* .rubberband, +rubberband, +flowbox rubberband, +treeview.view rubberband, +.content-view rubberband, +.content-view .rubberband, +XfdesktopIconView.view .rubberband { + border: 1px solid #6c6c6c; + background-color: rgba(21, 158, 167, 0.57); +} + +XfdesktopIconView.view:active { + background-color: rgba(172, 102, 21, 1); +} */