Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quick Start broken #8

Open
minguo33 opened this issue Nov 14, 2023 · 7 comments
Open

Quick Start broken #8

minguo33 opened this issue Nov 14, 2023 · 7 comments

Comments

@minguo33
Copy link

Hi, I have tried to get this working on Windows 11 and Windows 10, each time the experience was the same.

Installing jigsawwm from PIP and trying to use the quickstart example wm.pyw nothing happens.

When trying to call wm.pyw from a python interpreter receive this error:

wm.pyw, line 1, in <module>
    from jmk import hks
ImportError: cannot import name 'hks' from 'jmk' 

Trying to run jigsaw.pyw results again in nothing happening, and when calling it from a python interpreter receives this error:

jigsaw.pyw", line 2, in <module>
    from log import *
ModuleNotFoundError: No module named 'log'

Investigating that issue seems to imply python 'log' library has been renamed to 'logging' but I can't tell if that's what jigsawwm is trying use.

Interesting project, would like to test it out.
Are the example files still current? If not, do you have a working example to use?

@klesh
Copy link
Owner

klesh commented Nov 16, 2023

Thanks for reporting the problem, will look into it ASAP.

@klesh
Copy link
Owner

klesh commented Nov 22, 2023

Hi, @minguo33 , Sorry for taking so long to investigate the issue. I think the problem is that you tried to import the .pyw file in the examples which is not what they are meant for.
Please copy the code from the files you need and create your own pyw file to launch the jigsawwm.

@minguo33
Copy link
Author

Hi, @minguo33 , Sorry for taking so long to investigate the issue. I think the problem is that you tried to import the .pyw file in the examples which is not what they are meant for. Please copy the code from the files you need and create your own pyw file to launch the jigsawwm.

Hi @klesh , thanks for taking a look. Unfortunately, I haven't been able to get any of the examples to run whether or not I copy the code into a new file or download the source and try to run it. Can you give some guidance on how to get a working configuration?

When trying to test import statements from my python interpreter, I can import jmk, but not hks. (which is where my previous attempts got caught up.)


>>> from jigsawwm import jmk
>>> from jigsawwm import hks
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: cannot import name 'hks' from 'jigsawwm' (\JigsawWM-main\src\jigsawwm\__init__.py)

My environment is python 3.12, jigsawwm was installed with pip, which self reports as version 2.0.

@klesh
Copy link
Owner

klesh commented Nov 27, 2023

Hi, @minguo33 There is no hks module under the jigsawwm.
I think you copied the code from one of the examples, in this case, the hks is a variable from the jmk.pyw file which is an instance of a jmk.Hotkeys class for hotkeys subscription. Did you want to subscribe to hotkey events? if that so, you should creating your own instances just like the jmk.pyw does:

sysin, jmk, hks, sysout = create_jmk(layers, hotkeys, bypass_exe=bypass_exe)

@minguo33
Copy link
Author

minguo33 commented Nov 27, 2023

Hi again, @klesh , thank you for the assistance in trying to understand what is going on.

Here's my objective: Use a tiling window manager on windows.

I wanted to test out how yours performs, so I was less interested in the other modules but it seems I cannot directly use the wm.pym you link in the quickstart on the main github page to test that functionality.

So I started over and using your advice created a new file and copied the contents from jmk.pyw that seems relevant. I then tried to integrate the statements from wm.pym that make the window management function.

I think it is working now, thank you for your efforts and help.

Here is the configuration I created, in case anyone else gets caught up trying to make the quickstart work as is. (IIUC, they cannot be used as is, correct?)


from datetime import datetime

#from log import *

from jigsawwm import daemon, ui
from jigsawwm.jmk import *
from jigsawwm.tiler import tilers
from jigsawwm.w32.sendinput import send_combination, send_text
from jigsawwm.w32.vk import Vk
from jigsawwm.w32.window import minimize_active_window, toggle_maximize_active_window,inspect_active_window
from jigsawwm.wm import Theme, WindowManager


#######################
#  configuration
#######################

send_today = lambda: send_text(datetime.now().strftime("%Y-%m-%d"))
send_now = lambda: send_text(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
ctrl_w = lambda: send_combination(Vk.LCONTROL, Vk.W)
ctrl_shift_t = lambda: send_combination(Vk.LCONTROL, Vk.LSHIFT, Vk.T)
ctrl_pgup = lambda: send_combination(Vk.LCONTROL, Vk.PRIOR)
ctrl_pgdn = lambda: send_combination(Vk.LCONTROL, Vk.NEXT)

layers = [
    {  # layer 0
        # map capslock to ctrl when held and `  when tapped
        Vk.CAPITAL: JmkTapHold(tap=parse_key("`"), hold=Vk.LCONTROL),
        # Vk.ESCAPE: JmkTapHold(tap=Vk.ESCAPE, hold=Vk.LWIN),
        # Vk.T: JmkTapHold(tap=Vk.T, hold=3),
        # Vk.Y: JmkTapHold(tap=Vk.Y, hold=3),
        # Vk.A: JmkTapHold(tap=Vk.A, hold=Vk.LMENU),
        # Vk.S: JmkTapHold(tap=Vk.S, hold=Vk.LSHIFT),
        # Vk.D: JmkTapHold(tap=Vk.D, hold=Vk.LWIN),
        # Vk.F: JmkTapHold(tap=Vk.F, hold=Vk.LCONTROL),
        # Vk.G: JmkTapHold(tap=Vk.G, hold=1),
        # Vk.H: JmkTapHold(tap=Vk.H, hold=1),
        # Vk.J: JmkTapHold(tap=Vk.J, hold=Vk.RCONTROL),
        # Vk.K: JmkTapHold(tap=Vk.K, hold=Vk.RWIN),
        # Vk.L: JmkTapHold(tap=Vk.L, hold=Vk.RSHIFT),
        # hold ; as Alt
        Vka.SEMICOLON: JmkTapHold(tap=Vka.SEMICOLON, hold=Vk.RMENU),
        # Vk.TAB: JmkTapHold(tap=Vk.TAB, hold=2),
        # hold ' to switch to layer 2
        Vk.N: JmkTapHold(tap=Vk.N, hold=2),
        Vk.B: JmkTapHold(tap=Vk.B, hold=2),
        # hold Forward Button on the Mouse for swithcing to layer 1
        Vk.XBUTTON2: JmkTapHold(tap=Vk.XBUTTON2, hold=2),
        Vk.BROWSER_FORWARD: JmkTapHold(tap=Vk.XBUTTON2, hold=2),
        Vk.SPACE: JmkTapHold(tap=Vk.SPACE, hold=Vk.LSHIFT),
        Vka.SLASH: JmkTapHold(
            tap=Vka.SLASH, on_hold_up=lambda: rootLogger.setLevel(logging.DEBUG)
        ),
    },
    {  # layer 1
        # left hand
        Vk.A: JmkKey(Vk.HOME),
        Vk.E: JmkKey(Vk.END),
        Vk.D: JmkKey(Vk.DELETE),
        Vk.B: JmkKey("LCtrl+Left"),
        Vk.F: JmkKey("LCtrl+Right"),
        # right hand
        Vk.H: JmkKey(Vk.LEFT),
        Vk.J: JmkKey(Vk.DOWN),
        Vk.K: JmkKey(Vk.UP),
        Vk.L: JmkKey(Vk.RIGHT),
        Vk.U: JmkKey(ctrl_pgup),
        Vk.I: JmkKey(ctrl_pgdn),
        Vk.N: JmkKey(Vk.MEDIA_NEXT_TRACK),
        Vk.P: JmkKey(Vk.MEDIA_PREV_TRACK),
        Vk.OEM_COMMA: JmkKey(Vk.VOLUME_DOWN),
        Vk.OEM_PERIOD: JmkKey(Vk.VOLUME_UP),
        Vka.SLASH: JmkKey(Vk.MEDIA_PLAY_PAUSE),
    },
    {  # layer 2
        # tap to send today's date, hold to send now
        Vk.T: JmkTapHold(on_tap=send_today, on_hold_down=send_now),
        # tap to close tab, hold to reopen for Chrome
        Vk.LBUTTON: JmkTapHold(on_tap=ctrl_w, on_hold_down=ctrl_shift_t, term=0.5),
        # forward button + whell up  = ctrl + page up (previous tab)
        Vk.WHEEL_UP: JmkKey(ctrl_pgup),
        # forward button + wheel down  = ctrl + page down (next tab)
        Vk.WHEEL_DOWN: JmkKey(ctrl_pgdn),
        # exit
        Vk.ESCAPE: JmkKey(daemon.stop),
        # symbol
        Vk.A: JmkKey(lambda: send_text("@")),
        Vk.E: JmkKey(lambda: send_text("!")),
        Vk.S: JmkKey(lambda: send_text("#")),
        Vk.D: JmkKey(lambda: send_text("$")),
        Vk.X: JmkKey(lambda: send_text("%")),
        Vk.Y: JmkKey(lambda: send_text("^")),
        Vk.N: JmkKey(lambda: send_text("&")),
        Vk.R: JmkKey(lambda: send_text("*")),
        Vk.F: JmkKey(lambda: send_text("(")),
        Vk.G: JmkKey(lambda: send_text(")")),
        Vk.M: JmkKey(lambda: send_text("-")),
        Vk.P: JmkKey(lambda: send_text("+")),
        Vk.U: JmkKey(lambda: send_text("_")),
        Vk.Q: JmkKey(lambda: send_text("=")),
    },
    {  # layer 3
        # left hand
        Vk.Z: JmkKey(Vk.F1),
        Vk.X: JmkKey(Vk.F2),
        Vk.C: JmkKey(Vk.F3),
        Vk.V: JmkKey(Vk.F4),
        Vk.A: JmkKey(Vk.F5),
        Vk.S: JmkKey(Vk.F6),
        Vk.D: JmkKey(Vk.F7),
        Vk.F: JmkKey(Vk.F8),
        Vk.Q: JmkKey(Vk.F9),
        Vk.W: JmkKey(Vk.F10),
        Vk.E: JmkKey(Vk.F11),
        Vk.R: JmkKey(Vk.F12),
        # right hand
        Vk.Y: JmkKey(Vk.OEM_PERIOD),
        Vk.SPACE: JmkKey(Vk.KEY_0),
        Vk.M: JmkKey(Vk.KEY_1),
        Vk.OEM_COMMA: JmkKey(Vk.KEY_2),
        Vk.OEM_PERIOD: JmkKey(Vk.KEY_3),
        Vk.J: JmkKey(Vk.KEY_4),
        Vk.K: JmkKey(Vk.KEY_5),
        Vk.L: JmkKey(Vk.KEY_6),
        Vk.U: JmkKey(Vk.KEY_7),
        Vk.I: JmkKey(Vk.KEY_8),
        Vk.O: JmkKey(Vk.KEY_9),
        Vk.H: JmkKey(Vk.SUBTRACT),
        Vka.SEMICOLON: JmkKey(Vk.ADD),
        Vk.P: JmkKey(Vk.OEM_PLUS),
        Vk.N: JmkKey(Vk.MULTIPLY),
        Vka.SLASH: JmkKey(Vk.DIVIDE),
    },
]

wm = WindowManager(
    themes=[
        # Theme(
        #     name="OBS Dwindle",
        #     layout_tiler=tilers.obs_dwindle_layout_tiler,
        #     icon_name="obs.png",
        #     gap=2,
        #     strict=True,
        # ),
        Theme(
            name="Mono",
            layout_tiler=tilers.mono_layout_tiler,
            strict=True,
        ),
        Theme(
            name="WideScreen Dwindle",
            layout_tiler=tilers.widescreen_dwindle_layout_tiler,
            icon_name="wide-dwindle.png",
            gap=2,
            strict=True,
            new_window_as_master=True,
        ),
        Theme(
            name="Dwindle",
            layout_tiler=tilers.dwindle_layout_tiler,
            strict=True,
            gap=2,
            new_window_as_master=True,
        ),
    ],
    ignore_exe_names=[
        "7zFM.exe",
        "explorer.exe",
        # "Feishu.exe",
        "fdm.exe",
        # "WeChat.exe",
        "foobar2000.exe",
        "ApplicationFrameHost.exe",
        "notepad++.exe",
        "PotPlayerMini64.exe",
        "mintty.exe",
        "openvpn-gui.exe",
        "Cloudflare WARP.exe",
        "MediaInfo.exe",
        "SnippingTool.exe",
        "WeChat.exe",
    ],
    force_managed_exe_names=["Lens.exe"],
)



hotkeys = [
    ([Vk.WIN, Vk.J], wm.activate_next, ui.hide_windows_splash),
    ([Vk.WIN, Vk.K], wm.activate_prev, ui.hide_windows_splash),
    ([Vk.WIN, Vk.SHIFT, Vk.J], wm.swap_next),
    ([Vk.WIN, Vk.SHIFT, Vk.K], wm.swap_prev),
    ("Win+/", wm.set_master),
    ([Vk.WIN, Vk.SPACE], wm.next_theme),
    ([Vk.WIN, Vk.U], wm.prev_monitor),
    ([Vk.WIN, Vk.I], wm.next_monitor),
    ([Vk.WIN, Vk.SHIFT, Vk.U], wm.move_to_prev_monitor),
    ([Vk.WIN, Vk.SHIFT, Vk.I], wm.move_to_next_monitor),
    ([Vk.WIN, Vk.CONTROL, Vk.I], inspect_active_window),
]


bypass_exe = {
    "Snipaste.exe",
    "TextInputHost.exe",
}

#######################
#  setup jmk
#######################

sysin, jmk, hks, sysout = create_jmk(layers, hotkeys, bypass_exe=bypass_exe)


class WindowManagerService(daemon.Service):
    name = "Window Manager"
    is_running = False

    def start(self):
        self.is_running = True
        wm.install_hooks()
        for args in hotkeys:
            hks.register(*args)

    def stop(self):
        wm.uninstall_hooks()
        for args in hotkeys:
            hks.unregister(args[0])
        self.is_running = False


class JmkService(daemon.Service):
    name = "jmk"
    is_running = False

    def start(self):
        self.is_running = True
        sysin.install()

    def stop(self):
        sysin.uninstall()
        self.is_running = False


daemon.register(JmkService)
daemon.register(WindowManagerService)

if __name__ == "__main__":
    daemon.message_loop()

@gazpachoking
Copy link

gazpachoking commented Jan 17, 2024

Looks like the wm.pwy example is wrong. Specifically this line:

from jmk import hks

EDIT: Oh, I get it now. The quickstart seems to imply that you can just pick a file from the examples folder, but in fact they all depend on each other, and you have to download the whole examples folder to do anything with them.

@klesh
Copy link
Owner

klesh commented Jan 18, 2024

@gazpachoking You are totally correct. I meant to show cases that you may do for different features and how to combine them together.
However, it does seem a little bit confusing, I'm open to suggestion of making it clearer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants