LINUX.ORG.RU

DWM. tcl vs. centered master. Изменения порядка размещения окон

 ,


0

1

Всем доброго, дамы и господа.

Пару лет назад приобрёл ultrawide монитор. Несколько лет использую тайловые wm, в последнее время задержался на DWM. Поскольку монитор очень широкий, стандартный layout DWM мне показался, практически, не юзабельным, по этому нашёл патч three column (http://dwm.suckless.org/patches/three-column/). Для простых задач, типа администрирования локалхоста, вэба, игр, офиса и т.п., этого layout более чем достаточно, но для задач посерьёзней с ним уже тяжело, т.к. окно в мастер зоне может быть только одно окно:

tcl
+-----+-------------+-----+
|1    |             |4    |
|-----+             +-----+
|2    |      M      |5    |
|-----+             +-----+
|3    |             |6    |
+-----+-------------+-----+

Для исправления ситуации нашёл патч centered master (http://dwm.suckless.org/patches/centeredmaster/), который позволяет в мастер зоне держать более одного окна, собственно, то что мне и нужно (и даже больше). Но, при первой же попытке использования мне взорвал мозг порядок размещения окон:

centered master
+-----+-------------+-----+
|2    |             |1    |
|-----+             +-----+
|4    |      M      |3    |
|-----+             +-----+
|6    |             |5    |
+-----+-------------+-----+

Цифрами я показал порядок движения курсора, 1 - старт курсора, по возрастающей - движение курсора по нажатию mod+j.

Как можно заметить, в tcl окна размещаются некой «змейкой», которая хорошо раскладывается в прямую линию, мой мозг привык, что по нажатию mod+j курсор, условно, перемещается «вправо», по mod+k «влево», в centered master же порядок совсем другой: окна разбросаны по сторонам, и, помимо неудобства, связанного с банальной привычкой, приходится постоянно переводить взгляд при каджом переключении в centered master.

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

Ответ на: комментарий от serg002

Да, видел этот патч, когда искал что-то подходящее для ultrawide. Выбрал tcl, т.к. мастер зона по центру, мне это кажется более удобным: разок-другой вправо-влево, и уже второстепенное окно под курсором, да и в центр смотреть привычней.

Тем не менее благодарю за совет, когда совсем отчаюсь попробую всерьёз использовать этот layout.

Upd.

flexipatch не использовал, как я изначально понял это проект для упрощённого применения патчей с http://dwm.suckless.org/patches/, или я не прав?

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

Как по мне, то одно мастер по центру неудобно. А вот два мастера рядом с возможностью их делить пополам - очень юзабельно

Да, флекси для того, чтобы мозг не парить патчами

serg002 ★★★
()
Последнее исправление: serg002 (всего исправлений: 1)

Немного изменил алгоритм. Пробуйте.

void
centeredmaster(Monitor *m)
{
    unsigned int i, n, h, mw, mx, my, oty, ety, tw, sn, ln, rn;
    Client *c;

    /* count number of clients in the selected monitor */
    for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
    if (n == 0)
        return;

    /* initialize areas */
    mw = m->ww;
    mx = 0;
    my = 0;
    tw = mw;

    sn = (n - m->nmaster);
    if (sn % 2 == 0) {
        ln = sn / 2;
    } else {
        ln = sn / 2 + 1;
    }
    rn = sn - ln;

    if (n > m->nmaster) {
        /* go mfact box in the center if more than nmaster clients */
        mw = m->nmaster ? m->ww * m->mfact : 0;
        tw = m->ww - mw;

        if (sn > 0) {
            mx = (m->ww - mw) / 2;
            tw = (m->ww - mw) / 2;
        }
        if (sn == 1) {
            mw = m->ww - tw;
        }
    }

    oty = 0;
    ety = 0;

    for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
        if (i < m->nmaster) {
            /* nmaster clients are stacked vertically, in the center
             * of the screen */
            h = (m->wh - my) / (MIN(n, m->nmaster) - i);
            resize(c, m->wx + mx, m->wy + my, mw - (2*c->bw),
                    h - (2*c->bw), 0);
            my += HEIGHT(c);

        } else {
            /* stack clients are stacked vertically */
            if ((i - m->nmaster) < ln ) {
                h = m->wh / ln;
                resize(c, m->wx, m->wy + ety, tw - (2*c->bw),
                        h - (2*c->bw), 0);
                ety += HEIGHT(c);
            } else {
                h = m->wh / rn;
                resize(c, m->wx + mx + mw, m->wy + oty,
                        tw - (2*c->bw), h - (2*c->bw), 0);
                oty += HEIGHT(c);
            }
        }
}
bread
()
Ответ на: комментарий от serg002

Тоже стало интересно. Самое удобно автотайлинг или таблэйаут. А статичный по размеру стек имхо неудобно как ни крути. Иногда нужны 2окна по размеру как мастер иногда 3. А вот мелкие мало кому интересны.

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

Поведение, определённо поменялось, «змейка» не получилась, но прогресс на лицо.

При данном коде получил следующее:

+-----+-------------+-----+
|1    |     7 M     |4    |
|-----+-------------+-----+
|2    |     8 M     |5    |
|-----+-------------+-----+
|3    |     9 M     |6    |
+-----+-------------+-----+

целевая картина:

+-----+-------------+-----+
|1    |     6 M     |7    |
|-----+-------------+-----+
|2    |     5 M     |8    |
|-----+-------------+-----+
|3    |     4 M     |9    |
+-----+-------------+-----+
avrigus
() автор топика
Ответ на: комментарий от serg002

Не на ультрах эти окна как пиктограммы

Ну да, но я тайлю только терминалы. Тут фишка в том, что есть три колонки, и центральная ресайзится одновременно в двух направлениях.

bread
()

https://dwm.suckless.org/patches/columns/

Работает. Хороший для ультравайд layout. Можно поставить 2-3 мастера и работать как на обычном тайлинге. В каких-то кейсах может быть удобней и больше

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

Пофиксил стек, но в мастере оставил как есть, чтобы j/k работали предсказуемо. Получается так:

+-----+-------------+-----+
|1    |     4 M     |7    |
|-----+-------------+-----+
|2    |     5 M     |8    |
|-----+-------------+-----+
|3    |     6 M     |9    |
+-----+-------------+-----+
void
centeredmaster(Monitor *m)
{
    unsigned int i, n, h, mw, mx, my, oty, ety, tw, sn, ln, rn;
    Client *c;

    /* count number of clients in the selected monitor */
    for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
    if (n == 0)
        return;

    /* initialize areas */
    mw = m->ww;
    mx = 0;
    my = 0;
    tw = mw;

    sn = (n - m->nmaster);
    ln = (sn / 2) + (sn % 2);
    rn = sn - ln;

    if (n > m->nmaster) {
        /* go mfact box in the center if more than nmaster clients */
        mw = m->nmaster ? m->ww * m->mfact : 0;
        tw = m->ww - mw;

        if (sn > 0) {
            mx = (m->ww - mw) / 2;
            tw = (m->ww - mw) / 2;
        }
        if (sn == 1) {
            mw = m->ww - tw;
        }
    }

    oty = 0;
    ety = 0;

    for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
        if (i < m->nmaster) {
            /* nmaster clients are stacked vertically, in the center
             * of the screen */
            h = (m->wh - my) / (MIN(n, m->nmaster) - i);
            resize(c, m->wx + mx, m->wy + my, mw - (2*c->bw),
                    h - (2*c->bw), 0);
            my += HEIGHT(c);

        } else {
            /* stack clients are stacked vertically */
            if ((i - m->nmaster) < rn ) {
                h = m->wh / rn;
                resize(c, m->wx + mx + mw, m->wy + oty,
                        tw - (2*c->bw), h - (2*c->bw), 0);
                oty += HEIGHT(c);
            } else {
                h = m->wh / ln;
                resize(c, m->wx, m->wy + ety, tw - (2*c->bw),
                        h - (2*c->bw), 0);
                ety += HEIGHT(c);
            }
        }
}
bread
()
Ответ на: комментарий от bread

Странно, но при данном коде у меня выходит следующее:

+-----+-------------+-----+
|1    |     7 M     |4    |
|-----+-------------+-----+
|2    |     8 M     |5    |
|-----+-------------+-----+
|3    |     9 M     |6    |
+-----+-------------+-----+

т.е. сначала по mod+j обходится стек, и только потом мастер зона. как будто и разницы нет по сравнению с прошлым вариантом..

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

Хотел внести в свое сообщение изменения, но не вышло:

Прошу прощения, что-то у меня сразу не срослось: возможно не сделал make clean перед сборкой. Ваш код работает как и заявлено (dwm-6.4)! Благодарен!

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

Обнаружил проблему с ресайзингом и мастер зоной. Проявляется, когда на экране 2 окна:

  • мастер зона сместилась вправо, т.е. когда на экране 2 окна, мастер справа;
  • не возможно уменьшить размер мастер зоны даже до половины экрана;
  • чем меньше мастер зона, тем меньше размером будет создано третье окно по центру, постоянно приходится изменять размеры.

Такие вот вещи обнаружил.

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

А пока что быстрофикс (не тестировал):

void
centeredmaster(Monitor *m)
{
    unsigned int i, n, h, mw, mx, my, oty, ety, tw, sn, ln, rn;
    Client *c;

    /* count number of clients in the selected monitor */
    for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
    if (n == 0)
        return;

    sn = (n - m->nmaster);
    if (sn < 2) {
        tile(m);
        return;
    }
    ln = (sn / 2) + (sn % 2);
    rn = sn - ln;

    /* initialize areas */
    mw = m->ww;
    mx = 0;
    my = 0;
    tw = mw;

    if (n > m->nmaster) {
        /* go mfact box in the center if more than nmaster clients */
        mw = m->nmaster ? m->ww * m->mfact : 0;
        tw = m->ww - mw;

        if (sn > 0) {
            mx = (m->ww - mw) / 2;
            tw = (m->ww - mw) / 2;
        }
    }

    oty = 0;
    ety = 0;

    for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
        if (i < m->nmaster) {
            /* nmaster clients are stacked vertically, in the center
             * of the screen */
            h = (m->wh - my) / (MIN(n, m->nmaster) - i);
            resize(c, m->wx + mx, m->wy + my, mw - (2*c->bw),
                    h - (2*c->bw), 0);
            my += HEIGHT(c);

        } else {
            /* stack clients are stacked vertically */
            if ((i - m->nmaster) < rn ) {
                h = m->wh / rn;
                resize(c, m->wx + mx + mw, m->wy + oty,
                        tw - (2*c->bw), h - (2*c->bw), 0);
                oty += HEIGHT(c);
            } else {
                h = m->wh / ln;
                resize(c, m->wx, m->wy + ety, tw - (2*c->bw),
                        h - (2*c->bw), 0);
                ety += HEIGHT(c);
            }
        }
}

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

Нормально стало: мастер зона вернулась на место, третье окно создаётся размером с предыдущую мастер зону. Все работает на первый взгляд, спасибо.

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