1 /* 2 gcc -lX11 xtopmost.c 3 */ 4 #include <X11/X.h> 5 #include <X11/Xlib.h> 6 #include <X11/Xutil.h> 7 8 #include <stdlib.h> 9 #include <string.h> 10 #include <stdio.h> 11 12 #define _NET_WM_STATE_REMOVE 0 13 #define _NET_WM_STATE_ADD 1 14 #define _NET_WM_STATE_TOGGLE 2 15 16 Bool set_always_on_top(Display *dpy, Window wnd) 17 { 18 Atom wmStateAbove, wmNetWmState; 19 XClientMessageEvent xclient; 20 21 wmStateAbove = XInternAtom(dpy, "_NET_WM_STATE_ABOVE", 1); 22 if (wmStateAbove == None) 23 goto fail_above; 24 25 wmNetWmState = XInternAtom(dpy, "_NET_WM_STATE", 1); 26 if (wmNetWmState == None) 27 goto fail_state; 28 29 memset(&xclient, 0, sizeof(xclient)); 30 xclient.type = ClientMessage; 31 xclient.window = wnd; 32 xclient.message_type = wmNetWmState; 33 xclient.format = 32; 34 xclient.data.l[0] = _NET_WM_STATE_ADD; 35 xclient.data.l[1] = wmStateAbove; 36 37 XSendEvent(dpy, DefaultRootWindow(dpy), False, 38 SubstructureRedirectMask | SubstructureNotifyMask, 39 (XEvent *)&xclient); 40 41 XFlush(dpy); 42 return True; 43 fail_above: 44 fputs("cannot find _NET_WM_STATE_ABOVE atom\n", stderr); 45 return False; 46 fail_state: 47 fputs("cannot find _NET_WM_STATE atom\n", stderr); 48 return False; 49 } 50 51 int main(void) 52 { 53 int run = 1, status = EXIT_FAILURE; 54 Atom atom_wm_delete; 55 Display* dpy; 56 Window wnd; 57 XEvent e; 58 59 /* open a conenction to the display server */ 60 dpy = XOpenDisplay(NULL); 61 if (!dpy) { 62 fputs("cannot open display!\n", stderr); 63 return EXIT_FAILURE; 64 } 65 66 atom_wm_delete = XInternAtom(dpy, "WM_DELETE_WINDOW", True); 67 if (atom_wm_delete == None) { 68 fputs("cannot find WM_DELETE_WINDOW atom\n", stderr); 69 return EXIT_FAILURE; 70 } 71 72 /* create window */ 73 wnd = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 74 0, 0, 200, 100, 0, 0, 0); 75 if (!wnd) { 76 fputs("cannot create window!\n", stderr); 77 goto outdpy; 78 } 79 80 XSelectInput(dpy, wnd, ExposureMask | StructureNotifyMask); 81 XSetWMProtocols(dpy, wnd, &atom_wm_delete, 1); 82 XFlush(dpy); 83 84 XStoreName(dpy, wnd, "Always on top!"); 85 XMapWindow(dpy, wnd); 86 87 /* in this function, we set the window manager hint */ 88 set_always_on_top(dpy, wnd); 89 90 /* event loop */ 91 while (run) { 92 XNextEvent(dpy, &e); 93 94 switch (e.type) { 95 case Expose: 96 XClearWindow(dpy, e.xany.window); 97 XFlush(dpy); 98 break; 99 case ClientMessage: 100 if (e.xclient.data.l[0] == (long)atom_wm_delete) { 101 XUnmapWindow(dpy, wnd); 102 run = 0; 103 } 104 break; 105 } 106 } 107 108 /* cleanup */ 109 status = EXIT_SUCCESS; 110 XDestroyWindow(dpy, wnd); 111 outdpy: 112 XCloseDisplay(dpy); 113 return status; 114 }