В KDE, как я могу автоматически определить, на каком «рабочем столе» находится терминал Konsole? - PullRequest
4 голосов
/ 10 апреля 2009

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

EDIT: Я использую KDE 3.4 в корпоративной среде

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

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

Ответы [ 5 ]

5 голосов
/ 11 апреля 2009

На самом деле 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;
}
3 голосов
/ 10 апреля 2012

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

qdbus org.kde.kwin /KWin currentDesktop
3 голосов
/ 10 апреля 2009

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

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

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

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

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

2 голосов
/ 07 марта 2014

Новый ответ, потому что большинство ответов здесь получают текущий рабочий стол, а не тот, на котором находится терминал (сломается, если пользователь изменит рабочий стол во время выполнения скрипта).

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

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

2 голосов
/ 14 апреля 2009

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

  dcop kwin KWinInterface currentDesktop

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

Извините за мой плохой английский, Emilio

...