Change to the linux kernel coding style
[wmaker-crm.git] / WINGs / wwindow.c
dissimilarity index 94%
index 7e2c290..3bd0afe 100644 (file)
-
-#include <X11/Xmd.h>
-
-#include "WINGsP.h"
-
-#include <X11/Xatom.h>
-
-
-typedef struct W_Window {
-    W_Class widgetClass;
-    W_View *view;
-
-    struct W_Window *nextPtr;         /* next in the window list */
-
-    struct W_Window *owner;
-
-    char *title;
-
-    WMPixmap *miniImage;              /* miniwindow */
-    char *miniTitle;
-
-    char *wname;
-
-    WMSize resizeIncrement;
-    WMSize baseSize;
-    WMSize minSize;
-    WMSize maxSize;
-    WMPoint minAspect;
-    WMPoint maxAspect;
-
-    WMPoint upos;
-    WMPoint ppos;
-
-    WMAction *closeAction;
-    void *closeData;
-
-    int level;
-
-    struct {
-        unsigned style:4;
-        unsigned configured:1;
-        unsigned documentEdited:1;
-
-        unsigned setUPos:1;
-        unsigned setPPos:1;
-        unsigned setAspect:1;
-    } flags;
-} _Window;
-
-
-
-typedef struct {
-    CARD32 flags;
-    CARD32 window_style;
-    CARD32 window_level;
-    CARD32 reserved;
-    Pixmap miniaturize_pixmap;        /* pixmap for miniaturize button */
-    Pixmap close_pixmap;              /* pixmap for close button */
-    Pixmap miniaturize_mask;          /* miniaturize pixmap mask */
-    Pixmap close_mask;                /* close pixmap mask */
-    CARD32 extra_flags;
-} GNUstepWMAttributes;
-
-#define GSWindowStyleAttr      (1<<0)
-#define GSWindowLevelAttr      (1<<1)
-#define GSMiniaturizePixmapAttr        (1<<3)
-#define GSClosePixmapAttr      (1<<4)
-#define GSMiniaturizeMaskAttr  (1<<5)
-#define GSCloseMaskAttr                (1<<6)
-#define GSExtraFlagsAttr       (1<<7)
-
-/* extra flags */
-#define GSDocumentEditedFlag   (1<<0)
-#define GSNoApplicationIconFlag        (1<<5)
-
-#define WMFHideOtherApplications       10
-#define WMFHideApplication             12
-
-
-
-static void willResizeWindow(W_ViewDelegate *, WMView *, unsigned*, unsigned*);
-
-struct W_ViewDelegate _WindowViewDelegate = {
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    willResizeWindow
-};
-
-
-#define DEFAULT_WIDTH  400
-#define DEFAULT_HEIGHT 180
-#define DEFAULT_TITLE  ""
-
-
-static void destroyWindow(_Window *win);
-
-static void handleEvents();
-
-static void realizeWindow();
-
-static void
-realizeObserver(void *self, WMNotification *not)
-{
-    realizeWindow(self);
-}
-
-
-WMWindow*
-WMCreatePanelWithStyleForWindow(WMWindow *owner, char *name, int style)
-{
-    WMWindow *win;
-
-    win = WMCreateWindowWithStyle(owner->view->screen, name, style);
-    win->owner = owner;
-
-    return win;
-}
-
-
-
-WMWindow*
-WMCreatePanelForWindow(WMWindow *owner, char *name)
-{
-    return WMCreatePanelWithStyleForWindow(owner, name,
-                                           WMTitledWindowMask
-                                           |WMClosableWindowMask
-                                           |WMResizableWindowMask);
-}
-
-
-void
-WMChangePanelOwner(WMWindow *win, WMWindow *newOwner)
-{
-    win->owner = newOwner;
-
-    if (win->view->flags.realized && newOwner) {
-        XSetTransientForHint(win->view->screen->display, win->view->window,
-                             newOwner->view->window);
-    }
-}
-
-
-
-WMWindow*
-WMCreateWindow(WMScreen *screen, char *name)
-{
-    return WMCreateWindowWithStyle(screen, name, WMTitledWindowMask
-                                   |WMClosableWindowMask
-                                   |WMMiniaturizableWindowMask
-                                   |WMResizableWindowMask);
-}
-
-
-
-WMWindow*
-WMCreateWindowWithStyle(WMScreen *screen, char *name, int style)
-{
-    _Window *win;
-
-    win = wmalloc(sizeof(_Window));
-    memset(win, 0, sizeof(_Window));
-
-    win->widgetClass = WC_Window;
-
-    win->view = W_CreateTopView(screen);
-    if (!win->view) {
-        wfree(win);
-        return NULL;
-    }
-    win->view->self = win;
-
-    win->view->delegate = &_WindowViewDelegate;
-
-    win->wname = wstrdup(name);
-
-    /* add to the window list of the screen (application) */
-    win->nextPtr = screen->windowList;
-    screen->windowList = win;
-
-    WMCreateEventHandler(win->view, ExposureMask|StructureNotifyMask
-                         |ClientMessageMask|FocusChangeMask,
-                         handleEvents, win);
-
-    W_ResizeView(win->view, DEFAULT_WIDTH, DEFAULT_HEIGHT);
-
-    WMAddNotificationObserver(realizeObserver, win,
-                              WMViewRealizedNotification, win->view);
-
-    win->flags.style = style;
-
-    win->level = WMNormalWindowLevel;
-
-    /* kluge. Find a better solution */
-    W_SetFocusOfTopLevel(win->view, win->view);
-
-    return win;
-}
-
-
-
-static void
-setWindowTitle(WMWindow *win, const char *title)
-{
-    WMScreen *scr= win->view->screen;
-    XTextProperty property;
-    int result;
-
-    result = XmbTextListToTextProperty(scr->display,
-                                       (char**)&title, 1, XStdICCTextStyle,
-                                       &property);
-    if (result == XNoMemory || result == XLocaleNotSupported) {
-        wwarning("window title conversion error... using STRING encoding");
-        XStoreName(scr->display, win->view->window, title);
-    } else {
-        XSetWMName(scr->display, win->view->window, &property);
-        if (property.value)
-          XFree(property.value);
-    }
-
-    XChangeProperty(scr->display, win->view->window,
-                    scr->netwmName, scr->utf8String, 8,
-                    PropModeReplace, (unsigned char *)title, strlen(title));
-}
-
-
-static void
-setMiniwindowTitle(WMWindow *win, const char *title)
-{
-    WMScreen *scr= win->view->screen;
-    XTextProperty property;
-    int result;
-
-    result = XmbTextListToTextProperty(scr->display,
-                                       (char**)&title, 1, XStdICCTextStyle,
-                                       &property);
-    if (result == XNoMemory || result == XLocaleNotSupported) {
-        wwarning("icon title conversion error..using STRING encoding");
-        XSetIconName(scr->display, win->view->window, title);
-    } else {
-        XSetWMIconName(scr->display, win->view->window, &property);
-        if (property.value)
-          XFree(property.value);
-    }
-    
-    XChangeProperty(scr->display, win->view->window,
-                    scr->netwmIconName, scr->utf8String, 8,
-                    PropModeReplace, (unsigned char *)title, strlen(title));
-}
-
-
-static void
-setMiniwindow(WMWindow *win, RImage *image)
-{
-    WMScreen *scr= win->view->screen;
-    CARD32 *data;
-    int x, y;
-    int o;
-
-    if (!image)
-      return;
-
-    data = wmalloc((image->width * image->height + 2) * sizeof(CARD32));
-
-    o= 0;
-    data[o++] = image->width;
-    data[o++] = image->height;
-
-    for (y= 0; y < image->height; y++) {
-        for (x= 0; x < image->width; x++) {
-            CARD32 pixel;
-            int offs= (x+y*image->width);
-            
-            if (image->format == RRGBFormat)
-              pixel= image->data[offs*3]<<16 | image->data[offs*3+1]<<8 | image->data[offs*3+2];
-            else
-              pixel= image->data[offs*4]<<16 | image->data[offs*4+1]<<8 | image->data[offs*4+2] | image->data[offs*4+3] << 24;
-
-            data[o++]= pixel;
-        }
-    }
-
-    XChangeProperty(scr->display, win->view->window, scr->netwmIcon,
-                    XA_CARDINAL, 32, PropModeReplace,
-                    (unsigned char *)data,
-                    (image->width * image->height + 2));
-
-    wfree(data);
-}
-
-
-void
-WMSetWindowTitle(WMWindow *win, char *title)
-{
-    if (win->title!=NULL)
-        wfree(win->title);
-    if (title!=NULL)
-        win->title = wstrdup(title);
-    else
-        win->title = NULL;
-
-    if (win->view->flags.realized) {
-        setWindowTitle(win, title);
-    }
-}
-
-
-
-
-void
-WMSetWindowCloseAction(WMWindow *win, WMAction *action, void *clientData)
-{
-    Atom *atoms = NULL;
-    Atom *newAtoms;
-    int count;
-    WMScreen *scr = win->view->screen;
-
-    if (win->view->flags.realized) {
-        if (action && !win->closeAction) {
-            if (!XGetWMProtocols(scr->display, win->view->window, &atoms,
-                                 &count)) {
-                count = 0;
-            }
-            newAtoms = wmalloc((count+1)*sizeof(Atom));
-            if (count > 0)
-                memcpy(newAtoms, atoms, count*sizeof(Atom));
-            newAtoms[count++] = scr->deleteWindowAtom;
-            XSetWMProtocols(scr->display, win->view->window, newAtoms, count);
-            if (atoms)
-                XFree(atoms);
-            wfree(newAtoms);
-        } else if (!action && win->closeAction) {
-            int i, ncount;
-
-            if (XGetWMProtocols(scr->display, win->view->window, &atoms,
-                                &count) && count>0) {
-                newAtoms = wmalloc((count-1)*sizeof(Atom));
-                ncount = 0;
-                for (i=0; i < count; i++) {
-                    if (atoms[i]!=scr->deleteWindowAtom) {
-                        newAtoms[i] = atoms[i];
-                        ncount++;
-                    }
-                }
-                XSetWMProtocols(scr->display, win->view->window, newAtoms,
-                                ncount);
-                if (atoms)
-                    XFree(atoms);
-                wfree(newAtoms);
-            }
-        }
-    }
-    win->closeAction = action;
-    win->closeData = clientData;
-}
-
-
-
-static void
-willResizeWindow(W_ViewDelegate *self, WMView *view,
-                 unsigned *width, unsigned *height)
-{
-    WMWindow *win = (WMWindow*)view->self;
-
-    if (win->minSize.width > 0 && win->minSize.height > 0) {
-        if (*width < win->minSize.width)
-            *width = win->minSize.width;
-        if (*height < win->minSize.height)
-            *height = win->minSize.height;
-    }
-
-    if (win->maxSize.width > 0 && win->maxSize.height > 0) {
-        if (*width > win->maxSize.width)
-            *width = win->maxSize.width;
-        if (*height > win->maxSize.height)
-            *height = win->maxSize.height;
-    }
-}
-
-
-static void
-setSizeHints(WMWindow *win)
-{
-    XSizeHints *hints;
-
-    hints = XAllocSizeHints();
-    if (!hints) {
-        wwarning("could not allocate memory for window size hints");
-        return;
-    }
-
-    hints->flags = 0;
-
-    if (win->flags.setPPos) {
-        hints->flags |= PPosition;
-        hints->x = win->ppos.x;
-        hints->y = win->ppos.y;
-    }
-    if (win->flags.setUPos) {
-        hints->flags |= USPosition;
-        hints->x = win->upos.x;
-        hints->y = win->upos.y;
-    }
-    if (win->minSize.width>0 && win->minSize.height>0) {
-        hints->flags |= PMinSize;
-        hints->min_width = win->minSize.width;
-        hints->min_height = win->minSize.height;
-    }
-    if (win->maxSize.width>0 && win->maxSize.height>0) {
-        hints->flags |= PMaxSize;
-        hints->max_width = win->maxSize.width;
-        hints->max_height = win->maxSize.height;
-    }
-    if (win->baseSize.width>0 && win->baseSize.height>0) {
-        hints->flags |= PBaseSize;
-        hints->base_width = win->baseSize.width;
-        hints->base_height = win->baseSize.height;
-    }
-    if (win->resizeIncrement.width>0 && win->resizeIncrement.height>0) {
-        hints->flags |= PResizeInc;
-        hints->width_inc = win->resizeIncrement.width;
-        hints->height_inc = win->resizeIncrement.height;
-    }
-    if (win->flags.setAspect) {
-        hints->flags |= PAspect;
-        hints->min_aspect.x = win->minAspect.x;
-        hints->min_aspect.y = win->minAspect.y;
-        hints->max_aspect.x = win->maxAspect.x;
-        hints->max_aspect.y = win->maxAspect.y;
-    }
-
-
-    if (hints->flags) {
-        XSetWMNormalHints(win->view->screen->display, win->view->window, hints);
-    }
-    XFree(hints);
-}
-
-
-
-static void
-writeGNUstepWMAttr(WMScreen *scr, Window window, GNUstepWMAttributes *attr)
-{
-    unsigned long data[9];
-
-    /* handle idiot compilers where array of CARD32 != struct of CARD32 */
-    data[0] = attr->flags;
-    data[1] = attr->window_style;
-    data[2] = attr->window_level;
-    data[3] = 0;                      /* reserved */
-    /* The X protocol says XIDs are 32bit */
-    data[4] = attr->miniaturize_pixmap;
-    data[5] = attr->close_pixmap;
-    data[6] = attr->miniaturize_mask;
-    data[7] = attr->close_mask;
-    data[8] = attr->extra_flags;
-    XChangeProperty(scr->display, window, scr->attribsAtom, scr->attribsAtom,
-                    32, PropModeReplace,  (unsigned char *)data, 9);
-}
-
-
-static void
-setWindowMakerHints(WMWindow *win)
-{
-    GNUstepWMAttributes attribs;
-    WMScreen *scr = WMWidgetScreen(win);
-
-    memset(&attribs, 0, sizeof(GNUstepWMAttributes));
-    attribs.flags = GSWindowStyleAttr|GSWindowLevelAttr|GSExtraFlagsAttr;
-    attribs.window_style = win->flags.style;
-    attribs.window_level = win->level;
-    if (win->flags.documentEdited)
-        attribs.extra_flags = GSDocumentEditedFlag;
-    else
-        attribs.extra_flags = 0;
-
-    writeGNUstepWMAttr(scr, win->view->window, &attribs);
-}
-
-
-static void
-realizeWindow(WMWindow *win)
-{
-    XWMHints *hints;
-    XClassHint *classHint;
-    WMScreen *scr = win->view->screen;
-    Atom atoms[4];
-    int count;
-
-    classHint = XAllocClassHint();
-    classHint->res_name = win->wname;
-    classHint->res_class = WMGetApplicationName();
-    XSetClassHint(scr->display, win->view->window, classHint);
-    XFree(classHint);
-
-    hints = XAllocWMHints();
-    hints->flags = 0;
-    if (!scr->aflags.simpleApplication) {
-        hints->flags |= WindowGroupHint;
-        hints->window_group = scr->groupLeader;
-    }
-    if (win->miniImage) {
-        hints->flags |= IconPixmapHint;
-        hints->icon_pixmap = WMGetPixmapXID(win->miniImage);
-        hints->icon_mask = WMGetPixmapMaskXID(win->miniImage);
-        if (hints->icon_mask != None) {
-            hints->flags |= IconMaskHint;
-        }
-    }
-    if (hints->flags != 0)
-        XSetWMHints(scr->display, win->view->window, hints);
-    XFree(hints);
-
-    count = 0;
-    if (win->closeAction) {
-        atoms[count++] = scr->deleteWindowAtom;
-    }
-
-    if (count>0)
-        XSetWMProtocols(scr->display, win->view->window, atoms, count);
-
-    if (win->title || win->miniTitle)
-        XmbSetWMProperties(scr->display, win->view->window, win->title,
-                           win->miniTitle, NULL, 0, NULL, NULL, NULL);
-
-    setWindowMakerHints(win);
-
-    setSizeHints(win);
-
-    if (win->owner) {
-        XSetTransientForHint(scr->display, win->view->window,
-                             win->owner->view->window);
-    }
-    
-    if (win->title)
-      setWindowTitle(win, win->title);
-}
-
-
-
-void
-WMSetWindowAspectRatio(WMWindow *win, int minX, int minY,
-                       int maxX, int maxY)
-{
-    win->flags.setAspect = 1;
-    win->minAspect.x = minX;
-    win->minAspect.y = minY;
-    win->maxAspect.x = maxX;
-    win->maxAspect.y = maxY;
-    if (win->view->flags.realized)
-        setSizeHints(win);
-}
-
-
-
-void
-WMSetWindowInitialPosition(WMWindow *win, int x, int y)
-{
-    win->flags.setPPos = 1;
-    win->ppos.x = x;
-    win->ppos.y = y;
-    if (win->view->flags.realized)
-        setSizeHints(win);
-    WMMoveWidget(win, x, y);
-}
-
-
-
-void
-WMSetWindowUserPosition(WMWindow *win, int x, int y)
-{
-    win->flags.setUPos = 1;
-    win->upos.x = x;
-    win->upos.y = y;
-    if (win->view->flags.realized)
-        setSizeHints(win);
-    WMMoveWidget(win, x, y);
-}
-
-
-
-
-void
-WMSetWindowMinSize(WMWindow *win, unsigned width, unsigned height)
-{
-    win->minSize.width = width;
-    win->minSize.height = height;
-    if (win->view->flags.realized)
-        setSizeHints(win);
-}
-
-
-
-void
-WMSetWindowMaxSize(WMWindow *win, unsigned width, unsigned height)
-{
-    win->maxSize.width = width;
-    win->maxSize.height = height;
-    if (win->view->flags.realized)
-        setSizeHints(win);
-}
-
-
-void
-WMSetWindowBaseSize(WMWindow *win, unsigned width, unsigned height)
-{
-    /* TODO: validate sizes */
-    win->baseSize.width = width;
-    win->baseSize.height = height;
-    if (win->view->flags.realized)
-        setSizeHints(win);
-}
-
-
-void
-WMSetWindowResizeIncrements(WMWindow *win, unsigned wIncr, unsigned hIncr)
-{
-    win->resizeIncrement.width = wIncr;
-    win->resizeIncrement.height = hIncr;
-    if (win->view->flags.realized)
-        setSizeHints(win);
-}
-
-
-void
-WMSetWindowLevel(WMWindow *win, int level)
-{
-    win->level = level;
-    if (win->view->flags.realized)
-        setWindowMakerHints(win);
-}
-
-
-void
-WMSetWindowDocumentEdited(WMWindow *win, Bool flag)
-{
-    flag = ((flag==0) ? 0 : 1);
-    if (win->flags.documentEdited != flag) {
-        win->flags.documentEdited = flag;
-        if (win->view->flags.realized)
-            setWindowMakerHints(win);
-    }
-}
-
-
-void
-WMSetWindowMiniwindowImage(WMWindow *win, RImage *image)
-{
-    if (win->view->flags.realized)
-        setMiniwindow(win, image);
-}
-
-
-void
-WMSetWindowMiniwindowPixmap(WMWindow *win, WMPixmap *pixmap)
-{
-    if ((win->miniImage && !pixmap) || (!win->miniImage && pixmap)) {
-        if (win->miniImage)
-            WMReleasePixmap(win->miniImage);
-
-        if (pixmap)
-            win->miniImage = WMRetainPixmap(pixmap);
-        else
-            win->miniImage = NULL;
-
-        if (win->view->flags.realized) {
-            XWMHints *hints;
-
-            hints = XGetWMHints(win->view->screen->display, win->view->window);
-            if (!hints) {
-                hints = XAllocWMHints();
-                if (!hints) {
-                    wwarning("could not allocate memory for WM hints");
-                    return;
-                }
-                hints->flags = 0;
-            }
-            if (pixmap) {
-                hints->flags |= IconPixmapHint;
-                hints->icon_pixmap = WMGetPixmapXID(pixmap);
-                hints->icon_mask = WMGetPixmapMaskXID(pixmap);
-                if (hints->icon_mask != None) {
-                    hints->flags |= IconMaskHint;
-                }
-            }
-            XSetWMHints(win->view->screen->display, win->view->window, hints);
-            XFree(hints);
-        }
-    }
-}
-
-
-void
-WMSetWindowMiniwindowTitle(WMWindow *win, char *title)
-{
-    if ((win->miniTitle && !title) || (!win->miniTitle && title)
-        || (title && win->miniTitle && strcoll(title, win->miniTitle)!=0)) {
-        if (win->miniTitle)
-            wfree(win->miniTitle);
-
-        if (title)
-            win->miniTitle = wstrdup(title);
-        else
-            win->miniTitle = NULL;
-
-        if (win->view->flags.realized) {
-            setMiniwindowTitle(win, title);
-        }
-    }
-}
-
-
-void
-WMCloseWindow(WMWindow *win)
-{
-    WMUnmapWidget(win);
-    /* withdraw the window */
-    if (win->view->flags.realized)
-        XWithdrawWindow(win->view->screen->display, win->view->window,
-                        win->view->screen->screen);
-}
-
-
-static void
-handleEvents(XEvent *event, void *clientData)
-{
-    _Window *win = (_Window*)clientData;
-    W_View *view = win->view;
-
-
-    switch (event->type) {
-    case ClientMessage:
-        if (event->xclient.message_type == win->view->screen->protocolsAtom
-            && event->xclient.format == 32
-            && event->xclient.data.l[0]==win->view->screen->deleteWindowAtom) {
-
-            if (win->closeAction) {
-                (*win->closeAction)(win, win->closeData);
-            }
-        }
-        break;
-        /*
-         * was causing windows to ignore commands like closeWindow
-         * after the windows is iconized/restored or a workspace change
-         * if this is really needed, put the MapNotify portion too and
-         * fix the restack bug in wmaker
-         case UnmapNotify:
-         WMUnmapWidget(win);
-         break;
-         *
-         case MapNotify:
-         WMMapWidget(win);
-         break;
-
-         */
-    case DestroyNotify:
-        destroyWindow(win);
-        break;
-
-    case ConfigureNotify:
-        if (event->xconfigure.width != view->size.width
-            || event->xconfigure.height != view->size.height) {
-
-            view->size.width = event->xconfigure.width;
-            view->size.height = event->xconfigure.height;
-
-            if (view->flags.notifySizeChanged) {
-                WMPostNotificationName(WMViewSizeDidChangeNotification,
-                                       view, NULL);
-            }
-        }
-        if (event->xconfigure.x != view->pos.x
-            || event->xconfigure.y != view->pos.y) {
-
-            if (event->xconfigure.send_event) {
-                view->pos.x = event->xconfigure.x;
-                view->pos.y = event->xconfigure.y;
-            } else {
-                Window foo;
-
-                XTranslateCoordinates(view->screen->display,
-                                      view->window, view->screen->rootWin,
-                                      event->xconfigure.x, event->xconfigure.y,
-                                      &view->pos.x, &view->pos.y, &foo);
-            }
-        }
-        break;
-    }
-}
-
-
-
-
-static void
-destroyWindow(_Window *win)
-{
-    WMScreen *scr = win->view->screen;
-
-    WMRemoveNotificationObserver(win);
-
-    if (scr->windowList == win) {
-        scr->windowList = scr->windowList->nextPtr;
-    } else {
-        WMWindow *ptr;
-        ptr = scr->windowList;
-
-        if (ptr) {
-            while (ptr->nextPtr) {
-                if (ptr->nextPtr==win) {
-                    ptr->nextPtr = ptr->nextPtr->nextPtr;
-                    break;
-                }
-                ptr = ptr->nextPtr;
-            }
-        }
-    }
-
-    if (win->title) {
-        wfree(win->title);
-    }
-
-    if (win->miniTitle) {
-        wfree(win->miniTitle);
-    }
-
-    if (win->miniImage) {
-        WMReleasePixmap(win->miniImage);
-    }
-
-    if (win->wname)
-        wfree(win->wname);
-
-    wfree(win);
-}
-
-
+
+#include <X11/Xmd.h>
+
+#include "WINGsP.h"
+
+#include <X11/Xatom.h>
+
+typedef struct W_Window {
+       W_Class widgetClass;
+       W_View *view;
+
+       struct W_Window *nextPtr;       /* next in the window list */
+
+       struct W_Window *owner;
+
+       char *title;
+
+       WMPixmap *miniImage;    /* miniwindow */
+       char *miniTitle;
+
+       char *wname;
+
+       WMSize resizeIncrement;
+       WMSize baseSize;
+       WMSize minSize;
+       WMSize maxSize;
+       WMPoint minAspect;
+       WMPoint maxAspect;
+
+       WMPoint upos;
+       WMPoint ppos;
+
+       WMAction *closeAction;
+       void *closeData;
+
+       int level;
+
+       struct {
+               unsigned style:4;
+               unsigned configured:1;
+               unsigned documentEdited:1;
+
+               unsigned setUPos:1;
+               unsigned setPPos:1;
+               unsigned setAspect:1;
+       } flags;
+} _Window;
+
+typedef struct {
+       CARD32 flags;
+       CARD32 window_style;
+       CARD32 window_level;
+       CARD32 reserved;
+       Pixmap miniaturize_pixmap;      /* pixmap for miniaturize button */
+       Pixmap close_pixmap;    /* pixmap for close button */
+       Pixmap miniaturize_mask;        /* miniaturize pixmap mask */
+       Pixmap close_mask;      /* close pixmap mask */
+       CARD32 extra_flags;
+} GNUstepWMAttributes;
+
+#define GSWindowStyleAttr      (1<<0)
+#define GSWindowLevelAttr      (1<<1)
+#define GSMiniaturizePixmapAttr        (1<<3)
+#define GSClosePixmapAttr      (1<<4)
+#define GSMiniaturizeMaskAttr  (1<<5)
+#define GSCloseMaskAttr                (1<<6)
+#define GSExtraFlagsAttr       (1<<7)
+
+/* extra flags */
+#define GSDocumentEditedFlag   (1<<0)
+#define GSNoApplicationIconFlag        (1<<5)
+
+#define WMFHideOtherApplications       10
+#define WMFHideApplication             12
+
+static void willResizeWindow(W_ViewDelegate *, WMView *, unsigned *, unsigned *);
+
+struct W_ViewDelegate _WindowViewDelegate = {
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       willResizeWindow
+};
+
+#define DEFAULT_WIDTH  400
+#define DEFAULT_HEIGHT 180
+#define DEFAULT_TITLE  ""
+
+static void destroyWindow(_Window * win);
+
+static void handleEvents();
+
+static void realizeWindow();
+
+static void realizeObserver(void *self, WMNotification * not)
+{
+       realizeWindow(self);
+}
+
+WMWindow *WMCreatePanelWithStyleForWindow(WMWindow * owner, char *name, int style)
+{
+       WMWindow *win;
+
+       win = WMCreateWindowWithStyle(owner->view->screen, name, style);
+       win->owner = owner;
+
+       return win;
+}
+
+WMWindow *WMCreatePanelForWindow(WMWindow * owner, char *name)
+{
+       return WMCreatePanelWithStyleForWindow(owner, name,
+                                              WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
+}
+
+void WMChangePanelOwner(WMWindow * win, WMWindow * newOwner)
+{
+       win->owner = newOwner;
+
+       if (win->view->flags.realized && newOwner) {
+               XSetTransientForHint(win->view->screen->display, win->view->window, newOwner->view->window);
+       }
+}
+
+WMWindow *WMCreateWindow(WMScreen * screen, char *name)
+{
+       return WMCreateWindowWithStyle(screen, name, WMTitledWindowMask
+                                      | WMClosableWindowMask
+                                      | WMMiniaturizableWindowMask | WMResizableWindowMask);
+}
+
+WMWindow *WMCreateWindowWithStyle(WMScreen * screen, char *name, int style)
+{
+       _Window *win;
+
+       win = wmalloc(sizeof(_Window));
+       memset(win, 0, sizeof(_Window));
+
+       win->widgetClass = WC_Window;
+
+       win->view = W_CreateTopView(screen);
+       if (!win->view) {
+               wfree(win);
+               return NULL;
+       }
+       win->view->self = win;
+
+       win->view->delegate = &_WindowViewDelegate;
+
+       win->wname = wstrdup(name);
+
+       /* add to the window list of the screen (application) */
+       win->nextPtr = screen->windowList;
+       screen->windowList = win;
+
+       WMCreateEventHandler(win->view, ExposureMask | StructureNotifyMask
+                            | ClientMessageMask | FocusChangeMask, handleEvents, win);
+
+       W_ResizeView(win->view, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+
+       WMAddNotificationObserver(realizeObserver, win, WMViewRealizedNotification, win->view);
+
+       win->flags.style = style;
+
+       win->level = WMNormalWindowLevel;
+
+       /* kluge. Find a better solution */
+       W_SetFocusOfTopLevel(win->view, win->view);
+
+       return win;
+}
+
+static void setWindowTitle(WMWindow * win, const char *title)
+{
+       WMScreen *scr = win->view->screen;
+       XTextProperty property;
+       int result;
+
+       result = XmbTextListToTextProperty(scr->display, (char **)&title, 1, XStdICCTextStyle, &property);
+       if (result == XNoMemory || result == XLocaleNotSupported) {
+               wwarning("window title conversion error... using STRING encoding");
+               XStoreName(scr->display, win->view->window, title);
+       } else {
+               XSetWMName(scr->display, win->view->window, &property);
+               if (property.value)
+                       XFree(property.value);
+       }
+
+       XChangeProperty(scr->display, win->view->window,
+                       scr->netwmName, scr->utf8String, 8,
+                       PropModeReplace, (unsigned char *)title, strlen(title));
+}
+
+static void setMiniwindowTitle(WMWindow * win, const char *title)
+{
+       WMScreen *scr = win->view->screen;
+       XTextProperty property;
+       int result;
+
+       result = XmbTextListToTextProperty(scr->display, (char **)&title, 1, XStdICCTextStyle, &property);
+       if (result == XNoMemory || result == XLocaleNotSupported) {
+               wwarning("icon title conversion error..using STRING encoding");
+               XSetIconName(scr->display, win->view->window, title);
+       } else {
+               XSetWMIconName(scr->display, win->view->window, &property);
+               if (property.value)
+                       XFree(property.value);
+       }
+
+       XChangeProperty(scr->display, win->view->window,
+                       scr->netwmIconName, scr->utf8String, 8,
+                       PropModeReplace, (unsigned char *)title, strlen(title));
+}
+
+static void setMiniwindow(WMWindow * win, RImage * image)
+{
+       WMScreen *scr = win->view->screen;
+       CARD32 *data;
+       int x, y;
+       int o;
+
+       if (!image)
+               return;
+
+       data = wmalloc((image->width * image->height + 2) * sizeof(CARD32));
+
+       o = 0;
+       data[o++] = image->width;
+       data[o++] = image->height;
+
+       for (y = 0; y < image->height; y++) {
+               for (x = 0; x < image->width; x++) {
+                       CARD32 pixel;
+                       int offs = (x + y * image->width);
+
+                       if (image->format == RRGBFormat)
+                               pixel =
+                                   image->data[offs * 3] << 16 | image->data[offs * 3 +
+                                                                             1] << 8 | image->data[offs * 3 + 2];
+                       else
+                               pixel =
+                                   image->data[offs * 4] << 16 | image->data[offs * 4 +
+                                                                             1] << 8 | image->data[offs * 4 +
+                                                                                                   2] | image->
+                                   data[offs * 4 + 3] << 24;
+
+                       data[o++] = pixel;
+               }
+       }
+
+       XChangeProperty(scr->display, win->view->window, scr->netwmIcon,
+                       XA_CARDINAL, 32, PropModeReplace,
+                       (unsigned char *)data, (image->width * image->height + 2));
+
+       wfree(data);
+}
+
+void WMSetWindowTitle(WMWindow * win, char *title)
+{
+       if (win->title != NULL)
+               wfree(win->title);
+       if (title != NULL)
+               win->title = wstrdup(title);
+       else
+               win->title = NULL;
+
+       if (win->view->flags.realized) {
+               setWindowTitle(win, title);
+       }
+}
+
+void WMSetWindowCloseAction(WMWindow * win, WMAction * action, void *clientData)
+{
+       Atom *atoms = NULL;
+       Atom *newAtoms;
+       int count;
+       WMScreen *scr = win->view->screen;
+
+       if (win->view->flags.realized) {
+               if (action && !win->closeAction) {
+                       if (!XGetWMProtocols(scr->display, win->view->window, &atoms, &count)) {
+                               count = 0;
+                       }
+                       newAtoms = wmalloc((count + 1) * sizeof(Atom));
+                       if (count > 0)
+                               memcpy(newAtoms, atoms, count * sizeof(Atom));
+                       newAtoms[count++] = scr->deleteWindowAtom;
+                       XSetWMProtocols(scr->display, win->view->window, newAtoms, count);
+                       if (atoms)
+                               XFree(atoms);
+                       wfree(newAtoms);
+               } else if (!action && win->closeAction) {
+                       int i, ncount;
+
+                       if (XGetWMProtocols(scr->display, win->view->window, &atoms, &count) && count > 0) {
+                               newAtoms = wmalloc((count - 1) * sizeof(Atom));
+                               ncount = 0;
+                               for (i = 0; i < count; i++) {
+                                       if (atoms[i] != scr->deleteWindowAtom) {
+                                               newAtoms[i] = atoms[i];
+                                               ncount++;
+                                       }
+                               }
+                               XSetWMProtocols(scr->display, win->view->window, newAtoms, ncount);
+                               if (atoms)
+                                       XFree(atoms);
+                               wfree(newAtoms);
+                       }
+               }
+       }
+       win->closeAction = action;
+       win->closeData = clientData;
+}
+
+static void willResizeWindow(W_ViewDelegate * self, WMView * view, unsigned *width, unsigned *height)
+{
+       WMWindow *win = (WMWindow *) view->self;
+
+       if (win->minSize.width > 0 && win->minSize.height > 0) {
+               if (*width < win->minSize.width)
+                       *width = win->minSize.width;
+               if (*height < win->minSize.height)
+                       *height = win->minSize.height;
+       }
+
+       if (win->maxSize.width > 0 && win->maxSize.height > 0) {
+               if (*width > win->maxSize.width)
+                       *width = win->maxSize.width;
+               if (*height > win->maxSize.height)
+                       *height = win->maxSize.height;
+       }
+}
+
+static void setSizeHints(WMWindow * win)
+{
+       XSizeHints *hints;
+
+       hints = XAllocSizeHints();
+       if (!hints) {
+               wwarning("could not allocate memory for window size hints");
+               return;
+       }
+
+       hints->flags = 0;
+
+       if (win->flags.setPPos) {
+               hints->flags |= PPosition;
+               hints->x = win->ppos.x;
+               hints->y = win->ppos.y;
+       }
+       if (win->flags.setUPos) {
+               hints->flags |= USPosition;
+               hints->x = win->upos.x;
+               hints->y = win->upos.y;
+       }
+       if (win->minSize.width > 0 && win->minSize.height > 0) {
+               hints->flags |= PMinSize;
+               hints->min_width = win->minSize.width;
+               hints->min_height = win->minSize.height;
+       }
+       if (win->maxSize.width > 0 && win->maxSize.height > 0) {
+               hints->flags |= PMaxSize;
+               hints->max_width = win->maxSize.width;
+               hints->max_height = win->maxSize.height;
+       }
+       if (win->baseSize.width > 0 && win->baseSize.height > 0) {
+               hints->flags |= PBaseSize;
+               hints->base_width = win->baseSize.width;
+               hints->base_height = win->baseSize.height;
+       }
+       if (win->resizeIncrement.width > 0 && win->resizeIncrement.height > 0) {
+               hints->flags |= PResizeInc;
+               hints->width_inc = win->resizeIncrement.width;
+               hints->height_inc = win->resizeIncrement.height;
+       }
+       if (win->flags.setAspect) {
+               hints->flags |= PAspect;
+               hints->min_aspect.x = win->minAspect.x;
+               hints->min_aspect.y = win->minAspect.y;
+               hints->max_aspect.x = win->maxAspect.x;
+               hints->max_aspect.y = win->maxAspect.y;
+       }
+
+       if (hints->flags) {
+               XSetWMNormalHints(win->view->screen->display, win->view->window, hints);
+       }
+       XFree(hints);
+}
+
+static void writeGNUstepWMAttr(WMScreen * scr, Window window, GNUstepWMAttributes * attr)
+{
+       unsigned long data[9];
+
+       /* handle idiot compilers where array of CARD32 != struct of CARD32 */
+       data[0] = attr->flags;
+       data[1] = attr->window_style;
+       data[2] = attr->window_level;
+       data[3] = 0;            /* reserved */
+       /* The X protocol says XIDs are 32bit */
+       data[4] = attr->miniaturize_pixmap;
+       data[5] = attr->close_pixmap;
+       data[6] = attr->miniaturize_mask;
+       data[7] = attr->close_mask;
+       data[8] = attr->extra_flags;
+       XChangeProperty(scr->display, window, scr->attribsAtom, scr->attribsAtom,
+                       32, PropModeReplace, (unsigned char *)data, 9);
+}
+
+static void setWindowMakerHints(WMWindow * win)
+{
+       GNUstepWMAttributes attribs;
+       WMScreen *scr = WMWidgetScreen(win);
+
+       memset(&attribs, 0, sizeof(GNUstepWMAttributes));
+       attribs.flags = GSWindowStyleAttr | GSWindowLevelAttr | GSExtraFlagsAttr;
+       attribs.window_style = win->flags.style;
+       attribs.window_level = win->level;
+       if (win->flags.documentEdited)
+               attribs.extra_flags = GSDocumentEditedFlag;
+       else
+               attribs.extra_flags = 0;
+
+       writeGNUstepWMAttr(scr, win->view->window, &attribs);
+}
+
+static void realizeWindow(WMWindow * win)
+{
+       XWMHints *hints;
+       XClassHint *classHint;
+       WMScreen *scr = win->view->screen;
+       Atom atoms[4];
+       int count;
+
+       classHint = XAllocClassHint();
+       classHint->res_name = win->wname;
+       classHint->res_class = WMGetApplicationName();
+       XSetClassHint(scr->display, win->view->window, classHint);
+       XFree(classHint);
+
+       hints = XAllocWMHints();
+       hints->flags = 0;
+       if (!scr->aflags.simpleApplication) {
+               hints->flags |= WindowGroupHint;
+               hints->window_group = scr->groupLeader;
+       }
+       if (win->miniImage) {
+               hints->flags |= IconPixmapHint;
+               hints->icon_pixmap = WMGetPixmapXID(win->miniImage);
+               hints->icon_mask = WMGetPixmapMaskXID(win->miniImage);
+               if (hints->icon_mask != None) {
+                       hints->flags |= IconMaskHint;
+               }
+       }
+       if (hints->flags != 0)
+               XSetWMHints(scr->display, win->view->window, hints);
+       XFree(hints);
+
+       count = 0;
+       if (win->closeAction) {
+               atoms[count++] = scr->deleteWindowAtom;
+       }
+
+       if (count > 0)
+               XSetWMProtocols(scr->display, win->view->window, atoms, count);
+
+       if (win->title || win->miniTitle)
+               XmbSetWMProperties(scr->display, win->view->window, win->title,
+                                  win->miniTitle, NULL, 0, NULL, NULL, NULL);
+
+       setWindowMakerHints(win);
+
+       setSizeHints(win);
+
+       if (win->owner) {
+               XSetTransientForHint(scr->display, win->view->window, win->owner->view->window);
+       }
+
+       if (win->title)
+               setWindowTitle(win, win->title);
+}
+
+void WMSetWindowAspectRatio(WMWindow * win, int minX, int minY, int maxX, int maxY)
+{
+       win->flags.setAspect = 1;
+       win->minAspect.x = minX;
+       win->minAspect.y = minY;
+       win->maxAspect.x = maxX;
+       win->maxAspect.y = maxY;
+       if (win->view->flags.realized)
+               setSizeHints(win);
+}
+
+void WMSetWindowInitialPosition(WMWindow * win, int x, int y)
+{
+       win->flags.setPPos = 1;
+       win->ppos.x = x;
+       win->ppos.y = y;
+       if (win->view->flags.realized)
+               setSizeHints(win);
+       WMMoveWidget(win, x, y);
+}
+
+void WMSetWindowUserPosition(WMWindow * win, int x, int y)
+{
+       win->flags.setUPos = 1;
+       win->upos.x = x;
+       win->upos.y = y;
+       if (win->view->flags.realized)
+               setSizeHints(win);
+       WMMoveWidget(win, x, y);
+}
+
+void WMSetWindowMinSize(WMWindow * win, unsigned width, unsigned height)
+{
+       win->minSize.width = width;
+       win->minSize.height = height;
+       if (win->view->flags.realized)
+               setSizeHints(win);
+}
+
+void WMSetWindowMaxSize(WMWindow * win, unsigned width, unsigned height)
+{
+       win->maxSize.width = width;
+       win->maxSize.height = height;
+       if (win->view->flags.realized)
+               setSizeHints(win);
+}
+
+void WMSetWindowBaseSize(WMWindow * win, unsigned width, unsigned height)
+{
+       /* TODO: validate sizes */
+       win->baseSize.width = width;
+       win->baseSize.height = height;
+       if (win->view->flags.realized)
+               setSizeHints(win);
+}
+
+void WMSetWindowResizeIncrements(WMWindow * win, unsigned wIncr, unsigned hIncr)
+{
+       win->resizeIncrement.width = wIncr;
+       win->resizeIncrement.height = hIncr;
+       if (win->view->flags.realized)
+               setSizeHints(win);
+}
+
+void WMSetWindowLevel(WMWindow * win, int level)
+{
+       win->level = level;
+       if (win->view->flags.realized)
+               setWindowMakerHints(win);
+}
+
+void WMSetWindowDocumentEdited(WMWindow * win, Bool flag)
+{
+       flag = ((flag == 0) ? 0 : 1);
+       if (win->flags.documentEdited != flag) {
+               win->flags.documentEdited = flag;
+               if (win->view->flags.realized)
+                       setWindowMakerHints(win);
+       }
+}
+
+void WMSetWindowMiniwindowImage(WMWindow * win, RImage * image)
+{
+       if (win->view->flags.realized)
+               setMiniwindow(win, image);
+}
+
+void WMSetWindowMiniwindowPixmap(WMWindow * win, WMPixmap * pixmap)
+{
+       if ((win->miniImage && !pixmap) || (!win->miniImage && pixmap)) {
+               if (win->miniImage)
+                       WMReleasePixmap(win->miniImage);
+
+               if (pixmap)
+                       win->miniImage = WMRetainPixmap(pixmap);
+               else
+                       win->miniImage = NULL;
+
+               if (win->view->flags.realized) {
+                       XWMHints *hints;
+
+                       hints = XGetWMHints(win->view->screen->display, win->view->window);
+                       if (!hints) {
+                               hints = XAllocWMHints();
+                               if (!hints) {
+                                       wwarning("could not allocate memory for WM hints");
+                                       return;
+                               }
+                               hints->flags = 0;
+                       }
+                       if (pixmap) {
+                               hints->flags |= IconPixmapHint;
+                               hints->icon_pixmap = WMGetPixmapXID(pixmap);
+                               hints->icon_mask = WMGetPixmapMaskXID(pixmap);
+                               if (hints->icon_mask != None) {
+                                       hints->flags |= IconMaskHint;
+                               }
+                       }
+                       XSetWMHints(win->view->screen->display, win->view->window, hints);
+                       XFree(hints);
+               }
+       }
+}
+
+void WMSetWindowMiniwindowTitle(WMWindow * win, char *title)
+{
+       if ((win->miniTitle && !title) || (!win->miniTitle && title)
+           || (title && win->miniTitle && strcoll(title, win->miniTitle) != 0)) {
+               if (win->miniTitle)
+                       wfree(win->miniTitle);
+
+               if (title)
+                       win->miniTitle = wstrdup(title);
+               else
+                       win->miniTitle = NULL;
+
+               if (win->view->flags.realized) {
+                       setMiniwindowTitle(win, title);
+               }
+       }
+}
+
+void WMCloseWindow(WMWindow * win)
+{
+       WMUnmapWidget(win);
+       /* withdraw the window */
+       if (win->view->flags.realized)
+               XWithdrawWindow(win->view->screen->display, win->view->window, win->view->screen->screen);
+}
+
+static void handleEvents(XEvent * event, void *clientData)
+{
+       _Window *win = (_Window *) clientData;
+       W_View *view = win->view;
+
+       switch (event->type) {
+       case ClientMessage:
+               if (event->xclient.message_type == win->view->screen->protocolsAtom
+                   && event->xclient.format == 32
+                   && event->xclient.data.l[0] == win->view->screen->deleteWindowAtom) {
+
+                       if (win->closeAction) {
+                               (*win->closeAction) (win, win->closeData);
+                       }
+               }
+               break;
+               /*
+                * was causing windows to ignore commands like closeWindow
+                * after the windows is iconized/restored or a workspace change
+                * if this is really needed, put the MapNotify portion too and
+                * fix the restack bug in wmaker
+                case UnmapNotify:
+                WMUnmapWidget(win);
+                break;
+                *
+                case MapNotify:
+                WMMapWidget(win);
+                break;
+
+                */
+       case DestroyNotify:
+               destroyWindow(win);
+               break;
+
+       case ConfigureNotify:
+               if (event->xconfigure.width != view->size.width || event->xconfigure.height != view->size.height) {
+
+                       view->size.width = event->xconfigure.width;
+                       view->size.height = event->xconfigure.height;
+
+                       if (view->flags.notifySizeChanged) {
+                               WMPostNotificationName(WMViewSizeDidChangeNotification, view, NULL);
+                       }
+               }
+               if (event->xconfigure.x != view->pos.x || event->xconfigure.y != view->pos.y) {
+
+                       if (event->xconfigure.send_event) {
+                               view->pos.x = event->xconfigure.x;
+                               view->pos.y = event->xconfigure.y;
+                       } else {
+                               Window foo;
+
+                               XTranslateCoordinates(view->screen->display,
+                                                     view->window, view->screen->rootWin,
+                                                     event->xconfigure.x, event->xconfigure.y,
+                                                     &view->pos.x, &view->pos.y, &foo);
+                       }
+               }
+               break;
+       }
+}
+
+static void destroyWindow(_Window * win)
+{
+       WMScreen *scr = win->view->screen;
+
+       WMRemoveNotificationObserver(win);
+
+       if (scr->windowList == win) {
+               scr->windowList = scr->windowList->nextPtr;
+       } else {
+               WMWindow *ptr;
+               ptr = scr->windowList;
+
+               if (ptr) {
+                       while (ptr->nextPtr) {
+                               if (ptr->nextPtr == win) {
+                                       ptr->nextPtr = ptr->nextPtr->nextPtr;
+                                       break;
+                               }
+                               ptr = ptr->nextPtr;
+                       }
+               }
+       }
+
+       if (win->title) {
+               wfree(win->title);
+       }
+
+       if (win->miniTitle) {
+               wfree(win->miniTitle);
+       }
+
+       if (win->miniImage) {
+               WMReleasePixmap(win->miniImage);
+       }
+
+       if (win->wname)
+               wfree(win->wname);
+
+       wfree(win);
+}