diff --git a/.gitignore b/.gitignore index 213be4a..df76a45 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ - *.tpp +.env +*.pyc +*.tp diff --git a/src/TPPEntry.py b/src/TPPEntry.py new file mode 100644 index 0000000..ce01abc --- /dev/null +++ b/src/TPPEntry.py @@ -0,0 +1,622 @@ +#!/usr/bin/env python3 + +__version__ = "3.1.0" + +TP_PLUGIN_INFO = { + "sdk": 6, + "version": 310, + "name": "Windows Mover", + "id": "WindowMover", + "configuration": { + "colorDark": "#222423", + "colorLight": "#020202" + }, + "plugin_start_cmd": "%TP_PLUGIN_FOLDER%Window-Mover\\StartWinMover.bat" +} + +TP_PLUGIN_SETTINGS = { + "1": { + "name": "Build by", + "type": "text", + "default": "Killer_BOSS", + "readOnly": True + }, + "2": { + "name": "Version", + "type": "text", + "default": "0", + "readOnly": True + }, + "3": { + "name": "Is Running", + "type": "text", + "default": "False", + "readOnly": True + } +} + +TP_PLUGIN_CATEGORIES = { + "main": { + "id": "main", + "name": "Window Mover", + "imagepath": "%TP_PLUGIN_FOLDER%Window-Mover\\icon.png" + }, + "Simple": { + "id": "Simple", + "name": "Window Mover - Simple", + "imagepath": "%TP_PLUGIN_FOLDER%Window-Mover\\icon.png" + }, + "Advanced": { + "id": "Advanced", + "name": "Window Mover - Advanced", + "imagepath": "%TP_PLUGIN_FOLDER%Window-Mover\\icon.png" + } +} + +TP_PLUGIN_CONNECTORS = {} + +TP_PLUGIN_ACTIONS = { + "1": { + "id": "KillerBOSS.TP.Plugins.WindowMover.Windowpresets", + "name": "Window Mover: Simple Move Window by presets", + "prefix": "plugin", + "type": "communicate", + "doc": "Pre programmed Presets allows user to move X window to Top Left, Bottom Middle, Center etc...", + "tryInline": True, + "format": "Move $[2] on Display:$[3] to $[1] Allow Resize:$[4]", + "data": { + "1": { + "id": "KillerBOSS.TP.Plugins.WindowMover.Windowpresets.Presets", + "type": "choice", + "label": "choice", + "default": "Top Left", + "valueChoices": [ + "Top Left", + "Top Right", + "Top Middle", + "Bottom Left", + "Bottom Right", + "Bottom Middle", + "Top Half", + "Bottom Half", + "Left Half", + "Right Half", + "Left Middle", + "Right Middle", + "Center" + ] + }, + "2": { + "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.Window", + "label": "Window", + "type": "choice", + "default": "", + "valueChoices": [] + }, + "3": { + "id": "KillerBOSS.TP.Plugins.WindowMover.Windowpresets.Displays", + "type": "choice", + "label": "choice", + "valueChoices": [] + }, + "4": { + "id": "KillerBOSS.TP.Plugins.WindowMover.Windowpresets.AllowResize", + "type": "choice", + "label": "choice", + "default": "True", + "valueChoices": [ + "True", + "False" + ] + } + }, + "category": "Simple" + }, + "2": { + "id": "KillerBOSS.TP.Plugins.WindowMover.MoveByXandY", + "name": "Window Mover: Simple Increase X, Y", + "prefix": "plugin", + "type": "communicate", + "tryInline": True, + "doc": "Allow user to move window by x or y amount", + "hasHoldFunctionality": True, + "format": "$[4] Window:$[1] by X:$[2] and Y:$[3]", + "data": { + "1": { + "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.Window", + "label": "Window", + "type": "choice", + "default": "", + "valueChoices": [] + }, + "2": { + "id": "KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.X", + "label": "Move By X", + "type": "number", + "allowDecimals": False, + "default": 1 + }, + "3": { + "id": "KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.Y", + "label": "Move By Y", + "type": "number", + "allowDecimals": False, + "default": 1 + }, + "4": { + "id": "KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.Choice", + "label": "Update Choice", + "type": "choice", + "default": "Increase", + "valueChoices": [ + "Increase", + "Decrease" + ] + } + }, + "category": "Simple" + }, + "3": { + "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeTo", + "name": "Window Mover: Simple Resize Window", + "prefix": "plugin", + "type": "communicate", + "doc": "Ability to Resize Window to specific size.", + "tryInline": True, + "format": "Set $[1] Size to width:$[2] and height:$[3]", + "data": { + "1": { + "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.Window", + "label": "Window", + "type": "choice", + "default": "", + "valueChoices": [] + }, + "2": { + "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeTo.width", + "label": "Move By X", + "type": "number", + "allowDecimals": False, + "default": 400 + }, + "3": { + "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeTo.height", + "label": "Move By Y", + "type": "number", + "allowDecimals": False, + "default": 400 + } + }, + "category": "Simple" + }, + "4": { + "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease", + "name": "Window Mover: Simple Resize Increase Width, Height", + "prefix": "plugin", + "type": "communicate", + "doc": "Increase or Decrease window current width and height", + "tryInline": True, + "hasHoldFunctionality": True, + "format": "$[1]Window:$[2]by Width:$[3] and Height:$[4]", + "data": { + "1": { + "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.In&Decre", + "type": "choice", + "label": "choice", + "default": "Increase", + "valueChoices": [ + "Increase", + "Decrease" + ] + }, + "2": { + "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.Window", + "label": "Window", + "type": "choice", + "default": "", + "valueChoices": [] + }, + "3": { + "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.width", + "label": "Move By X", + "type": "number", + "allowDecimals": False, + "default": 1 + }, + "4": { + "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.height", + "label": "Move By Y", + "type": "number", + "allowDecimals": False, + "default": 1 + } + }, + "category": "Simple" + }, + "5": { + "id": "KillerBOSS.TP.Plugins.WindowMover.SysActions", + "name": "Window Mover: Simple focus, restore, minimize, and restore", + "prefix": "plugin", + "type": "communicate", + "doc": "Simple window action allows you to focus, restore, maximize, close and minimize.", + "tryInline": True, + "format": "$[1] Window:$[2]", + "data": { + "1": { + "id": "KillerBOSS.TP.Plugins.WindowMover.SysActions.Choice", + "type": "choice", + "label": "choice", + "default": "maximize", + "valueChoices": [ + "maximize", + "minimize", + "restore", + "focus", + "close" + ] + }, + "2": { + "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.Window", + "label": "Window", + "type": "choice", + "default": "", + "valueChoices": [] + } + }, + "category": "Simple" + }, + "6": { + "id": "KillerBOSS.TP.Plugins.WindowMover.customMove", + "name": "Window Mover: Simple Move Window by current data", + "prefix": "plugin", + "type": "communicate", + "tryInline": True, + "doc": "When selecting a window it'll auto populate x, y pos and width and height", + "format": "Load $[1] with X:$[2]Y:$[3]Width:$[4]height:$[5]", + "data": { + "1": { + "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.Window", + "label": "Window", + "type": "choice", + "default": "", + "valueChoices": [] + }, + "2": { + "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.X", + "type": "choice", + "label": "choice", + "valueChoices": [] + }, + "3": { + "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.Y", + "type": "choice", + "label": "choice", + "valueChoices": [] + }, + "4": { + "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.width", + "type": "choice", + "label": "choice", + "valueChoices": [] + }, + "5": { + "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.height", + "type": "choice", + "label": "choice", + "valueChoices": [] + } + }, + "category": "Simple" + }, + "7": { + "id": "KillerBOSS.TP.Plugins.WindowMover.Advanced.Windowpresets", + "name": "Window Mover: Advanced Move Window by presets", + "prefix": "plugin", + "type": "communicate", + "doc": "Pre programmed Presets allows user to move X window to Top Left, Bottom Middle, Center etc...", + "tryInline": True, + "format": "Move $[2] on Display:$[3] to $[1] Allow Resize:$[4]", + "data": { + "1": { + "id": "KillerBOSS.TP.Plugins.WindowMover.Windowpresets.Advanced.Presets", + "type": "choice", + "label": "choice", + "default": "Top Left", + "valueChoices": [ + "Top Left", + "Top Right", + "Bottom Left", + "Bottom Right" + ] + }, + "2": { + "id": "KillerBOSS.TP.Plugins.WindowMover.Advanced.Windowpreset.Window", + "label": "Window", + "type": "text", + "default": "" + }, + "3": { + "id": "KillerBOSS.TP.Plugins.WindowMover.Windowpresets.Advanced.Displays", + "type": "choice", + "label": "choice", + "valueChoices": [] + }, + "4": { + "id": "KillerBOSS.TP.Plugins.WindowMover.Windowpresets.Advanced.AllowResize", + "type": "choice", + "label": "choice", + "default": "True", + "valueChoices": [ + "True", + "False" + ] + } + }, + "category": "Advanced" + }, + "8": { + "id": "KillerBOSS.TP.Plugins.WindowMover.Advanced.MoveByXandY", + "name": "Window Mover: Advanced Increase X, Y", + "prefix": "plugin", + "type": "communicate", + "tryInline": True, + "doc": "Allow user to move window by x or y amount", + "hasHoldFunctionality": True, + "format": "$[4] Window:$[1] by X:$[2] and Y:$[3]", + "data": { + "1": { + "id": "KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.Advanced.Window", + "label": "Window", + "type": "text", + "default": "" + }, + "2": { + "id": "KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.Advanced.X", + "label": "Move By X", + "type": "number", + "allowDecimals": False, + "default": 1 + }, + "3": { + "id": "KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.Advanced.Y", + "label": "Move By Y", + "type": "number", + "allowDecimals": False, + "default": 1 + }, + "4": { + "id": "KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.Advanced.Choice", + "label": "Update Choice", + "type": "choice", + "default": "Increase", + "valueChoices": [ + "Increase", + "Decrease" + ] + } + }, + "category": "Advanced" + }, + "9": { + "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeTo.Advanced", + "name": "Window Mover: Advanced Resize Window", + "prefix": "plugin", + "type": "communicate", + "doc": "Ability to Resize Window to specific size.", + "tryInline": True, + "format": "Set $[1] width:$[2] and Height:$[3]", + "data": { + "1": { + "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeTo.Advanced.Window", + "label": "Window", + "type": "text", + "default": "" + }, + "2": { + "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeTo.Advanced.width", + "label": "Move By X", + "type": "number", + "allowDecimals": False, + "default": 400 + }, + "3": { + "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeTo.Advanced.height", + "label": "Move By Y", + "type": "number", + "allowDecimals": False, + "default": 400 + } + }, + "category": "Advanced" + }, + "10": { + "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.Advanced", + "name": "Window Mover: Advanced Resize Increase Width, hight", + "prefix": "plugin", + "type": "communicate", + "tryInline": True, + "doc": "Increase or Decrease window current width and height", + "hasHoldFunctionality": True, + "format": "$[1]Window:$[2]by Width:$[3] and Height:$[4]", + "data": { + "1": { + "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.Advanced.In&Decre", + "type": "choice", + "label": "choice", + "default": "Increase", + "valueChoices": [ + "Increase", + "Decrease" + ] + }, + "2": { + "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.Advanced.Window", + "label": "Window", + "type": "text", + "default": "" + }, + "3": { + "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.Advanced.width", + "label": "Move By X", + "type": "number", + "allowDecimals": False, + "default": 1 + }, + "4": { + "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.Advanced.height", + "label": "Increase height", + "type": "number", + "allowDecimals": False, + "default": 1 + } + }, + "category": "Advanced" + }, + "11": { + "id": "KillerBOSS.TP.Plugins.WindowMover.SysActions.Advanced", + "name": "Window Mover: Advanced focus, restore, minimize, and restore", + "prefix": "plugin", + "type": "communicate", + "doc": "Simple window action allows you to focus, restore, maximize, close and minimize.", + "tryInline": True, + "format": "$[1] Window:$[2]", + "data": { + "1": { + "id": "KillerBOSS.TP.Plugins.WindowMover.SysActions.Advanced.Choice", + "type": "choice", + "label": "choice", + "default": "maximize", + "valueChoices": [ + "maximize", + "minimize", + "restore", + "focus", + "close" + ] + }, + "2": { + "id": "KillerBOSS.TP.Plugins.WindowMover.SysActions.Advanced.Window", + "label": "Window", + "type": "text", + "default": "" + } + }, + "category": "Advanced" + }, + "12": { + "id": "KillerBOSS.TP.Plugins.WindowMover.Advanced.customMove", + "name": "Window Mover: Advanced Move Window by current data", + "prefix": "plugin", + "type": "communicate", + "doc": "When selecting a window it'll auto populate x, y pos and width and height", + "tryInline": True, + "format": "Load $[1] with X:$[2]Y:$[3]Width:$[4]height:$[5]", + "data": { + "1": { + "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.Advanced.Window", + "label": "Window", + "type": "text", + "default": "" + }, + "2": { + "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.Advanced.X", + "type": "number", + "label": "choice", + "default": 0, + "allowDecimals": False + }, + "3": { + "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.Advanced.Y", + "type": "number", + "label": "choice", + "default": 0, + "allowDecimals": False + }, + "4": { + "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.Advanced.width", + "type": "number", + "label": "choice", + "default": 0, + "allowDecimals": False + }, + "5": { + "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.Advanced.height", + "type": "number", + "label": "choice", + "default": 0, + "allowDecimals": False + } + }, + "category": "Advanced" + } +} + +TP_PLUGIN_STATES = { + "0": { + "id": "KillerBOSS.TP.Plugins.WindowMover.states.ActiveWindow", + "type": "text", + "desc": "Window Mover: Current Active Window", + "default": "None", + "doc": "Get current focused Window. This is useful in `Advanced` actions since you can run any actions to current Window.", + "category": "main" + }, + "1": { + "id": "KillerBOSS.TP.Plugins.WindowMover.states.ActiveWindow.X", + "type": "text", + "desc": "Window Mover: Current Active Window X pos", + "default": "None", + "doc": "Get current active Window x position. (counts from Top left corner window)", + "category": "main" + }, + "2": { + "id": "KillerBOSS.TP.Plugins.WindowMover.states.ActiveWindow.Y", + "type": "text", + "desc": "Window Mover: Current Active Window Y pos", + "doc": "Get current active Window y position. (counts from Top left corner window)", + "default": "None", + "category": "main" + }, + "3": { + "id": "KillerBOSS.TP.Plugins.WindowMover.states.ActiveWindow.width", + "type": "text", + "desc": "Window Mover: Current Active Window Width", + "doc": "Get current active window Width", + "default": "None", + "category": "main" + }, + "4": { + "id": "KillerBOSS.TP.Plugins.WindowMover.states.ActiveWindow.height", + "type": "text", + "desc": "Window Mover: Current Active Window height", + "doc": "Get current active Window height", + "default": "None", + "category": "main" + }, + "5": { + "id": "KillerBOSS.TP.Plugins.WindowMover.states.isCurrentWindowMaximized", + "type": "text", + "desc": "Window Mover: is Current Window Maximized", + "doc": "Let's you know if current Window is maximized or not. boolean True/False", + "default": "False", + "category": "main" + }, + "6": { + "id": "KillerBOSS.TP.Plugins.WindowMover.states.isCurrentWindowminimize", + "type": "text", + "desc": "Window Mover: is Current Window minimized", + "doc": "It let's you know if current Window is minimized or not. boolean True/False", + "default": "False", + "category": "main" + }, + "7": { + "id": "KillerBOSS.TP.Plugins.WindowMover.states.isCurrentWindowActive", + "type": "text", + "desc": "Window Mover: is Current Window Active", + "doc": "It shows if current Window is active. boolean True/Faluse", + "default": "False", + "category": "main" + } +} + +TP_PLUGIN_EVENTS = {} + diff --git a/src/build.py b/src/build.py new file mode 100644 index 0000000..2888620 --- /dev/null +++ b/src/build.py @@ -0,0 +1,82 @@ +from TouchPortalAPI import tppbuild +from sys import platform +import TPPEntry + +PLUGIN_MAIN = "main.py" +""" +PLUGIN_MAIN: This lets tppbuild know where your main python plugin file is located so it will know which file to compile. +""" + +PLUGIN_EXE_NAME = "WinMover" +""" +PLUGIN_EXE_NAME: This defines what you want your plugin executable to be named. tppbuild will also use this for the .tpp file in the format: + `pluginname + "_v" + version + "_" + os_name + ".tpp"` + If left blank, the file name from PLUGIN_MAIN is used (w/out .py extension). +""" + +PLUGIN_EXE_ICON = r"icon.png" +""" +PLUGIN_EXE_ICON: This should be a path to a .ico file. However if png passed in, it will automatically converted to ico. +""" + +PLUGIN_ENTRY = "TPPEntry.py" +""" +PLUGIN_ENTRY: This can be either path to entry.tp or path to a python file that contains infomation about entry. +Note if you pass in a entry.tp, tppbuild will automatically validate the json. If you pass in a python file, it will +build entry.tp & validate it for you. If validation fails, tppbuild will exit. +""" + +PLUGIN_ENTRY_INDENT = 2 +""" +PLUGIN_ENTRY_INDENT: This is used for generating new entry.tp with indentations using python entry struct. default is 2 indents. +""" + +PLUGIN_ROOT = "Window-Mover" +""" This is the root folder name that will be inside of .tpp """ + +PLUGIN_ICON = PLUGIN_EXE_ICON +""" Path to icon file used in entry.tp for category `imagepath`, if any. If left blank, TP will use a default icon. """ + +OUTPUT_PATH = r"./" +""" This tells tppbuild where you want finished build tpp to be saved at. Default "./" meaning current dir where tppbuild is running from. """ + +""" PLUGIN_VERSION: A version string for the generated .tpp file name. This example reads the `__version__` from the example plugin's code. """ +PLUGIN_VERSION = TPPEntry.__version__ +# If you only wants to use TP entry.tp version you can use the code blow this code will read entry.tp and grab its version. +""" +import json +import os +entry = os.path.join(os.path.split(__file__)[0], PLUGIN_ENTRY) +with open(entry, "r") as f: + PLUGIN_VERSION = str(json.load(f)['version']) +""" +# Or just set the PLUGIN_VERSION manually. +# PLUGIN_VERSION = "1.0.0-beta1" + +""" +If you have any required file(s) that your plugin needs, put them in this list. +""" +ADDITIONAL_FILES = [ + "StartWinMover.bat", + "Debug.bat" +] + +""" +start.sh file is not needed for Windows machine. as it can execute the exe itself where as +Mac and Linux requires to run `chmod +x program` in order to run it. +""" +if platform != "win32": + ADDITIONAL_FILES.append("start.sh") + +""" +Any additional arguments to be passed to Pyinstaller. Optional. +""" +ADDITIONAL_PYINSTALLER_ARGS = [ + "--log-level=WARN" +] + +ADDITIONAL_TPPSDK_ARGS = [ +] + +if __name__ == "__main__": + tppbuild.runBuild() \ No newline at end of file diff --git a/src/entry.tp b/src/entry.tp index 38c6bd6..b71a480 100644 --- a/src/entry.tp +++ b/src/entry.tp @@ -1,46 +1,83 @@ { "sdk": 3, - "version": 2100, + "version": 3000, "name": "Windows Mover", "id": "WindowMover", "configuration": { "colorDark": "#222423", "colorLight": "#020202" }, - "settings": [ - { - "name": "Build by", - "type": "text", - "default": "Killer_BOSS", - "readOnly": true - }, - { - "name": "Version", - "type": "text", - "default": "0", - "readOnly": true - }, - { - "name": "Is Running", - "type": "text", - "default": "False", - "readOnly": true - } - ], "plugin_start_cmd": "%TP_PLUGIN_FOLDER%Window-Mover\\StartWinMover.bat", "categories": [ { - "id": "Main", + "id": "main", "name": "Window Mover", "imagepath": "%TP_PLUGIN_FOLDER%Window-Mover\\icon.png", + "actions": [], + "states": [ + { + "id": "KillerBOSS.TP.Plugins.WindowMover.states.ActiveWindow", + "type": "text", + "desc": "Window Mover: Current Active Window", + "default": "None" + }, + { + "id": "KillerBOSS.TP.Plugins.WindowMover.states.ActiveWindow.X", + "type": "text", + "desc": "Window Mover: Current Active Window X pos", + "default": "None" + }, + { + "id": "KillerBOSS.TP.Plugins.WindowMover.states.ActiveWindow.Y", + "type": "text", + "desc": "Window Mover: Current Active Window Y pos", + "default": "None" + }, + { + "id": "KillerBOSS.TP.Plugins.WindowMover.states.ActiveWindow.width", + "type": "text", + "desc": "Window Mover: Current Active Window Width", + "default": "None" + }, + { + "id": "KillerBOSS.TP.Plugins.WindowMover.states.ActiveWindow.height", + "type": "text", + "desc": "Window Mover: Current Active Window height", + "default": "None" + }, + { + "id": "KillerBOSS.TP.Plugins.WindowMover.states.isCurrentWindowMaximized", + "type": "text", + "desc": "Window Mover: is Current Window Maximized", + "default": "False" + }, + { + "id": "KillerBOSS.TP.Plugins.WindowMover.states.isCurrentWindowminimize", + "type": "text", + "desc": "Window Mover: is Current Window minimized", + "default": "False" + }, + { + "id": "KillerBOSS.TP.Plugins.WindowMover.states.isCurrentWindowActive", + "type": "text", + "desc": "Window Mover: is Current Window Active", + "default": "False" + } + ], + "events": [] + }, + { + "id": "Simple", + "name": "Window Mover - Simple", + "imagepath": "%TP_PLUGIN_FOLDER%Window-Mover\\icon.png", "actions": [ { "id": "KillerBOSS.TP.Plugins.WindowMover.Windowpresets", "name": "Window Mover: Simple Move Window by presets", "prefix": "plugin", "type": "communicate", - "tryInline": true, "format": "Move {$KillerBOSS.TP.Plugins.WindowMover.customMove.Window$} on Display:{$KillerBOSS.TP.Plugins.WindowMover.Windowpresets.Displays$} to {$KillerBOSS.TP.Plugins.WindowMover.Windowpresets.Presets$} Allow Resize:{$KillerBOSS.TP.Plugins.WindowMover.Windowpresets.AllowResize$}", + "tryInline": true, "data": [ { "id": "KillerBOSS.TP.Plugins.WindowMover.Windowpresets.Presets", @@ -54,6 +91,10 @@ "Bottom Left", "Bottom Right", "Bottom Middle", + "Top Half", + "Bottom Half", + "Left Half", + "Right Half", "Left Middle", "Right Middle", "Center" @@ -61,8 +102,8 @@ }, { "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.Window", - "label": "Window", "type": "choice", + "label": "Window", "default": "", "valueChoices": [] }, @@ -70,6 +111,7 @@ "id": "KillerBOSS.TP.Plugins.WindowMover.Windowpresets.Displays", "type": "choice", "label": "choice", + "default": "", "valueChoices": [] }, { @@ -89,35 +131,35 @@ "name": "Window Mover: Simple Increase X, Y", "prefix": "plugin", "type": "communicate", + "format": "{$KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.Choice$} Window:{$KillerBOSS.TP.Plugins.WindowMover.customMove.Window$} by X:{$KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.X$} and Y:{$KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.Y$}", "tryInline": true, "hasHoldFunctionality": true, - "format": "{$KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.Choice$} Window:{$KillerBOSS.TP.Plugins.WindowMover.customMove.Window$} by X:{$KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.X$} and Y:{$KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.Y$}", "data": [ { "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.Window", - "label": "Window", "type": "choice", + "label": "Window", "default": "", "valueChoices": [] }, { "id": "KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.X", - "label": "Move By X", "type": "number", - "allowDecimals": false, - "default": 1 + "label": "Move By X", + "default": 1, + "allowDecimals": false }, { "id": "KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.Y", - "label": "Move By Y", "type": "number", - "allowDecimals": false, - "default": 1 + "label": "Move By Y", + "default": 1, + "allowDecimals": false }, { "id": "KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.Choice", - "label": "Update Choice", "type": "choice", + "label": "Update Choice", "default": "Increase", "valueChoices": [ "Increase", @@ -131,40 +173,40 @@ "name": "Window Mover: Simple Resize Window", "prefix": "plugin", "type": "communicate", - "tryInline": true, "format": "Set {$KillerBOSS.TP.Plugins.WindowMover.customMove.Window$} Size to width:{$KillerBOSS.TP.Plugins.WindowMover.ResizeTo.width$} and height:{$KillerBOSS.TP.Plugins.WindowMover.ResizeTo.height$}", + "tryInline": true, "data": [ { "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.Window", - "label": "Window", "type": "choice", + "label": "Window", "default": "", "valueChoices": [] }, { "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeTo.width", - "label": "Move By X", "type": "number", - "allowDecimals": false, - "default": 400 + "label": "Move By X", + "default": 400, + "allowDecimals": false }, { "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeTo.height", - "label": "Move By Y", "type": "number", - "allowDecimals": false, - "default": 400 + "label": "Move By Y", + "default": 400, + "allowDecimals": false } ] }, { "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease", - "name": "Window Mover: Simple Resize Increase Width, hight", + "name": "Window Mover: Simple Resize Increase Width, Height", "prefix": "plugin", "type": "communicate", + "format": "{$KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.In&Decre$}Window:{$KillerBOSS.TP.Plugins.WindowMover.customMove.Window$}by Width:{$KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.width$} and Height:{$KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.height$}", "tryInline": true, "hasHoldFunctionality": true, - "format": "{$KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.In&Decre$}Window:{$KillerBOSS.TP.Plugins.WindowMover.customMove.Window$}by Width:{$KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.width$} and Height:{$KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.height$}", "data": [ { "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.In&Decre", @@ -178,24 +220,24 @@ }, { "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.Window", - "label": "Window", "type": "choice", + "label": "Window", "default": "", "valueChoices": [] }, { "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.width", - "label": "Move By X", "type": "number", - "allowDecimals": false, - "default": 1 + "label": "Move By X", + "default": 1, + "allowDecimals": false }, { "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.height", - "label": "Move By Y", "type": "number", - "allowDecimals": false, - "default": 1 + "label": "Move By Y", + "default": 1, + "allowDecimals": false } ] }, @@ -204,8 +246,8 @@ "name": "Window Mover: Simple focus, restore, minimize, and restore", "prefix": "plugin", "type": "communicate", - "tryInline": true, "format": "{$KillerBOSS.TP.Plugins.WindowMover.SysActions.Choice$} Window:{$KillerBOSS.TP.Plugins.WindowMover.customMove.Window$}", + "tryInline": true, "data": [ { "id": "KillerBOSS.TP.Plugins.WindowMover.SysActions.Choice", @@ -222,8 +264,8 @@ }, { "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.Window", - "label": "Window", "type": "choice", + "label": "Window", "default": "", "valueChoices": [] } @@ -234,13 +276,13 @@ "name": "Window Mover: Simple Move Window by current data", "prefix": "plugin", "type": "communicate", - "tryInline": true, "format": "Load {$KillerBOSS.TP.Plugins.WindowMover.customMove.Window$} with X:{$KillerBOSS.TP.Plugins.WindowMover.customMove.X$}Y:{$KillerBOSS.TP.Plugins.WindowMover.customMove.Y$}Width:{$KillerBOSS.TP.Plugins.WindowMover.customMove.width$}height:{$KillerBOSS.TP.Plugins.WindowMover.customMove.height$}", + "tryInline": true, "data": [ { "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.Window", - "label": "Window", "type": "choice", + "label": "Window", "default": "", "valueChoices": [] }, @@ -248,35 +290,48 @@ "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.X", "type": "choice", "label": "choice", + "default": "", "valueChoices": [] }, { "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.Y", "type": "choice", "label": "choice", + "default": "", "valueChoices": [] }, { "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.width", "type": "choice", "label": "choice", + "default": "", "valueChoices": [] }, { "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.height", "type": "choice", "label": "choice", + "default": "", "valueChoices": [] } ] - }, + } + ], + "states": [], + "events": [] + }, + { + "id": "Advanced", + "name": "Window Mover - Advanced", + "imagepath": "%TP_PLUGIN_FOLDER%Window-Mover\\icon.png", + "actions": [ { "id": "KillerBOSS.TP.Plugins.WindowMover.Advanced.Windowpresets", "name": "Window Mover: Advanced Move Window by presets", "prefix": "plugin", "type": "communicate", - "tryInline": true, "format": "Move {$KillerBOSS.TP.Plugins.WindowMover.Advanced.Windowpreset.Window$} on Display:{$KillerBOSS.TP.Plugins.WindowMover.Windowpresets.Advanced.Displays$} to {$KillerBOSS.TP.Plugins.WindowMover.Windowpresets.Advanced.Presets$} Allow Resize:{$KillerBOSS.TP.Plugins.WindowMover.Windowpresets.Advanced.AllowResize$}", + "tryInline": true, "data": [ { "id": "KillerBOSS.TP.Plugins.WindowMover.Windowpresets.Advanced.Presets", @@ -292,14 +347,15 @@ }, { "id": "KillerBOSS.TP.Plugins.WindowMover.Advanced.Windowpreset.Window", - "label": "Window", "type": "text", + "label": "Window", "default": "" }, { "id": "KillerBOSS.TP.Plugins.WindowMover.Windowpresets.Advanced.Displays", "type": "choice", "label": "choice", + "default": "", "valueChoices": [] }, { @@ -319,34 +375,34 @@ "name": "Window Mover: Advanced Increase X, Y", "prefix": "plugin", "type": "communicate", + "format": "{$KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.Advanced.Choice$} Window:{$KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.Advanced.Window$} by X:{$KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.Advanced.X$} and Y:{$KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.Advanced.Y$}", "tryInline": true, "hasHoldFunctionality": true, - "format": "{$KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.Advanced.Choice$} Window:{$KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.Advanced.Window$} by X:{$KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.Advanced.X$} and Y:{$KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.Advanced.Y$}", "data": [ { "id": "KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.Advanced.Window", - "label": "Window", "type": "text", + "label": "Window", "default": "" }, { "id": "KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.Advanced.X", - "label": "Move By X", "type": "number", - "allowDecimals": false, - "default": 1 + "label": "Move By X", + "default": 1, + "allowDecimals": false }, { "id": "KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.Advanced.Y", - "label": "Move By Y", "type": "number", - "allowDecimals": false, - "default": 1 + "label": "Move By Y", + "default": 1, + "allowDecimals": false }, { "id": "KillerBOSS.TP.Plugins.WindowMover.MoveByXandY.Advanced.Choice", - "label": "Update Choice", "type": "choice", + "label": "Update Choice", "default": "Increase", "valueChoices": [ "Increase", @@ -360,28 +416,28 @@ "name": "Window Mover: Advanced Resize Window", "prefix": "plugin", "type": "communicate", - "tryInline": true, "format": "Set {$KillerBOSS.TP.Plugins.WindowMover.ResizeTo.Advanced.Window$} width:{$KillerBOSS.TP.Plugins.WindowMover.ResizeTo.Advanced.width$} and Height:{$KillerBOSS.TP.Plugins.WindowMover.ResizeTo.Advanced.height$}", + "tryInline": true, "data": [ { "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeTo.Advanced.Window", + "type": "text", "label": "Window", - "type": "test", "default": "" }, { "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeTo.Advanced.width", - "label": "Move By X", "type": "number", - "allowDecimals": false, - "default": 400 + "label": "Move By X", + "default": 400, + "allowDecimals": false }, { "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeTo.Advanced.height", - "label": "Move By Y", "type": "number", - "allowDecimals": false, - "default": 400 + "label": "Move By Y", + "default": 400, + "allowDecimals": false } ] }, @@ -390,9 +446,9 @@ "name": "Window Mover: Advanced Resize Increase Width, hight", "prefix": "plugin", "type": "communicate", + "format": "{$KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.Advanced.In&Decre$}Window:{$KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.Advanced.Window$}by Width:{$KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.Advanced.width$} and Height:{$KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.Advanced.height$}", "tryInline": true, "hasHoldFunctionality": true, - "format": "{$KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.Advanced.In&Decre$}Window:{$KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.Advanced.Window$}by Width:{$KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.Advanced.width$} and Height:{$KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.Advanced.height$}", "data": [ { "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.Advanced.In&Decre", @@ -406,23 +462,23 @@ }, { "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.Advanced.Window", - "label": "Window", "type": "text", + "label": "Window", "default": "" }, { "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.Advanced.width", - "label": "Move By X", "type": "number", - "allowDecimals": false, - "default": 1 + "label": "Move By X", + "default": 1, + "allowDecimals": false }, { "id": "KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.Advanced.height", - "label": "Increase height", "type": "number", - "allowDecimals": false, - "default": 1 + "label": "Increase height", + "default": 1, + "allowDecimals": false } ] }, @@ -431,8 +487,8 @@ "name": "Window Mover: Advanced focus, restore, minimize, and restore", "prefix": "plugin", "type": "communicate", - "tryInline": true, "format": "{$KillerBOSS.TP.Plugins.WindowMover.SysActions.Advanced.Choice$} Window:{$KillerBOSS.TP.Plugins.WindowMover.SysActions.Advanced.Window$}", + "tryInline": true, "data": [ { "id": "KillerBOSS.TP.Plugins.WindowMover.SysActions.Advanced.Choice", @@ -449,8 +505,8 @@ }, { "id": "KillerBOSS.TP.Plugins.WindowMover.SysActions.Advanced.Window", - "label": "Window", "type": "text", + "label": "Window", "default": "" } ] @@ -460,13 +516,13 @@ "name": "Window Mover: Advanced Move Window by current data", "prefix": "plugin", "type": "communicate", - "tryInline": true, "format": "Load {$KillerBOSS.TP.Plugins.WindowMover.customMove.Advanced.Window$} with X:{$KillerBOSS.TP.Plugins.WindowMover.customMove.Advanced.X$}Y:{$KillerBOSS.TP.Plugins.WindowMover.customMove.Advanced.Y$}Width:{$KillerBOSS.TP.Plugins.WindowMover.customMove.Advanced.width$}height:{$KillerBOSS.TP.Plugins.WindowMover.customMove.Advanced.height$}", + "tryInline": true, "data": [ { "id": "KillerBOSS.TP.Plugins.WindowMover.customMove.Advanced.Window", - "label": "Window", "type": "text", + "label": "Window", "default": "" }, { @@ -500,57 +556,28 @@ ] } ], - "events": [], - "states": [ - { - "id": "KillerBOSS.TP.Plugins.WindowMover.states.ActiveWindow", - "type": "text", - "desc": "Window Mover: Current Active Window", - "default": "None" - }, - { - "id": "KillerBOSS.TP.Plugins.WindowMover.states.ActiveWindow.X", - "type": "text", - "desc": "Window Mover: Current Active Window X pos", - "default": "None" - }, - { - "id": "KillerBOSS.TP.Plugins.WindowMover.states.ActiveWindow.Y", - "type": "text", - "desc": "Window Mover: Current Active Window Y pos", - "default": "None" - }, - { - "id": "KillerBOSS.TP.Plugins.WindowMover.states.ActiveWindow.width", - "type": "text", - "desc": "Window Mover: Current Active Window Width", - "default": "None" - }, - { - "id": "KillerBOSS.TP.Plugins.WindowMover.states.ActiveWindow.height", - "type": "text", - "desc": "Window Mover: Current Active Window height", - "default": "None" - }, - { - "id": "KillerBOSS.TP.Plugins.WindowMover.states.isCurrentWindowMaximized", - "type": "text", - "desc": "Window Mover: is Current Window Maximized", - "default": "False" - }, - { - "id": "KillerBOSS.TP.Plugins.WindowMover.states.isCurrentWindowminimize", - "type": "text", - "desc": "Window Mover: is Current Window minimized", - "default": "False" - }, - { - "id": "KillerBOSS.TP.Plugins.WindowMover.states.isCurrentWindowActive", - "type": "text", - "desc": "Window Mover: is Current Window Active", - "default": "False" - } - ] + "states": [], + "events": [] + } + ], + "settings": [ + { + "name": "Build by", + "type": "text", + "default": "Killer_BOSS", + "readOnly": true + }, + { + "name": "Version", + "type": "text", + "default": "0", + "readOnly": true + }, + { + "name": "Is Running", + "type": "text", + "default": "False", + "readOnly": false } ] -} \ No newline at end of file +} diff --git a/src/main.py b/src/main.py index 0a31e67..2e3deea 100644 --- a/src/main.py +++ b/src/main.py @@ -1,19 +1,21 @@ +import ctypes import subprocess -import pygetwindow as gw -from screeninfo import get_monitors -import TouchPortalAPI -from TouchPortalAPI import TYPES import sys -from ctypes import windll, wintypes -import win32gui -import win32api -import ctypes +import threading +from argparse import ArgumentParser from collections import namedtuple -import pywinauto -from time import sleep +from ctypes import windll, wintypes from ctypes.wintypes import tagPOINT from time import sleep -from threading import Thread + +import pygetwindow as gw +import pywinauto +import TouchPortalAPI as TP +import win32api +import win32gui +from screeninfo import get_monitors +from TouchPortalAPI import TYPES +from TouchPortalAPI.logger import Logger user32 = ctypes.WinDLL('user32') WindowInfo = namedtuple('WindowInfo', 'pid title') @@ -33,9 +35,26 @@ "PopupHost", "NVIDIA GeForce Overlay", "NVIDIA GPU Activity\n", - "Windows Input Experience" + "Windows Input Experience", + "Touch Portal Control Edit" ] +# TouchPortal Client +try: + TPClient = TP.Client( + pluginId = "WindowMover", # required ID of this plugin + sleepPeriod = 0.05, # allow more time than default for other processes + autoClose = True, # automatically disconnect when TP sends "closePlugin" message + checkPluginId = True, # validate destination of messages sent to this plugin + maxWorkers = 4, # run up to 4 event handler threads + updateStatesOnBroadcast = False, # do not spam TP with state updates on every page change + ) +except Exception as e: + sys.exit(f"Could not create TP Client, exiting. Error was:\n{repr(e)}") + +g_log = Logger("WindowMover") +no_permission_error = "Cannot change property of this Window. this could due to not running this program in Admin mode." + def list_windows(): OptionList = [] @WNDENUMPROC @@ -51,6 +70,7 @@ def enum_proc(hWnd, lParam): ProcessList = list(set(sorted(OptionList))) return [process for process in ProcessList if not process in processBlocklist] +# Unused function def getMonitorFriendlyName(): # Not sure how to use this correctly bc theres no way for me to verify which is which example \\\\.\\DISPLAY0 systemencoding = windll.kernel32.GetConsoleOutputCP() systemencoding = f"cp{systemencoding}" @@ -67,89 +87,102 @@ def get_desktop(): display.append({f"Display-{x}": {"width": monitor[x].width, "height": monitor[x].height, "x": monitor[x].x, "y": monitor[x].y}}) return display -def Move_Window(Title, Display, Where, resize=False): +def Move_Window(Title, Display, Where, resize=False, window_instance=0): try: - Window = gw.getWindowsWithTitle(Title)[0] + Window = gw.getWindowsWithTitle(Title)[window_instance] except IndexError: return Monitor = get_desktop() - print(Monitor) + g_log.debug(Monitor) + g_log.debug(f"Title {Title}, Display {Display}, Where {Where}, resize {resize}") + Indexnum = [] for x in Monitor: Indexnum.append(list(x.keys())[0]) + if Window.isMinimized: try: Window.restore() - except: - print('No Perm') + g_log.debug("Restore window. Because cannot move window when not active") + except Exception as e: + g_log.debug(no_permission_error) + g_log.error(e) if Display in Indexnum: indexnum = Indexnum.index(Display) - point = tagPOINT(Monitor[indexnum][Display]['x'],Monitor[indexnum][Display]['y']) + point = tagPOINT(Monitor[indexnum][Display]['x'], Monitor[indexnum][Display]['y']) monitor_area = win32api.GetMonitorInfo(user32.MonitorFromPoint(point, MonitorMode.get("MONITOR_DEFAULTTONEAREST"))) - print(monitor_area) + g_log.debug(monitor_area) + width = abs(monitor_area["Work"][2]-monitor_area["Work"][0]) height = abs(monitor_area["Work"][3]-monitor_area["Work"][1]) - print(monitor_area) + if resize == "True": try: - Window.resizeTo(int(width/2), int(height/2)) + if Where in (window_position := ["Top Half", "Bottom Half", "Left Half", "Right Half"]): + if Where in window_position[0:2]: + Window.resizeTo(int(width)+12, int(height/2)) + else: + Window.resizeTo(int(width/2)+12, int(height)) + else: + Window.resizeTo(int(width/2)+12, int(height/2)) except Exception as e: - print(e) - print('No Perm Reize') - if Where == "Top Left": - try: - Window.moveTo(monitor_area['Work'][0]-7, monitor_area['Work'][1]-7) - print("Top Left Moved to:",(monitor_area['Work'][0]-7, monitor_area['Work'][1]-7)) - except Exception: - print('No perm Top Left') - elif Where == "Top Right": - try: - Window.moveTo(int(monitor_area['Work'][2]-Window.width)+7, int(monitor_area['Work'][1])) - print("Top Right Moved to:",(int(monitor_area['Work'][2]-Window.width)+7, int(monitor_area['Work'][1]))) - except Exception: - print('No perm Top Right') - elif Where == "Top Middle": - try: - Window.moveTo(int(monitor_area['Work'][0]+(width-Window.width)/2), monitor_area['Work'][1]-7) - print("Top Middle Moved To:",(int(monitor_area['Work'][0]+(width-Window.width)/2), monitor_area['Work'][1]-7)) - except Exception as e: - print(e) - elif Where == "Bottom Middle": - try: - Window.moveTo(int(monitor_area['Work'][0]+(width-Window.width)/2), int(monitor_area['Work'][3]-Window.height)+7) - print("Bottom Middle Moved To:",(int(monitor_area['Work'][0]+(width-Window.width)/2), int(monitor_area['Work'][3]-Window.height)+7)) - except Exception as e: - print(e) - elif Where == "Left Middle": - try: - Window.moveTo(monitor_area['Work'][0]-7, int((monitor_area['Work'][1]+(height-Window.height))/2)) - print("Left Middle Moved To:",(monitor_area['Work'][0]-7, int((monitor_area['Work'][1]+(height-Window.height))/2))) - except Exception as e: - print(e) - elif Where == "Right Middle": - try: - Window.moveTo(int(monitor_area['Work'][2]-Window.width)+7, int((monitor_area['Work'][1]+(height-Window.height))/2)) - print("Right Middle Moved To:",(int(monitor_area['Work'][2]-Window.width)+7, int((monitor_area['Work'][1]+(height-Window.height))/2))) - except Exception as e: - print(e) - elif Where == "Bottom Left": - try: - Window.moveTo(int(monitor_area['Work'][0])-7, int(monitor_area['Work'][3]-Window.height)+7) - print("Bottom Left Moved To:",(int(monitor_area['Work'][0])-7, int(monitor_area['Work'][3]-Window.height)+7)) - except Exception as e: - print(e) - elif Where == "Buttom Right": - try: - Window.moveTo(int(monitor_area['Work'][2]-Window.width)+7, int(monitor_area['Work'][3]-Window.height)+7) - print("Bottom Right Moved To:",(int(monitor_area['Work'][2]-Window.width)+7, int(monitor_area['Work'][3]-Window.height)+7)) - except Exception as e: - print(e) - elif Where == "Center": - try: - Window.moveTo(int(monitor_area['Work'][0]+(width-Window.width)/2),int((monitor_area['Work'][1]+(height-Window.height))/2)) - print("Center Moved to:",(int(monitor_area['Work'][0]+(width-Window.width)/2),int((monitor_area['Work'][1]+(height-Window.height))/2))) - except Exception as e: - print(e) + g_log.debug(no_permission_error) + g_log.error(e) + + position_x = 0 + position_y = 0 + + match Where: + case "Top Left": + position_x = monitor_area['Work'][0]-7 + position_y = monitor_area['Work'][1] + case "Top Right": + position_x = int(monitor_area['Work'][2]-Window.width)+7 + position_y = int(monitor_area['Work'][1]) + case "Top Middle": + position_x = int(monitor_area['Work'][0]+(width-Window.width)/2) + position_y = monitor_area['Work'][1]-7 + case "Bottom Middle": + position_x = int(monitor_area['Work'][0]+(width-Window.width)/2) + position_y = int(monitor_area['Work'][3]-Window.height)+7 + case "Left Middle": + position_x = monitor_area['Work'][0]-7 + position_y = int((monitor_area['Work'][1]+(height-Window.height))/2) + case "Right Middle": + position_x = int(monitor_area['Work'][2]-Window.width)+7 + position_y = int((monitor_area['Work'][1]+(height-Window.height))/2) + case "Bottom Left": + position_x = int(monitor_area['Work'][0])-7 + position_y = int(monitor_area['Work'][3]-Window.height)+7 + case "Bottom Right": + position_x = int(monitor_area['Work'][2]-Window.width)+7 + position_y = int(monitor_area['Work'][3]-Window.height)+7 + case "Center": + position_x = int(monitor_area['Work'][0]+(width-Window.width)/2) + position_y = int((monitor_area['Work'][1]+(height-Window.height))/2) + case "Top Half": + position_x = monitor_area['Work'][0]-7 + position_y = monitor_area['Work'][1] + case "Bottom Half": + position_x = monitor_area['Work'][0]-7 + position_y = int(monitor_area['Work'][3]-Window.height) + case "Left Half": + position_x = monitor_area['Work'][0]-7 + position_y = monitor_area["Work"][1] + case "Right Half": + position_x = int(monitor_area['Work'][2]-Window.width)+6 + position_y = monitor_area["Work"][1] + case "_": + g_log.info(f"Unknown position: {Where}") + + try: + Window.moveTo(position_x, position_y) + except Exception as e: + g_log.debug(no_permission_error) + g_log.error(e) + + g_log.info(f"presets: {Where} process: {Title} positon: {Window.position} size: {Window.size}") + def ResizeTo(Title, width, height): try: @@ -160,11 +193,11 @@ def ResizeTo(Title, width, height): try: Window.restore() except: - print('No Perm') + g_log.debug(no_permission_error) try: Window.resizeTo(int(width),int(height)) except: - print('No Perm') + g_log.debug(no_permission_error) def MovebyXY(Title, X,Y): try: @@ -179,7 +212,7 @@ def MovebyXY(Title, X,Y): try: Window.move(int(X),int(Y)) except: - print('No Perm') + g_log.debug(no_permission_error) def increAndDecreResize(Title, width, height): try: @@ -190,11 +223,11 @@ def increAndDecreResize(Title, width, height): try: Window.restore() except: - print('No Perm') + g_log.debug(no_permission_error) try: Window.resize(int(width),int(height)) except: - print('No perm') + g_log.debug(no_permission_error) def focus_to_window(window_title=None): window = gw.getWindowsWithTitle(window_title)[0] @@ -202,39 +235,25 @@ def focus_to_window(window_title=None): try: pywinauto.application.Application().connect(handle=window._hWnd).top_window().set_focus() except: - print('No perm') + g_log.debug(no_permission_error) -def SysAction(Title, Action): +def SysAction(Title, action): try: Window = gw.getWindowsWithTitle(Title)[0] - print(Window) + g_log.debug(Window) except IndexError: return - if Action == "maximize": + if action in ["maximize", "minimize", "restore", "close"] : try: - Window.maximize() - except: - print('no perm') - elif Action == "minimize": - try: - Window.minimize() - except: - print('No Perm') - elif Action == "restore": - try: - Window.restore() - except: - print('No perm') - elif Action == "focus": + method = getattr(Window, action) + method() + except Exception as e: + g_log.info(f"Error running {action} on {Title}. Most likely a permission error. {e}") + elif action == "focus": try: focus_to_window(Title) - except: - return - elif Action == "close": - try: - Window.close() - except: - print('No Perm') + except Exception as e: + g_log.info(f"Unhandeled Error running {action} on {Title}. {e}") def CustomAction(Title, x, y, width, hight): try: @@ -246,40 +265,25 @@ def CustomAction(Title, x, y, width, hight): Window.moveTo(int(x),int(y)) Window.resizeTo(int(width),int(hight)) - -# Setup -TPClient = TouchPortalAPI.Client('WindowMover') -global running -running = False -runOnce = False - def stateUpdate(): - global runOnce + Timer = threading.Timer(0.25, stateUpdate) + monitor = [list(each.keys())[0].rstrip() for each in get_desktop()] + if TPClient.choiceUpdateList.get("KillerBOSS.TP.Plugins.WindowMover.Windowpresets.Displays") != monitor: + TPClient.choiceUpdate("KillerBOSS.TP.Plugins.WindowMover.Windowpresets.Displays", monitor) + TPClient.choiceUpdate('KillerBOSS.TP.Plugins.WindowMover.Windowpresets.Advanced.Displays', monitor) + g_log.debug(f'updating Display List {monitor}') - if not runOnce: - print("running once") - TPClient.choiceUpdate("KillerBOSS.TP.Plugins.WindowMover.Windowpresets.Displays", []) - TPClient.choiceUpdate('KillerBOSS.TP.Plugins.WindowMover.Windowpresets.Advanced.Displays', []) + if TPClient.choiceUpdateList.get("KillerBOSS.TP.Plugins.WindowMover.customMove.Window") != (processWindow := list_windows()): + TPClient.choiceUpdate("KillerBOSS.TP.Plugins.WindowMover.customMove.Window", processWindow) + g_log.debug(f"Updating process list {processWindow}") - TPClient.choiceUpdate("KillerBOSS.TP.Plugins.WindowMover.customMove.Window", []) - runOnce = True + currentFocusedWindow = gw.getActiveWindowTitle() + TPClient.stateUpdate('KillerBOSS.TP.Plugins.WindowMover.states.ActiveWindow', gw.getActiveWindowTitle()) - while running: - monitor = [list(each.keys())[0].rstrip() for each in get_desktop()] - if TPClient.choiceUpdateList.get("KillerBOSS.TP.Plugins.WindowMover.Windowpresets.Displays") != monitor: - TPClient.choiceUpdate("KillerBOSS.TP.Plugins.WindowMover.Windowpresets.Displays", monitor) - TPClient.choiceUpdate('KillerBOSS.TP.Plugins.WindowMover.Windowpresets.Advanced.Displays', monitor) - print('updating Display List', monitor) - - if TPClient.choiceUpdateList.get("KillerBOSS.TP.Plugins.WindowMover.customMove.Window") != (processWindow := list_windows()): - TPClient.choiceUpdate("KillerBOSS.TP.Plugins.WindowMover.customMove.Window", processWindow) - print("Updating process list", processWindow) - - try: - currentFocusedWindow = gw.getActiveWindowTitle() - TPClient.stateUpdate('KillerBOSS.TP.Plugins.WindowMover.states.ActiveWindow', currentFocusedWindow) - WindowInfo = gw.getWindowsWithTitle(currentFocusedWindow)[0] + if currentFocusedWindow and (WindowInfo := gw.getWindowsWithTitle(currentFocusedWindow)) and len(WindowInfo) > 0: + WindowInfo = WindowInfo[0] + if all(item in WindowInfo.__dir__() for item in ["top", "left", "width", "height", "isMaximized", "isMinimized", "isActive"]): TPClient.stateUpdateMany([ { "id": 'KillerBOSS.TP.Plugins.WindowMover.states.ActiveWindow.X', @@ -310,31 +314,35 @@ def stateUpdate(): "value": str(WindowInfo.isActive) } ]) - except (IndexError,AttributeError,ConnectionResetError): - pass - - sleep(0.2) # add delay + else: + g_log.debug("att is missing") + + if TPClient.isConnected(): + Timer.start() @TPClient.on(TYPES.onAction) def ManageAction(data): + g_log.debug(f"Connection: {data}") + g_log.info(f"Action: {data['actionId']}") + if data['actionId'] == "KillerBOSS.TP.Plugins.WindowMover.Windowpresets": - if data['data'][1]['value'] is not '': + if data['data'][1]['value']: Move_Window(data['data'][1]['value'], data['data'][2]['value'], data['data'][0]['value'],data['data'][3]['value']) if data['actionId'] == "KillerBOSS.TP.Plugins.WindowMover.ResizeTo": - if data['data'][0]['value'] is not '': + if data['data'][0]['value']: ResizeTo(data['data'][0]['value'], data['data'][1]['value'], data['data'][2]['value']) if data['actionId'] == "KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease": - if data['data'][1]['value'] is not '': + if data['data'][1]['value']: if data['data'][0]['value'] == "Increase": increAndDecreResize(data['data'][1]['value'], int(data['data'][2]['value']), int(data['data'][3]['value'])) elif data['data'][0]['value'] == "Decrease": increAndDecreResize(data['data'][1]['value'], -int(data['data'][2]['value']), -int(data['data'][3]['value'])) if data['actionId'] == 'KillerBOSS.TP.Plugins.WindowMover.SysActions': - if data['data'][1]['value'] is not '': + if data['data'][1]['value']: SysAction(data['data'][1]['value'],data['data'][0]['value']) if data['actionId'] == "KillerBOSS.TP.Plugins.WindowMover.MoveByXandY": - if data['data'][0]['value'] is not '': + if data['data'][0]['value']: if data['data'][3]['value'] == "Increase": MovebyXY(data['data'][0]['value'], data['data'][1]['value'], data['data'][2]['value']) elif data['data'][3]['value'] == "Decrease": @@ -343,96 +351,181 @@ def ManageAction(data): if data['data'][0]['value'] != '' and data['data'][1]['value'] != '' and data['data'][2]['value'] != '' and data['data'][3]['value'] != '' and data['data'][4]['value'] != '': CustomAction(data['data'][0]['value'],data['data'][1]['value'],data['data'][2]['value'],data['data'][3]['value'],data['data'][4]['value']) if data['actionId'] == "KillerBOSS.TP.Plugins.WindowMover.Advanced.MoveByXandY": - if data['data'][0]['value'] is not "" and data['data'][3]['value'] == 'Increase': + if data['data'][0]['value'] and data['data'][3]['value'] == 'Increase': MovebyXY(data['data'][0]['value'], data['data'][1]['value'], data['data'][2]['value']) - elif data['data'][0]['value'] is not "" and data['data'][3]['value'] == "Decrease": + elif data['data'][0]['value'] and data['data'][3]['value'] == "Decrease": MovebyXY(data['data'][0]['value'], -int(data['data'][1]['value']), -int(data['data'][2]['value'])) if data['actionId'] == "KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.Advanced": - if data['data'][1]['value'] is not "" and data['data'][0]['value'] == 'Increase': + if data['data'][1]['value'] and data['data'][0]['value'] == 'Increase': increAndDecreResize(data['data'][1]['value'], data['data'][2]['value'], data['data'][3]['value']) sleep(0.02) - elif data['data'][1]['value'] is not "" and data['data'][0]['value'] == "Decrease": + elif data['data'][1]['value'] and data['data'][0]['value'] == "Decrease": increAndDecreResize(data['data'][1]['value'], -int(data['data'][2]['value']), -int(data['data'][3]['value'])) sleep(0.02) if data['actionId'] == "KillerBOSS.TP.Plugins.WindowMover.Advanced.Windowpresets": - if data['data'][1]['value'] is not "": + if data['data'][1]['value']: Move_Window(data['data'][1]['value'],data['data'][2]['value'],data['data'][0]['value'], data['data'][3]['value']) if data['actionId'] == "KillerBOSS.TP.Plugins.WindowMover.ResizeTo.Advanced": - if data['data'][0]['value'] is not '': + if data['data'][0]['value']: ResizeTo(data['data'][0]['value'], data['data'][1]['value'], data['data'][2]['value']) if data['actionId'] == "KillerBOSS.TP.Plugins.WindowMover.Advanced.customMove": - if data['data'][0]['value'] is not '': + if data['data'][0]['value']: CustomAction(data['data'][0]['value'],data['data'][1]['value'],data['data'][2]['value'],data['data'][3]['value'],data['data'][4]['value']) if data['actionId'] == "KillerBOSS.TP.Plugins.WindowMover.SysActions.Advanced": - if data['data'][1]['value'] is not '': + if data['data'][1]['value']: SysAction(data['data'][1]['value'], data['data'][0]['value']) @TPClient.on(TYPES.onListChange) def listChange(data): + g_log.debug(f"Connection: {data}") if data['listId'] == "KillerBOSS.TP.Plugins.WindowMover.customMove.Window": try: findwindow = win32gui.FindWindow(None,data['value']) rect = win32gui.GetWindowRect(findwindow) except KeyError: return - TPClient.choiceUpdate("KillerBOSS.TP.Plugins.WindowMover.customMove.X", [str(rect[0])]) - TPClient.choiceUpdate("KillerBOSS.TP.Plugins.WindowMover.customMove.Y", [str(rect[1])]) - TPClient.choiceUpdate("KillerBOSS.TP.Plugins.WindowMover.customMove.width", [str(rect[2]-rect[0])]) - TPClient.choiceUpdate("KillerBOSS.TP.Plugins.WindowMover.customMove.height", [str(rect[3]-rect[1])]) + TPClient.choiceUpdateSpecific("KillerBOSS.TP.Plugins.WindowMover.customMove.X", [str(rect[0])], data["instanceId"]) + TPClient.choiceUpdateSpecific("KillerBOSS.TP.Plugins.WindowMover.customMove.Y", [str(rect[1])], data["instanceId"]) + TPClient.choiceUpdateSpecific("KillerBOSS.TP.Plugins.WindowMover.customMove.width", [str(rect[2]-rect[0])], data["instanceId"]) + TPClient.choiceUpdateSpecific("KillerBOSS.TP.Plugins.WindowMover.customMove.height", [str(rect[3]-rect[1])], data["instanceId"]) + g_log.info(f"Window: {data['value']} has been selected updating values") @TPClient.on(TYPES.onHold_down) def holdAction(data): + g_log.debug(f"Connection: {data}") + g_log.info(f"Action: {data['actionId']} is being held down") while True: + sleep(0.02) if TPClient.isActionBeingHeld('KillerBOSS.TP.Plugins.WindowMover.MoveByXandY'): if data['data'][3]['value'] == "Increase": MovebyXY(data['data'][0]['value'], data['data'][1]['value'], data['data'][2]['value']) - sleep(0.02) elif data['data'][3]['value'] == "Decrease": MovebyXY(data['data'][0]['value'], -int(data['data'][1]['value']), -int(data['data'][2]['value'])) - sleep(0.02) elif TPClient.isActionBeingHeld('KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease'): if data['data'][0]['value'] == "Increase": increAndDecreResize(data['data'][1]['value'], int(data['data'][2]['value']), int(data['data'][3]['value'])) - sleep(0.02) if data['data'][0]['value'] == "Decrease": increAndDecreResize(data['data'][1]['value'], -int(data['data'][2]['value']), -int(data['data'][3]['value'])) - sleep(0.02) elif TPClient.isActionBeingHeld('KillerBOSS.TP.Plugins.WindowMover.Advanced.MoveByXandY'): - if data['data'][0]['value'] is not "" and data['data'][3]['value'] == 'Increase': + if data['data'][0]['value'] and data['data'][3]['value'] == 'Increase': MovebyXY(data['data'][0]['value'], data['data'][1]['value'], data['data'][2]['value']) - sleep(0.02) - elif data['data'][0]['value'] is not "" and data['data'][3]['value'] == "Decrease": + elif data['data'][0]['value'] and data['data'][3]['value'] == "Decrease": MovebyXY(data['data'][0]['value'], -int(data['data'][1]['value']), -int(data['data'][2]['value'])) - sleep(0.02) elif TPClient.isActionBeingHeld('KillerBOSS.TP.Plugins.WindowMover.ResizeIncrease.Advanced'): - if data['data'][1]['value'] is not "" and data['data'][0]['value'] == 'Increase': + if data['data'][1]['value'] and data['data'][0]['value'] == 'Increase': increAndDecreResize(data['data'][1]['value'], data['data'][2]['value'], data['data'][3]['value']) - sleep(0.02) - elif data['data'][1]['value'] is not "" and data['data'][0]['value'] == "Decrease": + elif data['data'][1]['value'] and data['data'][0]['value'] == "Decrease": increAndDecreResize(data['data'][1]['value'], -int(data['data'][2]['value']), -int(data['data'][3]['value'])) - sleep(0.02) else: break + g_log.info(f"Action: {data['actionId']} is no longer being held down") @TPClient.on(TYPES.onConnect) def Onconnect(data): - global running - running = True - TPClient.settingUpdate("Version", "2.1") + g_log.info(f"Connected to TP v{data.get('tpVersionString', '?')}, plugin v{data.get('pluginVersion', '?')}.") + g_log.debug(f"Connection: {data}") + + TPClient.settingUpdate("Version", "3.1.0") TPClient.settingUpdate("Is Running","True") - Thread(target=stateUpdate).start() - print(data) + + TPClient.choiceUpdate("KillerBOSS.TP.Plugins.WindowMover.Windowpresets.Displays", []) + TPClient.choiceUpdate('KillerBOSS.TP.Plugins.WindowMover.Windowpresets.Advanced.Displays', []) + TPClient.choiceUpdate("KillerBOSS.TP.Plugins.WindowMover.customMove.Window", []) + + stateUpdate() @TPClient.on(TYPES.onShutdown) def Shutdown(data): - global running - running = False + g_log.debug(f"Connection: {data}") try: TPClient.settingUpdate("Is Running","False") - except: + except ConnectionResetError: pass - TPClient.disconnect() - sys.exit() + g_log.info('Received shutdown event from TP Client.') + +# Error handler +@TPClient.on(TYPES.onError) +def onError(exc): + g_log.error(f'Error in TP Client event handler: {repr(exc)}') + +def main(): + global TPClient, g_log + ret = 0 + + # default log file destination + logFile = f"./log.log" + # default log stream destination + logStream = sys.stdout + + # Set up and handle CLI arguments. These all relate to logging options. + # The plugin can be run with "-h" option to show available argument options. + # Addtionally, a file constaining any of these arguments can be specified on the command line + # with the `@` prefix. For example: `plugin-example.py @config.txt` + # The file must contain one valid argument per line, including the `-` or `--` prefixes. + # See the plugin-example-conf.txt file for an example config file. + parser = ArgumentParser(fromfile_prefix_chars='@') + parser.add_argument("-d", action='store_true', + help="Use debug logging.") + parser.add_argument("-w", action='store_true', + help="Only log warnings and errors.") + parser.add_argument("-q", action='store_true', + help="Disable all logging (quiet).") + parser.add_argument("-l", metavar="", + help=f"Log file name (default is '{logFile}'). Use 'none' to disable file logging.") + parser.add_argument("-s", metavar="", + help="Log to output stream: 'stdout' (default), 'stderr', or 'none'.") + + # his processes the actual command line and populates the `opts` dict. + opts = parser.parse_args() + del parser + + # trim option string (they may contain spaces if read from config file) + opts.l = opts.l.strip() if opts.l else 'none' + opts.s = opts.s.strip().lower() if opts.s else 'stdout' + g_log.info(opts) + + # Set minimum logging level based on passed arguments + logLevel = "INFO" + if opts.q: logLevel = None + elif opts.d: logLevel = "DEBUG" + elif opts.w: logLevel = "WARNING" + + # set log file if -l argument was passed + if opts.l: + logFile = None if opts.l.lower() == "none" else opts.l + # set console logging if -s argument was passed + if opts.s: + if opts.s == "stderr": logStream = sys.stderr + elif opts.s == "stdout": logStream = sys.stdout + else: logStream = None + + # Configure the Client logging based on command line arguments. + # Since the Client uses the "root" logger by default, + # this also sets all default logging options for any added child loggers, such as our g_log instance we created earlier. + TPClient.setLogFile(logFile) + TPClient.setLogStream(logStream) + TPClient.setLogLevel(logLevel) + + # ready to go + g_log.info(f"Starting WindowsMover v302 on {sys.platform}.") + + try: + TPClient.connect() + g_log.info('TP Client closed.') + except KeyboardInterrupt: + g_log.warning("Caught keyboard interrupt, exiting.") + except Exception: + from traceback import format_exc + g_log.error(f"Exception in TP Client:\n{format_exc()}") + ret = -1 + finally: + TPClient.disconnect() + + del TPClient + + g_log.info(f"WindowsMover stopped.") + return ret -TPClient.connect() +if __name__ == "__main__": + sys.exit(main())