客戶間通訊協定手冊

計算技術中,客戶間通訊協定手冊(Inter-Client Communication Conventions Manual:縮寫為ICCCMI39L即「I, 39個字母, L」)[1]X Window系統的標準協定。它規定有一個共同的X伺服器客戶間的通訊。它主要用於在視窗管理員和X伺服器的其他客戶之間的通訊。

歷史

編輯

它由MIT X聯盟David S. H. Rosenthal英語David S. H. Rosenthal在1988年設計,其版本1.0發行於1989年7月而版本2.0發行於1994年早期。

背景

編輯

X刻意的規定窗口互動的「機制而非政策」。因此,客戶互操作需要超出X協定自身的額外規定。

特徵

編輯

ICCCM規定剪下和貼上緩衝區,視窗管理員互動,對談任務管理,如何操縱共用資源和如何管理裝置顏色。這些底層功能一般實現在部件工具箱桌面環境之內。這把應用編程者隔離於直接與ICCCM自身打交道,因為這些功能被委託給了實現工具箱。

批評

編輯

ICCCM聲名狼藉於有歧義和難於正確實現[2]。進而有些部分被廢除或不再實踐上去實現[3]

針對目前需要而更新和澄清ICCCM的努力導致了擴充視窗管理員提示(EWMH),它獲得了相當廣泛接受並隨着需要出現而被持續擴充。

視窗管理員的基本工作原理

編輯

下面以Nick Welch寫的極小化的視窗管理員TinyWM[4]的原始碼,展示視窗管理員的基本工作原理,它做四件基本工作:通過Alt+Button1(滑鼠左鍵)拖動來互動式的移動(move)窗口,通過Alt+Button3(滑鼠右鍵)拖動來互動式的調整大小(resize)窗口,通過Alt+F1來前置(raise)窗口,通過滑鼠指標來聚焦(focus)窗口。

/* TinyWM is written by Nick Welch <mack@incise.org>, 2005.
 *
 * This software is in the public domain
 * and is provided AS IS, with NO WARRANTY. */

#include <X11/Xlib.h>

#define MAX(a, b) ((a) > (b) ? (a) : (b))

int main()
{
    Display * dpy;
    Window root;
    XWindowAttributes attr;
    XButtonEvent start;
    XEvent ev;

    if(!(dpy = XOpenDisplay(0x0))) return 1;

    root = DefaultRootWindow(dpy);

    XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("F1")), Mod1Mask, root,
            True, GrabModeAsync, GrabModeAsync);
    XGrabButton(dpy, 1, Mod1Mask, root, True, ButtonPressMask, GrabModeAsync,
            GrabModeAsync, None, None);
    XGrabButton(dpy, 3, Mod1Mask, root, True, ButtonPressMask, GrabModeAsync,
            GrabModeAsync, None, None);

    for(;;)
    {
        XNextEvent(dpy, &ev);
        if(ev.type == KeyPress && ev.xkey.subwindow != None)
            XRaiseWindow(dpy, ev.xkey.subwindow);
        else if(ev.type == ButtonPress && ev.xbutton.subwindow != None)
        {
            XGrabPointer(dpy, ev.xbutton.subwindow, True,
                    PointerMotionMask|ButtonReleaseMask, GrabModeAsync,
                    GrabModeAsync, None, None, CurrentTime);
            XGetWindowAttributes(dpy, ev.xbutton.subwindow, &attr);
            start = ev.xbutton;
        }
        else if(ev.type == MotionNotify)
        {
            int xdiff, ydiff;
            while(XCheckTypedEvent(dpy, MotionNotify, &ev));
            xdiff = ev.xbutton.x_root - start.x_root;
            ydiff = ev.xbutton.y_root - start.y_root;
            XMoveResizeWindow(dpy, ev.xmotion.window,
                attr.x + (start.button==1 ? xdiff : 0),
                attr.y + (start.button==1 ? ydiff : 0),
                MAX(1, attr.width + (start.button==3 ? xdiff : 0)),
                MAX(1, attr.height + (start.button==3 ? ydiff : 0)));
        }
        else if(ev.type == ButtonRelease)
            XUngrabPointer(dpy, CurrentTime);
    }
}

參照

編輯

外部連結

編輯