如何使窗户始终处于顶部



我创建了一个无框架的Qt/QML窗口,我真的很想知道设置其";始终在顶部";系统菜单标志。点击ALT+SPACE我可以调出无框窗口的系统菜单;始终在顶部";选项,窗口确实始终处于顶部,但我还没有找到一种程序化的方法来做到这一点。Qt.WindowStaysOnTopHint不工作,尝试wmctrl -r "window name" -b add,above也不工作,即使wmctrl适用于其他窗口。wmctrl不适用于我感兴趣的窗口显然与wmctrl -l:上机器名称列的N/A有关

francisco@Ubuntu:~$ wmctrl -l
0x02600006  0 Ubuntu Área de trabalho
0x03c00002  0 Ubuntu XdndCollectionWindowImp
0x03c00005  0 Ubuntu unity-launcher
0x03c00008  0 Ubuntu unity-panel
0x03c0000b  0 Ubuntu unity-dash
0x03c0000c  0 Ubuntu Hud
0x046000b3  0 Ubuntu How to make a window aways on top? - Stack Overflow - Mozilla Firefox
0x0520000b  0    N/A Qt Creator
0x05002396  0 Ubuntu francisco@Ubuntu: ~
0x0540000b  0    N/A backlight

我也经历了这个过程,但对于用户的询问,它对我也不起作用,同样的行为。设置了_NET_WM_STATE_ABOVE,但聚焦窗口,然后再次检查标志,它不再存在,只有在点击系统菜单时才有粘性。

这就是QML:https://gist.github.com/oblitum/8050586

相关askubuntu问题:https://askubuntu.com/questions/394998

编辑

通知

在相关的askubuntu问题中,我们发现wmctrl上应该有一个错误,因为它通过某些窗口的名称来定位它们。使用wmctrl -i -r <window id> -b add,above也解决了这个问题。

EWMH规范明确规定:

_NET_WM_STATE_BOVE和_NET_WM.STATE_BELOW主要用于用户偏好,应用程序不应使用,例如用于引起对其对话框的注意(在这种情况下应使用紧急提示,请参阅"紧急性"一节)。

因此,窗口管理器没有责任尊重那些直接(即通过XChangeProperty)设置此属性的应用程序。只有通过向根窗口发送客户端消息才能更改此属性哪个窗口管理器监听。

我不知道如何在像Qt这样的高级gui工具包中做到这一点,但下面是如何在普通X11中做到的。(有关示例实现,请参阅EWMH规范或_wnck_change_state)。

//file: test.c
//to build it, run
//shell> gcc test.c -lX11
#include <X11/Xlib.h>   
#define _NET_WM_STATE_REMOVE        0    /* remove/unset property */
#define _NET_WM_STATE_ADD           1    /* add/set property */
#define _NET_WM_STATE_TOGGLE        2    /* toggle property  */

// change a window's _NET_WM_STATE property so that it can be kept on top.
// @display: x11 display singleton.
// @xid    : the window to set on top.
Status x11_window_set_on_top (Display* display, Window xid)
{
XEvent event;
event.xclient.type = ClientMessage;
event.xclient.serial = 0;
event.xclient.send_event = True;
event.xclient.display = display;
event.xclient.window  = xid;
event.xclient.message_type = XInternAtom (display, "_NET_WM_STATE", False);
event.xclient.format = 32;
event.xclient.data.l[0] = _NET_WM_STATE_ADD;
event.xclient.data.l[1] = XInternAtom (display, "_NET_WM_STATE_ABOVE", False);
event.xclient.data.l[2] = 0; //unused.
event.xclient.data.l[3] = 0;
event.xclient.data.l[4] = 0;
return XSendEvent (display, DefaultRootWindow(display), False,
SubstructureRedirectMask|SubstructureNotifyMask, &event);
}
// a sample main function for testing.
// shell> ./a.out window_xid
int main (int argc, char** argv)
{
Window xid = strtol (argv[1], NULL, 0); 
Display* display = XOpenDisplay (NULL);
x11_window_set_on_top (display, xid);
XFlush (display); //for simplicity, no event loops here.
XCloseDisplay (display);
}

还要注意的是,在某些x11环境(例如compiz)中,系统菜单是由单独的decorator程序提供的,而不是由合成窗口管理器提供的。

在Go中,这就是你的做法:

import (
"github.com/BurntSushi/xgb"
"github.com/BurntSushi/xgb/xproto"
)
func (window *Window) AlwaysOnTop() {
xid := xproto.Window(window.WinId())
X, err := xgb.NewConn()
if err != nil {
log.Println(err)
return
}
defer X.Close()
state, err := xproto.InternAtom(X, false, uint16(len("_NET_WM_STATE")),
"_NET_WM_STATE").Reply()
if err != nil {
log.Println(err)
return
}
stateAbove, err := xproto.InternAtom(X, false,
uint16(len("_NET_WM_STATE_ABOVE")), "_NET_WM_STATE_ABOVE").Reply()
if err != nil {
log.Println(err)
return
}
evt := xproto.ClientMessageEvent{
Window: xid,
Format: 32,
Type:   state.Atom,
Data: xproto.ClientMessageDataUnionData32New([]uint32{
_NET_WM_STATE_ADD,
uint32(stateAbove.Atom),
0,
0,
0,
}),
}
err = xproto.SendEventChecked(X, false, xproto.Setup(X).DefaultScreen(X).Root,
xproto.EventMaskSubstructureRedirect|xproto.EventMaskSubstructureNotify,
string(evt.Bytes())).Check()
if err != nil {
log.Println(err)
}
}

其中CCD_ 9是窗口的本地X11句柄。

当您试图通过菜单选项将QML视图启动到"始终在顶部"模式时,我希望我能正确理解问题。

我在windows上尝试了以下代码,并将其输入到我的main中,它使我能够始终在顶部显示窗口,所以我相信视图对象也可以从菜单选项中更改。

QApplication app(argc, argv);
QDeclarativeView viewer;
**viewer.setWindowFlags(Qt::WindowStaysOnTopHint);**
viewer.setSource(QUrl::fromLocalFile("TestView.qml"));
viewer.showNormal();
return app.exec();

谢谢,泽山

最新更新