2012-01-30 56 views
13

Tôi đang cố gắng tạo một ứng dụng Linux - một trình bảo vệ màn hình, trong trường hợp này - và nó đang chứng minh đáng kể khó tìm thông tin về tác vụ đơn giản làm cửa sổ toàn màn hình. Ngay cả mã của các trình bảo vệ màn hình hiện tại cũng không đề cập đến cách họ quản lý nó, và tôi chưa thấy bất kỳ chức năng rõ ràng nào như XRemoveDecoration().X11/GLX - Chế độ toàn màn hình?

Sau nhiều dò dẫm xung quanh, tôi đã quản lý để tạo ra một cửa sổ đó là kích thước tương tự như máy tính để bàn, với điều này:

Window win = DefaultRootWindow(disp); 
XWindowAttributes getWinAttr; 
XGetWindowAttributes(disp, win, &getWinAttr); 
win = XCreateWindow(disp, win, 0, 0, getWinAttr.width, getWinAttr.height, 0, vInfo->depth, InputOutput, vInfo->visual, CWBorderPixel|CWColormap|CWEventMask|CWOverrideRedirect, &winAttr); 

Nhưng điều đó không làm bất cứ điều gì để thoát khỏi thanh tiêu đề và biên giới. Tôi biết có một cách, rõ ràng - nhưng tôi vẫn chưa tìm thấy bất cứ điều gì thậm chí chỉ theo hướng đó mà không dựa vào một số thư viện lớn khác đang được ném trên đầu trang (mà bảo vệ màn hình hiện có chắc chắn không sử dụng).

EDIT: Vui lòng không xóa thông tin khỏi bài đăng của tôi. Có một lý do rất tốt là tôi đã chỉ ra một cách rõ ràng rằng các trình bảo vệ màn hình hiện tại không sử dụng các thư viện tùy chọn, và đó là vì tôi đã phân tích mã nguồn cho hầu hết ngày hôm qua.

Tôi đã chọn câu trả lời mà hầu hết trả lời trực tiếp câu hỏi và áp dụng cho các ứng dụng nói chung.

Nếu bạn đã tìm thấy câu hỏi này nghiên cứu xscreensavers ... vẫn áp dụng tương tự. Có, xscreensaver có API riêng của nó - đó là phức tạp, và thực sự liên quan đến việc viết nhiều dòng mã hơn (vâng, nghiêm túc). Nếu bạn muốn OpenGL trong trình bảo vệ màn hình của mình, bạn sẽ cần phải trải qua một API khác là (xlockmore, một hệ thống cạnh tranh) và một lớp tương thích dịch nó sang xscreensaver.

Tuy nhiên, xscreensaver có thể chạy bất kỳ chương trình nào có thể sử dụng cửa sổ gốc ảo (xem vroot.h) làm trình bảo vệ màn hình. Vì vậy, lời khuyên của tôi là chỉ làm điều đó - bạn sẽ có nhiều quyền kiểm soát hơn, không giới hạn API và tính di động lớn hơn. (Một ví dụ Tôi nhìn thậm chí có thể biên dịch cho Linux hoặc Windows, với cùng một tập tin!)

+2

+1 cho rõ ràng là đã thực hiện một số nghiên cứu. – Flexo

Trả lời

10

Một cách là bỏ qua người quản lý cửa sổ:

XSetWindowAttributes wa;              
wa.override_redirect = True;           
XCreateWindow(..., &wa); 
+0

Bạn có thể muốn GrabKeyboard với tính năng này để nhận các sự kiện chính. – eile

+3

Điều đó ... thực sự hoạt động. Đang cố gắng để theo dõi các bước của bạn, tôi vẫn thấy thực tế không có tài nguyên liên quan đến việc sử dụng chuyển đổi đó, và không ai trong số các X Screensaver dường như có nó ... nhưng bởi jove, nó thực sự hoạt động! – DigitalMan

1

tôi thấy freeglut toàn màn hình hoạt động tốt, ngay cả khi lưu trữ shader dựa trên ứng dụng opengl bên trong. Ở đây mã nội bộ được gọi (nhánh X11 ...). HTH

#define _NET_WM_STATE_TOGGLE 2 
static int fghResizeFullscrToggle(void) 
{ 
    XWindowAttributes attributes; 

    if(glutGet(GLUT_FULL_SCREEN)) { 
     /* restore original window size */ 
     SFG_Window *win = fgStructure.CurrentWindow; 
     fgStructure.CurrentWindow->State.NeedToResize = GL_TRUE; 
     fgStructure.CurrentWindow->State.Width = win->State.OldWidth; 
     fgStructure.CurrentWindow->State.Height = win->State.OldHeight; 

    } else { 
     /* resize the window to cover the entire screen */ 
     XGetWindowAttributes(fgDisplay.Display, 
       fgStructure.CurrentWindow->Window.Handle, 
       &attributes); 

     /* 
     * The "x" and "y" members of "attributes" are the window's coordinates 
     * relative to its parent, i.e. to the decoration window. 
     */ 
     XMoveResizeWindow(fgDisplay.Display, 
       fgStructure.CurrentWindow->Window.Handle, 
       -attributes.x, 
       -attributes.y, 
       fgDisplay.ScreenWidth, 
       fgDisplay.ScreenHeight); 
    } 
    return 0; 
} 

static int fghEwmhFullscrToggle(void) 
{ 
    XEvent xev; 
    long evmask = SubstructureRedirectMask | SubstructureNotifyMask; 

    if(!fgDisplay.State || !fgDisplay.StateFullScreen) { 
     return -1; 
    } 

    xev.type = ClientMessage; 
    xev.xclient.window = fgStructure.CurrentWindow->Window.Handle; 
    xev.xclient.message_type = fgDisplay.State; 
    xev.xclient.format = 32; 
    xev.xclient.data.l[0] = _NET_WM_STATE_TOGGLE; 
    xev.xclient.data.l[1] = fgDisplay.StateFullScreen; 
    xev.xclient.data.l[2] = 0; /* no second property to toggle */ 
    xev.xclient.data.l[3] = 1; /* source indication: application */ 
    xev.xclient.data.l[4] = 0; /* unused */ 

    if(!XSendEvent(fgDisplay.Display, fgDisplay.RootWindow, 0, evmask, &xev)) { 
     return -1; 
    } 
    return 0; 
} 

static int fghToggleFullscreen(void) 
{ 
    /* first try the EWMH (_NET_WM_STATE) method ... */ 
    if(fghEwmhFullscrToggle() != -1) { 
     return 0; 
    } 

    /* fall back to resizing the window */ 
    if(fghResizeFullscrToggle() != -1) { 
     return 0; 
    } 
    return -1; 
} 


#endif /* TARGET_HOST_POSIX_X11 */ 
1

Cố gắng nhìn vào điều này cho một ví dụ:

Cảng Screensaver Thật Slick để GLX http://rss-glx.sourceforge.net/

Nhìn vào CreateWindow() chức năng trong driver.c.

+0

Thật không may, điều đó dường như không khác nhiều so với những gì tôi đã thử (và thiếu override_redirect đã kết thúc hoạt động), và bằng cách nào đó dường như thậm chí còn ít bình luận về những gì đang xảy ra hơn bình thường. – DigitalMan

+0

@DigitalMan Đọc INSTALL.xscreensaver. Ngoài ra, hãy kiểm tra Câu hỏi thường gặp này http://www.jwz.org/xscreensaver/faq.html#popup-windows. Giống như datenwolf đăng nó âm thanh như bạn đang tạo ra ứng dụng toàn màn hình của riêng bạn thay vì cắm vào màn hình tiết kiệm deamon. – Fred

1

Hoàn toàn không khó. Bạn chỉ cần thêm nguyên tử phù hợp vào danh sách bên phải như được mô tả here.

2

Thông tin bạn thiếu là các trình bảo vệ màn hình không chịu trách nhiệm về chế độ toàn màn hình. Trình bảo vệ màn hình sẽ quản lý cửa sổ bảo vệ màn hình, đặt nó vào lớp cửa sổ bảo vệ màn hình chuyên dụng và làm cho nó toàn màn hình.

Vì vậy, để viết trình bảo vệ màn hình, bạn đã rõ ràng.Nếu bạn đã viết về một trò chơi toàn màn hình, bạn phải đặt thuộc tính Chuyển hướng Ghi đè để ngăn cửa sổ bị quản lý bởi WM và làm cho nó che phủ toàn bộ màn hình.

+0

Điều đó có vẻ là trường hợp trong các mô-đun xscreensaver mặc định, có, nhưng các tiện ích OpenGL dường như phổ biến được tạo ra các cửa sổ riêng của họ. – DigitalMan

+0

@DigitalMan: Tạo cửa sổ! = Quản lý cửa sổ. Hiệu quả trình tiện ích xscreensaver hoạt động giống như trình quản lý cửa sổ, nhưng chỉ dành cho cửa sổ trình bảo vệ màn hình. Tiện ích mở rộng X-Screensaver tuyên bố một cửa sổ gốc sắp xếp bổ sung, luôn ở trên cùng của tất cả các cửa sổ khác và trình bảo vệ màn hình có trách nhiệm di chuyển cửa sổ chương trình hiệu ứng ở đó. – datenwolf

1

Cách tốt nhất và dễ dàng hơn để đạt được điều này là sử dụng Đặc điểm kỹ thuật ICCCM atom sẽ hoạt động với hầu hết các Trình quản lý cửa sổ gần đây nhất. Chỉ cần sử dụng mã sau:

Atom wm_state = XInternAtom (display, "_NET_WM_STATE", true); 
Atom wm_fullscreen = XInternAtom (display, "_NET_WM_STATE_FULLSCREEN", true); 

XChangeProperty(display, window, wm_state, XA_ATOM, 32, 
       PropModeReplace, (unsigned char *)&wm_fullscreen, 1); 

Cửa sổ của bạn có thể trong suốt, nếu có, chỉ cần sử dụng chức năng XSetBackground() nơi bạn cần và thực hiện.

Các vấn đề liên quan