wez / wezterm

A GPU-accelerated cross-platform terminal emulator and multiplexer written by @wez and implemented in Rust
https://wezfurlong.org/wezterm/
Other
14.89k stars 677 forks source link

Dropdown/Guake/Visor/hotkey terminal feature #1751

Open halfelf opened 2 years ago

halfelf commented 2 years ago

Is your feature request related to a problem? Please describe. The so-called "dropdown" terminal window can be activated or deactivated by a single keystroke. Many terminal emulators have integrated this feature, for example, KDE's yakuake, quake style guake in Gnome, tilda. Also iTerm2 could set to this mode by enable a system wide hotkey in config.

And here's a short video shows how this feature works in xfce-terminal.

This is a so important feature for terminal emulator that there is even an independent project to help people to get it.

Describe the solution you'd like A new key assignment:

keys = {
    # press F1 to popup or hide wezterm window
    {key="F1", mods="", action="ToggleDropdown"}
  }
wez commented 2 years ago

Related:

catalin560 commented 2 years ago

any news about this?

wez commented 2 years ago

If there was news it would be here, and mentioned in the ChangeLog

prgres commented 2 years ago

Bump, I'm really waiting for this feature too

wez commented 1 year ago

Folks, I have limited time for hacking on things that I don't or won't use. This is one of those features. I spend my available time how I want to spend it because it is my time, not yours! If you thumbs-down a simple statement about where you would find information about progress, you are showing a level of entitlement that simply demotivates me from wanting to work on it. "Bump" comments are in a similar category.

If you'd like to see this implemented, by all means thumb-up the original post at the top; that's useful when it comes to triaging issues because I can see a simple counter without having to scan the issues.

Keep in mind that there is only one of me and I'm doing this for fun. When you are toxic and entitled you make this not fun and I'd rather do something else with my time.

If you're really motivated to see this feature get implemented, this is open source and I'd love to help shepherd a contributor through a PR.

beckend commented 1 year ago

working linux XOrg setup:

~/.config/wezterm/wezterm.lua

local wezterm = require 'wezterm';

wezterm.on("format-window-title", function(tab, pane, tabs, panes, config)
  local zoomed = ""
  if tab.active_pane.is_zoomed then
    zoomed = "[Z] "
  end

  local index = ""
  if #tabs > 1 then
    index = string.format("[%d/%d] ", tab.tab_index + 1, #tabs)
  end

  return "wm_wezterm: " .. zoomed .. index .. tab.active_pane.title
end)

/any/location/script.sh

#!/usr/bin/env bash

TERMINAL_BIN="${1}"
NAME_WINDOW_SEARCH="${2}"

function toggle() {
  local WINDOW_ID=$(xdotool search --name "${NAME_WINDOW_SEARCH}")

  if [[ ${#WINDOW_ID} -gt 0 ]]; then
    xprop -id "${WINDOW_ID}" | grep _NET_WM_STATE_FOCUSED 1>/dev/null
    if [[ $? -eq 0 ]]; then
      # echo "Focused->Hidden"
      xdotool windowminimize "${WINDOW_ID}"
    else
      # echo "Hidden/Unfocused->Focused"
      xdotool windowactivate "${WINDOW_ID}"
    fi
  else
    sh -c "${TERMINAL_BIN}" &
  fi
}

toggle

I am using KDE, so I created a global shortcut which executes script.sh "wezterm" "wm_wezterm" every time the keyboard shortcut is pressed.

catalin560 commented 1 year ago

Bump, I'm really waiting for this feature too

sadly, it doesn't look like it will be implemented any time soon 😢 I'm sticking with Yakuake or Guake on Linux and Windows Terminal which has a dropdown mode.

wez commented 1 year ago

@beckend neat! Have you experimented with wezterm start --class to set a different window class? That might help you avoid needing to change the window title

beckend commented 1 year ago

--class hello, Tried it now, the --class seems not to work, rather I have no idea what it does.

wmctrl -l
...
0x0180001d -1 workstation-1.localdomain.internal Plasma
0x06e00003  0                                N/A wmctrl -l ~

I always get N/A on wezterm, that is why I had to use the title functionality and enforce a consistent title to match. This is the output as expected from the title callback:

wmctrl -l
0x05e00003  0                                N/A wm_wezterm: wmctrl -l ~
MuhammedZakir commented 1 year ago

Probably something wrong wih wmctrl? I was able to get the classname with both xdotool and xprop. Manipulating the window with xdo using the class name worked too.

digitallyserviced commented 1 year ago

So here is how I handle this... I use wezterm as a status bar/drop down/quake console. Screenshot_2022-07-06-12-37-59_1920x1080

Screenshot_2022-07-08-09-12-37_1920x1080

This script launches my wezterms with specific class names and specific configurations bspterm

this script is used like this

wezbar

example keybindings for wezbar to expand/collapse/runline/launch etc...

##---------- Keybindings for bspwm ----------##

# Terminal (wez)
super + Return
    bspterm

# Terminal (wezbar)
super + shift + Return
    bspterm -f

# Terminal (wez fullscreen'd)
super + t
    bspterm -s  

super + alt + b
    ~/.local/bin/wezbar collapse
super + alt + n
    ~/.local/bin/wezbar expand
super + alt + r
    ~/.local/bin/wezbar runline
super + M
    ~/.local/bin/wezmodal zsh
super + S 
    bspterm -m
super + V 
    ~/.local/bin/wezmodal fzf-clipcat

bspwmrc snippet for the rules applied....

bspc rule -a wezterm desktop='^1' follow=on focus=on
bspc rule -a wezbar desktop='^1' rectangle=1920x40+0+0 manage=off state=floating border=off
bspc rule -a wezssh desktop='^3' rectangle=1884x982+16+16 
bspc rule -a wezdebug desktop='^7' rectangle=1884x982+16+16 
# bspc rule -a wezmodal state=floating manage=off
bspc rule -a wezmodal rectangle=800x600+500+300 border=off follow=on sticky=on focus=on center=on state=floating

and my wezterm configs (beware it is a fucking mess because i haven't cleaned it and im always hacking on shit) .config/wezterm

but it works

Crandel commented 1 year ago

This is my Swaywm solution to toggle wezterm visibility by pressing F1

~/.config/sway/config

set {
  $term_id   quake_term
  $term      wezterm start --class $term_id
  $t_pos     border none, move position center, resize set width 100 ppt height 100 ppt
}

for_window {
  [app_id=$term_id] {
    move to scratchpad;
    [app_id=$term_id] scratchpad show;
    $t_pos
  }
}

bindsym --to-code {
  # Scratchpad bindsym
  ## Main terminal
  F1 exec swaymsg [app_id=$term_id]   scratchpad show || exec $term ,  $t_pos
}

exec $term
MiSawa commented 1 year ago

tdrop also works. My wezterm has a unix domain configured

-- in ~/.config/wezterm/wezterm.lua
unix_domains = {
  {
    name = 'dropdown',
  }
},

, and it'll be connected to it when it was triggered by a hotkey handled by sxhkd.

# in ~/.config/sxhkd/sxhkdrc
F11
  tdrop -mat -w -4 -h -38 --pre-unmap-hook='wmctrl -ir $wid -b remove,maximized_vert; xdotool windowsize $wid $width 10%' --class 'wezterm.dropdown' -f 'connect dropdown --class wezterm.dropdown' wezterm

F12
  tdrop -mat -w -4 -h 45% --pre-unmap-hook='wmctrl -ir $wid -b remove,maximized_vert; xdotool windowsize $wid $width 10%' --class 'wezterm.dropdown' -f 'connect dropdown --class wezterm.dropdown' wezterm

I have the --pre-unmap-hook arg since tdrop doesn't seem to work nicely with a snapping behavior and/or maximize/unmaximize behavior of the WM I use, so you may be able to just do tdrop -mat -w -4 -h -38 --class 'wezterm.dropdown' -f 'connect dropdown --class wezterm.dropdown' wezterm instead.

halfelf commented 1 year ago

Found a solution for mac, but not perfect.

Open Automator app, create a Quick Action task, with no input, and applying for all Applications.

Drag AppleScript to work flow and edit it like this:

tell application "WezTerm"
    activate
end tell

Save and give it a unique name like activate_wezterm. Generally this will add a service item for all apps under their service menu.

Then, open System Preferences, click Keyboard, then click Shortcuts.

Select App Shortcuts on the left, click the Add(+) button. In the Menu Title field, type activate_wezterm or the name you choose before, set a shortcut for it and all done.

To hide the front most window is similar and I just omit the procedure here.

Cons:

danielnbalasoiu commented 1 year ago

@halfelf, thank you for the workaround.

I followed the steps you described and after I press the shortcut keys, it switches me to an already openned WezTerm window or it will open a new one. In my case I configured WezTerm to open only on a specific virtual desktop, this means the shortcut will just switch to desktop 2 where the terminal is running.

This behaviour is different from the one described in this issue. Am I doing something wrong?

Thanks!

halfelf commented 1 year ago

@danielnbalasoiu I believe you're on the right track. I haven't tested it on a virtual desktop yet, and indeed I have seen some people talked about activate command has a strange behavior when I trying to solve this problem.

You could try this script or another one to focus on a window. And this may help locate desktop.

keturiosakys commented 1 year ago

If there are any yabai, skhd, and fish shell users on macOS - I wrote this quick script to quickly show and hide WezTerm (not quite Quake style as it still follows the tiling structure but you can customize it from here).

It uses an extra space as a hidden one (I use only 3 spaces, so 4 is hidden for me).

#!/usr/bin/env fish

set hidden_space 4

function main -a app
    set window (yabai -m query --windows | jq --arg app $app '.[] | select(.app==$app)')
    set is_visible (echo $window | jq '."is-visible"')
    set id (echo $window | jq '.id')

    if test -z "$is_visible"
        osascript \
            -e "on run (argv)" \
            -e "tell application (item 1 of argv) to activate" \
            -e "end" \
            -- "$app"
    else if $is_visible
        yabai -m window $id --space $hidden_space
        echo "$app hidden"
    else
        yabai -m window $id --space mouse && yabai -m window --focus $id
        echo "$app revealed"
    end
end

main $argv

and then in skhdrc:

alt - return: ~/.config/scripts/dropdown.fish WezTerm
cd-a commented 1 year ago

As a temporary workaround on macOS, I highly recommend using hammerspoon.

This will allow you to target any app with a key combination and either spawn it or show it.

Something as easy as this:

hs.hotkey.bind({"shift", "alt", "ctrl"}, "A", function()
  hs.application.launchOrFocus("Wezterm")
end)

I haven't tried that yet, but I'm sure you could use some launch arguments for position and name to spawn a separate Wezterm entity.

halfelf commented 1 year ago

@cd-a Thanks a lot! Hammerspoon responses keystroke much faster than my poor applescript.

For a classic dropdown behavior, I have this conf and tested:

hs.hotkey.bind({}, "F2", function()
    wez = hs.application.find("Wezterm")
    if wez then
        if wez:isFrontmost() then
            wez:hide()
        else
            wez:activate()
        end
    end
end)
noahbliss commented 1 year ago

+1. Guake is the best at the moment with the tmux like splits, gui configurator, and quake functionality but it's. so. slow.

svallory commented 9 months ago

For anyone using Karabiner, here's a complex modification config using ctrl+esc

gist link

{
  "title": "Quake-style Hotkey Window for Wezterm",
  "rules": [
    {
      "description": "Launch/show Wezterm if it is not in foreground",
      "manipulators": [
        {
          "type": "basic",
          "from": {
            "key_code": "escape",
            "modifiers": {
              "mandatory": ["control"]
            }
          },
          "to": [
            {
              "shell_command": "open '/Applications/WezTerm.app'"
            }
          ],
          "conditions": [
            {
              "type": "frontmost_application_unless",
              "bundle_identifiers": ["^com\\.github\\.wez\\.wezterm$"]
            }
          ]
        }
      ]
    },
    {
      "description": "Minimize Wezterm if it is in foreground",
      "manipulators": [
        {
          "type": "basic",
          "from": {
            "key_code": "escape",
            "modifiers": {
              "mandatory": ["control"]
            }
          },
          "to": [
            {
              "key_code": "h",
              "modifiers": ["command"]
            }
          ],
          "conditions": [
            {
              "type": "frontmost_application_if",
              "bundle_identifiers": ["^com\\.github\\.wez\\.wezterm$"]
            }
          ]
        }
      ]
    }
  ]
}
jmweir commented 8 months ago

Thank you to everyone for offering creative workarounds. Thank you @wez for creating this cool app!

orumin commented 7 months ago

In Windows, script of AutoHotKey will works like Quake Mode. I tested below script on AutoHotKey v2+:

#SingleInstance Force
#Warn

; Load a few environment variables
userprofile := EnvGet("USERPROFILE")

; read config file
configFile := userprofile . "\.QuakeLikeConsole.ini"
LoadConfig()

; Tray icon customization
A_IconTip := "Quake Like Console (key: " . key . ")"
Tray:= A_TrayMenu
Tray.Delete() ; remove standard Menu items
Tray.Add("Quake Like Console", Dummy)
Tray.Add("") ; separator
Tray.Add("&Suspend", ToggleSuspend)
Tray.Add("&Open config file", OpenConfig)
Tray.Add("") ; separator
Tray.Add("E&xit", ButtonExit)
Return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Handle Hotkey events
ToggleConsole(ThisHotkey)
{
    dim := GetActiveMonitorDimention()
    ;MsgBox( "monIndex: " . dim.index . " x: " . dim.x . " y: " . dim.y . " width: " . dim.width . " height: " . dim.height)
    DetectHiddenWindows(true)
    local hwnd_id := WinExist(windowMatcher)
    if (hwnd_id != 0) {
        DetectHiddenWindows(false)
        if WinActive() {
            WinHide()
        } else {
            DetectHiddenWindows(true)
            ; show window on top of monitor with your mouse cursor.
            ; window size set to width (1.0 * monitor pixel width) x height (heightRatio * monitor pixel height)
            WinMove(dim.x, dim.y, dim.width, dim.height * Float(heightRatio), hwnd_id)
            WinShow()
            WinActivate()
        }
    } else {
        Try {
            Run(command, workingDir)  ; see http://ahkscript.org/docs/commands/Run.htm
        } Catch Error as e {
            TrayTip("Could not execute command", command, 3)
            Throw e
        }
    }
    Return
}

GetActiveMonitorDimention()
{
    dim := {index: 0, x: 0, y: 0, width: 0, height: 0}
    CoordMode("Mouse", "Screen")
    MouseGetPos(&x, &y)
    local count := MonitorGetCount()
    Loop count {
        MonitorGet(A_Index, &Left, &Top, &Right, &Bottom)
        if (x >= Left) && (x <= Right) && (y <= Bottom) && (y >= Top) {
            dim.index := A_Index
            dim.x := Left
            dim.y := Top
            dim.width := Abs(Right - Left)
            dim.height := Abs(Top - Bottom)
        }
    } Until (dim.width > 0)
    return dim
}

LoadConfig() {
    global key, configFile, command, heightRatio, workingDir, windowMatcher, userprofile

    Try {
        Hotkey(key, "Toggle")
    }

    command := IniRead(configFile, "Settings", "command", A_Space)
    if (command = "") {
        command := userprofile . "\wezterm\wezterm-gui.exe"
        IniWrite(command, configFile, "Settings", "command")
    }

    workingDir := IniRead(configFile, "Settings", "workingDir", A_Space)
    if (workingDir = "") {
        workingDir := userprofile
        IniWrite(workingDir, configFile, "Settings", "workingDir")
    }

    windowMatcher := IniRead(configFile, "Settings", "windowMatcher", A_Space)
    if (windowMatcher = "") {
        windowMatcher := "ahk_exe wezterm-gui.exe"
        IniWrite(windowMatcher, configFile, "Settings", "windowMatcher")
    }

    key := IniRead(configFile, "Settings", "key", A_Space)
    if (key = "") {
        key := "^;"
        IniWrite(key, configFile, "Settings", "key")
    }

    heightRatio := IniRead(configFile, "Settings", "heightRatio", A_Space)
    if (heightRatio = "") {
        heightRatio := "0.6"
        IniWrite(heightRatio, configFile, "Settings", "heightRatio")
    }

    IniWrite("see https://www.autohotkey.com/docs/Hotkeys.htm", configFile, "Help", "key")
    IniWrite("see " . website, configFile, "Help", "windowMatcher")

    ; keyboard key (or key-combination) to toggle the console
    Try {
        Hotkey(key, ToggleConsole)
    } Catch Error {
        TrayTip("Invalid key", "using default: <C-;>", 3)
        key := "^;"
        IniWrite("^;", configFile, "Settings", "key")
        Hotkey(key, ToggleConsole)
    }
}

ButtonExit(A_ThisMenuItem, A_ThisMenuItemPos, MyMenu)
{
    ExitApp()
    Return
}

ToggleSuspend(A_ThisMenuItem, A_ThisMenuItemPos, MyMenu)
{
    Suspend(-1)
    Tray.ToggleCheck("&Suspend")
    Return
}

OpenConfig(A_ThisMenuItem, A_ThisMenuItemPos, MyMenu)
{
    RunWait(configFile)
    LoadConfig()
    Reload()
    Return
}

Dummy(A_ThisMenuItem, A_ThisMenuItemPos, MyMenu)
{
    Return
}

limitation: window will appear in primary monitor at first call.

Note: this script load configuration from %USERPROFILE%\.QuakeLikeConsole.ini. please configuration for your wezterm-gui.exe installation path and hot key (default is set to <C-;>)

calvinchoy commented 7 months ago

For the ones interested. Using AutoHotKeys v2 in windows 10 this works for me:

#SingleInstance Force
#`::ToggleApp()
ToggleApp() {
    AppClass := "org.wezfurlong.wezterm"

    ifWinActive, ahk_class %AppClass%
    {
         WinMinimize, ahk_class %AppClass%
    }
    else
    {
         WinActivate, ahk_class %AppClass%
    }
    IfWinNotExist, ahk_class %AppClass%
    {
        Run, "C:\Program Files\WezTerm\wezterm-gui.exe" ; Replace with the actual path to your application
    }
    return
}
SuperSandro2000 commented 6 months ago

Someone has a script that works with Plasma Wayland? 😅

Xinkai commented 6 months ago

Someone has a script that works with Plasma Wayland? 😅

You can use mine. Works with KWin5 on Wayland. https://github.com/Xinkai/kwin-wezterm-toggle

arusahni commented 6 months ago

I got annoyed and whipped something together over my holiday break.

Qurop. While I intend for it to be an all-purpose solution for creating dropdown windows, I've only been testing it with Wezterm. It's very much v0.1.0 and has only been tested on KDE w/Xorg. It's close enough to my Yakuake config that I don't miss it anymore. I'd happily accept additional PRs to shore it up for additional DE's and even Wayland.

peterjaric commented 6 months ago

This is the AutoHotkey script I'm using. Nothing fancy, but supports Windows virtual desktops:

; Show/hide wezterm
^AppsKey::
  if (WinActive("ahk_class org.wezfurlong.wezterm") = "0x0")
  {
    ; Hide and show window to make sure it opens on the current
    ; desktop. Otherwise it will open on the desktop where it was
    ; minimized and focus will be moved to that desktop.
    WinHide, ahk_class org.wezfurlong.wezterm
    WinShow, ahk_class org.wezfurlong.wezterm
    WinActivate, ahk_class org.wezfurlong.wezterm
  }
  else
  {
    WinMinimize, ahk_class org.wezfurlong.wezterm
    ; "Deactivate" wezterm by activating the taskbar so that the next
    ; hotkey press for wezterm will activate wezterm again instead of
    ; trying to minimize it.
    WinActivate, ahk_class Shell_TrayWnd
  }
return
micsama commented 5 months ago

this is good

micsama commented 5 months ago

I spent some time using hammerspoon to complete a script. You can try it out, and I think the effect is pretty good. I can continue to optimize it. It performs well on macos when Stage Manager is off.(if stage manager is on,maybe wezterm could become a floating window, then the effect would be better,)

hs.hotkey.bind({ "Alt" }, "`", function()
    wez = hs.application.find("Wezterm")
    if wez then
        if wez:isFrontmost() then
            wez:hide()
        else
            local nowspace = hs.spaces.focusedSpace()
            local screen = hs.screen.mainScreen()
            wez_window = wez:mainWindow()
            hs.spaces.moveWindowToSpace(wez_window, nowspace)
            local max = screen:fullFrame()
            local f = wez_window:frame()
            f.x = max.x
            f.y = max.y
            f.w = max.w
            f.h = max.h * 0.55
            hs.timer.doAfter(0.2, function()
                wez_window:setFrame(f)
            end)
            wez_window:focus()
        end
    end
end)
okuuva commented 4 months ago

I have a similar script as @micsama that I've used successfully with Kitty. I kinda got it working with WezTerm as well with one caveat: Kitty window can be moved on top of natively fullscreen app and focused but WezTerm can't. It moves to the space and focuses for a split second but then gets hidden by the fullscreen app even when the "Always on Top" is set. Unfortunately I think this isn't exactly a limitation in WezTerm but Kitty doing something odd with its rendering. I tried the script with Activity Monitor just to debug it and it behaves just like WezTerm.

Then again, we know iTerm and Kitty can be rendered over full screen apps as well as "normal" user spaces so it's definitely possible. I just don't know what kind of dirty hacks they have to resort to in order to implement this "floating window" type of behavior.

okuuva commented 4 months ago

Then again, we know iTerm and Kitty can be rendered over full screen apps as well as "normal" user spaces so it's definitely possible. I just don't know what kind of dirty hacks they have to resort to in order to implement this "floating window" type of behavior.

After doing some digging I believe it has something to do with NSWindow.CollectionBehavior. Not sure which settings should be set since the descriptions are a bit vague but I think one (or some) of these is (are) relevant:

Setting e.g. canJoinAllSpaces could work something like this:

diff --git a/window/src/os/macos/window.rs b/window/src/os/macos/window.rs
index 898a20347..d05e84e04 100644
--- a/window/src/os/macos/window.rs
+++ b/window/src/os/macos/window.rs
@@ -19,7 +19,7 @@ use cocoa::appkit::{
     self, CGFloat, NSApplication, NSApplicationActivateIgnoringOtherApps,
     NSApplicationPresentationOptions, NSBackingStoreBuffered, NSEvent, NSEventModifierFlags,
     NSOpenGLContext, NSOpenGLPixelFormat, NSPasteboard, NSRunningApplication, NSScreen, NSView,
-    NSViewHeightSizable, NSViewWidthSizable, NSWindow, NSWindowStyleMask,
+    NSViewHeightSizable, NSViewWidthSizable, NSWindow, NSWindowStyleMask, NSWindowCollectionBehavior,
 };
 use cocoa::base::*;
 use cocoa::foundation::{
@@ -1203,6 +1203,12 @@ impl WindowInner {
         }
     }

+    fn set_window_collection_behavior(&mut self) {
+        unsafe {
+            NSWindow::setCollectionBehavior_(*self.window, NSWindowCollectionBehavior::NSWindowCollectionBehaviorCanJoinAllSpaces)
+        }
+    }
+
     fn set_inner_size(&mut self, width: usize, height: usize) {
         unsafe {
             let frame = NSView::frame(*self.view as *mut _);

Plus all the related plumbing.

RedemptionC commented 3 months ago

just installed WezTerm and impressed by the full-screen ish appearance, then realized that the global hotkey is still not available?

oOosys commented 3 months ago

Linux Mint Xfce solution: Works for me simulating Guake-like Dropdown behavior toggling the visibility of the wezterm Window I prefer to trigger with F9 in order to avoid conflits with Guake on F12: toggle-coOo-Window-visibility Adapt it to your purposes. I assume that it provides through the style of code and the comments all what is needed to make it work including hiding/showing the Window no matter the current Workspace.

yashuvit89 commented 3 months ago

@RedemptionC I am able to use Hammerspoon configuration to achieve full screen. I've followed @micsama configuration and able to tweak for the full screen. This is the only change I've have to do f.h = max.h * 0.55 ------> f.h = max.h

Pasting my config for Hammerspoon, using this I can access wezterm in full screen mode with "Alt + `" shortcut

function bindHotkey(appName, key)
    hs.hotkey.bind({ "Alt" }, key, function()
        local app = hs.application.find(appName)
        if app then
            if app:isFrontmost() then
                app:hide()
            else
                local nowspace = hs.spaces.focusedSpace()
                local screen = hs.screen.mainScreen()
                local app_window = app:mainWindow()
                hs.spaces.moveWindowToSpace(app_window, nowspace)
                local max = screen:fullFrame()
                local f = app_window:frame()
                f.x = max.x
                f.y = max.y
                f.w = max.w
                f.h = max.h 
                hs.timer.doAfter(0.2, function()
                    app_window:setFrame(f)
                end)
                app_window:focus()
            end
        end
    end)
end

bindHotkey("Wezterm", "`")
bindHotkey("Obsidian", "o")
bindHotkey("Slack", "s")
bindHotkey("Chrome", "c")
erikLundstedt commented 1 month ago

tdrop also works. My wezterm has a unix domain configured

-- in ~/.config/wezterm/wezterm.lua
unix_domains = {
  {
    name = 'dropdown',
  }
},

, and it'll be connected to it when it was triggered by a hotkey handled by sxhkd.

# in ~/.config/sxhkd/sxhkdrc
F11
  tdrop -mat -w -4 -h -38 --pre-unmap-hook='wmctrl -ir $wid -b remove,maximized_vert; xdotool windowsize $wid $width 10%' --class 'wezterm.dropdown' -f 'connect dropdown --class wezterm.dropdown' wezterm

F12
  tdrop -mat -w -4 -h 45% --pre-unmap-hook='wmctrl -ir $wid -b remove,maximized_vert; xdotool windowsize $wid $width 10%' --class 'wezterm.dropdown' -f 'connect dropdown --class wezterm.dropdown' wezterm

I have the --pre-unmap-hook arg since tdrop doesn't seem to work nicely with a snapping behavior and/or maximize/unmaximize behavior of the WM I use, so you may be able to just do tdrop -mat -w -4 -h -38 --class 'wezterm.dropdown' -f 'connect dropdown --class wezterm.dropdown' wezterm instead.

Ive had some issues with tdrop being buggy when using it with wezterm on awesomewm I will definetly try this out

I usually bind tdrop to the "[MENU]" key on my keyboard(quite uncommon, but for me its really easy to press)

Kryan90 commented 1 month ago

Another solution for macos + yabai + skhd

#!/usr/bin/env bash
set -euo pipefail

window=$(yabai -m query --windows | jq 'map(select(.app == "WezTerm" or .app == "wezterm-gui")) | sort_by(.id) | last')
is_visible=$(echo "$window" | jq '."is-visible"')
id=$(echo "$window" | jq '.id')

# test if window was found, if not, open the app
if [ "$window" = "null" ]; then
  open -a "WezTerm"
elif [ "$is_visible" = "false" ]; then
  # if not visible, move the window to the current space and focus it
  yabai -m window "$id" --space mouse --focus
else
  # if visible, hide the window
  osascript -e "tell application \"System Events\" to set visible of first process ¬" \
            -e "whose name is \"wezterm-gui\" to false"
fi

yabairc

yabai -m rule --add app="^(wezterm-gui|WezTerm)" grid="6:6:2:0:2:1" manage=off
codevogel commented 3 weeks ago

For the ones interested. Using AutoHotKeys v2 in windows 10 this works for me:

#SingleInstance Force
#`::ToggleApp()
ToggleApp() {
    AppClass := "org.wezfurlong.wezterm"

    ifWinActive, ahk_class %AppClass%
    {
         WinMinimize, ahk_class %AppClass%
    }
    else
    {
         WinActivate, ahk_class %AppClass%
    }
    IfWinNotExist, ahk_class %AppClass%
    {
        Run, "C:\Program Files\WezTerm\wezterm-gui.exe" ; Replace with the actual path to your application
    }
    return
}

Awesome! I added this script to my dotfiles and symlinked it from the Startup folder. This is exactly what I was looking for. The only improvement I could think is that WezTerm would go away to the system tray on dismiss, then adds itself to the taskbar again on summon.