/* $Id: props.c,v 1.1 2004/08/28 19:25:46 dannybackx Exp $ */ /*****************************************************************************/ /** Copyright 1988 by Evans & Sutherland Computer Corporation, **/ /** Salt Lake City, Utah **/ /** Portions Copyright 1989 by the Massachusetts Institute of Technology **/ /** Cambridge, Massachusetts **/ /** **/ /** All Rights Reserved **/ /** **/ /** Permission to use, copy, modify, and distribute this software and **/ /** its documentation for any purpose and without fee is hereby **/ /** granted, provided that the above copyright notice appear in all **/ /** copies and that both that copyright notice and this permis- **/ /** sion notice appear in supporting documentation, and that the **/ /** names of Evans & Sutherland and M.I.T. not be used in advertising **/ /** in publicity pertaining to distribution of the software without **/ /** specific, written prior permission. **/ /** **/ /** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/ /** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/ /** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/ /** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/ /** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/ /** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/ /** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/ /** OR PERFORMANCE OF THIS SOFTWARE. **/ /*****************************************************************************/ /**************************************************************************** * This module is based on Twm, but has been siginificantly modified * by Rob Nation ****************************************************************************/ /*********************************************************************** * The rest of it is all my fault -- MLM * mwm - "LessTif Window Manager" ***********************************************************************/ #include #include #include #include #include "mwm.h" Atom XA_MIT_PRIORITY_COLORS; Atom XA_WM_CHANGE_STATE; Atom XA_WM_STATE; Atom XA_WM_COLORMAP_WINDOWS; Atom XA_WM_PROTOCOLS; Atom XA_WM_TAKE_FOCUS; Atom XA_WM_DELETE_WINDOW; Atom XA_WM_SAVE_YOURSELF; Atom XA_WM_DESKTOP; Atom XA_MWM_HINTS; Atom XA_MWM_MESSAGES; Atom XA_MWM_MENU; Atom XA_MWM_INFO; /*********************************************************************** * * * ***********************************************************************/ /* * Intern some commonly used atoms */ void PROP_Initialize(void) { XA_MIT_PRIORITY_COLORS = XInternAtom(dpy, "_MIT_PRIORITY_COLORS", False); XA_WM_CHANGE_STATE = XInternAtom(dpy, "WM_CHANGE_STATE", False); XA_WM_STATE = XInternAtom(dpy, "WM_STATE", False); XA_WM_COLORMAP_WINDOWS = XInternAtom(dpy, "WM_COLORMAP_WINDOWS", False); XA_WM_PROTOCOLS = XInternAtom(dpy, "WM_PROTOCOLS", False); XA_WM_TAKE_FOCUS = XInternAtom(dpy, "WM_TAKE_FOCUS", False); XA_WM_DELETE_WINDOW = XInternAtom(dpy, "WM_DELETE_WINDOW", False); XA_WM_SAVE_YOURSELF = XInternAtom(dpy, "WM_SAVE_YOURSELF", False); XA_WM_DESKTOP = XInternAtom(dpy, "WM_DESKTOP", False); XA_MWM_HINTS = XInternAtom(dpy, _XA_MWM_HINTS, False); XA_MWM_MESSAGES = XInternAtom(dpy, _XA_MWM_MESSAGES, False); XA_MWM_MENU = XInternAtom(dpy, _XA_MWM_MENU, False); XA_MWM_INFO = XInternAtom(dpy, _XA_MWM_INFO, False); } /* * set the behavior property on the root window. This will be used for the * f.set_behavior function */ void PROP_SetBehavior(ScreenInfo *scr, Boolean custom) { PropMotifWmInfo info; /* set the MWM_INFO property on the Root */ if (custom) info.flags = MWM_INFO_STARTUP_CUSTOM; else info.flags = MWM_INFO_STARTUP_STANDARD; info.wmWindow = scr->root_win; XChangeProperty(dpy, scr->root_win, XA_MWM_INFO, XA_MWM_INFO, 32, PropModeReplace, (unsigned char *)&info, PROP_MWM_INFO_ELEMENTS); } /* * clear the behavior property on the root window. */ void PROP_ClearBehavior(ScreenInfo *scr) { /* set the MWM_INFO property on the Root */ XChangeProperty(dpy, scr->root_win, XA_MWM_INFO, XA_MWM_INFO, 32, PropModeReplace, NULL, 0); } /* * get the current state of the behavior property. This also will be used * by f.set_behavior */ int PROP_GetBehavior(ScreenInfo *scr) { int actual_format, ret; Atom actual_type; unsigned long nitems, bytesafter; PropMotifWmInfo *info; if (XGetWindowProperty(dpy, scr->root_win, XA_MWM_INFO, 0L, PROP_MOTIF_WM_INFO_ELEMENTS, False, XA_MWM_INFO, &actual_type, &actual_format, &nitems, &bytesafter, (unsigned char **)&info) == Success) { if (nitems > 0 && info) ret = info->flags; else ret = 0; XFree((char *)info); return ret; } return 0; } /* * Make sure property priority colors is empty */ void PROP_SetPriorityColors(ScreenInfo *scr) { XChangeProperty(dpy, scr->root_win, XA_MIT_PRIORITY_COLORS, XA_CARDINAL, 32, PropModeReplace, NULL, 0); } /* * check the desktop. */ Boolean PROP_CheckDesktop(ScreenInfo *scr) { Atom atype; int aformat; unsigned long nitems, bytes_remain; unsigned char *prop; Boolean restart = False; /* * Set the current desktop number to zero * Multiple desks are available even in non-virtual * compilations */ scr->current_desk = 0; if ((XGetWindowProperty(dpy, scr->root_win, XA_WM_DESKTOP, 0L, 1L, True, XA_WM_DESKTOP, &atype, &aformat, &nitems, &bytes_remain, &prop)) == Success) { if (prop != NULL) { restart = True; scr->current_desk = *(unsigned long *)prop; } } return restart; } /* * This is used to tell applications which windows on the screen are * top level appication windows, and which windows are the icon windows * that go with them. */ void PROP_SetState(MwmWindow *tmp_win, int state) { unsigned long data[2]; /* "suggested" by ICCCM version 1 */ data[0] = (unsigned long)state; data[1] = (unsigned long)tmp_win->icon_w; /* data[2] = (unsigned long) tmp_win->icon_pixmap_w; */ XChangeProperty(dpy, tmp_win->w, XA_WM_STATE, XA_WM_STATE, 32, PropModeReplace, (unsigned char *)data, 2); } /* * ICCCM Client Messages - Section 4.2.8 of the ICCCM dictates that all * client messages will have the following form: * * event type ClientMessage * message type XA_WM_PROTOCOLS * window tmp->w * format 32 * data[0] message atom * data[1] time stamp */ void PROP_SendClientMessage(Window w, Atom a, Time timestamp) { XClientMessageEvent ev; ev.type = ClientMessage; ev.window = w; ev.message_type = XA_WM_PROTOCOLS; ev.format = 32; ev.data.l[0] = a; ev.data.l[1] = timestamp; XSendEvent(dpy, w, False, 0L, (XEvent *)&ev); } /* * verify that a client is expecting to receive a ClientMessage from mwm */ Boolean PROP_VerifyMwmMessage(MwmWindow *win, Atom message) { unsigned int i; for (i = 0; i < win->num_messages; i++) { if (win->mwm_messages[i] == message) return True; } return False; } /* * send a mwm specific message */ void PROP_SendMwmMessage(Window w, Atom a, Time timestamp) { XClientMessageEvent ev; ev.type = ClientMessage; ev.window = w; ev.message_type = XA_MWM_MESSAGES; ev.format = 32; ev.data.l[0] = a; ev.data.l[1] = timestamp; XSendEvent(dpy, w, False, 0L, (XEvent *)&ev); } /* * Reads the property MOTIF_WM_HINTS */ void PROP_GetMwmHints(MwmWindow *win) { int actual_format; Atom actual_type; unsigned long nitems, bytesafter; if (XGetWindowProperty(dpy, win->w, XA_MWM_HINTS, 0L, PROP_MOTIF_WM_HINTS_ELEMENTS, False, XA_MWM_HINTS, &actual_type, &actual_format, &nitems, &bytesafter, (unsigned char **)&win->mwm_hints) == Success) { if (nitems >= PROP_MOTIF_WM_HINTS_ELEMENTS) return; XFree((char *)win->mwm_hints); } win->mwm_hints = NULL; } /* * Reads the property MOTIF_WM_MENU */ void PROP_GetMwmMenu(MwmWindow *win) { int actual_format; Atom actual_type; unsigned long nitems, bytesafter; if (XGetWindowProperty(dpy, win->w, XA_MWM_MENU, 0L, 1024L, False, XA_MWM_MENU, &actual_type, &actual_format, &nitems, &bytesafter, (unsigned char **)&win->mwm_menu) == Success) { if (bytesafter) fprintf(stderr, "Maximum size of MWM_MENU exceeded\n"); return; } win->mwm_menu = NULL; } /* * Reads the property MOTIF_WM_MESSAGES */ void PROP_GetMwmMessages(MwmWindow *win) { int actual_format; Atom actual_type; unsigned long bytesafter; if (XGetWindowProperty(dpy, win->w, XA_MWM_MESSAGES, 0L, 1024L, False, AnyPropertyType, &actual_type, &actual_format, &win->num_messages, &bytesafter, (unsigned char **)&win->mwm_messages) == Success) { if (bytesafter) fprintf(stderr, "Maximum size of MWM_MESSAGES exceeded: %ld.\n", bytesafter); return; } win->mwm_messages = NULL; } /* * gets application supplied size info */ void PROP_GetWindowSizeHints(MwmWindow *win) { long supplied = 0; if (!XGetWMNormalHints(dpy, win->w, &win->hints, &supplied)) win->hints.flags = 0; /* Beat up our copy of the hints, so that all important field are * filled in! */ if (win->hints.flags & PResizeInc) { if (win->hints.width_inc == 0) win->hints.width_inc = 1; if (win->hints.height_inc == 0) win->hints.height_inc = 1; } else { win->hints.width_inc = 1; win->hints.height_inc = 1; } /* * ICCCM says that PMinSize is the default if no PBaseSize is given, * and vice-versa. */ if (!(win->hints.flags & PBaseSize)) { if (win->hints.flags & PMinSize) { win->hints.base_width = win->hints.min_width; win->hints.base_height = win->hints.min_height; } else { win->hints.base_width = 0; win->hints.base_height = 0; } } if (!(win->hints.flags & PMinSize)) { win->hints.min_width = win->hints.base_width; win->hints.min_height = win->hints.base_height; } if (!(win->hints.flags & PMaxSize)) { win->hints.max_width = MAX_WINDOW_WIDTH; win->hints.max_height = MAX_WINDOW_HEIGHT; } if (win->hints.max_width < win->hints.min_width) win->hints.max_width = MAX_WINDOW_WIDTH; if (win->hints.max_height < win->hints.min_height) win->hints.max_height = MAX_WINDOW_HEIGHT; /* Zero width/height windows are bad news! */ if (win->hints.min_height <= 0) win->hints.min_height = 1; if (win->hints.min_width <= 0) win->hints.min_width = 1; if (!(win->hints.flags & PWinGravity)) { win->hints.win_gravity = NorthWestGravity; win->hints.flags |= PWinGravity; } } /* * finds out which protocols the window supports */ void PROP_GetWmProtocols(MwmWindow *win) { unsigned long flags = 0L; Atom *protocols = NULL, *ap; int i, n; Atom atype; int aformat; unsigned long bytes_remain, nitems; if (win == NULL) return; /* * First, try the Xlib function to read the protocols. * This is what Twm uses. */ if (XGetWMProtocols(dpy, win->w, &protocols, &n)) { win->flags &= ~(WM_TAKES_FOCUS | WM_DELS_WINDOW | WM_SAVE_SELF | MWM_MESSAGES); for (i = 0, ap = protocols; i < n; i++, ap++) { if (*ap == (Atom)XA_WM_TAKE_FOCUS) flags |= WM_TAKES_FOCUS; if (*ap == (Atom)XA_WM_DELETE_WINDOW) flags |= WM_DELS_WINDOW; if (*ap == (Atom)XA_WM_SAVE_YOURSELF) flags |= WM_SAVE_SELF; if (*ap == (Atom)XA_MWM_MESSAGES) flags |= MWM_MESSAGES; } if (protocols) XFree((char *)protocols); } /* * Next, read it the hard way. mosaic from Coreldraw needs to * be read in this way. */ else if ((XGetWindowProperty(dpy, win->w, XA_WM_PROTOCOLS, 0L, 10L, False, XA_WM_PROTOCOLS, &atype, &aformat, &nitems, &bytes_remain, (unsigned char **)&protocols)) == Success) { win->flags &= ~(WM_TAKES_FOCUS | WM_DELS_WINDOW | WM_SAVE_SELF | MWM_MESSAGES); for (i = 0, ap = protocols; (unsigned long)i < nitems; i++, ap++) { if (*ap == (Atom)XA_WM_TAKE_FOCUS) flags |= WM_TAKES_FOCUS; if (*ap == (Atom)XA_WM_DELETE_WINDOW) flags |= WM_DELS_WINDOW; if (*ap == (Atom)XA_WM_SAVE_YOURSELF) flags |= WM_SAVE_SELF; if (*ap == (Atom)XA_MWM_MESSAGES) flags |= MWM_MESSAGES; } if (protocols) XFree((char *)protocols); } win->flags |= flags; } /* * Gets the WM_COLORMAP_WINDOWS property from the window * This property typically doesn't exist, but a few applications * use it. These seem to occur mostly on SGI machines. */ void PROP_GetWmColormapWindows(MwmWindow *tmp) { if (tmp->cmap_windows != (Window *)NULL) XFree((void *)tmp->cmap_windows); if (!XGetWMColormapWindows(dpy, tmp->w, &tmp->cmap_windows, &tmp->number_cmap_windows)) { tmp->number_cmap_windows = 0; tmp->cmap_windows = NULL; } } /* * get the icon name */ void PROP_GetWmIconName(MwmWindow *tmp) { Atom actual_type; int actual_format; unsigned long nitems, bytesafter; unsigned char *prop; if (XGetWindowProperty(dpy, tmp->w, XA_WM_ICON_NAME, 0L, 200L, False, XA_STRING, &actual_type, &actual_format, &nitems, &bytesafter, &prop) == Success && prop != NULL) { tmp->icon_label = (char *)prop; /* FIXME */ } }