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/swallow.c | 274 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 274 insertions(+) create mode 100644 src/swallow.c (limited to 'src/swallow.c') diff --git a/src/swallow.c b/src/swallow.c new file mode 100644 index 0000000..26836f1 --- /dev/null +++ b/src/swallow.c @@ -0,0 +1,274 @@ +/** + * @file swallow.c + * @author Joe Wingbermuehle + * @date 2005-2006 + * + * @brief Swallow tray component. + * + */ + +#include "jwm.h" +#include "swallow.h" +#include "main.h" +#include "tray.h" +#include "error.h" +#include "root.h" +#include "color.h" +#include "client.h" +#include "event.h" +#include "misc.h" + +typedef struct SwallowNode { + + TrayComponentType *cp; + + char *name; + char *command; + int border; + int userWidth; + int userHeight; + + struct SwallowNode *next; + +} SwallowNode; + +static SwallowNode *swallowNodes; + +static void Destroy(TrayComponentType *cp); +static void Resize(TrayComponentType *cp); + +/** Initialize swallow data. */ +void InitializeSwallow() { + swallowNodes = NULL; +} + +/** Start swallow processing. */ +void StartupSwallow() { + + SwallowNode *np; + + for(np = swallowNodes; np; np = np->next) { + if(np->command) { + RunCommand(np->command); + } + } + +} + +/** Stop swallow processing. */ +void ShutdownSwallow() { +} + +/** Destroy swallow data. */ +void DestroySwallow() { + + SwallowNode *np; + + while(swallowNodes) { + + np = swallowNodes->next; + + Assert(swallowNodes->name); + Release(swallowNodes->name); + + if(swallowNodes->command) { + Release(swallowNodes->command); + } + + Release(swallowNodes); + swallowNodes = np; + + } + +} + +/** Create a swallowed application tray component. */ +TrayComponentType *CreateSwallow(const char *name, const char *command, + int width, int height) { + + TrayComponentType *cp; + SwallowNode *np; + + if(!name) { + Warning("cannot swallow a client with no name"); + return NULL; + } + + /* Make sure this name isn't already used. */ + for(np = swallowNodes; np; np = np->next) { + if(!strcmp(np->name, name)) { + Warning("cannot swallow the same client multiple times"); + return NULL; + } + } + + np = Allocate(sizeof(SwallowNode)); + np->name = CopyString(name); + np->command = CopyString(command); + + np->next = swallowNodes; + swallowNodes = np; + + cp = CreateTrayComponent(); + np->cp = cp; + cp->object = np; + cp->Destroy = Destroy; + cp->Resize = Resize; + + if(width) { + cp->requestedWidth = width; + np->userWidth = 1; + } else { + cp->requestedWidth = 1; + np->userWidth = 0; + } + if(height) { + cp->requestedHeight = height; + np->userHeight = 1; + } else { + cp->requestedHeight = 1; + np->userHeight = 0; + } + + return cp; + +} + +/** Process an event on a swallowed window. */ +int ProcessSwallowEvent(const XEvent *event) { + + SwallowNode *np; + int width, height; + + for(np = swallowNodes; np; np = np->next) { + if(event->xany.window == np->cp->window) { + switch(event->type) { + case DestroyNotify: + np->cp->window = None; + np->cp->requestedWidth = 1; + np->cp->requestedHeight = 1; + ResizeTray(np->cp->tray); + break; + case ResizeRequest: + np->cp->requestedWidth + = event->xresizerequest.width + np->border * 2; + np->cp->requestedHeight + = event->xresizerequest.height + np->border * 2; + ResizeTray(np->cp->tray); + break; + case ConfigureNotify: + /* I don't think this should be necessary, but somehow + * resize requests slip by sometimes... */ + width = event->xconfigure.width + np->border * 2; + height = event->xconfigure.height + np->border * 2; + if( width != np->cp->requestedWidth + && height != np->cp->requestedHeight) { + np->cp->requestedWidth = width; + np->cp->requestedHeight = height; + ResizeTray(np->cp->tray); + } + break; + default: + break; + } + return 1; + } + } + + return 0; + +} + +/** Handle a tray resize. */ +void Resize(TrayComponentType *cp) { + + int width, height; + + SwallowNode *np = (SwallowNode*)cp->object; + + if(cp->window != None) { + + width = cp->width - np->border * 2; + height = cp->height - np->border * 2; + + JXResizeWindow(display, cp->window, width, height); + + } + +} + +/** Destroy a swallow tray component. */ +void Destroy(TrayComponentType *cp) { + + ClientProtocolType protocols; + + if(cp->window) { + + JXReparentWindow(display, cp->window, rootWindow, 0, 0); + JXRemoveFromSaveSet(display, cp->window); + + protocols = ReadWMProtocols(cp->window); + if(protocols & PROT_DELETE) { + SendClientMessage(cp->window, ATOM_WM_PROTOCOLS, + ATOM_WM_DELETE_WINDOW); + } else { + JXKillClient(display, cp->window); + } + + } + +} + +/** Determine if this is a window to be swallowed, if it is, swallow it. */ +int CheckSwallowMap(const XMapEvent *event) { + + SwallowNode *np; + XClassHint hint; + XWindowAttributes attr; + + for(np = swallowNodes; np; np = np->next) { + + if(np->cp->window != None) { + continue; + } + + Assert(np->cp->tray->window != None); + + if(JXGetClassHint(display, event->window, &hint)) { + if(!strcmp(hint.res_name, np->name)) { + + /* Swallow the window. */ + JXSelectInput(display, event->window, + StructureNotifyMask | ResizeRedirectMask); + JXAddToSaveSet(display, event->window); + JXSetWindowBorder(display, event->window, colors[COLOR_TRAY_BG]); + JXReparentWindow(display, event->window, + np->cp->tray->window, 0, 0); + JXMapRaised(display, event->window); + JXFree(hint.res_name); + JXFree(hint.res_class); + np->cp->window = event->window; + + /* Update the size. */ + JXGetWindowAttributes(display, event->window, &attr); + np->border = attr.border_width; + if(!np->userWidth) { + np->cp->requestedWidth = attr.width + 2 * np->border; + } + if(!np->userHeight) { + np->cp->requestedHeight = attr.height + 2 * np->border; + } + + ResizeTray(np->cp->tray); + + return 1; + + } + } + + } + + return 0; + +} + -- cgit v1.2.3