Могу ли я свернуть окно в окно на Unity?

17

На 4Dwm Irix была возможность свернуть окна в коробку (в отличие от панели задач, используемой современными оконными менеджерами). Я видел это также на старом HPUX.

Смотрите квадрат "консоли" на связанном изображении:

введите описание изображения здесь

Возможно ли добиться этого в Ubuntu, либо с помощью плагина, либо с помощью какого-нибудь оконного менеджера, кроме Unity?

Artium
источник
Странный, но интересный вопрос :) Я мог бы придумать что-то подобное. Будет ли значок иметь значение, или он может быть общим? Как это ведет себя? как значок на рабочем столе или минимальное «окно».
Джейкоб Влейм
@JacobVlijm Значок не является общим. Каждое приложение имеет собственную иконку в виде иконок свернутых окон в Unity)
Artium
Это можно сделать и в Unity, но окно будет отображаться на рабочем столе (с соответствующим значком приложения и именем окна). Вы хотели бы сделать снимок? (будет интересной, но сложной работой, лучше спросите, прежде чем я начну :))
Джейкоб Влейм
1
Да, это может быть полезно для меня. Мне приходится работать с множеством открытых окон, и, на мой взгляд, такой способ их организации лучше. Я ничего не знаю о Unity, поэтому могу помочь только с тестированием.
Artium

Ответы:

18

К моему собственному удивлению, это работает довольно хорошо, пока у вас не слишком много других вещей на рабочем столе .

Я работал с ним некоторое время, и это кажется странной, но, как ни странно, хорошей альтернативой частым переключениям рабочего пространства. Освежающий за свою простоту.

На практике

Решение на самом деле в значительной степени то, что вы описываете:

  • Нажатие комбинации клавиш приведет к «окну» окна на вашем рабочем столе из окна:

    введите описание изображения здесь

    в иконку с внешним видом приложения:

    введите описание изображения здесь

  • Дважды щелкните значок, и окно снова появится, и значок исчезнет.

Как это устроено

Рассказ (объяснение):

  • При нажатии сочетания клавиш скрипт вызывается с аргументом box:

    windowbox box
    
  • Сценарий тогда:

    • читает идентификатор окна переднего окна
    • проверяет, является ли это "нормальным" окном (например, вы не захотите удалить свой рабочий стол)
    • Ищет имя процесса приложения, владеющего окном.
    • Ищет соответствующий значок в .desktopфайле соответствующего приложения в/usr/share/applications
    • создает .desktopфайл с уникальным именем со Exec=строкой, которая вызывает скрипт (при двойном щелчке) с аргументом show:

      windowbox show
      

.desktopФайл будет добавлен ряд дополнительных аргументов аргументов, например, идентификатор окна, имя (File-) из .desktopфайла.

Впоследствии:

  • Затем .desktopфайл становится исполняемым, чтобы сделать его объектом двойного щелчка.

  • При .desktopдвойном щелчке по файлу окно (пере) отображается, .desktopфайл удаляется с вашего рабочего стола.

Как настроить

  1. Как и практически всегда, когда вы хотите поиграться с окнами, сценарию нужны wmctrlи xdotool:

    sudo apt-get install xdotool wmctrl
    
  2. Создать каталог ~/bin( ~расшифровывается как ваш домашний каталог)
  3. Скопируйте приведенный ниже скрипт в пустой файл, сохраните его как windowbox(без расширения) в ~/bin.

    #!/usr/bin/env python3
    import subprocess
    import sys
    import os
    
    # --- On Unity, there is a (y-wise) deviation in window placement
    # set to zero for other window managers
    deviation = 28
    # ---
    
    args = sys.argv[1:]
    
    get = lambda cmd: subprocess.check_output(cmd).decode("utf-8").strip()
    
    def find_dtop():
        # get the localized path to the Desktop folder
        home = os.environ["HOME"]
        dr_file = home+"/.config/user-dirs.dirs"
        return [home+"/"+ l.split("/")[-1].strip() \
                for l in open(dr_file).readlines() \
                if l.startswith("XDG_DESKTOP_DIR=")][0].replace('"', "")
    
    def check_windowtype(w_id):
        # check the type of window; only unmap "NORMAL" windows
        return "_NET_WM_WINDOW_TYPE_NORMAL" in get(["xprop", "-id", w_id])
    
    def get_process(w_id):
        # get the name of the process, owning the window and window x/y position
        w_list = get(["wmctrl", "-lpG"]).splitlines()
        pid = [l for l in w_list if w_id in l][0].split()
        proc = get(["ps", "-p", pid[2], "-o", "comm="])
        xy = (" ").join(pid[3:5])
        return (proc, xy)
    
    def read_f(f, string, proc):
        # search for a possible match in a targeted .desktop file
        try:
            with open(f) as read:
                for l in read:
                    if all([l.startswith(string), proc in l]):
                        in_f = True
                        break
                    else:
                        in_f = False
        except:
            in_f = False
        return in_f
    
    def get_icon(proc, w_name):
        # search appropriate icon in /usr/share/applications
        exceptions = [item for item in [
            ["soffice", "libreoffice-main"],
            ["gnome-terminal", "utilities-terminal"],
            ["nautilus", "folder"],
            ] if item[0] in proc]
        if exceptions:
            if exceptions == [["soffice", "libreoffice-main"]]:
                loffice = [
                    ["Calc", "libreoffice-calc"],
                    ["Writer", "libreoffice-writer"],
                    ["Base", "libreoffice-base"],
                    ["Draw", "libreoffice-draw"],
                    ["Impress", "libreoffice-impress"],
                    ]
                match = [m[1] for m in loffice if m[0] in w_name]
                if match:
                    return match[0]
                else:
                    return exceptions[0][1]
            else:      
                return exceptions[0][1]
        else:
            default = "/usr/share/applications"
            dtfiles = [default+"/"+f for f in os.listdir(default)]
            for f in dtfiles:
                if read_f(f, "Exec=", proc) == True:   
                    for l in open(f).readlines():
                        if l.startswith("Icon="):
                            icon = l.replace("Icon=", "").strip()
                            print(f)
                            break
                    break
            return icon
    
    def create_name():
        # create unique (file-) name for boxed window
        n = 1
        while True:
            name = dtop+"/"+"boxed_"+str(n)+".desktop"
            if os.path.exists(name):
                n += 1
            else:
                break
        return name
    
    def convert_wid(w_id):
        # convert window- id, xdotool format, into wmctrl format
        w_id = hex(int(w_id))
        return w_id[:2]+(10-len(w_id))*"0"+w_id[2:]
    
    def create_icon(w_id, w_name, icon, pos):
        # create the launcher, representing the boxed window
        boxedwindow = create_name()
        f_content =[
                "[Desktop Entry]",
                "Name=[WINDOW] "+w_name,
                "Exec=windowbox show "+w_id+" '"+boxedwindow+"' "+pos,
                "Icon="+icon,
                "Type=Application",
                ]
        if icon == "generic":
            f_content.pop(3)
        with open(boxedwindow, "wt") as boxed:
            for l in f_content:
                boxed.write(l+"\n")
        command = "chmod +x "+"'"+boxedwindow+"'"
        subprocess.call(["/bin/bash", "-c", command])
    
    if args[0] == "box":
        dtop = find_dtop()
        w_id = convert_wid(get(["xdotool", "getactivewindow"]))
        w_name = get(["xdotool", "getwindowname", w_id])
        if check_windowtype(w_id) == True:
            procdata = get_process(w_id)
            procname = procdata[0]
            icon = get_icon(procname, w_name); icon = icon if icon != None else "generic"
            create_icon(w_id, w_name, icon, procdata[1])
            subprocess.call(["xdotool", "windowunmap", w_id])
    
    elif args[0] == "show":
        w_id = args[1]
        subprocess.call(["xdotool", "windowmap", w_id])    
        subprocess.call(["xdotool", "windowmove", "--sync", w_id, args[3], str(int(args[4])-deviation)])
        os.remove(args[2])
  4. Сделайте скрипт исполняемым

  5. Для того, чтобы вновь созданная директория «всплывала» $PATH, либо выйдите из системы, либо запустите ее source ~/.profile(из окна терминала)
  6. Тест - запустить скрипт из окна терминала командой:

    windowbox box
    

    Окно должно исчезнуть, на рабочем столе должно появиться «коробочное» окно.

  7. Если все работает нормально, добавьте следующую команду для сочетания клавиш: выберите значок шестеренки в правом верхнем углу экрана:

    Значок передач

  8. Перейти к System SettingsKeyboardShortcutsCustom Shortcuts. Нажмите +и добавьте команду:

    windowbox box
    

Это должно сделать это.

Важная заметка

Использует скрипт xdotool«swindowunmap чтобы сделать окно невидимым. Созданная «коробка» (иконка) на вашем рабочем столе - это единственные «ворота» в скрытое окно. Другими словами: не удаляйте файлы рабочего стола вручную. Окно будет потеряно навсегда, если вы это сделаете.

Работа, которую нужно сделать [править 20-12: сделано ]

Скрипт все еще может использовать некоторые уточнения:

  • Геометрия окна не восстанавливается по определению. Можно исправить очень хорошо, но я думал, что покажу вам первый результат.
  • В большинстве случаев окно в штучной упаковке имеет правильную иконку. Функция get_process(w_id)могла бы использовать некоторое улучшение как бы то ни было. Если процесс не найден в качестве команды /usr/share/applications, файл имеет общий значок.

Предоставление значкам в штучной упаковке другого размера, чем другие значки

Сценарий всегда называет созданные .desktopфайлы и т. Д., В зависимости от «доступного» имени на момент создания (имена файлов, а не отображаемое имя). boxed_1.desktopboxed_2.desktop

Вы можете изменить размер файлов (в общем), щелкнув правой кнопкой мыши> размер значка. Хорошей новостью является то, что если вы удалите файл и создадите его заново, размер запоминается. Даже если вы создадите файл снова после перезагрузки. Это означает, что если вы когда-нибудь изменили размер окон в штучной упаковке (например, 1-5), они всегда будут иметь одинаковый размер, когда вы (скрипт) создадите их снова!

введите описание изображения здесь

Якоб Влейм
источник
2
Я не могу устоять перед собой, не оставив комментарий, очень хороший ответ от вас :)
Раван
Ницца! Несколько комментариев: 1. Я заменил строку dtop = "/home/jacob/Bureaublad"с путем к моему рабочему столу ( dtop = "/home/" + user + "/Desktop") 2. Восстановление двойным щелчком не сработало. Я подозреваю, что source ~/.profileнедостаточно будет войти в систему / выйти быстро, чтобы проверить это. 3. В единстве можно изменить размеры значков вручную (щелкните правой кнопкой мыши -> изменить размер значка), можно ли добавить какой-либо параметр f_contentдля установки размера значка?
Artium
4
Когда я начал читать первый абзац этого ответа, я просто знал, что внизу будет оранжевый значок! ;-): P
Fabby
1
Здравствуйте, @Artium. Я обновил скрипт, теперь он имеет несколько важных улучшений, в том числе улучшенный поиск значков и восстановление геометрии. Веселитесь!
Джейкоб Влейм
1
@Artium Я знаю, но попробуйте тот, что в скрипте, это обычный значок папки, похожий на ваше изображение. наверное просто ссылка на ту же иконку.
Джейкоб Влейм
7

Вы можете использовать fvwm для достижения этой цели.

  1. Установите fvwm:

    sudo apt-get update
    sudo apt-get install fvwm
    
  2. Найдите их, которые используют функцию iconify - здесь их несколько: http://www.jmcunx.com/fvwm_theme.html Некоторые из них похожи на снимок экрана, который вы показываете.

  3. Скопируйте текст темы, затем перейдите к ~/.fvwm/(сначала показать скрытые файлы), затем создайте файл.fvwm2rc

  4. Откройте этот файл в текстовом редакторе (например, gedit) и вставьте в него текст темы.

  5. Перезагрузите компьютер, выберите fvwm и войдите.

введите описание изображения здесь

Mateo
источник