kwo pushed a commit to branch master. http://git.enlightenment.org/e16/e16.git/commit/?id=85912e39e2f8a85496ffe678587a4e505ea0d0a0
commit 85912e39e2f8a85496ffe678587a4e505ea0d0a0 Author: Kim Woelders <[email protected]> Date: Fri Jan 28 11:28:31 2022 +0100 New feature - Making windows stick on specific desks/areas --- src/desktops.c | 53 +++++++++++++++++++++++++++++++- src/ewin-ops.c | 10 ++++++- src/ewin-ops.h | 3 +- src/ewins.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/ewins.h | 26 ++++++++++++++-- src/ipc.c | 52 ++++++++++++++++++++++++++++++-- src/snaps.c | 52 ++++++++++++++++++++++++++++---- 7 files changed, 276 insertions(+), 15 deletions(-) diff --git a/src/desktops.c b/src/desktops.c index 1fdc9597..d091e8ad 100644 --- a/src/desktops.c +++ b/src/desktops.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors - * Copyright (C) 2004-2021 Kim Woelders + * Copyright (C) 2004-2022 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 @@ -53,6 +53,13 @@ #include "xprop.h" #include "xwin.h" +#define DEBUG_DESKS 0 +#if DEBUG_DESKS +#define Dprintf(fmt...) if(EDebug(EDBUG_TYPE_DESKS))Eprintf(fmt) +#else +#define Dprintf(fmt...) +#endif + #define DESK_EVENT_MASK1 \ (ButtonPressMask | ButtonReleaseMask) #define DESK_EVENT_MASK2 \ @@ -1195,6 +1202,28 @@ DeskSwitchDone(void) FocusNewDesk(); } +static int +_doDeskGotoEndDeferred(void *data __UNUSED__) +{ + Dprintf("%s\n", __func__); + + /* The "deferring" is an attempt to delay the pinned window moving + * to after a potential area move following a desk switch. + * Otherwise we will move windows that are pinned to the target desktop + * initial area but not on the target area. */ + EwinsMovePinnedToDesk(desks.current); + + return 0; +} + +static void +_DeskGotoEndDeferred(void) +{ + Dprintf("%s\n", __func__); + + TIMER_ADD_NP(0, _doDeskGotoEndDeferred, NULL); +} + static void _DeskGotoStart(Desk * dsk) { @@ -1217,6 +1246,8 @@ _DeskGotoEnd(Desk * dsk) if (EDebug(EDBUG_TYPE_DESKS)) Eprintf("%s: %d\n", __func__, dsk->num); + + _DeskGotoEndDeferred(); } static int @@ -1732,6 +1763,7 @@ typedef struct { EWin **ewins_slide; int n_ewins_desk, n_ewins_slide; int slide_dx, slide_dy; + int ax, ay; } slide_area_data_t; static void @@ -1747,12 +1779,26 @@ _DeskCurrentGotoAreaEnd(slide_area_data_t * sad) dx = sad->slide_dx; dy = sad->slide_dy; + if (EDebug(EDBUG_TYPE_DESKS)) + Eprintf("%s: %d,%d\n", __func__, sad->ax, sad->ay); + /* move all windows to their final positions */ for (i = 0; i < num; i++) { ewin = lst[i]; if (EwinIsTransientChild(ewin)) continue; + + if (EwinIsPinnedMisplaced(ewin, DesksGetCurrentNum(), sad->ax, sad->ay)) + { + EwinMoveToDesktopAtNocheck(ewin, DesksGetCurrent(), + ewin->vx - + ewin->area_x * WinGetW(VROOT), + ewin->vy - + ewin->area_y * WinGetH(VROOT)); + continue; + } + if (EoGetDesk(ewin) != DesksGetCurrent() && !EoIsFloating(ewin)) continue; @@ -1844,6 +1890,8 @@ DeskCurrentGotoArea(int ax, int ay) sad->n_ewins_slide = 0; sad->slide_dx = dx; sad->slide_dy = dy; + sad->ax = ax; + sad->ay = ay; if (Conf.desks.slidein && Conf.desks.slidespeed > 10) { @@ -1862,6 +1910,9 @@ DeskCurrentGotoArea(int ax, int ay) if (EoIsFloating(ewin) && Conf.movres.mode_move == MR_OPAQUE) continue; + if (EwinIsPinnedMisplaced(ewin, EoGetDeskNum(ewin), ax, ay)) + continue; + wnum++; wl = EREALLOC(EWin *, wl, wnum); wl[wnum - 1] = ewin; diff --git a/src/ewin-ops.c b/src/ewin-ops.c index 4c67abdf..a5fdff72 100644 --- a/src/ewin-ops.c +++ b/src/ewin-ops.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors - * Copyright (C) 2004-2021 Kim Woelders + * Copyright (C) 2004-2022 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 @@ -57,6 +57,7 @@ static const WinOp winops[] = { {"shadow", 0, 1, 1, EWIN_OP_SHADOW}, /* Place before "shade" */ {"shade", 2, 1, 1, EWIN_OP_SHADE}, {"stick", 2, 1, 1, EWIN_OP_STICK}, + {"pin", 0, 1, 1, EWIN_OP_PIN}, {"focus", 2, 1, 0, EWIN_OP_FOCUS}, {"desk", 2, 1, 1, EWIN_OP_DESK}, @@ -476,6 +477,13 @@ EwinMoveToDesktopAt(EWin * ewin, Desk * dsk, int x, int y) doEwinMoveResize(ewin, dsk, x, y, 0, 0, MRF_DESK | MRF_MOVE); } +void +EwinMoveToDesktopAtNocheck(EWin * ewin, Desk * dsk, int x, int y) +{ + doEwinMoveResize(ewin, dsk, x, y, 0, 0, + MRF_DESK | MRF_MOVE | MRF_NOCHECK_ONSCREEN); +} + void EwinOpMove(EWin * ewin, int source, int x, int y) { diff --git a/src/ewin-ops.h b/src/ewin-ops.h index 09cf8f88..e8d85c39 100644 --- a/src/ewin-ops.h +++ b/src/ewin-ops.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2011 Kim Woelders + * Copyright (C) 2005-2022 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 @@ -36,6 +36,7 @@ typedef enum { EWIN_OP_SHADE, EWIN_OP_STICK, EWIN_OP_FOCUS, + EWIN_OP_PIN, EWIN_OP_DESK, EWIN_OP_AREA, diff --git a/src/ewins.c b/src/ewins.c index 30065e89..e6da7a65 100644 --- a/src/ewins.c +++ b/src/ewins.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors - * Copyright (C) 2004-2021 Kim Woelders + * Copyright (C) 2004-2022 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 @@ -1920,6 +1920,78 @@ EwinWarpTo(EWin * ewin, int force) Mode.mouse_over_ewin = ewin; } +int +EwinIsPinnedMisplaced(EWin * ewin, int desk, int ax, int ay) +{ + return ((int)EoGetDeskNum(ewin) != desk || + ewin->area_x != ax || ewin->area_y != ay) && + EwinIsPinnedOn(ewin, desk, ax, ay) >= 0; +} + +int +EwinIsPinnedOn(EWin * ewin, int desk, int ax, int ay) +{ + unsigned int i; + DeskArea *dxy = ewin->pinned; + + for (i = 0; i < ewin->num_pinned; i++, dxy++) + { + if (dxy->desk == desk && dxy->ax == ax && dxy->ay == ay) + return i; + } + + return -1; +} + +void +EwinPinOn(EWin * ewin, int on, int desk, int ax, int ay) +{ + int ix; + unsigned int num; + + if (on == -2) + { + /* Cleaar all */ + EFREE_NULL(ewin->pinned); + ewin->num_pinned = 0; + goto done; + } + + if (desk < 0 || ax < 0 || ay < 0) + return; + + ix = EwinIsPinnedOn(ewin, desk, ax, ay); + + if (on < 0) + on = ix < 0; /* Toggle */ + + if (on) + { + if (ix >= 0) + return; /* Already set */ + + num = ewin->num_pinned++; + ewin->pinned = EREALLOC(DeskArea, ewin->pinned, ewin->num_pinned); + ewin->pinned[num].all = 0; + ewin->pinned[num].desk = desk; + ewin->pinned[num].ax = ax; + ewin->pinned[num].ay = ay; + } + else + { + if (ix < 0) + return; /* Not set */ + + ewin->num_pinned--; + num = ewin->num_pinned - ix; /* Items to move */ + if (num != 0) + memmove(ewin->pinned + ix, ewin->pinned + 1, num * sizeof(DeskArea)); + } + + done: + SnapshotEwinUpdate(ewin, SNAP_USE_STICKY); +} + typedef union { unsigned int all; struct { @@ -2228,6 +2300,27 @@ EwinsMoveStickyToDesk(Desk * dsk) } } +void +EwinsMovePinnedToDesk(Desk * dsk) +{ + EWin *const *lst, *ewin; + int i, num, ax, ay; + + DeskGetArea(dsk, &ax, &ay); + + lst = EwinListStackGet(&num); + for (i = 0; i < num; i++) + { + ewin = lst[num - 1 - i]; + if (!EwinIsPinnedMisplaced(ewin, dsk->num, ax, ay)) + continue; + + EwinMoveToDesktopAtNocheck(ewin, dsk, + ewin->vx - ewin->area_x * WinGetW(VROOT), + ewin->vy - ewin->area_y * WinGetH(VROOT)); + } +} + void EwinsManage(void) { diff --git a/src/ewins.h b/src/ewins.h index 8ec49d61..94a2ef29 100644 --- a/src/ewins.h +++ b/src/ewins.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors - * Copyright (C) 2004-2021 Kim Woelders + * Copyright (C) 2004-2022 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 @@ -64,6 +64,15 @@ typedef struct { void (*Close)(EWin * ewin); } EWinOps; +typedef union { + unsigned int all; + struct { + unsigned char rsvd; + unsigned char desk; + unsigned char ax, ay; + }; +} DeskArea; + struct _ewin { EObj o; char type; @@ -250,7 +259,12 @@ struct _ewin { int num_groups; Group **groups; + int area_x, area_y; + + unsigned int num_pinned; + DeskArea *pinned; + char *session_id; PmapMask mini_pmm; @@ -410,7 +424,13 @@ EWin **EwinListTransientFor(const EWin * ewin, int *num); void EwinsManage(void); void EwinsSetFree(void); void EwinsShowDesktop(int on); -void EwinsMoveStickyToDesk(Desk * d); +void EwinsMoveStickyToDesk(Desk * dsk); +void EwinsMovePinnedToDesk(Desk * dsk); + +void EwinPinOn(EWin * ewin, int on, int desk, int ax, int ay); +int EwinIsPinnedOn(EWin * ewin, int desk, int ax, int ay); +int EwinIsPinnedMisplaced(EWin * ewin, + int desk, int ax, int ay); /* ewin-ops.c */ /* Move/resize flags */ @@ -425,6 +445,8 @@ void EwinMoveResizeWithGravity(EWin * ewin, int x, int y, int w, int h, int grav); void EwinMoveToDesktop(EWin * ewin, Desk * d); void EwinMoveToDesktopAt(EWin * ewin, Desk * d, int x, int y); +void EwinMoveToDesktopAtNocheck(EWin * ewin, Desk * dsk, + int x, int y); void EwinIconify(EWin * ewin); void EwinAlone(EWin * ewin); void EwinDeIconify(EWin * ewin); diff --git a/src/ipc.c b/src/ipc.c index 029bf558..b8ef4825 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors - * Copyright (C) 2004-2021 Kim Woelders + * Copyright (C) 2004-2022 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 @@ -427,9 +427,9 @@ static void IpcWinop(const WinOp * wop, EWin * ewin, const char *prm) { char param1[128], param2[128]; - unsigned int val; + unsigned int i, val; char on; - int a, b; + int a, b, d; param1[0] = param2[0] = '\0'; sscanf(prm, "%127s %127s", param1, param2); @@ -508,6 +508,47 @@ IpcWinop(const WinOp * wop, EWin * ewin, const char *prm) EwinOpActivate(ewin, OPSRC_USER, 1); break; + case EWIN_OP_PIN: + if (!param1[0]) + { + IpcPrintf("Error: no parameters supplied\n"); + goto done; + } + else if (!strcmp(param1, "?")) + { + for (i = 0; i < ewin->num_pinned; i++) + IpcPrintf("%2d: %d,%d\n", ewin->pinned[i].desk, + ewin->pinned[i].ax, ewin->pinned[i].ay); + } + else if (!strcmp(param1, "clear")) + { + EwinPinOn(ewin, -2, 0, 0, 0); + } + else + { + if (!strcmp(param1, "on")) + on = 1; + else if (!strcmp(param1, "off")) + on = 0; + else if (!strcmp(param1, "tgl")) + on = -1; + else + break; + + if (param2[0] == '*') + { + d = EoGetDeskNum(ewin); + DeskGetArea(EoGetDesk(ewin), &a, &b); + } + else + { + a = b = d = -1; + sscanf(prm, "%*s %u %u %u", &d, &a, &b); + } + EwinPinOn(ewin, on, d, a, b); + } + break; + case EWIN_OP_DESK: if (!param1[0]) { @@ -1546,6 +1587,7 @@ IPC_Compat(const char *params) */ static void IPC_Help(const char *params); +/**INDENT-OFF**/ static const IpcItem IPCArray[] = { { IPC_Help, @@ -1606,6 +1648,9 @@ static const IpcItem IPCArray[] = { " win_op <windowid> title <title>\n" " win_op <windowid> <close/kill>\n" " win_op <windowid> <focus/iconify/alone/shade/stick>\n" + " win_op <windowid> pin <on/off/tgl> desk area_x area_y\n" + " pin ?\n" + " pin clear\n" #if USE_COMPOSITE " win_op <windowid> <fade/shadow>\n" #endif @@ -1706,6 +1751,7 @@ static const IpcItem IPCArray[] = { " keys <string>\n"}, #endif }; +/**INDENT-ON**/ static int ipc_item_count = 0; static const IpcItem **ipc_item_list = NULL; diff --git a/src/snaps.c b/src/snaps.c index a783bdec..c98fdcd9 100644 --- a/src/snaps.c +++ b/src/snaps.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors - * Copyright (C) 2004-2020 Kim Woelders + * Copyright (C) 2004-2022 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 @@ -21,6 +21,7 @@ * 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. */ +#include <arpa/inet.h> #include "E.h" #include "borders.h" #include "desktops.h" @@ -33,6 +34,7 @@ #include "settings.h" #include "snaps.h" #include "timers.h" +#include "util.h" #include "xwin.h" struct _snapshot { @@ -57,6 +59,8 @@ struct _snapshot { int layer; char shaded; char sticky; + int *pinned; + int num_pinned; unsigned int flags[2]; char *cmd; int *groups; @@ -349,6 +353,10 @@ static void _SnapUpdateEwinSticky(Snapshot * sn, const EWin * ewin) { sn->sticky = EoIsSticky(ewin); + sn->num_pinned = ewin->num_pinned; + EFREE_NULL(sn->pinned); + if (sn->num_pinned) + sn->pinned = EMEMDUP(int, ewin->pinned, ewin->num_pinned); } static void @@ -1118,7 +1126,15 @@ SnapshotsSaveReal(void) if (sn->use_flags & SNAP_USE_LAYER) fprintf(f, "LAYER: %i\n", sn->layer); if (sn->use_flags & SNAP_USE_STICKY) - fprintf(f, "STICKY: %i\n", sn->sticky); + { + fprintf(f, "STICKY: %i", sn->sticky); + if (sn->pinned) + { + for (i = 0; i < sn->num_pinned; i++) + fprintf(f, " %06x", htonl(sn->pinned[i])); + } + fprintf(f, "\n"); + } if (sn->use_flags & SNAP_USE_SHADED) fprintf(f, "SHADE: %i\n", sn->shaded); if (sn->use_flags & SNAP_USE_SKIP_LISTS) @@ -1317,7 +1333,20 @@ _SnapshotsLoad(FILE * fs) else if (!strcmp(buf, "STICKY")) { sn->use_flags |= SNAP_USE_STICKY; - sn->sticky = atoi(s); + a = b = 0; + sscanf(s, "%d %n", &a, &b); + sn->sticky = a; + for (;;) + { + s += b; + b = 0; + sscanf(s, "%x %n", &a, &b); + if (b <= 0) + break; + sn->num_pinned++; + sn->pinned = EREALLOC(int, sn->pinned, sn->num_pinned); + sn->pinned[sn->num_pinned - 1] = htonl(a); + } } else if (!strcmp(buf, "SHADE")) { @@ -1427,7 +1456,11 @@ SnapshotEwinApply(EWin * ewin) SNAP_USE_OPACITY; if (use_flags & SNAP_USE_STICKY) - EoSetSticky(ewin, sn->sticky); + { + EoSetSticky(ewin, sn->sticky); + ewin->num_pinned = sn->num_pinned; + ewin->pinned = EMEMDUP(DeskArea, sn->pinned, sn->num_pinned); + } if (use_flags & SNAP_USE_DESK) EoSetDesk(ewin, DeskGetValid(sn->desktop)); @@ -1452,8 +1485,15 @@ SnapshotEwinApply(EWin * ewin) if (!EoIsSticky(ewin)) { DeskGetArea(EoGetDesk(ewin), &ax, &ay); - ewin->client.x += ((sn->area_x - ax) * WinGetW(VROOT)); - ewin->client.y += ((sn->area_y - ay) * WinGetH(VROOT)); + if (EwinIsPinnedOn(ewin, DesksGetCurrentNum(), ax, ay) >= 0) + { + EoSetDesk(ewin, DesksGetCurrent()); + } + else + { + ewin->client.x += ((sn->area_x - ax) * WinGetW(VROOT)); + ewin->client.y += ((sn->area_y - ay) * WinGetH(VROOT)); + } } } --
