LINUX.ORG.RU

Активная область некоего приложения вместо рабочего стола


0

2

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

Объясню на пальцах. Например, при запуске nautilus мы видим рамку окна, заголовок окна, меню окна, панели (основная, боковая, адреса, состояния) и активную область где и показаны сами файлы. Вот хочется, чтобы эта активная область с файлами занимала место рабочего стола, т.е. чтобы при входе в систему запускался такой nautilus (насколько я знаю, он и так ответсвенен за значки на обычном рабочем столе), не занимал места в списке окон на панели и отображал свои файлы на месте рабочего стола, при этом была бы возможность перемещаться по директориям, открывать файлы, видеть / не видеть боковую панель (для внешних носителей, сети и ftp томов), панель с вкладками и т.п.

Ну и тоже самое в случае с браузером, консолью, emacs-ом и т.п. По сути, нужно чтобы всё окно приложения кроме рамки и заголовка занимало рабочий стол, какие там в нём панели видны / не видны решается средствами самого приложения.

Нет ли в нынешнем гноме (другом DE или WM?) таких возможностей?

P.S. Ещё лучше - если на каждый рабочий стол можно назначить своё приложение.

1. Создаешь правила в WM для класса приложения: запускать без заголовка, распахнутым на весь экран, видимым на всех рабочих стола.

2. Запускаешь приложение с измененным классом окна. (Чтобы не путалось с другими, «нормальными» копиями того же приложения).

3. Делаешь при помощи xbindkeys и bash-скрипта хоткей на спрятать/показать окно приложения.

Если нужно на разные на разных рабочих столах:

1. Делаешь N правил в WM с привязкой к разным рабочим столам.

2. Запускаешь N приложений.

3. Делаешь при помощи xbindkeys и bash-скрипта хоткей на спрятать/показать окно приложения, приложение скипт выбирает в зависимости от текущего рабочего стола.

Я ничего не упустил?

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

Упустил. Еще его надо указывать для него «Всегда внизу».

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

Я считаю, что «всегда внизу» — это тупость. Хоткеем поднял, хоткеем опустил.

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

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

strangeman ★★★★ ()

Нет ли в нынешнем гноме (другом DE или WM?) таких возможностей?

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

Ещё лучше - если на каждый рабочий стол можно назначить своё приложение.

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

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

1. Погуглил про WM_CLASS - получается с помощью devilspie. Возможно, в compiz-е тоже можно.

2. А это как?

Для gnome-terminal работает:

$ gnome-terminal --disable-factory --name=foo --class=foo &
$ xprop
...
WM_CLASS(STRING) = "foo", "foo"
...

для nautilus - нет:

$ nautilus --name=foo --class=foo &
$ xprop
WM_CLASS(STRING) = "nautilus", "Nautilus"

У emacs, chromium вообще нет --class. WM_CLASS в окружении тоже не помогает.

Можно, конечно, раздобыть Window по PID и присвоить WM_CLASS средствами xlib, но может проще можно?

quasimoto ★★★★ ()

В KDE такое возможно, плазмоидами

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

Тогда вместо пунктов 1 и 2 такой костыль:

Пишем bash-скрипт, который принимает имя класса и команду запуска.

Скрипт запускает указанную команду, ждет появления окна с указанным классом и присваивает окну все нужные свойства (развернуть, закрепить в нижнем слое и т.п.)

Появление окна можно ловить при помощи wmctrl -lx

Присваивать свойства можно при помощи того же wmctrl. Отключение заголовка окна ванильный wmctrl не поддерживает, но можно нагуглить патч, добавляющий такую поддержку, где-то как-то я его видел.

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

Еще мой склероз мне подсказывает, что baverman писал как-то некий аналог devilspie на питоне.

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

Возможно, та утилита подойдёт для твоей задачи, поищи.

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

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

/*
 * wm_class.c -- run a program with specified WM_CLASS property.
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>

void handle_error(const char *message)
{
    printf("%s\n", message);
    exit(-1);
}

int main(int argc, char **argv)
{
    if (argc < 4)
        handle_error("usage: wm_class <name> <class> <program> [<argument>*]");

    char *name = argv[1], *class = argv[2], *prog = argv[3], **args = &argv[3];

    pid_t pid = fork();

    switch (pid) {
    case -1:
        handle_error("system error: fork");
    case 0:
        execvp(prog, args);
        handle_error("can't execute the program");
    }

    sleep(1);

    int done = 0;

    Display *display = XOpenDisplay(NULL);

    if (display == NULL)
        handle_error("system error: XOpenDisplay");

    Window window = XDefaultRootWindow(display);

    /* So, this works only for applications that set the _NET_WM_PID property. */
    Atom net_wm_pid = XInternAtom(display, "_NET_WM_PID", True);

    if (net_wm_pid == None)
        handle_error("can't find the _NET_WM_PID property");

    /* Walk around whole tree of windows. */
    void traverse(void)
    {
        Atom type;
        int format;
        unsigned long nitems, nbytes;
        unsigned char *prop = NULL;

        if (Success == XGetWindowProperty(display, window, net_wm_pid, 0, 1, False,
                                          XA_CARDINAL, &type, &format, &nitems,
                                          &nbytes, &prop)) {
            if (prop != NULL) {
                if (pid == *(unsigned long*)prop) {
                    XClassHint *hint = XAllocClassHint();
                    hint->res_name = name;
                    hint->res_class = class;
                    XSetClassHint(display, window, hint);
                    XFree(hint);
                    done++;
                }
                XFree(prop);
            }
        }

        Window root, parent, *child;
        unsigned childrens;

        if (0 != XQueryTree(display, window, &root, &parent, &child, &childrens)) {
            for (unsigned i = 0; i < childrens; i++) {
                window = child[i];
                traverse();
            }
            XFree(child);
         }
    }

    traverse();

    if (!done)
        printf("can't find the program windows (or maybe the program don't set the _NET_WM_PID property)\n");

    XCloseDisplay(display);

    return 0;
}

// KLUDGE:
//   total heap usage: 1,729 allocs, 1,728 frees
//   definitely lost: 124 bytes in 1 blocks

но оно работает только для приложений у которых один процесс со своими окошками. У chromium непонятно сколько разных процессов, но это ещё можно решить - сделать traverse по потомкам самого первого. А вот у nautilus / gnome-terminal висит всегда один процесс (!) которому передаются вновь создаваемые окна, тут уже не обойтись без демона который будет хватать создаваемые окна и предпринимать какие-то действия (без привлечения PID).

quasimoto ★★★★ ()

Сделал проще - пишутся нужные правила декорации для devilspie, потом при старте системы запускаются нужные приложения с обычными классами, запускается devilspie -a &, тот производит декорацию, затем делается killall devilspie, так что новые версии приложений не декорируются. Всё.

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