LINUX.ORG.RU

Оконная мозаика

 ,


12

6

С год назад я уже показывал разные нестандартные способы переключения окошек. Но если одно из них очень просто заменяется связкой dmenu+wmctrl, то вот цветастую штуковину за пределами xmonad никто изобретать не собирался. А удобная же штуковина! Но ведь главный принцип опенсорса — если чего-то нужного тебе нет, просто сделай это сам, верно? Поэтому в свободное время были изучены некоторые доки по иксам, и началось пиление велосипеда, названного чуть позже xwinmosaic.

Итого: программа написана на чистом С + GTK+2, а для работы нужен только EWMH-совместимый оконный менеджер (почти любой, некоторых в том списке нет). Идея та же — для каждого класса окна назначается свой цвет, что позвволяет легче находить нужное окно в списке. Окна, использовавшиеся недавно, выстраиваются ближе к центру. Для работы достаточно повесить запуск xwinmosaic на какой-нибудь хоткей средствами WM.

Жизнь была простой и беззаботной, когда тестирование производилось лишь на своей машинке с kwin, openbox и xmonad, однако после показа сей приблуды ограниченному кругу людей было выловлено (и вылавливается) неограниченное количество багов, как-никак: Си (сегфолты), зоопарк WM (куча неработающих или работающих по-другому функций), своё собственное отсутствие опыта, наконец.

Тем не менее, за неделю программу удалось причесать, и теперь она умеет:


  • Собственно, переключение между окнами
  • Чтение списка элементов из stdin и вывод выбранного элемента в stdout (что позволяет реализовывать похожее на dmenu поведение или даже изменять существующие скрипты простой заменой вызова dmenu на xwinmosaic, только аргументы придётся поменять)
  • Emacs (C-n C-p C-f C-b) / vim (hjkl)-подобная навигация для любителей.
  • Более-менее приличный поиск по элементам (а также по классам окон), в чем-то похожий на тот, что в ido-mode (например, «ff» найдёт все окна Firefox) — активизируется сразу при наборе в стандартном режиме и по / в режиме vim
  • окно непрямоугольной формы (на заднем плане не скриншот экрана, как в xmonad, а сами окошки, в которые можно тыкать), хотя поведение со скриншотом тоже пришлось реализовывать, так как оказалось, что не все ещё WM могут обогнать в функциональности TWM и не реализуют корректное поведение с XShape.
  • Для режима переключения окон реализовано обновление имён и самого списка окон в реальном времени, показ номера десктопа, на котором находится окно, и даже их иконки (всего этого в оригинале не было)
  • Возможность появления центра мозаики под курсором мыши (что показано на первом скриншоте, получается весьма прикольно)
  • Попытка уместить все элементы на экране вместо примитивного выстраивания их ромбиком (из-за чего к иксмонадовскому GridSelect были большие претензии)
  • Куда более приятные цвета, благодаря использованию цветовой модели HSL.
  • Ну и ещё что-то, наверное забыл упомянуть.


Ради забавы было реализовано даже подобие dmenu_run — получается очень радостно и эпилептично (спасибо, Artificial_Thought!).

На скриншотах, собственно, можно наблюдать xwinmosaic в режиме переключения окон и в режиме переключения буферов емакса (невероятно удобно, между прочим) — спасибо за идею и оригинальный скрипт для dmenu товарищу lazyklimm!
Шрифты — PT Sans в интерфейсе, Consolas в емаксе, убунтопатчи; всё та же старая обоина с Ктулху (очень мотивирует), а больше там ничего и не видно, вроде.

Надеюсь, кому-нибудь оно приглянется, поэтому ссылки:
Github: https://github.com/soulthreads/xwinmosaic (не забывайте писать в issues в случае обнаружения багов)
Пакеты для дебиана/убунты: https://launchpad.net/~soulthreads/ archive/xwinmosaic/ (могут быть немного неактуальными)
Арч: https://aur.archlinux.org/packages.php?ID=59660
Gentoo: https://github.com/soulthreads/xwinmosaic/blob/master/contrib/gentoo/xwinmosa... (надо будет напроситься к кому-нибудь в оверлей)

Вот как-то так, надеюсь, вам не надоело чтение этих многобуков.

>>> Просмотр (1024x1200, 302 Kb)



Проверено: JB ()

Ответ на: комментарий от Artificial_Thought
                     
(progn
(defun get-icon (buf)
  (if (string= (substring (symbol-name (with-current-buffer buf major-mode)) 0 6)
               "jabber")
      "im-jabber"
    "emacs"))

(mapconcat (quote (lambda (s) (format "%s, %s" s (get-icon s))))
            (remove-if (quote (lambda (name) (string= (substring name 0 1) " ")))
                       (mapcar (quote buffer-name) (buffer-list)))
                       "\n")
)

например так

lazyklimm ★★★★★ ()
Ответ на: комментарий от Zubok

Попытался починить множественное открытие программы. Делает так: берёт на самом старте список всех окон, и если среди них присутствует окошко с классом «xwinmosaic», то не запускается. Проверьте.

SoulThreads ()
Ответ на: комментарий от lazyklimm

c screenshot чад кутежа на twinview

А попробуй вот теперь, я попытался это починить (на нетбуке, конечно, сложно, но вдруг?)

SoulThreads ()
Ответ на: комментарий от SoulThreads

Можно через файл pid проверять, можно через семафоры. Есть вариант, чтобы приложение проверяло наличие своего окна, запрашивая X-сервер через XGetSelectionOwner(), кто владеет специально заведенным тобой уникальным атомом (хотя уникальность - это всегда большой вопрос). Если таким атомом какое-то окно владеет, то можно дальше не запускаться. Так как программка только для X Window System, то можно рассматривать последний вариант.

Еще можно глянуть в libunique.

Существует какой-то вариант с DBus, но я бы не стал еще сюда DBus приколачивать. :)

Zubok ★★★★★ ()
Ответ на: комментарий от Minoru

Охтэ, нажал Super+<n>, а у меня Emacs поднялся и автоматом remember-mode включил! :)

Zubok ★★★★★ ()
Ответ на: комментарий от SoulThreads

Еще, кстати, вариант, но только я не знаю точно, как будет работать. Это XGrabKeyboard как только окно фокус ввода получило. А как только теряет, то закрываться автоматом. То есть чтобы никто больше события клавиатуры не получал.

Zubok ★★★★★ ()
Ответ на: комментарий от Zubok

Поведение с XGrabKeyboard не было реализовано, потому что хочется иметь возможность сделать вдруг M-tab, на другой воркспейс переключиться, или, там, например, плеер на паузу хоткеем поставить.
Сейчас, в принципе, мозаика при потере фокуса закрывается, но для скриншота был добавлен ещё один костыль, который мозаику не закрывал, пока пользователь какую-либо клавишу не нажал. Сделано это было по той причине, что awesome в режиме screenshot по какой-то неведомой причине передёргивал фокус окна при запуске, и оно сразу же закрывалось. А так как win вы не отжимали, окно события KeyPressEvent не получало, вот и плодились инстанции. Теперь должно работать нормально, если я ещё каких-нибудь багов не наделал. :)

SoulThreads ()
Ответ на: комментарий от lazyklimm

Я понял, просто иначе этот скрипт разрастается до неудобоваримых размеров. Решил просто оставить как есть и думаю написать небольшую инструкцию как собственно эти get-icon и get-color в емаксе определять.

Artificial_Thought ★★★★ ()
Ответ на: комментарий от vyazovoi

Перейти-или-открыть к n-ной закрепленной программе. Фишка всяких OS X и новомодных юнити (лично я запилил патч для fluxbox, сочетающий этот подход и традиционный, как-нибудь обнародую на ЛОРе).

Minoru ★★★ ()
Ответ на: комментарий от Minoru

Ну и да, Ваш К.О. спешит заметить, что профит в безошибочном переключении между n часто используемых программ не глядя. А как с этим обстоит в случае с подходом, предлагаемым топикстартером?

Minoru ★★★ ()
Ответ на: комментарий от SoulThreads

Хорошая программа получилась, спасибо. Правда с дефолтным конфигом awesome она не очень корректно работает — необходимо добавить в rc.lua

c:raise()
сразу после
client.add_signal("focus", function(c) 

И добавьте пожалуйста в емаксоподобный набор комбинаций «C-g» - как Esc, для закрытия.

Array ()
Ответ на: комментарий от Minoru

не ну с fluxbox конечно молодец, но в stumpwm C-n «is not bound» так что эту мозайку никто не отменял

vyazovoi ★★★ ()
Ответ на: комментарий от Minoru

А как с этим обстоит в случае с подходом, предлагаемым топикстартером?

А тут суть не столько в скоростном переключении, сколько в обозрении, где что вообще находится. Из упомянутых юнити и макоси ведь Expo с введением винсемёрочного win+n не выкинули? Ну и поиск помогает ускориться.

Мне, скажем, пригождается, чтобы быстро посмотреть — сколько там в джаббере сообщений понаписали, не переключаясь туда-сюда. :)

К тому же, программа предоставляет более-менее универсальный интерфейс, так что её можно задействовать не только для переключения окошек, но и для кучи других задач — что здесь в комментариях уже и продемонстрировали.

Не стоит забывать, наконец, что оно не требует даже вмешательства в код WM — чем не плюс? :)

SoulThreads ()
Ответ на: комментарий от Array

«C-g» - как Esc, для закрытия.

А сделать действительно как Esc (сперва скрывается поиск, если активен, а потом уж закрывается) или чтобы сразу закрывало?

P.S. Емаксовая часть вообще неслабо так уже разрастается. :)

SoulThreads ()
Ответ на: комментарий от Artificial_Thought

Да что-то с каждым фичреквестом желание это сделать возрастает. Но я пока держусь.

SoulThreads ()
Ответ на: комментарий от SoulThreads

Спасибо. Для awesome может пригодится следующий скрипт:

#! /bin/bash                                            
xwinmosaic && echo 'client.focus:raise()' | awesome-client
Иначе WM только отдает фокус выбранному окну, но не поднимает его над другими.

Array ()
Ответ на: комментарий от Artificial_Thought

просто иначе этот скрипт разрастается до неудобоваримых размеров. Решил просто оставить как есть и думаю написать небольшую инструкцию как собственно эти get-icon и get-color в емаксе определять.

если «оставить как есть» - оставил бы изначальный скрипт :), с get-color оно разрастается не сильнее, чем с твоими добавлениями

lazyklimm ★★★★★ ()
Ответ на: комментарий от lazyklimm

Мы там немного переделали, теперь цвет бокса для переключения буферов берётся по хешу major-mode этого буфера. Как с классом окна в иксах в общем.

Artificial_Thought ★★★★ ()
Ответ на: комментарий от lazyklimm

n бывают разные

читаем еще раз:

закрепленной

Minoru ★★★ ()
Ответ на: комментарий от lazyklimm

Да, а кроме расцветки по режиму, оно теперь ещё по этому режиму и искать может заодно.

SoulThreads ()

Что-то на wmfs у меня не заработало. Ни на float, ни в других вариациях. Просто форма. Если на клавиатуре что-то нажимаешь - отображается внизу в окошке, а так - просто растянутая форма, без каких-либо ярлыков/подписей. Параметры не помогли.

alozovskoy ★★★★★ ()
Ответ на: комментарий от Artificial_Thought

по последним измениям

1) вынос емаксового кода в отдельный файл слегка усложняет первоначальную настройку - в первых версиях dmenu-шного скрипта я тоже так делал, потом отказался

2) если уж выносишь - выноси всё, из шелла достаточно дергать что-то вроде

emacsclient --eval '(xmosaic-list-buffers)'
lazyklimm ★★★★★ ()
Ответ на: комментарий от lazyklimm

ещё

(save-excursion
                 (set-buffer buffer-name)
                 major-mode)
чуть длиннее чем
(with-current-buffer buf major-mode)

во избежание копирования условий в cond, get-color-name и get-icon-name можно объединить и возвращать консом

lazyklimm ★★★★★ ()
Ответ на: комментарий от lazyklimm

во избежание копирования условий в cond, get-color-name и get-icon-name можно объединить и возвращать консом

да и вообще, лучше вынести все эти условия в alist

lazyklimm ★★★★★ ()
Ответ на: комментарий от SoulThreads
$ wmctrl -l
0x02000009  0 UNO mc [alozovskoy@UNO]:~
0x02200009  0 UNO alozovskoy@UNO: ~
0x016771b0  0 UNO Оконная мозаика - Скриншоты - Галерея - Google Chrome
0x01000003  0 UNO alozovskoy@gmail.com - Sylpheed 3.0.2
alozovskoy ★★★★★ ()
Ответ на: комментарий от lazyklimm

как-нибудь так, например

(setq xwinmosaic-buffers-alist
             '(("jabber" "im-jabber" "#666666")
               ("haskell" "text-x-haskell")))

(defun get-mode-icon-color (mode)
    (let ((icon-color (assoc mode xwinmosaic-modes-alist)))
         (when icon-color (cdr icon-color))))
lazyklimm ★★★★★ ()
Ответ на: комментарий от alozovskoy

Весело. Сейчас установил wmfs, запустил — действительно. Однако xwinmosaic_run и переключалки емакса работают. Значит, фильтр окон на каком-то этапе сбоит. Спасибо за багрепорт, буду разбираться.

SoulThreads ()
Ответ на: комментарий от SoulThreads

Вам спасибо! Считаю, очень нужное и полезное дело делаете!

alozovskoy ★★★★★ ()
Ответ на: комментарий от alozovskoy

Причину нашёл: wmfs не выставляет окошкам свойство _NET_WM_DESKTOP (номер рабочего стола), а у меня на этот случай фильтр как раз срабатывает (потому что мало ли что там может быть). Я, конечно, фильтр подправлю, но главное, чтобы теперь у кого-нибудь другого что-нибудь не отвалилось. :)

В гите я это исправил, но неплохо было бы написать багрепорт разработчикам wmfs, чтобы они стандарты соблюдали.

SoulThreads ()

Офигенно. Продолжайте в том же духе.

Spectator ()
Ответ на: комментарий от SoulThreads

UPD: Зато wmfs выставляет свойство _WMFS_TAG. Нехорошо как-то получается.

SoulThreads ()
Ответ на: комментарий от SoulThreads

Да, все работает, класс, спасибо! Сейчас попробую багрепорт им написать.

alozovskoy ★★★★★ ()
Ответ на: комментарий от frost_ii

А я как-то даже этим и не заморачивался. Стоит себе и стоит, что его двигать. :) Но насколько вспомнил, он как бы по центру картинки находится, если рассматривать ктулху вместе с его тенью.

SoulThreads ()

главный принцип опенсорса — если чего-то нужного тебе нет, просто сделай это сам, верно?

О, это было когда-то. Сейчас если что-то идет «не так», начинается перебор дистров, где это работает из коробки. После чего дистр признается лучшим в мире, до следующего «неразрешимого» косяка :)

Buy ★★★★★ ()
Ответ на: комментарий от Artificial_Thought

в общем, как-то так оно вроде лучше смотрится


(require 'cl)

(defvar xwm-modes-alist   
      '(("jabber" "im-jabber" "#666666")
        ("haskell" "text-x-haskell")
        ("python" "text-x-python")
        ("sh" "application-x-shellscript")
        ("c-mode" "text-x-csrc")
        ("" "emacs")))


(defun get-buffer-mode-str (buffer-name)
  (format "%s" 
          (with-current-buffer buffer-name major-mode)))

(defun get-mode-icon-color (name)
  (cdar (remove-if-not (lambda (ic) 
                         (string-match (car ic) (get-buffer-mode-str name)))
                       xwm-modes-alist)))

(defun valid-buffer-names () 
  (remove-if '(lambda (name) (string= (substring name 0 1) " "))
             (mapcar 'buffer-name (buffer-list))))

(defun xwm-buffers ()
  (mapconcat  '(lambda (s) 
                 (let ((ic-list (get-mode-icon-color s)))
                   (format ", %s,%s,%s,%s"
                           (or (second ic-list) "")
                           (first ic-list)
                           s
                           (get-buffer-mode-str s))))
            (valid-buffer-names)
            "\n"))

lazyklimm ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.