【问题标题】:Invert the colors of a region in Xlib反转 Xlib 中区域的颜色
【发布时间】:2016-11-27 18:15:29
【问题描述】:

我想知道是否可以使用 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, &focused, &revert_to);
    XGetWMName(dpy, focused, &text_prop);

    printf("Active Window name: %s\n", text_prop.value);
    pm = XCreatePixmap(dpy, focused, 200, 200, 1);
    gc = XCreateGC(dpy, focused, 0, NULL);

    gcv.function = GXcopyInverted;

    XChangeGC(dpy, gc, GCFunction, &gcv);

    XFlushGC(dpy, gc);

    XGetGCValues(dpy, gc, 1, &gcv_ret);
    printf("Function while copying from focused window to pixmap: %d\n", gcv_ret.function);

    XCopyArea(dpy, focused, pm, gc, 0, 0, 200, 200, 0, 0);

    gcv.function = GXcopy;

    XChangeGC(dpy, gc, GCFunction, &gcv);
    XFlushGC(dpy, gc);

    XGetGCValues(dpy, gc, 1, &gcv_ret);
    printf("Function while copying from pixmap to focused window: %d\n", 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/#!topic/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(&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, &focused, &revert_to);
    XGetWMName(dpy, focused, &text_prop);

    printf("Active Window name: %s\n", 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, &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, &gcv);

    XFlushGC(dpy, gc);
    while(1) {

        XNextEvent(dpy, &e);
        if(e.type == Expose) {
            XSetInputFocus(dpy, target, RevertToNone, CurrentTime);
        } else if (e.type == MapNotify) {
            printf("Map notify\n");
        } else if (e.type == KeyPress) {
            XLookupString(&e.xkey, text, 255, &key,0);
            if (text[0] == 'c') {
                printf("Copying plane\n");
                XCopyArea(dpy, focused, target, gc, 0, 0, 200, 200, 0, 0);
                XFlush(dpy);
            }
            if (text[0] == 'q') {
                printf("Quitting ...\n");
                break;
            }
        }
    }
}

【问题讨论】:

  • 惠 - 有帮助!我需要一些东西来使窗口闪烁,然后通过使这个副本成为焦点窗口自身然后退出来拼凑一些东西。我不能在不丢失 Flash 的情况下删除它的映射部分,所以我最终在 KDE 中的图标栏上出现抖动,但它比没有铃声和没有视觉反馈要好得多,因为 Konsole 忽略了可访问性的东西(至少对于我的设置)

标签: x11 xlib


【解决方案1】:

您可以尝试以下方法:

  • 根据您的区域大小创建像素图
  • 使用XCopyArea将区域从你原来的区域复制到新的Pixmap,设置GC(Graphic Context)的函数属性GXCopy为XGCopyInverted;为此使用 XChangeGC()。
  • 使用“直接”副本将像素图复制回原件。

请注意,这只会对 RGB 值进行位反转,这对于彩色图像可能看起来不太好,但对于黑白(灰度)效果很好。

【讨论】:

  • 抱歉耽搁了。感谢你的回答。会试试这个并更新
  • 是的,除了一件事:您使用相同的 gc 将最终副本复制到 act_win,它使用的是 XCopyInverted。所以你会将你的反转副本反转回你的窗口....为 act_win 使用不同的(或当前的 gc)
  • 试过了,还是不行。我没有看到屏幕的一部分倒置。代码有什么问题吗?
  • 还尝试更改github.com/alexer/python-xlib/blob/master/Xlib/protocol/…中列出的'function'的dict值
  • 也尝试使用 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(&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, &focused, &revert_to);
    XGetWMName(dpy, focused, &text_prop);

    printf("Active Window name: %s\n", 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, &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, &gcv);

    XFlushGC(dpy, gc);
    while(1) {

        XNextEvent(dpy, &e);
        if(e.type == Expose) {
            XSetInputFocus(dpy, target, RevertToNone, CurrentTime);
        } else if (e.type == MapNotify) {
            printf("Map notify\n");
        } else if (e.type == KeyPress) {
            XLookupString(&e.xkey, text, 255, &key,0);
            if (text[0] == 'c') {
                printf("Copying plane\n");
                XCopyArea(dpy, focused, target, gc, 0, 0, 200, 200, 0, 0);
                XFlush(dpy);
            }
            if (text[0] == 'q') {
                printf("Quitting ...\n");
                break;
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-27
    • 1970-01-01
    • 2011-06-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多