From a041d9898e6d699bd8c0c25482ec574feb03c547 Mon Sep 17 00:00:00 2001 From: "John Ankarstr\\xf6m" Date: Sat, 29 May 2021 12:54:47 +0200 Subject: First commit This is the original state of the released tarball for JWM 1.8, which will serve as my starting point for further modifications. --- src/hint.c | 970 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 970 insertions(+) create mode 100644 src/hint.c (limited to 'src/hint.c') diff --git a/src/hint.c b/src/hint.c new file mode 100644 index 0000000..6ab096b --- /dev/null +++ b/src/hint.c @@ -0,0 +1,970 @@ +/**************************************************************************** + * Functions to handle hints. + * Copyright (C) 2004 Joe Wingbermuehle + ****************************************************************************/ + +#include "jwm.h" +#include "hint.h" +#include "client.h" +#include "main.h" +#include "tray.h" +#include "desktop.h" +#include "misc.h" + +/* MWM Defines */ +#define MWM_HINTS_FUNCTIONS (1L << 0) +#define MWM_HINTS_DECORATIONS (1L << 1) +#define MWM_HINTS_INPUT_MODE (1L << 2) +#define MWM_HINTS_STATUS (1L << 3) + +#define MWM_FUNC_ALL (1L << 0) +#define MWM_FUNC_RESIZE (1L << 1) +#define MWM_FUNC_MOVE (1L << 2) +#define MWM_FUNC_MINIMIZE (1L << 3) +#define MWM_FUNC_MAXIMIZE (1L << 4) +#define MWM_FUNC_CLOSE (1L << 5) + +#define MWM_DECOR_ALL (1L << 0) +#define MWM_DECOR_BORDER (1L << 1) +#define MWM_DECOR_RESIZEH (1L << 2) +#define MWM_DECOR_TITLE (1L << 3) +#define MWM_DECOR_MENU (1L << 4) +#define MWM_DECOR_MINIMIZE (1L << 5) +#define MWM_DECOR_MAXIMIZE (1L << 6) + +#define MWM_INPUT_MODELESS 0 +#define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1 +#define MWM_INPUT_SYSTEM_MODAL 2 +#define MWM_INPUT_FULL_APPLICATION_MODAL 3 + +#define MWM_TEAROFF_WINDOW (1L << 0) + +typedef struct { + + unsigned long flags; + unsigned long functions; + unsigned long decorations; + long inputMode; + unsigned long status; + +} PropMwmHints; + +typedef struct { + Atom *atom; + const char *name; +} ProtocolNode; + +typedef struct { + Atom *atom; + const char *name; +} AtomNode; + +Atom atoms[ATOM_COUNT]; + +static const AtomNode atomList[] = { + + { &atoms[ATOM_COMPOUND_TEXT], "COMPOUND_TEXT" }, + { &atoms[ATOM_UTF8_STRING], "UTF8_STRING" }, + + { &atoms[ATOM_WM_STATE], "WM_STATE" }, + { &atoms[ATOM_WM_PROTOCOLS], "WM_PROTOCOLS" }, + { &atoms[ATOM_WM_DELETE_WINDOW], "WM_DELETE_WINDOW" }, + { &atoms[ATOM_WM_TAKE_FOCUS], "WM_TAKE_FOCUS" }, + { &atoms[ATOM_WM_LOCALE_NAME], "WM_LOCALE_NAME" }, + { &atoms[ATOM_WM_CHANGE_STATE], "WM_CHANGE_STATE" }, + { &atoms[ATOM_WM_COLORMAP_WINDOWS], "WM_COLORMAP_WINDOWS" }, + + { &atoms[ATOM_NET_SUPPORTED], "_NET_SUPPORTED" }, + { &atoms[ATOM_NET_NUMBER_OF_DESKTOPS], "_NET_NUMBER_OF_DESKTOPS" }, + { &atoms[ATOM_NET_DESKTOP_NAMES], "_NET_DESKTOP_NAMES" }, + { &atoms[ATOM_NET_DESKTOP_GEOMETRY], "_NET_DESKTOP_GEOMETRY" }, + { &atoms[ATOM_NET_DESKTOP_VIEWPORT], "_NET_DESKTOP_VIEWPORT" }, + { &atoms[ATOM_NET_CURRENT_DESKTOP], "_NET_CURRENT_DESKTOP" }, + { &atoms[ATOM_NET_ACTIVE_WINDOW], "_NET_ACTIVE_WINDOW" }, + { &atoms[ATOM_NET_WORKAREA], "_NET_WORKAREA" }, + { &atoms[ATOM_NET_SUPPORTING_WM_CHECK], "_NET_SUPPORTING_WM_CHECK" }, + { &atoms[ATOM_NET_FRAME_EXTENTS], "_NET_FRAME_EXTENTS" }, + { &atoms[ATOM_NET_WM_DESKTOP], "_NET_WM_DESKTOP" }, + { &atoms[ATOM_NET_WM_STATE], "_NET_WM_STATE" }, + { &atoms[ATOM_NET_WM_STATE_STICKY], "_NET_WM_STATE_STICKY" }, + { &atoms[ATOM_NET_WM_STATE_MAXIMIZED_VERT], "_NET_WM_STATE_MAXIMIZED_VERT"}, + { &atoms[ATOM_NET_WM_STATE_MAXIMIZED_HORZ], "_NET_WM_STATE_MAXIMIZED_HORZ"}, + { &atoms[ATOM_NET_WM_STATE_SHADED], "_NET_WM_STATE_SHADED" }, + { &atoms[ATOM_NET_WM_STATE_FULLSCREEN], "_NET_WM_STATE_FULLSCREEN" }, + { &atoms[ATOM_NET_WM_ALLOWED_ACTIONS], "_NET_WM_ALLOWED_ACTIONS" }, + { &atoms[ATOM_NET_WM_ACTION_MOVE], "_NET_WM_ACTION_MOVE" }, + { &atoms[ATOM_NET_WM_ACTION_RESIZE], "_NET_WM_ACTION_RESIZE" }, + { &atoms[ATOM_NET_WM_ACTION_MINIMIZE], "_NET_WM_ACTION_MINIMIZE" }, + { &atoms[ATOM_NET_WM_ACTION_SHADE], "_NET_WM_ACTION_SHADE" }, + { &atoms[ATOM_NET_WM_ACTION_STICK], "_NET_WM_ACTION_STICK" }, + { &atoms[ATOM_NET_WM_ACTION_MAXIMIZE_HORZ], "_NET_WM_ACTION_MAXIMIZE_HORZ"}, + { &atoms[ATOM_NET_WM_ACTION_MAXIMIZE_VERT], "_NET_WM_ACTION_MAXIMIZE_VERT"}, + { &atoms[ATOM_NET_WM_ACTION_CHANGE_DESKTOP], + "_NET_WM_ACTION_CHANGE_DESKTOP"}, + { &atoms[ATOM_NET_WM_ACTION_CLOSE], "_NET_WM_ACTION_CLOSE" }, + { &atoms[ATOM_NET_CLOSE_WINDOW], "_NET_CLOSE_WINDOW" }, + { &atoms[ATOM_NET_MOVERESIZE_WINDOW], "_NET_MOVERESIZE_WINDOW" }, + { &atoms[ATOM_NET_WM_NAME], "_NET_WM_NAME" }, + { &atoms[ATOM_NET_WM_ICON], "_NET_WM_ICON" }, + { &atoms[ATOM_NET_WM_WINDOW_TYPE], "_NET_WM_WINDOW_TYPE" }, + { &atoms[ATOM_NET_WM_WINDOW_TYPE_DESKTOP],"_NET_WM_WINDOW_TYPE_DESKTOP" }, + { &atoms[ATOM_NET_WM_WINDOW_TYPE_DOCK], "_NET_WM_WINDOW_TYPE_DOCK" }, + { &atoms[ATOM_NET_CLIENT_LIST], "_NET_CLIENT_LIST" }, + { &atoms[ATOM_NET_CLIENT_LIST_STACKING], "_NET_CLIENT_LIST_STACKING" }, + { &atoms[ATOM_NET_WM_STRUT_PARTIAL], "_NET_WM_STRUT_PARTIAL" }, + { &atoms[ATOM_NET_WM_STRUT], "_NET_WM_STRUT" }, + { &atoms[ATOM_NET_SYSTEM_TRAY_OPCODE], "_NET_SYSTEM_TRAY_OPCODE" }, + + { &atoms[ATOM_WIN_LAYER], "_WIN_LAYER" }, + { &atoms[ATOM_WIN_STATE], "_WIN_STATE" }, + { &atoms[ATOM_WIN_WORKSPACE], "_WIN_WORKSPACE" }, + { &atoms[ATOM_WIN_WORKSPACE_COUNT], "_WIN_WORKSPACE_COUNT" }, + { &atoms[ATOM_WIN_SUPPORTING_WM_CHECK], "_WIN_SUPPORTING_WM_CHECK" }, + { &atoms[ATOM_WIN_PROTOCOLS], "_WIN_PROTOCOLS" }, + + { &atoms[ATOM_MOTIF_WM_HINTS], "_MOTIF_WM_HINTS" }, + + { &atoms[ATOM_JWM_RESTART], "_JWM_RESTART" }, + { &atoms[ATOM_JWM_EXIT], "_JWM_EXIT" } + +}; + +static void WriteNetState(ClientNode *np); +static void WriteNetAllowed(ClientNode *np); +static void WriteWinState(ClientNode *np); +static void ReadWMHints(Window win, ClientState *state); +static void ReadMotifHints(Window win, ClientState *state); + +/**************************************************************************** + ****************************************************************************/ +void InitializeHints() { +} + +/**************************************************************************** + ****************************************************************************/ +void StartupHints() { + + unsigned long array[128]; + Atom supported[ATOM_COUNT]; + Window win; + char *data; + unsigned int x; + unsigned int count; + + /* Intern the atoms */ + for(x = 0; x < ATOM_COUNT; x++) { + *atomList[x].atom = JXInternAtom(display, atomList[x].name, False); + } + + /* _NET_SUPPORTED */ + for(x = FIRST_NET_ATOM; x <= LAST_NET_ATOM; x++) { + supported[x - FIRST_NET_ATOM] = atoms[x]; + } + JXChangeProperty(display, rootWindow, atoms[ATOM_NET_SUPPORTED], + XA_ATOM, 32, PropModeReplace, (unsigned char*)supported, + LAST_NET_ATOM - FIRST_NET_ATOM + 1); + + /* _WIN_PROTOCOLS */ + for(x = FIRST_WIN_ATOM; x <= LAST_WIN_ATOM; x++) { + supported[x - FIRST_WIN_ATOM] = atoms[x]; + } + JXChangeProperty(display, rootWindow, atoms[ATOM_WIN_PROTOCOLS], + XA_ATOM, 32, PropModeReplace, (unsigned char*)supported, + LAST_WIN_ATOM - FIRST_WIN_ATOM + 1); + + /* _NET_NUMBER_OF_DESKTOPS */ + SetCardinalAtom(rootWindow, ATOM_NET_NUMBER_OF_DESKTOPS, desktopCount); + + /* _NET_DESKTOP_NAMES */ + count = 0; + for(x = 0; x < desktopCount; x++) { + count += strlen(desktopNames[x]) + 1; + } + data = AllocateStack(count); + count = 0; + for(x = 0; x < desktopCount; x++) { + strcpy(data + count, desktopNames[x]); + count += strlen(desktopNames[x]) + 1; + } + JXChangeProperty(display, rootWindow, atoms[ATOM_NET_DESKTOP_NAMES], + atoms[ATOM_UTF8_STRING], 8, PropModeReplace, + (unsigned char*)data, count); + ReleaseStack(data); + + /* _NET_DESKTOP_GEOMETRY */ + array[0] = rootWidth; + array[1] = rootHeight; + JXChangeProperty(display, rootWindow, atoms[ATOM_NET_DESKTOP_GEOMETRY], + XA_CARDINAL, 32, PropModeReplace, + (unsigned char*)array, 2); + + /* _NET_DESKTOP_VIEWPORT */ + array[0] = 0; + array[1] = 0; + JXChangeProperty(display, rootWindow, atoms[ATOM_NET_DESKTOP_VIEWPORT], + XA_CARDINAL, 32, PropModeReplace, + (unsigned char*)array, 2); + + /* _NET_WORKAREA */ + for(x = 0; x < desktopCount; x++) { + array[x * 4 + 0] = 0; + array[x * 4 + 1] = 0; + array[x * 4 + 2] = rootWidth; + array[x * 4 + 3] = rootHeight; + } + JXChangeProperty(display, rootWindow, atoms[ATOM_NET_WORKAREA], + XA_CARDINAL, 32, PropModeReplace, + (unsigned char*)array, desktopCount * 4); + + win = GetSupportingWindow(); + JXChangeProperty(display, win, atoms[ATOM_NET_WM_NAME], + atoms[ATOM_UTF8_STRING], 8, PropModeReplace, + (unsigned char*)"JWM", 3); + + SetWindowAtom(rootWindow, ATOM_NET_SUPPORTING_WM_CHECK, win); + SetWindowAtom(win, ATOM_NET_SUPPORTING_WM_CHECK, win); + + SetWindowAtom(rootWindow, ATOM_WIN_SUPPORTING_WM_CHECK, win); + SetWindowAtom(win, ATOM_WIN_SUPPORTING_WM_CHECK, win); + + SetCardinalAtom(rootWindow, ATOM_WIN_WORKSPACE_COUNT, desktopCount); + +} + +/**************************************************************************** + ****************************************************************************/ +void ShutdownHints() { +} + +/**************************************************************************** + ****************************************************************************/ +void DestroyHints() { +} + +/**************************************************************************** + ****************************************************************************/ +void ReadCurrentDesktop() { + + unsigned long temp; + + currentDesktop = 0; + + if(GetCardinalAtom(rootWindow, ATOM_NET_CURRENT_DESKTOP, &temp)) { + ChangeDesktop(temp); + } else if(GetCardinalAtom(rootWindow, ATOM_WIN_WORKSPACE, &temp)) { + ChangeDesktop(temp); + } else { + ChangeDesktop(0); + } + +} + +/**************************************************************************** + * Read client protocls/hints. + * This is called while the client is being added to management. + ****************************************************************************/ +void ReadClientProtocols(ClientNode *np) { + + Status status; + ClientNode *pp; + + Assert(np); + + ReadWMName(np); + ReadWMClass(np); + ReadWMNormalHints(np); + ReadWMColormaps(np); + + status = JXGetTransientForHint(display, np->window, &np->owner); + if(!status) { + np->owner = None; + } + + np->state = ReadWindowState(np->window); + if(np->minWidth == np->maxWidth && np->minHeight == np->maxHeight) { + np->state.border &= ~BORDER_RESIZE; + } + + /* Set the client to the same layer as its owner. */ + if(np->owner != None) { + pp = FindClientByWindow(np->owner); + if(pp) { + np->state.layer = pp->state.layer; + } + } + +} + +/**************************************************************************** + ****************************************************************************/ +void WriteState(ClientNode *np) { + + unsigned long data[2]; + + Assert(np); + + if(np->state.status & STAT_MAPPED) { + data[0] = NormalState; + } else if(np->state.status & STAT_MINIMIZED) { + data[0] = IconicState; + } else { + data[0] = WithdrawnState; + } + data[1] = None; + + JXChangeProperty(display, np->window, atoms[ATOM_WM_STATE], + atoms[ATOM_WM_STATE], 32, PropModeReplace, + (unsigned char*)data, 2); + + WriteNetState(np); + WriteNetAllowed(np); + WriteWinState(np); + +} + +/**************************************************************************** + ****************************************************************************/ +void WriteNetState(ClientNode *np) { + + unsigned long values[5]; + int north, south, east, west; + int index; + + Assert(np); + + index = 0; + + if(np->state.status & STAT_MAXIMIZED) { + values[index++] = atoms[ATOM_NET_WM_STATE_MAXIMIZED_VERT]; + values[index++] = atoms[ATOM_NET_WM_STATE_MAXIMIZED_HORZ]; + } + + if(np->state.status & STAT_SHADED) { + values[index++] = atoms[ATOM_NET_WM_STATE_SHADED]; + } + + if(np->state.status & STAT_STICKY) { + values[index++] = atoms[ATOM_NET_WM_STATE_STICKY]; + } + + if(np->state.status & STAT_FULLSCREEN) { + values[index++] = atoms[ATOM_NET_WM_STATE_FULLSCREEN]; + } + + JXChangeProperty(display, np->window, atoms[ATOM_NET_WM_STATE], + XA_ATOM, 32, PropModeReplace, (unsigned char*)values, index); + + GetBorderSize(np, &north, &south, &east, &west); + + /* left, right, top, bottom */ + values[0] = west; + values[1] = east; + values[2] = north; + values[3] = south; + + JXChangeProperty(display, np->window, atoms[ATOM_NET_FRAME_EXTENTS], + XA_CARDINAL, 32, PropModeReplace, (unsigned char*)values, 4); + +} + +/**************************************************************************** + ****************************************************************************/ +void WriteNetAllowed(ClientNode *np) { + + unsigned long values[10]; + int index; + + Assert(np); + + index = 0; + + if(np->state.border & BORDER_TITLE) { + values[index++] = atoms[ATOM_NET_WM_ACTION_SHADE]; + } + + if(np->state.border & BORDER_MIN) { + values[index++] = atoms[ATOM_NET_WM_ACTION_MINIMIZE]; + } + + if(np->state.border & BORDER_MAX) { + values[index++] = atoms[ATOM_NET_WM_ACTION_MAXIMIZE_HORZ]; + values[index++] = atoms[ATOM_NET_WM_ACTION_MAXIMIZE_VERT]; + } + + if(np->state.border & BORDER_CLOSE) { + values[index++] = atoms[ATOM_NET_WM_ACTION_CLOSE]; + } + + if(np->state.border & BORDER_RESIZE) { + values[index++] = atoms[ATOM_NET_WM_ACTION_RESIZE]; + } + + if(np->state.border & BORDER_MOVE) { + values[index++] = atoms[ATOM_NET_WM_ACTION_MOVE]; + } + + if(!(np->state.status & STAT_STICKY)) { + values[index++] = atoms[ATOM_NET_WM_ACTION_CHANGE_DESKTOP]; + } + + values[index++] = atoms[ATOM_NET_WM_ACTION_STICK]; + + JXChangeProperty(display, np->window, atoms[ATOM_NET_WM_ALLOWED_ACTIONS], + XA_ATOM, 32, PropModeReplace, (unsigned char*)values, index); + +} + +/**************************************************************************** + ****************************************************************************/ +void WriteWinState(ClientNode *np) { + + unsigned long flags; + + Assert(np); + + flags = 0; + if(np->state.status & STAT_STICKY) { + flags |= WIN_STATE_STICKY; + } + if(np->state.status & STAT_MINIMIZED) { + flags |= WIN_STATE_MINIMIZED; + } + if(np->state.status & STAT_MAXIMIZED) { + flags |= WIN_STATE_MAXIMIZED_VERT; + flags |= WIN_STATE_MAXIMIZED_HORIZ; + } + if(np->state.status & STAT_NOLIST) { + flags |= WIN_STATE_HIDDEN; + } + if(np->state.status & STAT_SHADED) { + flags |= WIN_STATE_SHADED; + } + + SetCardinalAtom(np->window, ATOM_WIN_STATE, flags); + +} + +/**************************************************************************** + * Read all hints needed to determine the current window state. + ****************************************************************************/ +ClientState ReadWindowState(Window win) { + + ClientState result; + Status status; + unsigned long count, x; + unsigned long extra; + Atom realType; + int realFormat; + unsigned char *temp; + Atom *state; + unsigned long card; + int maxVert, maxHorz; + int fullScreen; + + Assert(win != None); + + result.status = STAT_NONE; + result.border = BORDER_DEFAULT; + result.layer = LAYER_NORMAL; + result.desktop = currentDesktop; + + ReadWMHints(win, &result); + ReadMotifHints(win, &result); + + /* _NET_WM_DESKTOP */ + if(GetCardinalAtom(win, ATOM_NET_WM_DESKTOP, &card)) { + if(card == ~0UL) { + result.status |= STAT_STICKY; + } else if(card < desktopCount) { + result.desktop = card; + } else { + result.desktop = desktopCount - 1; + } + } + + /* _NET_WM_STATE */ + status = JXGetWindowProperty(display, win, + atoms[ATOM_NET_WM_STATE], 0, 32, False, XA_ATOM, &realType, + &realFormat, &count, &extra, &temp); + if(status == Success) { + if(count > 0) { + maxVert = 0; + maxHorz = 0; + fullScreen = 0; + state = (unsigned long*)temp; + for(x = 0; x < count; x++) { + if(state[x] == atoms[ATOM_NET_WM_STATE_STICKY]) { + result.status |= STAT_STICKY; + } else if(state[x] == atoms[ATOM_NET_WM_STATE_SHADED]) { + result.status |= STAT_SHADED; + } else if(state[x] == atoms[ATOM_NET_WM_STATE_MAXIMIZED_VERT]) { + maxVert = 1; + } else if(state[x] == atoms[ATOM_NET_WM_STATE_MAXIMIZED_HORZ]) { + maxHorz = 1; + } else if(state[x] == atoms[ATOM_NET_WM_STATE_FULLSCREEN]) { + fullScreen = 1; + } + } + if(maxVert && maxHorz) { + result.status |= STAT_MAXIMIZED; + } + if(fullScreen) { + result.status |= STAT_FULLSCREEN; + } + } + if(temp) { + JXFree(temp); + } + } + + /* _NET_WM_WINDOW_TYPE */ + status = JXGetWindowProperty(display, win, + atoms[ATOM_NET_WM_WINDOW_TYPE], 0, 32, False, XA_ATOM, &realType, + &realFormat, &count, &extra, &temp); + if(status == Success) { + if(count > 0) { + state = (unsigned long*)temp; + for(x = 0; x < count; x++) { + if(state[x] == atoms[ATOM_NET_WM_WINDOW_TYPE_DESKTOP]) { + result.status |= STAT_STICKY | STAT_NOLIST; + result.layer = 0; + result.border = BORDER_NONE; + } else if(state[x] == atoms[ATOM_NET_WM_WINDOW_TYPE_DOCK]) { + result.status |= STAT_STICKY | STAT_NOLIST; + result.layer = 0; + result.border = BORDER_NONE; + } + } + } + if(temp) { + JXFree(temp); + } + } + + /* _WIN_STATE */ + if(GetCardinalAtom(win, ATOM_WIN_STATE, &card)) { + if(card & WIN_STATE_STICKY) { + result.status |= STAT_STICKY; + } + if(card & WIN_STATE_MINIMIZED) { + result.status |= STAT_MINIMIZED; + } + if(card & WIN_STATE_HIDDEN) { + result.status |= STAT_NOLIST; + } + if(card & WIN_STATE_SHADED) { + result.status |= STAT_SHADED; + } + if((card & WIN_STATE_MAXIMIZED_VERT) + && (card & WIN_STATE_MAXIMIZED_HORIZ)) { + result.status |= STAT_MAXIMIZED; + } + } + + /* _WIN_LAYER */ + if(GetCardinalAtom(win, ATOM_WIN_LAYER, &card)) { + result.layer = card; + } + + return result; + +} + +/**************************************************************************** + ****************************************************************************/ +void ReadWMName(ClientNode *np) { + + unsigned long count; + int status; + unsigned long extra; + Atom realType; + int realFormat; + unsigned char *name; + + Assert(np); + + if(np->name) { + JXFree(np->name); + } + + status = JXGetWindowProperty(display, np->window, + atoms[ATOM_NET_WM_NAME], 0, 1024, False, + atoms[ATOM_UTF8_STRING], &realType, &realFormat, &count, &extra, &name); + if(status != Success) { + np->name = NULL; + } else { + np->name = (char*)name; + } + + if(!np->name) { + if(JXFetchName(display, np->window, &np->name) == 0) { + np->name = NULL; + } + } + + if(!np->name) { + status = JXGetWindowProperty(display, np->window, XA_WM_NAME, + 0, 1024, False, atoms[ATOM_COMPOUND_TEXT], &realType, + &realFormat, &count, &extra, &name); + if(status != Success) { + np->name = NULL; + } else { + np->name = (char*)name; + } + } + +} + +/**************************************************************************** + ****************************************************************************/ +void ReadWMClass(ClientNode *np) { + + XClassHint hint; + + Assert(np); + + if(JXGetClassHint(display, np->window, &hint)) { + np->instanceName = hint.res_name; + np->className = hint.res_class; + } + +} + +/**************************************************************************** + ****************************************************************************/ +ClientProtocolType ReadWMProtocols(Window w) { + + ClientProtocolType result; + unsigned long count, x; + int status; + unsigned long extra; + Atom realType; + int realFormat; + unsigned char *temp; + Atom *p; + + Assert(w != None); + + result = PROT_NONE; + status = JXGetWindowProperty(display, w, atoms[ATOM_WM_PROTOCOLS], + 0, 32, False, XA_ATOM, &realType, &realFormat, &count, &extra, &temp); + p = (Atom*)temp; + + if(status != Success || !p) { + return result; + } + + for(x = 0; x < count; x++) { + if(p[x] == atoms[ATOM_WM_DELETE_WINDOW]) { + result |= PROT_DELETE; + } else if(p[x] == atoms[ATOM_WM_TAKE_FOCUS]) { + result |= PROT_TAKE_FOCUS; + } + } + + JXFree(p); + + return result; + +} + +/**************************************************************************** + ****************************************************************************/ +void ReadWMNormalHints(ClientNode *np) { + + XSizeHints hints; + long temp; + + Assert(np); + + if(!JXGetWMNormalHints(display, np->window, &hints, &temp)) { + np->sizeFlags = 0; + } else { + np->sizeFlags = hints.flags; + } + + if(np->sizeFlags & PResizeInc) { + np->xinc = Max(1, hints.width_inc); + np->yinc = Max(1, hints.height_inc); + } else { + np->xinc = 1; + np->yinc = 1; + } + + if(np->sizeFlags & PMinSize) { + np->minWidth = Max(0, hints.min_width); + np->minHeight = Max(0, hints.min_height); + } else { + np->minWidth = 1; + np->minHeight = 1; + } + + if(np->sizeFlags & PMaxSize) { + np->maxWidth = hints.max_width; + np->maxHeight = hints.max_height; + if(np->maxWidth <= 0) { + np->maxWidth = rootWidth; + } + if(np->maxHeight <= 0) { + np->maxHeight = rootHeight; + } + } else { + np->maxWidth = rootWidth; + np->maxHeight = rootHeight; + } + + if(np->sizeFlags & PBaseSize) { + np->baseWidth = hints.base_width; + np->baseHeight = hints.base_height; + } else if(np->sizeFlags & PMinSize) { + np->baseWidth = np->minWidth; + np->baseHeight = np->minHeight; + } else { + np->baseWidth = 0; + np->baseHeight = 0; + } + + if(np->sizeFlags & PAspect) { + np->aspect.minx = hints.min_aspect.x; + np->aspect.miny = hints.min_aspect.y; + np->aspect.maxx = hints.max_aspect.x; + np->aspect.maxy = hints.max_aspect.y; + if(np->aspect.minx < 1) { + np->aspect.minx = 1; + } + if(np->aspect.miny < 1) { + np->aspect.miny = 1; + } + if(np->aspect.maxx < 1) { + np->aspect.maxx = 1; + } + if(np->aspect.maxy < 1) { + np->aspect.maxy = 1; + } + } + + if(np->sizeFlags & PWinGravity) { + np->gravity = hints.win_gravity; + } else { + np->gravity = 1; + } + +} + +/**************************************************************************** + ****************************************************************************/ +void ReadWMColormaps(ClientNode *np) { + + Window *windows; + ColormapNode *cp; + int count; + int x; + + Assert(np); + + if(JXGetWMColormapWindows(display, np->window, &windows, &count)) { + if(count > 0) { + + /* Free old colormaps. */ + while(np->colormaps) { + cp = np->colormaps->next; + Release(np->colormaps); + np->colormaps = cp; + } + + /* Put the maps in the list in order so they will come out in + * reverse order. This way they will be installed with the + * most important last. + * Keep track of at most colormapCount colormaps for each + * window to avoid doing extra work. */ + count = Min(colormapCount, count); + for(x = 0; x < count; x++) { + cp = Allocate(sizeof(ColormapNode)); + cp->window = windows[x]; + cp->next = np->colormaps; + np->colormaps = cp; + } + + JXFree(windows); + + } + } + +} + +/**************************************************************************** + ****************************************************************************/ +void ReadWMHints(Window win, ClientState *state) { + + XWMHints *wmhints; + + Assert(win != None); + Assert(state); + + wmhints = JXGetWMHints(display, win); + if(wmhints) { + switch(wmhints->flags & StateHint) { + case IconicState: + state->status |= STAT_MINIMIZED; + break; + default: + if(!(state->status & STAT_MINIMIZED)) { + state->status |= STAT_MAPPED; + } + break; + } + JXFree(wmhints); + } else { + state->status |= STAT_MAPPED; + } + +} + +/**************************************************************************** + * Read _MOTIF_WM_HINTS + ****************************************************************************/ +void ReadMotifHints(Window win, ClientState *state) { + + PropMwmHints *mhints; + Atom type; + unsigned long itemCount, bytesLeft; + unsigned char *data; + int format; + + Assert(win != None); + Assert(state); + + if(JXGetWindowProperty(display, win, atoms[ATOM_MOTIF_WM_HINTS], + 0L, 20L, False, atoms[ATOM_MOTIF_WM_HINTS], &type, &format, + &itemCount, &bytesLeft, &data) != Success) { + return; + } + + mhints = (PropMwmHints*)data; + if(mhints) { + + if((mhints->flags & MWM_HINTS_FUNCTIONS) + && !(mhints->functions & MWM_FUNC_ALL)) { + + if(!(mhints->functions & MWM_FUNC_RESIZE)) { + state->border &= ~BORDER_RESIZE; + } + if(!(mhints->functions & MWM_FUNC_MOVE)) { + state->border &= ~BORDER_MOVE; + } + if(!(mhints->functions & MWM_FUNC_MINIMIZE)) { + state->border &= ~BORDER_MIN; + } + if(!(mhints->functions & MWM_FUNC_MAXIMIZE)) { + state->border &= ~BORDER_MAX; + } + if(!(mhints->functions & MWM_FUNC_CLOSE)) { + state->border &= ~BORDER_CLOSE; + } + } + + if((mhints->flags & MWM_HINTS_DECORATIONS) + && !(mhints->decorations & MWM_DECOR_ALL)) { + + if(!(mhints->decorations & MWM_DECOR_BORDER)) { + state->border &= ~BORDER_OUTLINE; + } + if(!(mhints->decorations & MWM_DECOR_TITLE)) { + state->border &= ~BORDER_TITLE; + } + if(!(mhints->decorations & MWM_DECOR_MINIMIZE)) { + state->border &= ~BORDER_MIN; + } + if(!(mhints->decorations & MWM_DECOR_MAXIMIZE)) { + state->border &= ~BORDER_MAX; + } + } + + JXFree(mhints); + } +} + +/**************************************************************************** + ****************************************************************************/ +int GetCardinalAtom(Window window, AtomType atom, unsigned long *value) { + + unsigned long count; + int status; + unsigned long extra; + Atom realType; + int realFormat; + unsigned char *data; + int ret; + + Assert(window != None); + Assert(value); + + status = JXGetWindowProperty(display, window, atoms[atom], 0, 1, False, + XA_CARDINAL, &realType, &realFormat, &count, &extra, &data); + + ret = 0; + if(status == Success && data) { + if(count == 1) { + *value = *(unsigned long*)data; + ret = 1; + } + JXFree(data); + } + + return ret; + +} + +/**************************************************************************** + ****************************************************************************/ +int GetWindowAtom(Window window, AtomType atom, Window *value) { + unsigned long count; + int status; + unsigned long extra; + Atom realType; + int realFormat; + unsigned char *data; + int ret; + + Assert(window != None); + Assert(value); + + status = JXGetWindowProperty(display, window, atoms[atom], 0, 1, False, + XA_WINDOW, &realType, &realFormat, &count, &extra, &data); + + ret = 0; + if(status == Success && data) { + if(count == 1) { + *value = *(Window*)data; + ret = 1; + } + JXFree(data); + } + + return ret; + +} + +/**************************************************************************** + ****************************************************************************/ +void SetCardinalAtom(Window window, AtomType atom, unsigned long value) { + + Assert(window != None); + + JXChangeProperty(display, window, atoms[atom], XA_CARDINAL, 32, + PropModeReplace, (unsigned char*)&value, 1); + +} + +/**************************************************************************** + ****************************************************************************/ +void SetWindowAtom(Window window, AtomType atom, unsigned long value) { + + Assert(window != None); + + JXChangeProperty(display, window, atoms[atom], XA_WINDOW, 32, + PropModeReplace, (unsigned char*)&value, 1); + +} + + -- cgit v1.2.3