summaryrefslogtreecommitdiff
path: root/selection.c
diff options
context:
space:
mode:
authorDennis Kasprzyk <onestone@beryl-project.org>2007-05-17 12:42:14 +0200
committerDennis Kasprzyk <onestone@beryl-project.org>2007-05-17 12:42:14 +0200
commit3fc23b3a1de0851539bbe8133ea9f4a102a4041e (patch)
tree6ae60f4603df9ad687249fa0aebaac427bac83d4 /selection.c
parent2ea16a99890c1822cd1faf2ef8637d39c471d3f4 (diff)
downloadgroup-3fc23b3a1de0851539bbe8133ea9f4a102a4041e.tar.gz
group-3fc23b3a1de0851539bbe8133ea9f4a102a4041e.tar.bz2
added the files
Diffstat (limited to 'selection.c')
-rw-r--r--selection.c357
1 files changed, 357 insertions, 0 deletions
diff --git a/selection.c b/selection.c
new file mode 100644
index 0000000..d8c9ebf
--- /dev/null
+++ b/selection.c
@@ -0,0 +1,357 @@
+#include "group.h"
+
+/**
+ *
+ * Beryl group plugin
+ *
+ * selection.c
+ *
+ * Copyright : (C) 2006 by Patrick Niklaus, Roi Cohen, Danny Baumann
+ * Authors: Patrick Niklaus <patrick.niklaus@googlemail.com>
+ * Roi Cohen <roico@beryl-project.org>
+ * Danny Baumann <maniac@beryl-project.org>
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ **/
+
+/*
+ * groupWindowInRegion
+ *
+ */
+ static Bool
+ groupWindowInRegion(CompWindow *w, Region src, float precision)
+ {
+ Region buf = XCreateRegion();
+ XIntersectRegion(w->region, src, buf);
+
+ // buf area
+ int i;
+ int area = 0;
+ BOX *box;
+ for(i = 0; i < buf->numRects; i++) {
+ box = &buf->rects[i];
+ area += (box->x2 - box->x1) * (box->y2 - box->y1); // width * height
+ }
+
+ XDestroyRegion(buf);
+
+ if (area >= WIN_WIDTH(w) * WIN_HEIGHT(w) * precision) {
+ XSubtractRegion(src, w->region, src);
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ /*
+ * groupFindGroupInWindows
+ *
+ */
+ static Bool groupFindGroupInWindows(GroupSelection *group, CompWindow **windows, int nWins)
+ {
+ int i;
+ for (i = 0; i < nWins; i++) {
+ CompWindow *cw = windows[i];
+ GROUP_WINDOW(cw);
+ if (gw->group == group)
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ /*
+ * groupFindWindowsInRegion
+ *
+ */
+ CompWindow **groupFindWindowsInRegion(CompScreen * s, Region reg, int *c)
+ {
+ float precision = groupGetSelectPrecision(s) / 100.0f;
+
+ CompWindow **ret = NULL;
+ int count = 0;
+ CompWindow *w;
+ for (w = s->reverseWindows; w; w = w->prev) {
+ if (matchEval(groupGetWindowMatch(s), w) &&
+ !w->invisible &&
+ groupWindowInRegion(w, reg, precision))
+ {
+ GROUP_WINDOW(w);
+ if (gw->group && groupFindGroupInWindows(gw->group, ret, count))
+ continue;
+
+ if (count == 0) {
+ ret = calloc(1, sizeof(CompWindow));
+ ret[0] = w;
+ } else {
+ ret = realloc(ret, sizeof(CompWindow) * (count + 1));
+ ret[count] = w;
+ }
+
+ count++;
+ }
+ }
+
+ (*c) = count;
+ return ret;
+}
+
+/*
+ * groupDeleteSelectionWindow
+ *
+ */
+void groupDeleteSelectionWindow(CompDisplay * d, CompWindow * w)
+{
+ GROUP_DISPLAY(d);
+
+ if (gd->tmpSel.nWins > 0 && gd->tmpSel.windows) {
+ CompWindow **buf = gd->tmpSel.windows;
+ gd->tmpSel.windows = (CompWindow **) calloc(gd->tmpSel.nWins - 1, sizeof(CompWindow *));
+
+ int counter = 0;
+ int i;
+ for (i = 0; i < gd->tmpSel.nWins; i++) {
+ if (buf[i]->id == w->id)
+ continue;
+ gd->tmpSel.windows[counter++] = buf[i];
+ }
+
+ gd->tmpSel.nWins = counter;
+ free(buf);
+ }
+}
+
+/*
+ * groupAddWindowToSelection
+ *
+ */
+void groupAddWindowToSelection(CompDisplay * d, CompWindow * w)
+{
+ GROUP_DISPLAY(d);
+
+ gd->tmpSel.windows = (CompWindow **) realloc(gd->tmpSel.windows, sizeof(CompWindow *) * (gd->tmpSel.nWins + 1));
+
+ gd->tmpSel.windows[gd->tmpSel.nWins] = w;
+ gd->tmpSel.nWins++;
+}
+
+/*
+ * groupSelectWindow
+ *
+ */
+void groupSelectWindow(CompDisplay * d, CompWindow * w)
+{
+ GROUP_DISPLAY(d);
+ GROUP_WINDOW(w);
+
+ // select singe window
+ if (matchEval(groupGetWindowMatch(w->screen), w) &&
+ !w->invisible && !gw->inSelection && !gw->group) {
+
+ groupAddWindowToSelection(d, w);
+
+ gw->inSelection = TRUE;
+ addWindowDamage(w);
+ }
+ // unselect single window
+ else if (matchEval(groupGetWindowMatch(w->screen), w) &&
+ !w->invisible && gw->inSelection && !gw->group) {
+
+ groupDeleteSelectionWindow(d, w);
+ gw->inSelection = FALSE;
+ addWindowDamage(w);
+ }
+ // select group
+ else if (matchEval(groupGetWindowMatch(w->screen), w) &&
+ !w->invisible && !gw->inSelection && gw->group) {
+
+ int i;
+ for (i = 0; i < gw->group->nWins; i++) {
+ CompWindow *cw = gw->group->windows[i];
+ GROUP_WINDOW(cw);
+
+ groupAddWindowToSelection(d, cw);
+
+ gw->inSelection = TRUE;
+ addWindowDamage(cw);
+ }
+ }
+ // Unselect group
+ else if (matchEval(groupGetWindowMatch(w->screen), w) &&
+ !w->invisible && gw->inSelection && gw->group) {
+
+ GroupSelection *group = gw->group;
+ CompWindow **buf = gd->tmpSel.windows;
+ gd->tmpSel.windows = (CompWindow **) calloc(gd->tmpSel.nWins - gw->group->nWins, sizeof(CompWindow *));
+
+ int counter = 0;
+ int i;
+ for (i = 0; i < gd->tmpSel.nWins; i++) {
+ CompWindow *cw = buf[i];
+ GROUP_WINDOW(cw);
+
+ if (gw->group == group) {
+ gw->inSelection = FALSE;
+ addWindowDamage(cw);
+ continue;
+ }
+
+ gd->tmpSel.windows[counter++] = buf[i];
+ }
+ gd->tmpSel.nWins = counter;
+ free(buf);
+ }
+
+}
+
+/*
+ * groupSelectSingle
+ *
+ */
+Bool
+groupSelectSingle(CompDisplay * d, CompAction * action,
+ CompActionState state, CompOption * option, int nOption)
+{
+ CompWindow *w = (CompWindow *) findWindowAtDisplay(d, d->activeWindow);
+
+ if (w)
+ groupSelectWindow(d, w);
+
+ return TRUE;
+}
+
+/*
+ * groupSelect
+ *
+ */
+Bool
+groupSelect(CompDisplay * d, CompAction * action, CompActionState state,
+ CompOption * option, int nOption)
+{
+ CompWindow *w = (CompWindow *) findWindowAtDisplay(d, d->activeWindow);
+ if (!w)
+ return FALSE;
+
+ GROUP_SCREEN(w->screen);
+
+ if (gs->grabState == ScreenGrabNone) {
+ groupGrabScreen(w->screen, ScreenGrabSelect);
+
+ if (state & CompActionStateInitKey)
+ action->state |= CompActionStateTermKey;
+
+ if (state & CompActionStateInitButton)
+ action->state |= CompActionStateTermButton;
+
+ gs->x1 = gs->x2 = pointerX;
+ gs->y1 = gs->y2 = pointerY;
+ }
+
+ return TRUE;
+}
+
+/*
+ * groupSelectTerminate
+ *
+ */
+Bool
+groupSelectTerminate(CompDisplay * d, CompAction * action,
+ CompActionState state, CompOption * option,
+ int nOption)
+{
+ CompScreen *s;
+ Window xid;
+
+ xid = getIntOptionNamed(option, nOption, "root", 0);
+
+ for (s = d->screens; s; s = s->next) {
+ if (xid && s->root != xid)
+ continue;
+ break;
+ }
+
+ if (s) {
+ GROUP_SCREEN(s);
+
+ if (gs->grabState == ScreenGrabSelect) {
+ groupGrabScreen(s, ScreenGrabNone);
+
+ if (gs->x1 != gs->x2 && gs->y1 != gs->y2) {
+ Region reg = XCreateRegion();
+ XRectangle rect;
+
+ rect.x = MIN(gs->x1, gs->x2) - 2;
+ rect.y = MIN(gs->y1, gs->y2) - 2;
+ rect.width = MAX(gs->x1, gs->x2) - MIN(gs->x1, gs->x2) + 4;
+ rect.height = MAX(gs->y1, gs->y2) - MIN(gs->y1, gs->y2) + 4;
+ XUnionRectWithRegion(&rect, reg, reg);
+
+ damageScreenRegion(s, reg);
+
+ int count;
+ CompWindow **ws = groupFindWindowsInRegion(s, reg, &count);
+
+ if (ws) {
+ // select windows
+ int i;
+ for (i = 0; i < count; i++) {
+ CompWindow *cw = ws[i];
+
+ groupSelectWindow(d, cw);
+ }
+ if (groupGetAutoGroup(s)) {
+ groupGroupWindows(d, NULL, 0, NULL, 0);
+ }
+ free(ws);
+ }
+
+ XDestroyRegion(reg);
+ }
+ }
+
+ }
+
+ action->state &=
+ ~(CompActionStateTermKey | CompActionStateTermButton);
+
+ return FALSE;
+}
+
+/*
+ * groupDamageSelectionRect
+ *
+ */
+void
+groupDamageSelectionRect(CompScreen* s, int xRoot, int yRoot)
+{
+ GROUP_SCREEN(s);
+ REGION reg;
+
+ reg.rects = &reg.extents;
+ reg.numRects = 1;
+
+ reg.extents.x1 = MIN(gs->x1, gs->x2) - 5;
+ reg.extents.y1 = MIN(gs->y1, gs->y2) - 5;
+ reg.extents.x2 = MAX(gs->x1, gs->x2) + 5;
+ reg.extents.y2 = MAX(gs->y1, gs->y2) + 5;
+ damageScreenRegion(s, &reg);
+
+ gs->x2 = xRoot;
+ gs->y2 = yRoot;
+
+ reg.extents.x1 = MIN(gs->x1, gs->x2) - 5;
+ reg.extents.y1 = MIN(gs->y1, gs->y2) - 5;
+ reg.extents.x2 = MAX(gs->x1, gs->x2) + 5;
+ reg.extents.y2 = MAX(gs->y1, gs->y2) + 5;
+ damageScreenRegion(s, &reg);
+}