jjzjj

c - X11 - 在叠加窗口上绘制

coder 2023-06-19 原文

我想在屏幕上的特定像素处绘制简单的图元(类似于 question )。为了做到这一点,我使用窗口管理器的覆盖窗口在所有窗口之上绘制。我可以看到我正在绘制的形状和鼠标事件通过但我没有看到例如覆盖窗口下方的窗口移动(除非我终止我的应用程序)。我是 Xlib 编程的新手,很抱歉问了一个可能很简单的问题。

#include <assert.h>
#include <stdio.h>
#include <X11/Xlib.h>

#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xfixes.h>
#include <X11/extensions/shape.h>

#include <cairo.h>
#include <cairo-xlib.h>

Display *d;
Window overlay;
Window root;
int width, height;

void
allow_input_passthrough (Window w)
{
    XserverRegion region = XFixesCreateRegion (d, NULL, 0);

    XFixesSetWindowShapeRegion (d, w, ShapeBounding, 0, 0, 0);
    XFixesSetWindowShapeRegion (d, w, ShapeInput, 0, 0, region);

    XFixesDestroyRegion (d, region);
}

void
prep_overlay (void)
{
    overlay = XCompositeGetOverlayWindow (d, root);
    allow_input_passthrough (overlay);
}

void draw(cairo_t *cr) {
    int quarter_w = width / 4;
    int quarter_h = height / 4;
    cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
    cairo_rectangle(cr, quarter_w, quarter_h, quarter_w * 2, quarter_h * 2);
    cairo_fill(cr);
}

int main() {
    d = XOpenDisplay(NULL);

    int s = DefaultScreen(d);
    root = RootWindow(d, s);

    XCompositeRedirectSubwindows (d, root, CompositeRedirectAutomatic);
    XSelectInput (d, root, SubstructureNotifyMask);

    width = DisplayWidth(d, s);
    height = DisplayHeight(d, s);

    prep_overlay();

    cairo_surface_t *surf = cairo_xlib_surface_create(d, overlay,
                                  DefaultVisual(d, s),
                                  width, height);
    cairo_t *cr = cairo_create(surf);

    XSelectInput(d, overlay, ExposureMask);

    draw(cr);

    XEvent ev;
    while (1) {
    XNextEvent(d, &ev);
        if (ev.type == Expose) {
            draw(cr);
        }
    }

    cairo_destroy(cr);
    cairo_surface_destroy(surf);
    XCloseDisplay(d);
    return 0;
}

如何在覆盖窗口上绘制像素并仍然看到下面的窗口?

最佳答案

我可以建议一个更简单、纯 X11 的解决方案,它没有我遇到并提到的闪烁问题 here .它使用 override_redirect Xlib 中的功能:

#include <assert.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/X.h>
#include <X11/Xutil.h>

#include <cairo.h>
#include <cairo-xlib.h>

#include <chrono>
#include <thread>

void draw(cairo_t *cr) {
    cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.5);
    cairo_rectangle(cr, 0, 0, 200, 200);
    cairo_fill(cr);
}

int main() {
    Display *d = XOpenDisplay(NULL);
    Window root = DefaultRootWindow(d);
    int default_screen = XDefaultScreen(d);

    // these two lines are really all you need
    XSetWindowAttributes attrs;
    attrs.override_redirect = true;

    XVisualInfo vinfo;
    if (!XMatchVisualInfo(d, DefaultScreen(d), 32, TrueColor, &vinfo)) {
        printf("No visual found supporting 32 bit color, terminating\n");
        exit(EXIT_FAILURE);
    }
    // these next three lines add 32 bit depth, remove if you dont need and change the flags below
    attrs.colormap = XCreateColormap(d, root, vinfo.visual, AllocNone);
    attrs.background_pixel = 0;
    attrs.border_pixel = 0;

    // Window XCreateWindow(
    //     Display *display, Window parent,
    //     int x, int y, unsigned int width, unsigned int height, unsigned int border_width,
    //     int depth, unsigned int class, 
    //     Visual *visual,
    //     unsigned long valuemask, XSetWindowAttributes *attributes
    // );
    Window overlay = XCreateWindow(
        d, root,
        0, 0, 200, 200, 0,
        vinfo.depth, InputOutput, 
        vinfo.visual,
        CWOverrideRedirect | CWColormap | CWBackPixel | CWBorderPixel, &attrs
    );

    XMapWindow(d, overlay);

    cairo_surface_t* surf = cairo_xlib_surface_create(d, overlay,
                                  vinfo.visual,
                                  200, 200);
    cairo_t* cr = cairo_create(surf);

    draw(cr);
    XFlush(d);

    // show the window for 10 seconds
    std::this_thread::sleep_for(std::chrono::milliseconds(10000));

    cairo_destroy(cr);
    cairo_surface_destroy(surf);

    XUnmapWindow(d, overlay);
    XCloseDisplay(d);
    return 0;
}

我继续添加了 32 位深度,但你明白了。如果需要,您可以将其删除。

请注意,就原始问题而言(在 覆盖窗口上绘图),这是行不通的。这会绘制一个 窗口,该窗口的外观和行为与问题中的其他要求非常相似。但是,它不保证在作为 X11 一部分的复合覆盖窗口上进行任何直接绘制。

它所做的只是告诉窗口管理器“不要以任何方式弄乱或装饰这个窗口”,这本身就是一个建议,窗口管理器没有义务遵守这条规则(尽管几乎所有人都这样做) .您可能不想直接在叠加窗口上绘制,因为那样会干扰合成器并且几乎肯定无法正确绘制任何内容。我什至不确定如果合成器已经请求访问复合覆盖,你会怎么做,一次只有一个进程可以访问它。

此外,叠加窗口与窗口管理器无关,它是合成器 (Xcomposite) 的一部分。

关于c - X11 - 在叠加窗口上绘制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21780789/

有关c - X11 - 在叠加窗口上绘制的更多相关文章

  1. ruby - 安装libv8(3.11.8.13)出错,Bundler无法继续 - 2

    运行bundleinstall后出现此错误:Gem::Package::FormatError:nometadatafoundin/Users/jeanosorio/.rvm/gems/ruby-1.9.3-p286/cache/libv8-3.11.8.13-x86_64-darwin-12.gemAnerroroccurredwhileinstallinglibv8(3.11.8.13),andBundlercannotcontinue.Makesurethat`geminstalllibv8-v'3.11.8.13'`succeedsbeforebundling.我试试gemin

  2. ruby - (Ruby || Python) 窗口管理器 - 2

    我想用这两种语言中的任何一种(最好是ruby​​)制作一个窗口管理器。老实说,除了我需要加载某种X模块外,我不知道从哪里开始。因此,如果有人有线索,如果您能指出正确的方向,那就太好了。谢谢 最佳答案 XCB,X的下一代API使用XML格式定义X协议(protocol),并使用脚本生成特定语言绑定(bind)。它在概念上与SWIG类似,只是它描述的不是CAPI,而是X协议(protocol)。目前,C和Python存在绑定(bind)。理论上,Ruby端口只是编写一个从XML协议(protocol)定义语言到Ruby的翻译器的问题。生

  3. ruby - ri 有空文件 – Ubuntu 11.10, Ruby 1.9 - 2

    我正在运行Ubuntu11.10并像这样安装Ruby1.9:$sudoapt-getinstallruby1.9rubygems一切都运行良好,但ri似乎有空文档。ri告诉我文档是空的,我必须安装它们。我执行此操作是因为我读到它会有所帮助:$rdoc--all--ri现在,当我尝试打开任何文档时:$riArrayNothingknownaboutArray我搜索的其他所有内容都是一样的。 最佳答案 这个呢?apt-getinstallri1.8编辑或者试试这个:(非rvm)geminstallrdocrdoc-datardoc-da

  4. ruby - rails 3.2.2(或 3.2.1)+ Postgresql 9.1.3 + Ubuntu 11.10 连接错误 - 2

    我正在使用PostgreSQL9.1.3(x86_64-pc-linux-gnu上的PostgreSQL9.1.3,由gcc-4.6.real(Ubuntu/Linaro4.6.1-9ubuntu3)4.6.1,64位编译)和在ubuntu11.10上运行3.2.2或3.2.1。现在,我可以使用以下命令连接PostgreSQLsupostgres输入密码我可以看到postgres=#我将以下详细信息放在我的config/database.yml中并执行“railsdb”,它工作正常。开发:adapter:postgresqlencoding:utf8reconnect:falsedat

  5. ruby-on-rails - Rails 2.3.11 DateTime BigDecimal 精度 - 2

    我目前有一个运行Ruby1.8.7和Rails2.3.2的RubyonRails项目我有一些从数据库中读取数据的单元测试,特别是两个连续项目的日期时间列,这两个项目应该相隔24小时。在一项测试中,我将项目2的日期时间设置为与项目1的日期时间相同。当我执行断言以确保两个值相等时,测试在rails2.3.2下工作正常。当我升级到rails2.3.11时,测试失败显示两次之间的差异将关闭并出现以下错误:expectedbutwas.这两个版本的rails中似乎存在浮点转换问题。如何解决float问题? 最佳答案 这也发生在我身上,我最终这

  6. Win10 / 11新电脑最简单跳过联网激活和使用本地账户登录方法 - 2

    跳过联网激活:OOBE界面直接按Ctrl+Shift+F3进入审核模式。这样就可以直接进入系统进行一些硬件测试等,而不用联网激活导致新机无法退货。需要注意的是,在审核模式下进行的一些操作都会保留,并不会在退出后自动还原!安装的软件在正常开机进系统后还会看见!如果电脑确实没连互联网又不想强行跳过OOBE(网上很多教程会叫你直接结束OOBE进程,但这是不推荐的,因为一些厂商自带优化程序和系统初始化设置在后面都会应用,对于笔记本跳过的话你会发现驱动和内置应用都没有装上。其实这部分脚本就在系统盘的Recovery隐藏文件夹下),可以参考以下方式:https://www.landiannews.com/

  7. ruby - 处理在 keyup 事件上发生的 javascript 弹出窗口 - 2

    我在HTML页面上有一个文本字段,用于检查您是否输入了1到365之间的值。如果用户输入了无效值,如非数字字符或不在范围内的值,它显示一个弹出窗口。我在watirwiki上看到有一个select_no_wait方法,用于在您从列表中选择无效值时关闭弹出窗口。处理键盘事件时出现的弹出窗口的好方法是什么?我是否需要按照select_no_wait方法的实现方式进行操作,或者我们是否可以启动一个不同的进程来消除调用set方法时可能出现的弹出窗口。带有Javascript验证函数的HTML文件示例如下:varnum=0functionvalidate(e){varcharPressed=Stri

  8. ruby - Watir Webdriver 如何关闭子窗口 - 2

    我正在将一些遗留的Watir脚本迁移到Watir-Webdriver。除了他们如何设计Watir-Webdriver来处理弹出窗口之外,迁移大部分进行得很顺利。他们没有使用久经考验的“附加”方法,而是用简化的“窗口”方法取而代之。语法非常简单,但是我很难理解如何在不关闭父窗口的情况下关闭单独的子窗口。目前我的代码是这样的-b.button(:xpath=>PREVIEWBUTTON).clickb.window(:title,POPUPWINDOW).useDOb.closeend目前正在发生的是b.close方法正在关闭子窗口和父窗口。我不确定为什么会这样,因为b.close方法包含

  9. ruby-on-rails - 在 El Capitan 上安装 Rails 时出现 -lgmp 错误的库未找到(Mac OS 10.11.1 (15B42)) - 2

    在使用Rubyv2.2.2的ElCapitan(MacOSX10.11.1)上安装Rails时,出现以下错误:ERROR:Errorinstallingnokogiri:ERROR:Failedtobuildgemnativeextension./Users/jon/.rvm/rubies/ruby-2.2.2/bin/ruby-r./siteconf20151117-26799-ux15fd.rbextconf.rb--use-system-librariescheckingiftheCcompileraccepts...***extconf.rbfailed***Couldnotc

  10. ruby - 如何在 selenium-webdriver 中获取窗口标题、ID 和名称? - 2

    我正在尝试从selenium-webdriver(ruby)实现以下方法get_all_window_idsget_all_window_titlesget_all_window_names我运行了SeleniumIDE并将我的脚本导出到RubyTest::Unit。另存为.rb使用AptanaStudio3打开我的脚本进行编辑初始代码片段如下:require"rubygems"require"selenium-webdriver"require"test/unit"classSwitchToPopup3我不断得到的错误是NoMethodError:undefinedmethod`ge

随机推荐