Как в KDE я могу автоматически определить, на каком рабочем столе находится терминал Konsole?

У меня есть несколько «рабочих столов», между которыми я переключаюсь для разных задач в среде KDE Linux. Как я могу автоматически определить, на каком рабочем столе отображается окно моей Konsole (консоли kde)?

РЕДАКТИРОВАТЬ: я использую KDE 3.4 в корпоративной среде

Это связано с программированием. Мне нужно программно (ака автоматически) определить, на каком рабочем столе находится пользователь, а затем взаимодействовать с окнами X на этом рабочем столе из скрипта Python.

Должен ли я обойти все вопросы, связанные с Microsoft IDE, как не связанные с программированием? Как насчет вопросов о «программировании» Win32? Должен ли я попытаться закрыть их тоже?


person Ross Rogers    schedule 10.04.2009    source источник
comment
Почему вы пытаетесь определить это? Что вы будете делать с результатом, когда найдете его? Не зная этого, лучший ответ: нажмите кнопку консоли на панели задач и посмотрите, на какой рабочий стол она переключится.   -  person davr    schedule 10.04.2009
comment
нужна хоть какая-то информация. кде4, кде3? какая консольная версия?   -  person Johannes Schaub - litb    schedule 10.04.2009
comment
Мне нужно определить рабочий стол в коде, а не просить пользователя сказать мне, на каком рабочем столе он находится.   -  person Ross Rogers    schedule 10.04.2009
comment
Консоль убер все!   -  person olegst    schedule 16.06.2017


Ответы (6)


С dcop, протоколом связи рабочего стола kde, вы можете легко получить текущую рабочую среду.

  dcop kwin KWinInterface currentDesktop

команда. Если вы работаете с новым kde 4.x, dcop больше не используется, и вы можете преобразовать команду в вызов DBUS. Должно быть довольно просто отправлять/получать сообщения dbous с помощью API Python.

Извини за мой плохой английский, Эмилио.

person Emilio    schedule 13.04.2009
comment
Наконец-то нашел версию вышеуказанной команды, не зависящую от KDE/Gnome. Это xprop -root | egrep '^_NET_CURRENT_DESKTOP' - person Ross Rogers; 10.02.2011
comment
dcop устарел; вместо dcop вы можете использовать dbus. Смотрите мой альтернативный ответ ниже. - person Kimball Robinson; 20.09.2013

На самом деле EWMH _NET_CURRENT_DESKTOP дает вам текущий рабочий стол для X, а не относительно приложения. Вот фрагмент C, чтобы получить _WM_DESKTOP приложения. Если запустить из рассматриваемой KDE Konsole, она покажет, на каком рабочем столе он находится, даже если это не активный рабочий стол или он не находится в фокусе.

#include <X11/Xlib.h>
#include <X11/Shell.h>
...

Atom net_wm_desktop = 0;
long desktop;
Status ret;

/* see if we've got a desktop atom */
Atom net_wm_desktop = XInternAtom( display, "_NET_WM_DESKTOP", False);
if( net_wm_desktop == None ) {
    return;
}

/* find out what desktop we're currently on */
if ( XGetWindowProperty(display, window, net_wm_desktop, 0, 1, 
            False, XA_CARDINAL, (Atom *) &type_ret, &fmt_ret, 
            &nitems_ret, &bytes_after_ret, 
            (unsigned char**)&data) != Success || data == NULL
) {
fprintf(stderr, "XGetWindowProperty() failed");
    if ( data == NULL ) {
        fprintf(stderr, "No data returned from XGetWindowProperty()" );
    }
    return;
}
desktop = *data;
XFree(data);

а desktop должен быть индексом виртуального рабочего стола, в котором в данный момент находится Konsole. Это не то же самое, что заголовок многоголового дисплея. Если вы хотите определить, какая головка, вам нужно использовать XineramaQueryScreens (расширение Xinerama, не уверен, есть ли эквивалент XRandR или нет. Не работает для TwinView nVidia.

Вот отрывок из некоторого кода, который я написал, который, учитывая x и y, вычисляет границы экрана (sx, sy и sw с шириной экрана и sh для высоты экрана). Вы можете легко адаптировать его, чтобы просто возвращать, какой «экран» или головка x и y включены. (Экран имеет особое значение в X11).

#include <X11/X.h>
#include <X11/extensions/Xinerama.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

Bool xy2bounds(Display* d,int x, int y, int* sx, int* sy, int* sw, int* sh) {
   *sx = *sy = *sw = *sh = -1;   /* Set to invalid, for error condition */
   XineramaScreenInfo *XinInfo;
   int xin_screens = -1;
    int i;
   int x_origin, y_origin, width, height;
   Bool found = False;

   if ( d == NULL )
      return False;
   if ( (x < 0) || (y < 0) )
      return False;

   if ( True == XineramaIsActive(d) ) {
      XinInfo = XineramaQueryScreens( d, &xin_screens );
      if ( (NULL == XinInfo) || (0 == xin_screens) ) {
         return False;
      }
   } else {
      /* Xinerama is not active, so return usual width/height values */
      *sx = 0;
      *sy = 0;
      *sw = DisplayWidth( d, XDefaultScreen(d) );
      *sh = DisplayHeight( d, XDefaultScreen(d) );
      return True;
   }

   for ( i = 0; i < xin_screens; i++ ) {
      x_origin = XinInfo[i].x_org;
      y_origin = XinInfo[i].y_org;
      width = XinInfo[i].width;
      height = XinInfo[i].height;
      printf("Screens: (%d) %dx%d - %dx%d\n", i,
            x_origin, y_origin, width, height );

      if ( (x >= x_origin) && (y >= y_origin) ) {
         if ( (x <= x_origin+width) && (y <= y_origin+height) ) {
            printf("Found Screen[%d] %dx%d - %dx%d\n",
               i, x_origin, y_origin, width, height );

            *sx = x_origin;
            *sy = y_origin;
            *sw = width;
            *sh = height;
            found = True;
            break;
         }
      }
   }

   assert( found == True );

   return found;
}
person mctylr    schedule 11.04.2009
comment
Я работаю над вашим примером кода, но не могу понять, как получить дескриптор Window для окна Konsole? - person Ross Rogers; 14.04.2009
comment
Я забыл эту деталь, но это должно быть возможно с xwininfo или xprop. - person mctylr; 14.04.2009
comment
+1 за указание на то, что другие ответы дают текущий рабочий стол, а не рабочий стол терминала скрипта. @mctylr Я добавил ответ, который делает это с помощью xprop. - person ctrl-alt-delor; 07.03.2014

Ссылаясь на принятый ответ... dcop устарел; вместо dcop вы можете использовать dbus (qdbus — это инструмент командной строки для dbus).

qdbus org.kde.kwin /KWin currentDesktop
person Kimball Robinson    schedule 10.04.2012
comment
В KDE 5.12 на Kubuntu 18.04 это qdbus org.kde.KWin /KWin currentDesktop. - person Dirk Hillbrecht; 25.07.2018

Оконный менеджер KDE, а также GNOME и все WM, соответствующие стандартам freedesktop, поддерживают Расширенные подсказки диспетчера окон (EWMH).

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

Я никогда не работал с KDE, но Gnome предоставляет такую ​​функциональность, поэтому я предполагаю, что в KDE она тоже есть.

Также можно получить доступ к подмножеству этих подсказок с помощью чистых функций Xlib. Это подмножество — подсказки ICCCM. Если мне не изменяет память, правильный доступ к виртуальному рабочему столу есть только в EWMH.

Обновление: Найдено! (_NET_CURRENT_DESKTOP)

person kazanaki    schedule 10.04.2009

Новый ответ, потому что БОЛЬШИНСТВО ответов здесь получают текущий рабочий стол, а не тот, на котором находится терминал (сломается, если пользователь изменит рабочий стол во время работы скрипта).

xprop -id $WINDOWID | sed -rn -e 's/_NET_WM_DESKTOP\(CARDINAL\) = ([^)]+)/\1/pg'

Я проверил это в цикле при смене рабочего стола, все работает нормально (тестовый скрипт ниже, вам нужно проверить вывод вручную после запуска).

while true
do
  xprop -id $WINDOWID | sed -rn -e  's/_NET_WM_DESKTOP\(CARDINAL\) = ([^)]+)/\1/pg'
  sleep 1
done

Спасибо за другие ответы и комментарии, за то, что помогли мне на полпути.

person ctrl-alt-delor    schedule 07.03.2014

Я искал то же самое, но с еще одним ограничением, я не хочу запускать команду оболочки для достижения результата. Начиная с ответа Кимбалла Робинсона, вот что я получил.

Протестировано в Python 3.7, Debian 10.3, KDE Plasma 5.14.5.

import dbus 

bus = dbus.SessionBus()
proxy = bus.get_object("org.kde.KWin", "/KWin")
int( proxy.currentDesktop(dbus_interface="org.kde.KWin") )
person Nicola Mingotti    schedule 08.04.2020