#x11 #xlib
#x11 #xlib
Вопрос:
Я хочу знать, возможно ли инвертировать цвета региона с помощью Xlib. Область может быть прямоугольной областью, определяемой двумя координатами (от x1, y1 до x2, y2). Ниже приведен код последней измененной версии скрипта, который используется для инвертирования части активного окна в соответствии с предложениями JvO
import Xlib
from Xlib import X, display, Xutil
d = display.Display()
screen = d.screen()
bgsize = 20
act_win = d.get_input_focus().focus
wmname = act_win.get_wm_name()
wmclass = act_win.get_wm_class()
if wmclass is None and wmname is None:
act_win = act_win.query_tree().parent
wmname = act_win.get_wm_name()
print "Active Window: %s" % ( wmname, )
#
# Creating a pixmap of size 200x2000 from active window
#
pm = act_win.create_pixmap(200, 2000, screen.root_depth)
#
# Creating two graphics contexts, one to be inverted, and one normal
#
gc = pm.create_gc()
#
# Inverting the to be inverted graphics context
# Changes after looking at code at:
# https://github.com/alexer/python-xlib/blob/master/Xlib/protocol/structs.py
#
gc.change(function = X.GXcopyInverted)
#
# Copying the content of act_win to pix map using to_invert_gc
#
# copy_area(gc, src_drawable, src_x, src_y, width, height, dst_x, dst_y)
#
pm.copy_area(gc, act_win, 0, 0, 200, 2000, 0, 0, onerror=None)
#
# Copying back the content of pixmap to act_win using norm_gc
#
# copy_area(gc, src_drawable, src_x, src_y, width, height, dst_x, dst_y)
#
gc.change(function = X.GXcopy)
act_win.copy_area(gc, pm, 0, 0, 200, 2000, 0, 0, onerror=None)
Версия приведенного выше кода на языке C приведена ниже:
#include <X11/Xlib.h>
#include <assert.h>
#include <unistd.h>
#include <stdio.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdarg.h>
void main(void) {
Display *dpy;
Window root_window, focused;
Pixmap pm;
GC gc;
XGCValues gcv, gcv_ret;
int revert_to;
XTextProperty text_prop;
int screen;
dpy = XOpenDisplay(":0.0");
screen = DefaultScreen(dpy);
root_window = RootWindow (dpy, DefaultScreen(dpy));
XGetInputFocus(dpy, amp;focused, amp;revert_to);
XGetWMName(dpy, focused, amp;text_prop);
printf("Active Window name: %sn", text_prop.value);
pm = XCreatePixmap(dpy, focused, 200, 200, 1);
gc = XCreateGC(dpy, focused, 0, NULL);
gcv.function = GXcopyInverted;
XChangeGC(dpy, gc, GCFunction, amp;gcv);
XFlushGC(dpy, gc);
XGetGCValues(dpy, gc, 1, amp;gcv_ret);
printf("Function while copying from focused window to pixmap: %dn", gcv_ret.function);
XCopyArea(dpy, focused, pm, gc, 0, 0, 200, 200, 0, 0);
gcv.function = GXcopy;
XChangeGC(dpy, gc, GCFunction, amp;gcv);
XFlushGC(dpy, gc);
XGetGCValues(dpy, gc, 1, amp;gcv_ret);
printf("Function while copying from pixmap to focused window: %dn", gcv_ret.function);
XCopyArea(dpy, pm, focused, gc, 50, 50, 200, 200, 0, 0);
XFlush(dpy);
}
Скомпилировал приведенный выше код с помощью gcc inv.c -o inv -lX11. Компиляция прошла успешно, но выполнение кода не приводит к инвертированию какой-либо части сфокусированного окна
Ниже приведен вывод:
urc@ubuntu-desktop: ~/Temporary Files$ ./inv
Active Window name: urc@ubuntu-desktop: ~/Temporary Files
Function while copying from focused window to pixmap: 12
Function while copying from pixmap to focused window: 3
urc@ubuntu-desktop: ~/Temporary Files$
Проблема, по-видимому, связана с параметром с именем «режим подокна» в параметре GC, для которого установлено значение ClipByChildren (по умолчанию). Установка значения IncludeInferiors заставила его работать. Решение было найдено по следующей ссылке:
https://groups.google.com/forum /#!тема/comp.windows.x/_TcGJq2uhmI
И вспомогательный пример кода на:
http://www.mit.edu/afs.new/sipb/user/web/src/xpunt/xpunt.c
Ниже приведен рабочий код:
#include <X11/Xlib.h>
#include <assert.h>
#include <unistd.h>
#include <stdio.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdarg.h>
void sleep_ms(int milliseconds) // cross-platform sleep function
{
#ifdef WIN32
Sleep(milliseconds);
#elif _POSIX_C_SOURCE >= 199309L
struct timespec ts;
ts.tv_sec = milliseconds / 1000;
ts.tv_nsec = (milliseconds % 1000) * 1000000;
nanosleep(amp;ts, NULL);
#else
usleep(milliseconds * 1000);
#endif
}
void main(void) {
Display *dpy;
Window root_window, focused, target, default_root_window;
Pixmap pm;
GC gc;
XGCValues gcv, gcv_ret;
int revert_to;
XTextProperty text_prop;
int screen, depth, whiteColor, blackColor;
XEvent e;
char text[1];
KeySym key;
dpy = XOpenDisplay(":0.0");
screen = DefaultScreen(dpy);
depth = DefaultDepth(dpy, screen);
whiteColor = WhitePixel(dpy, screen);
blackColor = BlackPixel(dpy, screen);
root_window = RootWindow (dpy, screen);
XGetInputFocus(dpy, amp;focused, amp;revert_to);
XGetWMName(dpy, focused, amp;text_prop);
printf("Active Window name: %sn", text_prop.value);
target = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 400, 400, 1, whiteColor, blackColor);
XSelectInput(dpy, target, ButtonPressMask | StructureNotifyMask | ExposureMask | KeyPressMask | PropertyChangeMask | VisibilityChangeMask);
XMapRaised(dpy, target);
for(;;) {
XNextEvent(dpy, amp;e);
if (e.type == MapNotify)
break;
}
pm = XCreatePixmap(dpy, focused, 200, 200, depth);
gc = XCreateGC(dpy, focused, 0, NULL);
XSetSubwindowMode(dpy, gc, IncludeInferiors);
gcv.function = GXcopyInverted;
XChangeGC(dpy, gc, GCFunction, amp;gcv);
XFlushGC(dpy, gc);
while(1) {
XNextEvent(dpy, amp;e);
if(e.type == Expose) {
XSetInputFocus(dpy, target, RevertToNone, CurrentTime);
} else if (e.type == MapNotify) {
printf("Map notifyn");
} else if (e.type == KeyPress) {
XLookupString(amp;e.xkey, text, 255, amp;key,0);
if (text[0] == 'c') {
printf("Copying planen");
XCopyArea(dpy, focused, target, gc, 0, 0, 200, 200, 0, 0);
XFlush(dpy);
}
if (text[0] == 'q') {
printf("Quitting ...n");
break;
}
}
}
}
Комментарии:
1. Ух — полезно! Мне нужно было что-то, чтобы заставить окно мигать, и я собрал что-то вместе, заставив это скопировать сфокусированное окно в себя, а затем выйти. Я не могу удалить часть отображения, не потеряв при этом flash, поэтому в итоге я получаю дрожание на панели значков в KDE, но это намного лучше, чем отсутствие звонка и визуальной обратной связи, поскольку элементы доступности игнорируются Консолью (по крайней мере, для моей настройки)
Ответ №1:
Вы можете попробовать следующее:
- Создайте растровое изображение размером с ваш регион
- Используйте XCopyArea, чтобы скопировать область из вашего исходного региона в новое растровое изображение, установив для атрибута функции GXCopy GC (графический контекст) значение XGCopyInverted; для этого используйте XChangeGC() .
- Скопируйте растровое изображение обратно в оригинал с помощью «прямой» копии.
Обратите внимание, что это приведет к инвертированию значений RGB, что может не очень хорошо смотреться на цветных изображениях, но отлично работает для черно-белого (оттенки серого).
Комментарии:
1. Ой, извините за задержку. Спасибо за ответ. Попробует это и обновит
2. Да, за исключением одного: вы используете тот же gc для своей окончательной копии
act_win
, в которую используется XCopyInverted. Таким образом, вы бы инвертировали свою перевернутую копию обратно в свое окно…. Используйте другой (или текущий gc) для act_win3. Пробовал, но все равно не работает. Я не вижу инвертированной части экрана. Что-нибудь не так в коде?
4. Также попытался изменить значение dict для ‘function’, как указано в github.com/alexer/python-xlib/blob/master/Xlib/protocol /…
5. Пробовал также использовать C, но, похоже, что-то еще идет не так. Прикрепленный код C
Ответ №2:
Приведенный ниже код теперь работает:
#include <X11/Xlib.h>
#include <assert.h>
#include <unistd.h>
#include <stdio.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdarg.h>
void sleep_ms(int milliseconds) // cross-platform sleep function
{
#ifdef WIN32
Sleep(milliseconds);
#elif _POSIX_C_SOURCE >= 199309L
struct timespec ts;
ts.tv_sec = milliseconds / 1000;
ts.tv_nsec = (milliseconds % 1000) * 1000000;
nanosleep(amp;ts, NULL);
#else
usleep(milliseconds * 1000);
#endif
}
void main(void) {
Display *dpy;
Window root_window, focused, target, default_root_window;
Pixmap pm;
GC gc;
XGCValues gcv, gcv_ret;
int revert_to;
XTextProperty text_prop;
int screen, depth, whiteColor, blackColor;
XEvent e;
char text[1];
KeySym key;
dpy = XOpenDisplay(":0.0");
screen = DefaultScreen(dpy);
depth = DefaultDepth(dpy, screen);
whiteColor = WhitePixel(dpy, screen);
blackColor = BlackPixel(dpy, screen);
root_window = RootWindow (dpy, screen);
XGetInputFocus(dpy, amp;focused, amp;revert_to);
XGetWMName(dpy, focused, amp;text_prop);
printf("Active Window name: %sn", text_prop.value);
target = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 400, 400, 1, whiteColor, blackColor);
XSelectInput(dpy, target, ButtonPressMask | StructureNotifyMask | ExposureMask | KeyPressMask | PropertyChangeMask | VisibilityChangeMask);
XMapRaised(dpy, target);
for(;;) {
XNextEvent(dpy, amp;e);
if (e.type == MapNotify)
break;
}
pm = XCreatePixmap(dpy, focused, 200, 200, depth);
gc = XCreateGC(dpy, focused, 0, NULL);
XSetSubwindowMode(dpy, gc, IncludeInferiors);
gcv.function = GXcopyInverted;
XChangeGC(dpy, gc, GCFunction, amp;gcv);
XFlushGC(dpy, gc);
while(1) {
XNextEvent(dpy, amp;e);
if(e.type == Expose) {
XSetInputFocus(dpy, target, RevertToNone, CurrentTime);
} else if (e.type == MapNotify) {
printf("Map notifyn");
} else if (e.type == KeyPress) {
XLookupString(amp;e.xkey, text, 255, amp;key,0);
if (text[0] == 'c') {
printf("Copying planen");
XCopyArea(dpy, focused, target, gc, 0, 0, 200, 200, 0, 0);
XFlush(dpy);
}
if (text[0] == 'q') {
printf("Quitting ...n");
break;
}
}
}
}