From 272e3631898255a8838daae0c7887d20cb384e8e Mon Sep 17 00:00:00 2001 From: Kim Woelders Date: Sun, 13 Feb 2005 22:54:17 +0000 Subject: [PATCH] Implement window matches doing window ops. SVN revision: 13360 --- src/E.h | 1 + src/Makefile.am | 1 + src/ewin-ops.c | 66 +++++++++++++- src/ewin-ops.h | 72 +++++++++++++++ src/ewins.c | 8 +- src/ipc.c | 119 ++---------------------- src/windowmatch.c | 228 +++++++++++++++++++++++++++++++++++++++++----- 7 files changed, 356 insertions(+), 139 deletions(-) create mode 100644 src/ewin-ops.h diff --git a/src/E.h b/src/E.h index 92fd89fe..1b1fea86 100644 --- a/src/E.h +++ b/src/E.h @@ -2161,6 +2161,7 @@ int WindowMatchConfigLoad(FILE * fs); void *WindowMatchEwin(EWin * ewin); Border *WindowMatchEwinBorder(const EWin * ewin); const char *WindowMatchEwinIcon(const EWin * ewin); +void WindowMatchEwinOps(EWin * ewin); /* x.c */ Display *EDisplayOpen(const char *dstr); diff --git a/src/Makefile.am b/src/Makefile.am index 8de54694..f1321125 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -21,6 +21,7 @@ e16_SOURCES = \ econfig.h \ ecore-e16.h \ emodule.h \ + ewin-ops.h \ timestamp.h \ aclass.c \ actions.c \ diff --git a/src/ewin-ops.c b/src/ewin-ops.c index fbf52689..14b13351 100644 --- a/src/ewin-ops.c +++ b/src/ewin-ops.c @@ -21,9 +21,73 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "E.h" -#include "ecompmgr.h" +#include "ecompmgr.h" /* FIXME - Resize hack - to be removed */ +#include "ewin-ops.h" #include +static const WinOp winops[] = { + {"close", 2, 1, 0, EWIN_OP_CLOSE}, + {"kill", 0, 1, 0, EWIN_OP_KILL}, + {"iconify", 2, 1, 1, EWIN_OP_ICONIFY}, + {"opacity", 2, 1, 1, EWIN_OP_OPACITY}, + {"shadow", 0, 1, 1, EWIN_OP_SHADOW}, /* Place before "shade" */ + {"shade", 2, 1, 1, EWIN_OP_SHADE}, + {"stick", 2, 1, 1, EWIN_OP_STICK}, + {"fixedpos", 0, 1, 1, EWIN_OP_FIXED_POS}, + {"never_use_area", 0, 1, 1, EWIN_OP_NEVER_USE_AREA}, + {"focusclick", 0, 1, 1, EWIN_OP_FOCUS_CLICK}, + {"neverfocus", 0, 1, 1, EWIN_OP_FOCUS_NEVER}, + {"title", 2, 1, 1, EWIN_OP_TITLE}, + {"toggle_width", 0, 1, 0, EWIN_OP_MAX_WIDTH}, + {"tw", 2, 1, 0, EWIN_OP_MAX_WIDTH}, + {"toggle_height", 0, 1, 0, EWIN_OP_MAX_HEIGHT}, + {"th", 0, 1, 0, EWIN_OP_MAX_HEIGHT}, + {"toggle_size", 0, 1, 0, EWIN_OP_MAX_SIZE}, + {"ts", 2, 1, 0, EWIN_OP_MAX_SIZE}, + {"raise", 2, 1, 0, EWIN_OP_RAISE}, + {"lower", 2, 1, 0, EWIN_OP_LOWER}, + {"layer", 2, 1, 1, EWIN_OP_LAYER}, + {"border", 2, 1, 0, EWIN_OP_BORDER}, + {"desk", 2, 1, 1, EWIN_OP_DESK}, + {"area", 2, 1, 1, EWIN_OP_AREA}, + {"move", 2, 1, 1, EWIN_OP_MOVE}, + {"resize", 0, 1, 1, EWIN_OP_SIZE}, + {"sz", 2, 1, 1, EWIN_OP_SIZE}, + {"move_relative", 0, 1, 0, EWIN_OP_MOVE_REL}, + {"mr", 2, 1, 0, EWIN_OP_MOVE_REL}, + {"resize_relative", 0, 1, 0, EWIN_OP_SIZE_REL}, + {"sr", 2, 1, 0, EWIN_OP_SIZE_REL}, + {"focus", 2, 1, 0, EWIN_OP_FOCUS}, + {"fullscreen", 2, 1, 1, EWIN_OP_FULLSCREEN}, + {"skiplists", 4, 1, 1, EWIN_OP_SKIP_LISTS}, + {"zoom", 2, 1, 0, EWIN_OP_ZOOM}, + {"snap", 0, 1, 0, EWIN_OP_SNAP}, + {NULL, 0, 0, 0, EWIN_OP_INVALID} /* Terminator */ +}; + +const WinOp * +EwinOpFind(const char *op) +{ + const WinOp *wop; + + wop = winops; + for (; wop->name; wop++) + { + if (wop->len) + { + if (!strncmp(op, wop->name, wop->len)) + return wop; + } + else + { + if (!strcmp(op, wop->name)) + return wop; + } + } + + return NULL; +} + void SlideEwinTo(EWin * ewin, int fx, int fy, int tx, int ty, int speed) { diff --git a/src/ewin-ops.h b/src/ewin-ops.h new file mode 100644 index 00000000..8e03807b --- /dev/null +++ b/src/ewin-ops.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2005 Kim Woelders + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies of the Software, its documentation and marketing & publicity + * materials, and acknowledgment shall be given in the documentation, materials + * and software packages that this Software was used. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef _EWIN_OPS_H_ +#define _EWIN_OPS_H_ + +typedef enum +{ + EWIN_OP_INVALID, + EWIN_OP_CLOSE, + EWIN_OP_KILL, + EWIN_OP_ICONIFY, + EWIN_OP_OPACITY, + EWIN_OP_SHADOW, + EWIN_OP_SHADE, + EWIN_OP_STICK, + EWIN_OP_FIXED_POS, + EWIN_OP_NEVER_USE_AREA, + EWIN_OP_FOCUS_CLICK, + EWIN_OP_FOCUS_NEVER, + EWIN_OP_TITLE, + EWIN_OP_MAX_WIDTH, + EWIN_OP_MAX_HEIGHT, + EWIN_OP_MAX_SIZE, + EWIN_OP_RAISE, + EWIN_OP_LOWER, + EWIN_OP_LAYER, + EWIN_OP_BORDER, + EWIN_OP_DESK, + EWIN_OP_AREA, + EWIN_OP_MOVE, + EWIN_OP_SIZE, + EWIN_OP_MOVE_REL, + EWIN_OP_SIZE_REL, + EWIN_OP_FOCUS, + EWIN_OP_FULLSCREEN, + EWIN_OP_SKIP_LISTS, + EWIN_OP_ZOOM, + EWIN_OP_SNAP, +} winop_e; + +typedef struct +{ + const char *name; + char len; + char ok_ipc; + char ok_match; + char op; +} WinOp; + +const WinOp *EwinOpFind(const char *op); + +#endif /* _EWIN_OPS_H_ */ diff --git a/src/ewins.c b/src/ewins.c index abec7f76..b6f8141f 100644 --- a/src/ewins.c +++ b/src/ewins.c @@ -518,9 +518,10 @@ Adopt(EWin * ewin, Window win) #if 0 /* Do we want this? */ MatchEwinToSM(ewin); #endif - MatchEwinToSnapInfo(ewin); + WindowMatchEwinOps(ewin); /* Window matches */ + MatchEwinToSnapInfo(ewin); /* Saved settings */ if (Mode.wm.startup) - EHintsGetInfo(ewin); + EHintsGetInfo(ewin); /* E restart hints */ ICCCM_MatchSize(ewin); EwinAdopt(ewin); @@ -599,7 +600,8 @@ AdoptInternal(Window win, Border * border, int type) ewin->client.no_resize_h = ewin->client.no_resize_v = 1; break; } - MatchEwinToSnapInfo(ewin); + WindowMatchEwinOps(ewin); /* Window matches */ + MatchEwinToSnapInfo(ewin); /* Saved settings */ ICCCM_MatchSize(ewin); EwinAdopt(ewin); diff --git a/src/ipc.c b/src/ipc.c index 017c0f43..e6db2348 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -22,6 +22,7 @@ */ #include #include "E.h" +#include "ewin-ops.h" #define SS(s) ((s) ? (s) : NoText) static const char NoText[] = "-NONE-"; @@ -374,113 +375,6 @@ doMoveConstrainedNoGroup(EWin * ewin, const char *params) } #endif -typedef enum -{ - EWIN_OP_INVALID, - EWIN_OP_CLOSE, - EWIN_OP_KILL, - EWIN_OP_ICONIFY, - EWIN_OP_OPACITY, - EWIN_OP_SHADOW, - EWIN_OP_SHADE, - EWIN_OP_STICK, - EWIN_OP_FIXED_POS, - EWIN_OP_NEVER_USE_AREA, - EWIN_OP_FOCUS_CLICK, - EWIN_OP_FOCUS_NEVER, - EWIN_OP_TITLE, - EWIN_OP_MAX_WIDTH, - EWIN_OP_MAX_HEIGHT, - EWIN_OP_MAX_SIZE, - EWIN_OP_RAISE, - EWIN_OP_LOWER, - EWIN_OP_LAYER, - EWIN_OP_BORDER, - EWIN_OP_DESK, - EWIN_OP_AREA, - EWIN_OP_MOVE, - EWIN_OP_SIZE, - EWIN_OP_MOVE_REL, - EWIN_OP_SIZE_REL, - EWIN_OP_FOCUS, - EWIN_OP_FULLSCREEN, - EWIN_OP_SKIP_LISTS, - EWIN_OP_ZOOM, - EWIN_OP_SNAP, -} winop_e; - -typedef struct -{ - const char *name; - char len; - char ok_ipc; - char ok_match; - char op; -} WinOp; - -static const WinOp winops[] = { - {"close", 2, 1, 1, EWIN_OP_CLOSE}, - {"kill", 0, 1, 1, EWIN_OP_KILL}, - {"iconify", 2, 1, 1, EWIN_OP_ICONIFY}, - {"opacity", 2, 1, 1, EWIN_OP_OPACITY}, - {"shadow", 0, 1, 1, EWIN_OP_SHADOW}, /* Place before "shade" */ - {"shade", 2, 1, 1, EWIN_OP_SHADE}, - {"stick", 2, 1, 1, EWIN_OP_STICK}, - {"fixedpos", 0, 1, 1, EWIN_OP_FIXED_POS}, - {"never_use_area", 0, 1, 1, EWIN_OP_NEVER_USE_AREA}, - {"focusclick", 0, 1, 1, EWIN_OP_FOCUS_CLICK}, - {"neverfocus", 0, 1, 1, EWIN_OP_FOCUS_NEVER}, - {"title", 2, 1, 1, EWIN_OP_TITLE}, - {"toggle_width", 0, 1, 1, EWIN_OP_MAX_WIDTH}, - {"tw", 2, 1, 1, EWIN_OP_MAX_WIDTH}, - {"toggle_height", 0, 1, 1, EWIN_OP_MAX_HEIGHT}, - {"th", 0, 1, 1, EWIN_OP_MAX_HEIGHT}, - {"toggle_size", 0, 1, 1, EWIN_OP_MAX_SIZE}, - {"ts", 2, 1, 1, EWIN_OP_MAX_SIZE}, - {"raise", 2, 1, 1, EWIN_OP_RAISE}, - {"lower", 2, 1, 1, EWIN_OP_LOWER}, - {"layer", 2, 1, 1, EWIN_OP_LAYER}, - {"border", 2, 1, 1, EWIN_OP_BORDER}, - {"desk", 2, 1, 1, EWIN_OP_DESK}, - {"area", 2, 1, 1, EWIN_OP_AREA}, - {"move", 2, 1, 1, EWIN_OP_MOVE}, - {"resize", 0, 1, 1, EWIN_OP_SIZE}, - {"sz", 2, 1, 1, EWIN_OP_SIZE}, - {"move_relative", 0, 1, 1, EWIN_OP_MOVE_REL}, - {"mr", 2, 1, 1, EWIN_OP_MOVE_REL}, - {"resize_relative", 0, 1, 1, EWIN_OP_SIZE_REL}, - {"sr", 2, 1, 1, EWIN_OP_SIZE_REL}, - {"focus", 2, 1, 1, EWIN_OP_FOCUS}, - {"fullscreen", 2, 1, 1, EWIN_OP_FULLSCREEN}, - {"skiplists", 4, 1, 1, EWIN_OP_SKIP_LISTS}, - {"zoom", 2, 1, 1, EWIN_OP_ZOOM}, - {"snap", 0, 1, 1, EWIN_OP_SNAP}, - {NULL, 0, 0, 0, EWIN_OP_INVALID} /* Terminator */ -}; - -static const WinOp * -WinopFind(const char *op) -{ - const WinOp *wop; - - wop = winops; - for (; wop->name; wop++) - { - if (wop->len) - { - if (!strncmp(op, wop->name, wop->len)) - break; - } - else - { - if (!strcmp(op, wop->name)) - break; - } - } - - return wop; -} - static void IPC_WinOps(const char *params, Client * c __UNUSED__) { @@ -521,14 +415,19 @@ IPC_WinOps(const char *params, Client * c __UNUSED__) goto done; } - wop = WinopFind(operation); + wop = EwinOpFind(operation); + if (!wop) + { + IpcPrintf("Error: unknown operation"); + goto done; + } switch (wop->op) { default: - case EWIN_OP_INVALID: + /* We should not get here */ IpcPrintf("Error: unknown operation"); - break; + return; case EWIN_OP_CLOSE: EwinOpClose(ewin); diff --git a/src/windowmatch.c b/src/windowmatch.c index cea35706..560c7725 100644 --- a/src/windowmatch.c +++ b/src/windowmatch.c @@ -23,6 +23,9 @@ */ #include "E.h" #include "conf.h" +#include "ewin-ops.h" + +static int WindowMatchEwinOpsParse(EWin * ewin, const char *ops); struct _windowmatch { @@ -298,19 +301,18 @@ WindowMatchConfigLoad(FILE * fs) static WindowMatch * WindowMatchDecode(const char *line) { - char match[32], value[1024], op[32], args[1024]; + char match[32], value[1024], op[32]; + const char *args; WindowMatch *wm = NULL; int err, num, w1, w2, h1, h2; - match[0] = value[0] = op[0] = args[0] = '\0'; - num = sscanf(line, "%32s %1024s %32s %1024s", match, value, op, args); - if (num < 4) + match[0] = value[0] = op[0] = '\0'; + num = sscanf(line, "%32s %1024s %32s %n", match, value, op, &w1); + if (num < 3) + return NULL; + args = line + w1; + if (*args == '\0') return NULL; - -#if 0 - Eprintf("-- %s\n", s); - Eprintf("++ %s %s %s %s\n", match, value, op, args); -#endif err = 0; @@ -399,10 +401,17 @@ WindowMatchDecode(const char *line) break; case MATCH_OP_ICON: + /* FIXME - Check if exists */ wm->args = Estrdup(args); break; case MATCH_OP_WINOP: + if (WindowMatchEwinOpsParse(NULL, args)) + { + Eprintf("WindowMatchDecode: Error (%s): %s\n", args, line); + err = 1; + goto done; + } wm->args = Estrdup(args); break; } @@ -584,22 +593,8 @@ WindowMatchType(const EWin * ewin, int type) { wm = lst[i]; - switch (type) - { - default: - continue; - - case MATCH_OP_BORDER: - if (!wm->border) - continue; - break; - - case MATCH_OP_ICON: - case MATCH_OP_WINOP: - if (!wm->args) - continue; - break; - } + if (wm->op != type) + continue; if (!WindowMatchTest(ewin, lst[i])) continue; @@ -644,6 +639,189 @@ WindowMatchEwinIcon(const EWin * ewin) return NULL; } +static int +GetBoolean(const char *value) +{ + /* We set off if "0" or "off", otherwise on */ + if (!value) + return 1; + else if (!strcmp(value, "0") || !strcmp(value, "off")) + return 0; + return 1; +} + +#define WINOP_GET_BOOL(item, val) item = GetBoolean(val) + +static void +WindowMatchEwinOpsAction(EWin * ewin, int op, const char *args) +{ + int a, b; + + /* NB! This must only be used when a new client is being adopted */ + + switch (op) + { + default: + /* We should not get here */ + return; + + case EWIN_OP_ICONIFY: + WINOP_GET_BOOL(ewin->client.start_iconified, args); + break; + + case EWIN_OP_SHADE: + WINOP_GET_BOOL(ewin->shaded, args); + break; + + case EWIN_OP_STICK: + WINOP_GET_BOOL(ewin->o.sticky, args); + break; + + case EWIN_OP_FIXED_POS: + WINOP_GET_BOOL(ewin->fixedpos, args); + break; + + case EWIN_OP_NEVER_USE_AREA: + WINOP_GET_BOOL(ewin->never_use_area, args); + break; + + case EWIN_OP_FOCUS_CLICK: + WINOP_GET_BOOL(ewin->focusclick, args); + break; + + case EWIN_OP_FOCUS_NEVER: + WINOP_GET_BOOL(ewin->neverfocus, args); + break; + + case EWIN_OP_FULLSCREEN: + WINOP_GET_BOOL(ewin->st.fullscreen, args); + break; + + case EWIN_OP_SKIP_LISTS: + WINOP_GET_BOOL(ewin->skipwinlist, args); + ewin->skipfocus = ewin->skiptask = ewin->skipwinlist; + break; + +#if USE_COMPOSITE + case EWIN_OP_OPACITY: + EoSetOpacity(ewin, OpacityExt(atoi(args))); + break; + + case EWIN_OP_SHADOW: + WINOP_GET_BOOL(ewin->o.shadow, args); + break; +#endif + + case EWIN_OP_TITLE: + _EFREE(ewin->icccm.wm_name); + ewin->icccm.wm_name = Estrdup(args); + break; + + case EWIN_OP_LAYER: + EoSetLayer(ewin, atoi(args)); + break; + + case EWIN_OP_DESK: + EoSetDesk(ewin, atoi(args)); + break; + + case EWIN_OP_AREA: + a = b = 0; + if (sscanf(args, "%u %u", &a, &b) < 2) + break; + MoveEwinToArea(ewin, a, b); /* FIXME - We should not move here */ + break; + + case EWIN_OP_MOVE: + a = ewin->client.x; + b = ewin->client.y; + if (sscanf(args, "%i %i", &a, &b) < 2) + break; + ewin->client.x = a; + ewin->client.y = b; + ewin->client.already_placed = 1; + break; + + case EWIN_OP_SIZE: + a = ewin->client.w; + b = ewin->client.h; + if (sscanf(args, "%u %u", &a, &b) < 2) + break; + ewin->client.w = a; + ewin->client.h = b; + break; + } +} + +static int +WindowMatchEwinOpsParse(EWin * ewin, const char *ops) +{ + int err, len; + const WinOp *wop; + char *ops2, *s, *p, op[32]; + + if (!ops) + return -1; + + /* Parse ':' separated operations list, e.g. "layer 3:desk 1: shade" */ + p = ops2 = Estrdup(ops); + + err = 0; + for (; p; p = s) + { + /* Break at ':' */ + s = strchr(p, ':'); + if (s) + *s++ = '\0'; + + len = 0; + sscanf(p, "%31s %n", op, &len); + if (len <= 0) + break; + p += len; + + wop = EwinOpFind(op); + if (!wop || !wop->ok_match) + { + err = -1; + break; + } + + /* If ewin is NULL, we are validating the configuration */ + if (ewin) + WindowMatchEwinOpsAction(ewin, wop->op, p); + } + + Efree(ops2); + + return err; +} + +void +WindowMatchEwinOps(EWin * ewin) +{ + WindowMatch **lst, *wm; + int i, num; + + lst = (WindowMatch **) ListItemType(&num, LIST_TYPE_WINDOWMATCH); + for (i = 0; i < num; i++) + { + wm = lst[i]; + + if (wm->op != MATCH_OP_WINOP) + continue; + + if (!WindowMatchTest(ewin, lst[i])) + continue; + + /* Match found - do the ops */ + WindowMatchEwinOpsParse(ewin, wm->args); + } + + if (lst) + Efree(lst); +} + /* * Winmatch module */