LINUX.ORG.RU

Помогите допилить управлялку расположения и геометрии клиентов с клавиатуры

 , ,


8

3

Год и два года назад как-то поднимал уже эту тему, но не срослось.

Демка гифка, чтобы не читать много текста ниже: http://i.imgur.com/cpKRBXM.gif

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

Например: есть фокус-клиент, я нажимаю на mod4 + 9 на нампаде, т.е. верхнюю правую кнопку (KP_Prior), что означает, что клиент должен переместиться в верхний правый угол текущего дисплея и иметь геометрию четверти дисплея:

+---------------------+  +---------------------+  +---------------------+
| +---------+         |  | +-----------------+ |  |         +---------+ |
| |    7    |         |  | |         8       | |  |         |    9    | |
| |         |         |  | |                 | |  |         |         | |
| +---------+         |  | +-----------------+ |  |         +---------+ |
|                     |  |                     |  |                     |
|                     |  |                     |  |                     |
|                     |  |                     |  |                     |
|                     |  |                     |  |                     |
+---------------------+  +---------------------+  +---------------------+
+---------------------+  +---------------------+  +---------------------+
| +---------+         |  | +-----------------+ |  |         +---------+ |
| |         |         |  | |                 | |  |         |         | |
| |         |         |  | |                 | |  |         |         | |
| |    4    |         |  | |        5        | |  |         |    6    | |
| |         |         |  | |                 | |  |         |         | |
| |         |         |  | |                 | |  |         |         | |
| |         |         |  | |                 | |  |         |         | |
| +---------+         |  | +-----------------+ |  |         +---------+ |
+---------------------+  +---------------------+  +---------------------+
+---------------------+  +---------------------+  +---------------------+
|                     |  |                     |  |                     |
|                     |  |                     |  |                     |
|                     |  |                     |  |                     |
|                     |  |                     |  |                     |
| +---------+         |  | +-----------------+ |  |         +---------+ |
| |    1    |         |  | |         2       | |  |         |    3    | |
| |         |         |  | |                 | |  |         |         | |
| +---------+         |  | +-----------------+ |  |         +---------+ |
+---------------------+  +---------------------+  +---------------------+
Управление кнопками нампада в целом такое (расположение / геометрия), mod4+:

  • 1  — левый нижний угол / пол длины / пол высоты
  • 2  — нижняя часть / вся длина / пол высоты
  • 3  — правый нижний угол / пол длины / пол высоты
  • 4  — левая часть / пол длины / вся высота
  • 5  — максимизация (типа mod4+M, но без переключения режима floating)
  • 6  — правая часть / пол длины / вся высота
  • 7  — левый верхний угол / пол длины / пол высоты
  • 8  — верхняя часть / вся длина / пол высоты
  • 9  — верхний правый угол / пол длины / пол высоты

Для одно-мониторной конфигурации я запилил уже давно:

local wa = screen[mouse.screen].workarea -- текущий screen
local ph = 22 -- высота панели
local ww = wa.width -- длина текущего screen
local wh = wa.height -- высота текущего screen

clientkeys = awful.util.table.join(

awful.key({modkey}, "KP_Left",  function (c) c:geometry( { width = ww / 2, height = wh, x = 0, y = ph } ) end),
awful.key({modkey}, "KP_Right", function (c) c:geometry( { width = ww / 2, height = wh, x = ww / 2, y = ph } ) end),
awful.key({modkey}, "KP_Up",    function (c) c:geometry( { width = ww, height = wh / 2, x = 0, y = ph } ) end),
awful.key({modkey}, "KP_Down",  function (c) c:geometry( { width = ww, height = wh / 2, x = 0, y = wh / 2 + ph } ) end),
awful.key({modkey}, "KP_Prior", function (c) c:geometry( { width = ww / 2, height = wh / 2, x = ww / 2, y = ph } ) end),
awful.key({modkey}, "KP_Next",  function (c) c:geometry( { width = ww / 2, height = wh / 2, x = ww / 2, y = wh / 2 + ph } ) end),
awful.key({modkey}, "KP_Home",  function (c) c:geometry( { width = ww / 2, height = wh / 2, x = 0, y = ph } ) end),
awful.key({modkey}, "KP_End",   function (c) c:geometry( { width = ww / 2, height = wh / 2, x = 0, y = wh / 2 + ph } ) end),
awful.key({modkey}, "KP_Begin", function (c) c:geometry( { width = ww, height = wh, x = 0, y = ph } ) end),

)
Всё отлично работает, но когда два дисплея, начиная каша малаша, почему-то не хочет считать геометрию и расположение фокусного скрина, от чего плясать нужно? Не screen[mouse.screen]? Тогда что? Помогите допилить, может и вам (это очень удобно, отвечаю!) пригодится и вашим родственникам и друзьям.

sudo cast actionless, Worron, fjfalcon, zhuravlik, Faiver, r3lgar; (простие, если вы бог осома, а я вас запамятовал).

Спасибо.



Последнее исправление: kep (всего исправлений: 2)

У тебя текущий скрин один раз за время жизни wm что ли определяется или я чего-то не понимаю?
Дай лучше целиком код, а то в lua с наскока тяжко разбираться.

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

Это и есть код целиком, остальное осомский дефолт.

У тебя текущий скрин один раз за время жизни wm

Текущий скрин — это скрин, на котором сейчас фокус, т.е. например у меня дисплей ноута и подключенный к нему дополнительный монитор, где грубо говоря активный зафокушенный клиент — это и есть «текущий скрин».

Из соображений универсальности, например также в тех случаях, когда дисплеев больше 2х, лучше не писать screen[1] и screen[2], а отлавливать текущий активный фокусный.

kep
() автор топика

Вот это офигенно. А стандартная высота панели такая?
В общем, годно, скопирую себе. Если еще допилишь, кастани

sehellion ★★★★★
()

У тебя мониторы разного разрешения? Если да, то всё понятно, ww хранит размер первого. Нужно доставать координаты в колбеке

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

У тебя мониторы разного разрешения?

Да, 1600x900 + 1920x1080

Нужно доставать координаты в колбеке

для этого и создал тред :)

kep
() автор топика
Ответ на: комментарий от sehellion

А стандартная высота панели такая?

ЕМНИП 20, меняется здесь:

-- Create the wibox
mywibox[s] = awful.wibox({ position = "top", screen = s })
путём добавления в строку «height = 22», например.
mywibox[1] = awful.wibox({ position = "top", screen = 1, height = 22 })

Если еще допилишь, кастани

подпишись на тред и ожидай результат, уверен, боги осома не бросят нас, но если у тебя один монитор, то уже готово, просто скопируй себей в конфиг из топика.

kep
() автор топика
Ответ на: комментарий от kep
local ph = 22 -- высота панели
local ww;local wh;
function gg
  local wa = screen[mouse.screen].workarea -- текущий screen
  ww = wa.width -- длина текущего screen
  wh = wa.height -- высота текущего screen
end

clientkeys = awful.util.table.join(
  awful.key({modkey}, "KP_Left",  function (c) gg(); c:geometry( { width = ww / 2, height = wh, x = 0, y = ph } ) end),

Функция gg обновляет ww и wh, её надо вызывать в колбеке до изменения геометрии окна

disarmer ★★★
()
Последнее исправление: disarmer (всего исправлений: 1)
Ответ на: комментарий от disarmer

добавил () после gg в объявлении функции, а то не работало.

Что же, уже лучше, теперь он умеет высчитывать геометрию текущего дисплея, но клиента перемещает не на текущий скрин, а всегда на первый, т.е. тот, который x = 0, как бы дать ему понять, что x = 0 — это не в целом, а текущего скрина x-то?

kep
() автор топика

Поздно ты меня кастанул, у меня уже полгода как второй монитор сдох, помочь ничем не смогу.

Но, это, у тебя там маус.скрин, а если курсор не на том скрине, где фокусованный клиент? Тут без коллбэков и странных воркараундов не обойтись, а в луа я не силён, особенно, когда им пытаются изобразить ООП (то есть в осоме почти всегда, лол).

В принципе тема интересная, и на будущее пригодится (не сабж, но некоторые реализации, как минимум), так что я просто буду почитывать тред.

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

ну ты просто делишь x и y на два, а от них надо сначала отнять x и y рабочего пространства

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

Есть, вот так раскидывает правильно:

local ph = 22 -- высота панели
local ww
local wh
local xx

function gg() 
  local wa = screen[mouse.screen].workarea
  ww = wa.width
  wh = wa.height 
  wx = wa.x
end

awful.key({ modkey }, "KP_Left",  function (c) gg(); c:geometry( { width = ww / 2, height = wh, x = wx, y = ph } ) end),

kep
() автор топика

[решено]

Всем большое спасибо, друзья! Теперь работает как нужно на много-мониторной конфиругации!

Я сейчас обновляю и дорабатываю серию Pro и по такому же типу пилю новую тему: Awesome Blender Theme, которая будет повторять тему блендера всех скинов, туда эта настройка по манипулированию клиентов и войдет, еще раз спасибо!

local ph = 22 -- panel height
local ww
local wh
local xx
local wy

function gg() 
  local wa = screen[mouse.screen].workarea
  ww = wa.width
  wh = wa.height 
  wx = wa.x
  wy = wa.y
end

clientkeys = awful.util.table.join(

  awful.key({ modkey }, "KP_Left",  function (c) gg(); c:geometry( { width = ww / 2, height = wh, x = wx, y = ph } ) end),
  awful.key({ modkey }, "KP_Right", function (c) gg(); c:geometry( { width = ww / 2, height = wh, x = wx + ww / 2, y = ph } ) end),
  awful.key({ modkey }, "KP_Up",    function (c) gg(); c:geometry( { width = ww, height = wh / 2, x = wx, y = ph } ) end),
  awful.key({ modkey }, "KP_Down",  function (c) gg(); c:geometry( { width = ww, height = wh / 2, x = wx, y = wh / 2 + ph } ) end),
  awful.key({ modkey }, "KP_Prior", function (c) gg(); c:geometry( { width = ww / 2, height = wh / 2, x = wx + ww / 2, y = ph } ) end),
  awful.key({ modkey }, "KP_Next",  function (c) gg(); c:geometry( { width = ww / 2, height = wh / 2, x = wx + ww / 2, y = wh / 2 + ph } ) end),
  awful.key({ modkey }, "KP_Home",  function (c) gg(); c:geometry( { width = ww / 2, height = wh / 2, x = wx, y = ph } ) end),
  awful.key({ modkey }, "KP_End",   function (c) gg(); c:geometry( { width = ww / 2, height = wh / 2, x = wx, y = wh / 2 + ph } ) end),
  awful.key({ modkey }, "KP_Begin", function (c) gg(); c:geometry( { width = ww, height = wh, x = wx, y = ph } ) end),

)

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

ты её правильно берешь — workarea

просто когда у тебя один дисплей то x и y будут 0, поэтому у тебя всё работало

actionless ★★★★★
()
Ответ на: [решено] от kep

Там коррекция по высоте панели точно нужна? Workarea вроде дает геометрию уже с ее учетом. Подозреваю для одно-мониторной конфигурации этот параметр получался однажды и до объявления панели.

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

Возможно берет и с учетом панели, но размещение и размер клиентов не должны залазить на панель же.

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

Короче, ph == wy, и аналогичного поведения можно добиться так

awful.key({ modkey }, "KP_Left",  function (c) local wa = screen[c.screen].workarea; wa.width = wa.width / 2; c:geometry(wa) end)
независимо от расположения панели.

Worron ★★★
()
Последнее исправление: Worron (всего исправлений: 1)
Ответ на: комментарий от Worron

Можешь пожалуйста показать как будет KP_Right, а то я не могу въехать, что подставлять в этом случае в c:geometry().

kep
() автор топика
Ответ на: комментарий от Worron

Спасибо, получилось чуть длиннее (если я не добавил лишние операции конечно), но зато универсальнее, кроме того я добавил к тем, что есть в вики перемещения клиентов не только up/down/right/left, но и по диагонали тоже, тот же хоткей только с шифтом:

awful.key({ modkey }, "KP_Up",    function (c) local wa = screen[c.screen].workarea; wa.height = wa.height / 2; c:geometry(wa) end),
awful.key({ modkey }, "KP_Prior", function (c) local wa = screen[c.screen].workarea; wa.x = wa.x + wa.width / 2; wa.width = wa.width / 2; wa.height = wa.height / 2; c:geometry(wa) end),
awful.key({ modkey }, "KP_Right", function (c) local wa = screen[c.screen].workarea; wa.x = wa.x + wa.width / 2; wa.width = wa.width / 2; c:geometry(wa) end),
awful.key({ modkey }, "KP_Next",  function (c) local wa = screen[c.screen].workarea; wa.x = wa.x + wa.width / 2; wa.y = wa.y + wa.height / 2; wa.width = wa.width / 2; wa.height = wa.height / 2; c:geometry(wa) end),
awful.key({ modkey }, "KP_Down",  function (c) local wa = screen[c.screen].workarea; wa.y = wa.y + wa.height / 2; wa.height = wa.height / 2; c:geometry(wa) end),
awful.key({ modkey }, "KP_End",   function (c) local wa = screen[c.screen].workarea; wa.y = wa.y + wa.height / 2; wa.width = wa.width / 2; wa.height = wa.height / 2; c:geometry(wa) end),
awful.key({ modkey }, "KP_Left",  function (c) local wa = screen[c.screen].workarea; wa.width = wa.width / 2; c:geometry(wa) end),
awful.key({ modkey }, "KP_Home",  function (c) local wa = screen[c.screen].workarea; wa.width = wa.width / 2; wa.height = wa.height / 2; c:geometry(wa) end),
awful.key({ modkey }, "KP_Begin", function (c) local wa = screen[c.screen].workarea; c:geometry(wa) end),
просто двигать клиенты и увеличивать/уменьшать:
awful.key({ modkey, "Shift" }, "KP_Up",       function () awful.client.moveresize(   0, -20,   0,   0) end), -- ↑
awful.key({ modkey, "Shift" }, "KP_Prior",    function () awful.client.moveresize(  20, -20,   0,   0) end), -- ↗
awful.key({ modkey, "Shift" }, "KP_Right",    function () awful.client.moveresize(  20,   0,   0,   0) end), -- →
awful.key({ modkey, "Shift" }, "KP_Next",     function () awful.client.moveresize(  20,  20,   0,   0) end), -- ↘
awful.key({ modkey, "Shift" }, "KP_Down",     function () awful.client.moveresize(   0,  20,   0,   0) end), -- ↓
awful.key({ modkey, "Shift" }, "KP_End",      function () awful.client.moveresize( -20,  20,   0,   0) end), -- ↙
awful.key({ modkey, "Shift" }, "KP_Left",     function () awful.client.moveresize( -20,   0,   0,   0) end), -- ←
awful.key({ modkey, "Shift" }, "KP_Home",     function () awful.client.moveresize( -20, -20,   0,   0) end), -- ↖
awful.key({ modkey, "Shift" }, "KP_Add",      function () awful.client.moveresize( -20, -20,  40,  40) end), -- +
awful.key({ modkey, "Shift" }, "KP_Subtract", function () awful.client.moveresize(  20,  20, -40, -40) end), -- -

kep
() автор топика
Ответ на: комментарий от mjollnir

(border_width)

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

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

kep
() автор топика
Ответ на: комментарий от f1u77y

Статусбар это панель? А как же они видят на каком теге ургент-вызов клиента, на каком теге они сейчас, на какой тег перенести клиент и т.п.?

более красивенько

они бесполезны, но при этом занимают место, впрочем если нравится, то почему нет.

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

они бесполезны, но при этом занимают место, впрочем если нравится, то почему нет.

я о том же.

А как же они видят на каком теге ургент-вызов клиента, на каком теге они сейчас

я вот, когда юзал standalone wm без статусбара, подобные вещи(а точнее моменты их изменения) костылил при помощи libnotify(или использовал «искоробочные» возможности wm). и ничего, не умер

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