使用WebKit可以在透明背景上呈现Web内容吗?

36

我正试图评估一个对WebKit的补丁可能性,使得所有呈现的图形都能呈现在完全透明的背景上。

期望的效果是以没有任何背景的方式呈现网页内容,它应该漂浮在桌面上(或者浏览器窗口后面显示的任何内容上)。

有人见过这样的应用程序吗?(我可以想到一些终端仿真器可以这样做。)如果有人在WebKit(或可能是Gecko?)内部工作过,您觉得能够实现这一点吗?


更新: 我已经意识到Mac OSX仪表盘小部件使用了这种精确技术。所以,这一定是可能的。


更新2: 我已经在Linux上编译了WebKit,并注意到配置选项包括:

--enable-dashboard-support
enable Dashboard support default=yes

我越来越接近了,有人能帮忙吗?


更新 3:我继续在各种相关邮件列表的帖子中找到关于这个的参考资料。


我意识到这是可能的,但由于许可要求(目标是嵌入式播放器),这并不理想,我们正在尽可能保持不受限制。我意识到Adobe有一些补丁似乎还没有回到WebKit中。(在Gtk构建中支持无窗口插件是一个重要的问题)。 - Mark Renouf
5个回答

31

已解决!

通过不断的研究、搜索论坛和源代码仓库,我拼凑出了只使用libwebkit和标准的compiz桌面(任何带有合成功能的Xorg桌面都可以)来完成此操作所需的必要步骤。

对于当前的libwebkit(1.1.10-SVN),有一个Ubuntu PPA:

deb http://ppa.launchpad.net/webkit-team/ppa/ubuntu jaunty main
deb-src http://ppa.launchpad.net/webkit-team/ppa/ubuntu jaunty main

就代码而言,关键在于调用webkit_web_view_set_transparent函数。

当然,你运行它的系统应该有一张能力强大的显卡(如Intel、Radeon或NVIDIA),并且运行一个类似Compiz的组合窗口管理器。

最后,为了真正看到透明效果,你所查看的内容必须使用CSS3设置透明背景,否则它仍然完全不透明。

这很简单:

BODY { background-color: rgba(0,0,0,0); }

这里是最简单的支持透明度的 WebKit 浏览器应用程序的完整示例:

#include <gtk/gtk.h>
#include <webkit/webkit.h>

static void destroy_cb(GtkWidget* widget, gpointer data) {
  gtk_main_quit();
}

int main(int argc, char* argv[]) {
  gtk_init(&argc, &argv);

  if(!g_thread_supported())
    g_thread_init(NULL);

  // Create a Window, set colormap to RGBA
  GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  GdkScreen *screen = gtk_widget_get_screen(window);
  GdkColormap *rgba = gdk_screen_get_rgba_colormap (screen);

  if (rgba && gdk_screen_is_composited (screen)) {
    gtk_widget_set_default_colormap(rgba);
    gtk_widget_set_colormap(GTK_WIDGET(window), rgba);
  }

  gtk_window_set_default_size(GTK_WINDOW(window), 800, 800);
  g_signal_connect(window, "destroy", G_CALLBACK(destroy_cb), NULL);

  // Optional: for dashboard style borderless windows
  gtk_window_set_decorated(GTK_WINDOW(window), FALSE);


  // Create a WebView, set it transparent, add it to the window
  WebKitWebView* web_view = web_view = WEBKIT_WEB_VIEW(webkit_web_view_new());
  webkit_web_view_set_transparent(web_view, TRUE);
  gtk_container_add (GTK_CONTAINER(window), GTK_WIDGET(web_view));

  // Load a default page
  webkit_web_view_load_uri(web_view, "http://stackoverflow.com/");

  // Show it and continue running until the window closes
  gtk_widget_grab_focus(GTK_WIDGET(web_view));
  gtk_widget_show_all(window);
  gtk_main();
  return 0;
}

屏幕截图!


3
干得好。我不确定CSS3对于透明背景是否必要,我认为旧的CSS1 BODY { background-color: transparent; } 应该也能够工作。尽管我没有试过。 - Paul D. Waite
2
需要注意的是,当加载像Flash这样不支持ARGB色彩空间的插件时,应用程序会崩溃。当它们尝试通过XEmbed API(X11:BadMatch错误)绘制到屏幕上时,应用程序会崩溃。 - Mark Renouf
可能我不再继续进行这项工作了,因为我已经换了工作,也不再开发这个产品了。你可以接手它。 - Mark Renouf
1
这段代码在我的64位Arch Linux上编译通过:clang main.c -o program \pkg-config --cflags --libs gtk+-2.0 webkit-1.0``,但是当我将它指向一个本地Web服务器并加载一个带有透明背景的页面时,它显示为深灰色。 - Anko

2
在Safari 1.3和2中,有一个隐藏的调试菜单(通过终端使用命令 defaults write com.apple.Safari IncludeDebugMenu 1 来调用),其中包括一个“使用透明窗口”的选项。不确定这是WebKit还是Safari的功能。(在Safari 3中,调试菜单似乎已被“开发”菜单(在偏好设置>高级中启用)所取代,后者没有透明窗口选项。)

谢谢你的提示。这让我找对了方向。我敢打赌,当时调试菜单选项可控制对 set_transparent 函数的调用。 - Mark Renouf

1

1

基本上,您希望设置ARGB颜色空间以发送到窗口管理器。显然,只有支持合成的窗口管理器才能利用此功能。

您可能需要与screenlet和compiz开发人员交谈,他们应该能够提供更多帮助。


我同意,这只是其中的一半。但是,我如何在网页中设置背景颜色,以便最终呈现的图像不会始终是不透明的呢?是否只需设置BODY { opacity: 0; }即可? - Mark Renouf
应该是这样的,但不确定。Compiz/Screenlet团队已经实现了桌面小部件窗口的渲染。 - ewanm89
我认为他们甚至使用了Webkit(事实上,我认为除了Gecko之外,每个主要渲染引擎都已经有了桌面小部件渲染解决方案)。 - ewanm89
据我所知,screenlets都是由Python控制的直接Gtk/Cairo。我在他们的文档中找不到任何关于WebKit的参考。 - Mark Renouf
1
就网页而言,不透明度属性应用于HTML元素的内容以及其背景,因此BODY {opacity: 0;}将使您在body标记内看不见任何东西。我认为WebKit支持带有alpha透明度的颜色值,所以你可以使用 body { background-color: rgba(0,0,0,0); }。我认为背景颜色的默认值是透明的,因此您可能不需要设置它。 - Paul D. Waite
感谢您的帮助...您提供的信息是解决方案的关键部分! - Mark Renouf

1
我有一个新的解决方案,非常容易实现,适用于单个屏幕截图。它使用 node.js 和 phantom.js 库。
  1. install node.js
  2. run 'npm install -g phantomjs' in console/terminal
  3. save the following as script.js and run it from console 'phantomjs script.js'

    var page = require('webpage').create();
    page.viewportSize = { width: 1920, height: 1500 };
    page.open("http://www.theWebYouWantToRender");
    page.onLoadFinished = function(status) {
        page.evaluate(function() {
            document.body.style.background = 'transparent';
        });
    
        page.render('render.png');
        phantom.exit();
    };
    
  4. profit? :) enjoy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接