2 * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3 * Copyright (C) 2004-2009 Kim Woelders
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies of the Software, its documentation and marketing & publicity
14 * materials, and acknowledgment shall be given in the documentation, materials
15 * and software packages that this Software was used.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 #include "iclass.h" /* FIXME - Should not be here */
40 static const WinOp winops[] = {
41 {"border", 2, 1, 0, EWIN_OP_BORDER},
42 {"title", 2, 1, 1, EWIN_OP_TITLE},
44 {"focusclick", 0, 1, 1, EWIN_OP_FOCUS_CLICK}, /* Place before "focus" */
46 {"close", 2, 1, 0, EWIN_OP_CLOSE},
47 {"kill", 0, 1, 0, EWIN_OP_KILL},
48 {"iconify", 2, 1, 1, EWIN_OP_ICONIFY},
49 {"alone", 0, 1, 0, EWIN_OP_ALONE},
50 {"opacity", 2, 1, 1, EWIN_OP_OPACITY},
51 {"focused_opacity", 0, 1, 1, EWIN_OP_FOCUSED_OPACITY},
52 {"shadow", 0, 1, 1, EWIN_OP_SHADOW}, /* Place before "shade" */
53 {"shade", 2, 1, 1, EWIN_OP_SHADE},
54 {"stick", 2, 1, 1, EWIN_OP_STICK},
55 {"focus", 2, 1, 0, EWIN_OP_FOCUS},
57 {"desk", 2, 1, 1, EWIN_OP_DESK},
58 {"area", 2, 1, 1, EWIN_OP_AREA},
59 {"move", 2, 1, 1, EWIN_OP_MOVE},
60 {"size", 2, 1, 1, EWIN_OP_SIZE},
61 {"sz", 2, 1, 1, EWIN_OP_SIZE},
62 {"move_relative", 0, 1, 0, EWIN_OP_MOVE_REL},
63 {"mr", 2, 1, 0, EWIN_OP_MOVE_REL},
64 {"resize_relative", 0, 1, 0, EWIN_OP_SIZE_REL},
65 {"sr", 2, 1, 0, EWIN_OP_SIZE_REL},
67 {"toggle_width", 0, 1, 0, EWIN_OP_MAX_WIDTH},
68 {"tw", 2, 1, 0, EWIN_OP_MAX_WIDTH},
69 {"toggle_height", 0, 1, 0, EWIN_OP_MAX_HEIGHT},
70 {"th", 0, 1, 0, EWIN_OP_MAX_HEIGHT},
71 {"toggle_size", 0, 1, 0, EWIN_OP_MAX_SIZE},
72 {"ts", 2, 1, 0, EWIN_OP_MAX_SIZE},
73 {"fullscreen", 2, 1, 1, EWIN_OP_FULLSCREEN},
74 {"zoom", 2, 1, 0, EWIN_OP_ZOOM},
76 {"layer", 2, 1, 1, EWIN_OP_LAYER},
77 {"raise", 2, 1, 0, EWIN_OP_RAISE},
78 {"lower", 2, 1, 0, EWIN_OP_LOWER},
80 {"snap", 0, 1, 0, EWIN_OP_SNAP},
82 {"never_use_area", 0, 1, 1, EWIN_OP_NEVER_USE_AREA},
83 {"no_button_grabs", 0, 1, 1, EWIN_OP_NO_BUTTON_GRABS},
84 {"skiplists", 4, 1, 1, EWIN_OP_SKIP_LISTS},
85 {"autoshade", 0, 1, 1, EWIN_OP_AUTOSHADE},
87 {"no_app_focus", 0, 1, 1, EWIN_OP_INH_APP_FOCUS},
88 {"no_app_move", 0, 1, 1, EWIN_OP_INH_APP_MOVE},
89 {"no_app_size", 0, 1, 1, EWIN_OP_INH_APP_SIZE},
90 {"no_user_close", 0, 1, 1, EWIN_OP_INH_USER_CLOSE},
91 {"no_user_move", 0, 1, 1, EWIN_OP_INH_USER_MOVE},
92 {"no_user_size", 0, 1, 1, EWIN_OP_INH_USER_SIZE},
93 {"no_wm_focus", 0, 1, 1, EWIN_OP_INH_WM_FOCUS},
95 {"fade", 0, 1, 1, EWIN_OP_FADE},
96 {"no_redir", 4, 1, 1, EWIN_OP_NO_REDIRECT},
97 {"no_argb", 0, 1, 1, EWIN_OP_NO_ARGB},
99 {NULL, 0, 0, 0, EWIN_OP_INVALID} /* Terminator */
103 EwinOpFind(const char *op)
108 for (; wop->name; wop++)
112 if (!strncmp(op, wop->name, wop->len))
117 if (!strcmp(op, wop->name))
126 EwinDetermineArea(EWin * ewin)
131 dsk = EoGetDesk(ewin);
132 ewin->vx = dsk->current_area_x * EoGetW(dsk) + EoGetX(ewin);
133 ewin->vy = dsk->current_area_y * EoGetH(dsk) + EoGetY(ewin);
135 if (EwinIsOnScreen(ewin))
137 ax = dsk->current_area_x;
138 ay = dsk->current_area_y;
142 ax = (ewin->vx + EoGetW(ewin) / 2) / EoGetW(dsk);
143 ay = (ewin->vy + EoGetH(ewin) / 2) / EoGetH(dsk);
144 DesksFixArea(&ax, &ay);
147 if (ax != ewin->area_x || ay != ewin->area_y)
151 HintsSetWindowArea(ewin);
155 #define MRF_DESK (1<<0)
156 #define MRF_MOVE (1<<1)
157 #define MRF_RESIZE (1<<2)
158 #define MRF_RAISE (1<<3)
159 #define MRF_FLOAT (1<<4)
160 #define MRF_UNFLOAT (1<<5)
163 doEwinMoveResize(EWin * ewin, Desk * dsk, int x, int y, int w, int h, int flags)
165 static int call_depth = 0;
166 int dx, dy, sw, sh, xo, yo;
167 char move, resize, reparent, raise, floating, configure;
172 if (call_depth > 256)
176 if (EDebug(EDBUG_TYPE_MOVERESIZE))
177 Eprintf("doEwinMoveResize(%d,%d) %#lx f=%x d=%d %d+%d %d*%d %s\n",
178 call_depth, Mode.mode, EwinGetClientXwin(ewin), flags,
179 (dsk) ? (int)dsk->num : -1, x, y, w, h, EwinGetTitle(ewin));
181 pdesk = (ewin->o.stacked >= 0) ? EoGetDesk(ewin) : NULL;
182 reparent = move = resize = raise = 0;
183 floating = EoIsFloating(ewin);
185 if (flags & (MRF_DESK | MRF_FLOAT | MRF_UNFLOAT))
187 if (flags & MRF_FLOAT)
189 if (EoIsFloating(ewin) == 0)
191 dsk = (pdesk == NULL) ? EoGetDesk(ewin) : pdesk;
194 else if (EoIsFloating(ewin) == 1)
201 else if (flags & MRF_UNFLOAT)
208 if (EoIsSticky(ewin) && !EoIsFloating(ewin))
209 dsk = DesksGetCurrent();
216 dsk = EoGetDesk(ewin);
219 if (Mode.mode == MODE_NONE && Mode.move.check)
221 /* Don't throw windows offscreen */
224 if (EoIsSticky(ewin))
232 DeskGetArea(dsk, &ax, &ay);
235 sw *= Conf.desks.areas_nx;
236 sh *= Conf.desks.areas_ny;
239 if (ewin->state.shaded)
241 /* Keep shaded windows entirely on-screen */
247 /* Keep at least 8 pixels on-screen */
248 dx = EoGetW(ewin) / 4;
251 dy = EoGetH(ewin) / 4;
256 if (x < xo - EoGetW(ewin) + dx)
257 x = xo - EoGetW(ewin) + dx;
258 else if (x > xo + sw - dx)
260 if (y < yo - EoGetH(ewin) + dy)
261 y = yo - EoGetH(ewin) + dy;
262 else if (y > yo + sh - dy)
266 if (flags & MRF_RAISE)
269 if (!(flags & MRF_MOVE))
275 if (!(flags & MRF_RESIZE))
282 if (ewin->ops && ewin->ops->Layout)
284 ewin->ops->Layout(ewin, &x, &y, &w, &h);
288 ICCCM_SizeMatch(ewin, w, h, &w, &h);
295 if ((w != ewin->client.w) || (h != ewin->client.h))
300 /* Don't touch frame size while shaded */
301 if (ewin->state.shaded)
308 w = ewin->client.w + ewin->border->border.left +
309 ewin->border->border.right;
310 h = ewin->client.h + ewin->border->border.top +
311 ewin->border->border.bottom;
315 dx = x - EoGetX(ewin);
316 dy = y - EoGetY(ewin);
317 if ((dx != 0) || (dy != 0))
319 ewin->client.x = x + ewin->border->border.left;
320 ewin->client.y = y + ewin->border->border.top;
323 Eprintf("repa=%d float=%d raise=%d move=%d resz=%d\n",
324 reparent, floating, raise, move, resize);
326 if (EoIsShown(ewin) && (move || reparent))
327 ModulesSignal(ESIGNAL_EWIN_CHANGE, ewin);
330 EoReparent(ewin, EoObj(dsk), x, y);
332 EoMoveResize(ewin, x, y, w, h);
335 if (Mode.mode == MODE_NONE || resize || Conf.movres.update_while_moving)
339 if (Conf.movres.enable_sync_request)
340 EwinSyncRequestSend(ewin);
344 if (flags & MRF_RESIZE)
346 if (!ewin->state.shaded)
347 EMoveResizeWindow(ewin->win_container,
348 ewin->border->border.left,
349 ewin->border->border.top,
350 ewin->client.w, ewin->client.h);
353 EMoveResizeWindow(ewin->win_container, -30, -30, 1, 1);
356 EMoveResizeWindow(EwinGetClientWin(ewin), 0, 0, ewin->client.w,
358 EwinBorderCalcSizes(ewin, 0);
360 /* Clear maximized state on resize */
361 if (resize && !ewin->state.maximizing && !ewin->state.shading)
363 if (ewin->state.maximized_horz || ewin->state.maximized_vert)
365 ewin->state.maximized_horz = 0;
366 ewin->state.maximized_vert = 0;
367 HintsSetWindowState(ewin);
370 if (resize && ewin->state.shaped)
371 ewin->update.shape = 1;
374 EwinPropagateShapes(ewin);
378 EoSetFloating(ewin, floating);
385 ICCCM_Configure(ewin);
387 if (Conf.movres.enable_sync_request)
388 EwinSyncRequestWait(ewin);
392 if (flags & (MRF_DESK | MRF_MOVE | MRF_FLOAT | MRF_UNFLOAT))
394 lst = EwinListTransients(ewin, &num, 0);
395 for (i = 0; i < num; i++)
396 doEwinMoveResize(lst[i], dsk, EoGetX(lst[i]) + dx,
397 EoGetY(lst[i]) + dy, 0, 0,
398 flags & (MRF_DESK | MRF_MOVE |
399 MRF_FLOAT | MRF_UNFLOAT));
403 EwinDetermineArea(ewin);
404 if (Mode.op_source == OPSRC_USER)
405 EwinSetPlacementGravity(ewin, x, y);
407 if ((flags & (MRF_MOVE | MRF_RESIZE)) && ewin->ops && ewin->ops->MoveResize)
408 ewin->ops->MoveResize(ewin, resize);
410 if (Mode.mode == MODE_NONE)
412 if (TransparencyUpdateNeeded())
413 EwinBorderDraw(ewin, resize, 1); /* Update the border */
415 SnapshotEwinUpdate(ewin, SNAP_USE_POS | SNAP_USE_SIZE);
418 ModulesSignal(ESIGNAL_EWIN_CHANGE, ewin);
423 HintsSetWindowDesktop(ewin);
424 SnapshotEwinUpdate(ewin, SNAP_USE_DESK);
431 EwinMove(EWin * ewin, int x, int y)
433 doEwinMoveResize(ewin, NULL, x, y, 0, 0, MRF_MOVE);
437 EwinResize(EWin * ewin, int w, int h)
439 doEwinMoveResize(ewin, NULL, 0, 0, w, h, MRF_RESIZE);
443 EwinMoveResize(EWin * ewin, int x, int y, int w, int h)
445 doEwinMoveResize(ewin, NULL, x, y, w, h, MRF_MOVE | MRF_RESIZE);
449 EwinMoveResizeWithGravity(EWin * ewin, int x, int y, int w, int h, int grav)
451 EwinGetPosition(ewin, x, y, grav, &x, &y);
452 doEwinMoveResize(ewin, NULL, x, y, w, h, MRF_MOVE | MRF_RESIZE);
456 EwinMoveToDesktop(EWin * ewin, Desk * dsk)
458 doEwinMoveResize(ewin, dsk, 0, 0, 0, 0, MRF_DESK);
462 EwinMoveToDesktopAt(EWin * ewin, Desk * dsk, int x, int y)
464 doEwinMoveResize(ewin, dsk, x, y, 0, 0, MRF_DESK | MRF_MOVE);
468 EwinOpMove(EWin * ewin, int source, int x, int y)
470 Mode.op_source = source;
471 EwinMove(ewin, x, y);
476 EwinOpResize(EWin * ewin, int source, int w, int h)
478 Mode.op_source = source;
479 EwinResize(ewin, w, h);
484 EwinOpMoveResize(EWin * ewin, int source, int x, int y, int w, int h)
486 Mode.op_source = source;
487 EwinMoveResize(ewin, x, y, w, h);
492 EwinOpMoveToDesktopAt(EWin * ewin, int source, Desk * dsk, int x, int y)
494 Mode.op_source = source;
495 EwinMoveToDesktopAt(ewin, dsk, x, y);
500 EwinOpFloatAt(EWin * ewin, int source, int x, int y)
502 Mode.op_source = source;
503 doEwinMoveResize(ewin, EoGetDesk(ewin), x, y, 0, 0, MRF_MOVE | MRF_FLOAT);
508 EwinOpUnfloatAt(EWin * ewin, int source, Desk * dsk, int x, int y)
510 Mode.op_source = source;
511 doEwinMoveResize(ewin, dsk, x, y, 0, 0, MRF_MOVE | MRF_UNFLOAT);
516 EwinIconify(EWin * ewin)
518 static int call_depth = 0;
526 if (GetZoomEWin() == ewin)
529 if (ewin->state.inhibit_iconify)
532 if (ewin->state.state != EWIN_STATE_MAPPED)
535 if (call_depth > 256)
539 was_shaded = ewin->state.shaded;
541 if (!EwinIsTransient(ewin))
542 ModulesSignal(ESIGNAL_EWIN_ICONIFY, ewin);
544 ewin->state.iconified = 1;
547 /* Save position at which the window was iconified */
548 EwinRememberPositionSet(ewin);
550 if (was_shaded != ewin->state.shaded)
551 EwinInstantShade(ewin, 0);
555 lst = EwinListTransients(ewin, &num, 0);
556 for (i = 0; i < num; i++)
559 if (e->state.iconified)
565 if (lst && call_depth == 1)
566 GNOME_SetClientList();
570 EwinStateUpdate(ewin);
571 HintsSetWindowState(ewin);
577 EwinAlone(EWin * ewin)
579 EWin *const *lst, *item;
582 lst = EwinListGetForDesk(&num, EoGetDesk(ewin));
584 for (i = 0; i < num; i++)
588 if (item == ewin || EwinIsTransient(item) ||
589 item->state.iconified || item->state.donthide ||
590 item->area_x != ewin->area_x || item->area_y != ewin->area_y)
597 GetOnScreenPos(int x, int y, int w, int h, int *px, int *py)
601 if (x + w > 4 && x <= WinGetW(VROOT) - 4 &&
602 y + h > 4 && y <= WinGetH(VROOT) - 4)
607 x = (x + dx) % WinGetW(VROOT);
611 y = (y + dy) % WinGetH(VROOT);
622 EwinDeIconify1(EWin * ewin, int dx, int dy)
624 static int call_depth = 0;
629 if (call_depth > 256)
633 if (ewin->state.state != EWIN_STATE_ICONIC || !ewin->state.iconified)
636 EwinRememberPositionGet(ewin, DesksGetCurrent(), &x, &y);
638 EwinMoveToDesktopAt(ewin, DesksGetCurrent(), x + dx, y + dy);
640 if (!EwinIsTransient(ewin))
641 ModulesSignal(ESIGNAL_EWIN_DEICONIFY, ewin);
643 ewin->state.iconified = 0;
644 ewin->state.showingdesk = 0;
648 ICCCM_DeIconify(ewin);
650 lst = EwinListTransients(ewin, &num, 0);
651 for (i = 0; i < num; i++)
654 if (!e->state.iconified)
657 EwinDeIconify1(e, dx, dy);
660 if (lst && call_depth == 1)
661 GNOME_SetClientList();
665 EwinStateUpdate(ewin);
666 HintsSetWindowState(ewin);
672 EwinDeIconify(EWin * ewin)
674 int x, y, ox, oy, dx, dy;
676 EwinRememberPositionGet(ewin, DesksGetCurrent(), &x, &y);
680 /* If we iconified an offscreen window, get it back on screen */
681 if (!ewin->state.showingdesk)
682 GetOnScreenPos(x, y, EoGetW(ewin), EoGetH(ewin), &x, &y);
687 EwinDeIconify1(ewin, dx, dy);
691 EwinUnStick(EWin * ewin)
693 if (!EoIsSticky(ewin))
696 SoundPlay(SOUND_WINDOW_UNSTICK);
698 EoSetSticky(ewin, 0);
699 EwinMoveToDesktopAt(ewin, DesksGetCurrent(), EoGetX(ewin), EoGetY(ewin));
700 EwinBorderUpdateState(ewin);
701 EwinStateUpdate(ewin);
702 HintsSetWindowState(ewin);
703 HintsSetWindowDesktop(ewin);
704 SnapshotEwinUpdate(ewin, SNAP_USE_STICKY);
708 EwinStick(EWin * ewin)
712 if (EoIsSticky(ewin))
715 SoundPlay(SOUND_WINDOW_STICK);
717 /* Avoid "losing" windows made sticky while not in the current viewport */
718 dx = EoGetW(ewin) / 2;
719 dy = EoGetH(ewin) / 2;
720 x = (EoGetX(ewin) + dx) % WinGetW(VROOT);
724 y = (EoGetY(ewin) + dy) % WinGetH(VROOT);
729 EoSetSticky(ewin, 1);
730 EwinMoveToDesktopAt(ewin, DesksGetCurrent(), x, y);
731 EwinBorderUpdateState(ewin);
732 EwinStateUpdate(ewin);
733 HintsSetWindowState(ewin);
734 HintsSetWindowDesktop(ewin);
735 SnapshotEwinUpdate(ewin, SNAP_USE_STICKY);
739 EwinInstantShade(EWin * ewin, int force)
741 XSetWindowAttributes att;
745 if ((ewin->border->border.left == 0) && (ewin->border->border.right == 0)
746 && (ewin->border->border.top == 0) && (ewin->border->border.bottom == 0))
748 if (GetZoomEWin() == ewin)
750 if (ewin->state.shaded && !force)
758 EwinBorderMinShadeSize(ewin, &minw, &minh);
760 switch (ewin->border->shadedir)
764 att.win_gravity = EastGravity;
768 att.win_gravity = WestGravity;
769 if (!Mode.wm.startup)
774 att.win_gravity = SouthGravity;
778 att.win_gravity = SouthGravity;
779 if (!Mode.wm.startup)
785 EChangeWindowAttributes(EwinGetClientWin(ewin), CWWinGravity, &att);
786 ewin->state.shaded = 2;
787 EoMoveResize(ewin, x, y, w, h);
788 EMoveResizeWindow(ewin->win_container, -30, -30, 1, 1);
789 EwinBorderCalcSizes(ewin, 1);
793 EwinInstantUnShade(EWin * ewin)
795 XSetWindowAttributes att;
798 if (GetZoomEWin() == ewin)
800 if (!ewin->state.shaded)
808 switch (ewin->border->shadedir)
812 w = ewin->client.w + ewin->border->border.left +
813 ewin->border->border.right;
816 w = ewin->client.w + ewin->border->border.left +
817 ewin->border->border.right;
818 x = x + EoGetW(ewin) - w;
821 h = ewin->client.h + ewin->border->border.top +
822 ewin->border->border.bottom;
825 h = ewin->client.h + ewin->border->border.top +
826 ewin->border->border.bottom;
827 y = y + EoGetH(ewin) - h;
832 att.win_gravity = NorthWestGravity;
833 EChangeWindowAttributes(EwinGetClientWin(ewin), CWWinGravity, &att);
835 ewin->state.shaded = 0;
836 EwinMoveResize(ewin, x, y, ewin->client.w, ewin->client.h);
839 #define _EWIN_ADJUST_SHAPE(ewin, xo, yo) \
841 EShapeSetShape(ewin->win_container, xo, yo, EwinGetClientWin(ewin)); \
842 ewin->update.shape = 1; \
857 _EwinShadeStart(_ewin_shade_data * esd)
859 EWin *ewin = esd->ewin;
861 XSetWindowAttributes att;
864 esd->dk = 1024 * Conf.shading.speed * Conf.animation.step / 1000000;
866 esd->start.x = EoGetX(ewin);
867 esd->start.y = EoGetY(ewin);
868 esd->start.w = EoGetW(ewin);
869 esd->start.h = EoGetH(ewin);
870 esd->final = esd->start;
872 ewin->state.shading = 1;
874 EwinBorderMinShadeSize(ewin, &minw, &minh);
877 Eprintf("EwinShade-B %d\n", ewin->border->shadedir);
881 switch (ewin->border->shadedir)
885 att.win_gravity = EastGravity;
886 esd->a = esd->start.w;
888 esd->final.w = esd->b;
891 att.win_gravity = WestGravity;
892 esd->a = esd->start.w;
894 esd->c = esd->start.x + esd->start.w;
895 esd->final.x = esd->c - esd->b;
896 esd->final.w = esd->b;
899 att.win_gravity = SouthGravity;
900 esd->a = esd->start.h;
902 esd->final.h = esd->b;
905 att.win_gravity = SouthGravity;
906 esd->a = esd->start.h;
908 esd->c = esd->start.y + esd->start.h;
909 esd->final.y = esd->c - esd->b;
910 esd->final.h = esd->b;
914 EChangeWindowAttributes(EwinGetClientWin(ewin), CWWinGravity, &att);
918 _EwinShadeEnd(_ewin_shade_data * esd)
920 EWin *ewin = esd->ewin;
922 EoMoveResize(ewin, esd->final.x, esd->final.y, esd->final.w, esd->final.h);
923 ewin->state.shaded = 2;
924 EMoveResizeWindow(ewin->win_container, -30, -30, 1, 1);
925 if (ewin->state.shaped)
926 _EWIN_ADJUST_SHAPE(ewin, 0, 0);
928 EwinMoveResize(ewin, EoGetX(ewin), EoGetY(ewin), ewin->client.w,
933 Eprintf("EwinShade-E\n");
936 ewin->state.shading = 0;
938 EwinStateUpdate(ewin);
939 HintsSetWindowState(ewin);
940 SnapshotEwinUpdate(ewin, SNAP_USE_SHADED);
946 _EwinShadeRun(void *data)
948 _ewin_shade_data *esd = (_ewin_shade_data *) data;
949 EWin *ewin = esd->ewin;
950 int k, x, y, w, h, ww, hh, cow, coh, shx, shy;
952 if (!EwinFindByPtr(ewin)) /* Check, window may be gone */
965 cow = ewin->client.w;
966 coh = ewin->client.h;
970 switch (ewin->border->shadedir)
974 w = ((esd->a * (1024 - k)) + (esd->b * k)) >> 10;
977 ww = w - ewin->border->border.left - ewin->border->border.right;
981 shx = ww - ewin->client.w;
984 w = ((esd->a * (1024 - k)) + (esd->b * k)) >> 10;
988 ww = w - ewin->border->border.left - ewin->border->border.right;
994 h = ((esd->a * (1024 - k)) + (esd->b * k)) >> 10;
997 hh = h - ewin->border->border.top - ewin->border->border.bottom;
1001 shy = hh - ewin->client.h;
1004 h = ((esd->a * (1024 - k)) + (esd->b * k)) >> 10;
1008 hh = h - ewin->border->border.top - ewin->border->border.bottom;
1012 shy = hh - ewin->client.h;
1015 EMoveResizeWindow(ewin->win_container,
1016 ewin->border->border.left,
1017 ewin->border->border.top, cow, coh);
1018 if (ewin->state.shaped)
1019 _EWIN_ADJUST_SHAPE(ewin, shx, shy);
1020 EoMoveResize(ewin, x, y, w, h);
1021 EwinBorderCalcSizes(ewin, 1);
1023 esd->k = k += esd->dk;
1032 EwinShade(EWin * ewin)
1034 _ewin_shade_data *esd;
1036 if ((ewin->border->border.left == 0) && (ewin->border->border.right == 0) &&
1037 (ewin->border->border.top == 0) && (ewin->border->border.bottom == 0))
1039 if (GetZoomEWin() == ewin)
1041 if (ewin->state.shaded || ewin->state.shading || ewin->state.iconified)
1043 if ((ewin->border) && (!strcmp(ewin->border->name, "BORDERLESS")))
1046 SoundPlay(SOUND_SHADE);
1048 DeskRestack(EoGetDesk(ewin)); /* Do any pending stacking ops now */
1050 esd = EMALLOC(_ewin_shade_data, 1);
1052 _EwinShadeStart(esd);
1053 if ((Conf.shading.animate) || (ewin->type == EWIN_TYPE_MENU))
1054 AnimatorAdd(_EwinShadeRun, esd);
1060 _EwinUnshadeStart(_ewin_shade_data * esd)
1062 EWin *ewin = esd->ewin;
1063 int cow, coh, clx, cly;
1064 XSetWindowAttributes att;
1067 esd->dk = 1024 * Conf.shading.speed * Conf.animation.step / 1000000;
1069 esd->start.x = EoGetX(ewin);
1070 esd->start.y = EoGetY(ewin);
1071 esd->start.w = EoGetW(ewin);
1072 esd->start.h = EoGetH(ewin);
1073 esd->final = esd->start;
1075 ewin->state.shading = 1;
1076 ewin->state.shaded = 0;
1078 cow = ewin->client.w;
1079 coh = ewin->client.h;
1084 Eprintf("EwinUnShade-B %d\n", ewin->border->shadedir);
1088 switch (ewin->border->shadedir)
1092 att.win_gravity = EastGravity;
1093 esd->a = ewin->border->border.left + ewin->border->border.right;
1094 esd->b = ewin->client.w + esd->a;
1095 esd->c = 0; /* Not used */
1096 esd->final.w = esd->b;
1098 clx = -ewin->client.w;
1101 att.win_gravity = WestGravity;
1102 esd->a = ewin->border->border.left + ewin->border->border.right;
1103 esd->b = ewin->client.w + esd->a;
1104 esd->c = esd->start.x + esd->start.w; /* NB! w != a is possible */
1105 esd->final.x = esd->c - esd->b;
1106 esd->final.w = esd->b;
1110 att.win_gravity = SouthGravity;
1111 esd->a = ewin->border->border.top + ewin->border->border.bottom;
1112 esd->b = ewin->client.h + esd->a;
1113 esd->c = 0; /* Not used */
1114 esd->final.h = esd->b;
1116 cly = 1 - ewin->client.h;
1119 att.win_gravity = SouthGravity;
1120 esd->a = ewin->border->border.top + ewin->border->border.bottom;
1121 esd->b = ewin->client.h + esd->a;
1122 esd->c = esd->start.y + esd->start.h; /* NB! h != a is possible */
1123 esd->final.y = esd->c - esd->b;
1124 esd->final.h = esd->b;
1126 cly = 1 - ewin->client.h;
1130 EChangeWindowAttributes(EwinGetClientWin(ewin), CWWinGravity, &att);
1131 EMoveResizeWindow(ewin->win_container,
1132 ewin->border->border.left, ewin->border->border.top,
1134 EWindowSync(EwinGetClientWin(ewin)); /* Gravity - recache */
1135 EMoveResizeWindow(EwinGetClientWin(ewin), clx, cly,
1136 ewin->client.w, ewin->client.h);
1137 EMapWindow(EwinGetClientWin(ewin));
1138 EMapWindow(ewin->win_container);
1142 _EwinUnshadeEnd(_ewin_shade_data * esd)
1144 EWin *ewin = esd->ewin;
1145 XSetWindowAttributes att;
1147 EoMoveResize(ewin, esd->final.x, esd->final.y, esd->final.w, esd->final.h);
1150 att.win_gravity = NorthWestGravity;
1151 EChangeWindowAttributes(EwinGetClientWin(ewin), CWWinGravity, &att);
1153 EMoveResizeWindow(EwinGetClientWin(ewin), 0, 0, ewin->client.w,
1155 EMoveResizeWindow(ewin->win_container, ewin->border->border.left,
1156 ewin->border->border.top, ewin->client.w, ewin->client.h);
1158 if (ewin->state.shaped)
1159 _EWIN_ADJUST_SHAPE(ewin, 0, 0);
1161 EwinMoveResize(ewin, EoGetX(ewin), EoGetY(ewin), ewin->client.w,
1166 Eprintf("EwinUnShade-E\n");
1169 ewin->state.shading = 0;
1171 EwinStateUpdate(ewin);
1172 HintsSetWindowState(ewin);
1173 SnapshotEwinUpdate(ewin, SNAP_USE_SHADED);
1179 _EwinUnshadeRun(void *data)
1181 _ewin_shade_data *esd = (_ewin_shade_data *) data;
1182 EWin *ewin = esd->ewin;
1183 int k, x, y, w, h, ww, hh, cow, coh, shx, shy;
1185 if (!EwinFindByPtr(ewin)) /* Check, window may be gone */
1198 cow = ewin->client.w;
1199 coh = ewin->client.h;
1203 switch (ewin->border->shadedir)
1207 w = ((esd->a * (1024 - k)) + (esd->b * k)) >> 10;
1212 shx = ww - ewin->client.w;
1215 w = ((esd->a * (1024 - k)) + (esd->b * k)) >> 10;
1223 h = ((esd->a * (1024 - k)) + (esd->b * k)) >> 10;
1228 shy = hh - ewin->client.h;
1231 h = ((esd->a * (1024 - k)) + (esd->b * k)) >> 10;
1237 shy = hh - ewin->client.h;
1240 EMoveResizeWindow(ewin->win_container,
1241 ewin->border->border.left,
1242 ewin->border->border.top, cow, coh);
1243 if (ewin->state.shaped)
1244 _EWIN_ADJUST_SHAPE(ewin, shx, shy);
1245 EoMoveResize(ewin, x, y, w, h);
1246 EwinBorderCalcSizes(ewin, 1);
1248 esd->k = k += esd->dk;
1252 _EwinUnshadeEnd(esd);
1257 EwinUnShade(EWin * ewin)
1259 _ewin_shade_data *esd;
1261 if (GetZoomEWin() == ewin)
1263 TIMER_DEL(ewin->timer);
1264 if (!ewin->state.shaded || ewin->state.shading || ewin->state.iconified)
1267 SoundPlay(SOUND_UNSHADE);
1269 DeskRestack(EoGetDesk(ewin)); /* Do any pending stacking ops now */
1271 esd = EMALLOC(_ewin_shade_data, 1);
1273 _EwinUnshadeStart(esd);
1274 if ((Conf.shading.animate) || (ewin->type == EWIN_TYPE_MENU))
1275 AnimatorAdd(_EwinUnshadeRun, esd);
1277 _EwinUnshadeEnd(esd);
1281 EwinOpFullscreen(EWin * ewin, int source __UNUSED__, int on)
1283 int x, y, w, h, ww, hh;
1288 if (ewin->state.fullscreen == (unsigned)on)
1295 if (ewin->state.inhibit_fullscreeen)
1297 ewin->save_fs.x = EoGetX(ewin);
1298 ewin->save_fs.y = EoGetY(ewin);
1299 ewin->save_fs.w = ewin->client.w;
1300 ewin->save_fs.h = ewin->client.h;
1301 ewin->save_fs.layer = EoGetLayer(ewin);
1303 ScreenGetAvailableArea(EoGetX(ewin), EoGetY(ewin), &x, &y, &w, &h);
1305 /* Fixup if available space doesn't match ICCCM size constraints */
1306 ICCCM_SizeMatch(ewin, w, h, &ww, &hh);
1307 if (w == ww && h == hh)
1309 b = BorderFind("BORDERLESS");
1316 l = (l < 0) ? 0 : l;
1318 t = (t < 0) ? 0 : t;
1319 b = BorderCreateFiller(l, w - ww - l, t, h - hh - t);
1323 EwinBorderSetTo(ewin, b);
1325 if (Conf.place.raise_fullscreen)
1327 EoSetLayer(ewin, 8);
1328 lst = EwinListTransients(ewin, &num, 0);
1329 for (i = 0; i < num; i++)
1331 lst[i]->save_fs.layer = EoGetLayer(lst[i]);
1332 EoSetLayer(lst[i], lst[i]->save_fs.layer +
1333 EoGetLayer(ewin) - ewin->save_fs.layer);
1339 ewin->state.maximizing = 1;
1340 EwinMoveResize(ewin, x, y, w, h);
1341 ewin->state.maximizing = 0;
1342 ewin->state.fullscreen = 1;
1343 EwinStateUpdate(ewin);
1347 x = ewin->save_fs.x;
1348 y = ewin->save_fs.y;
1349 w = ewin->save_fs.w;
1350 h = ewin->save_fs.h;
1351 GetOnScreenPos(x, y, w, h, &x, &y);
1352 b = ewin->normal_border;
1353 EwinBorderSetTo(ewin, b);
1355 if (Conf.place.raise_fullscreen)
1357 lst = EwinListTransients(ewin, &num, 0);
1358 for (i = 0; i < num; i++)
1359 EoSetLayer(lst[i], lst[i]->save_fs.layer);
1362 EoSetLayer(ewin, ewin->save_fs.layer);
1364 ewin->state.fullscreen = 0;
1365 EwinStateUpdate(ewin);
1367 ewin->state.maximizing = 1;
1368 EwinMoveResize(ewin, x, y, w, h);
1369 ewin->state.maximizing = 0;
1372 HintsSetWindowState(ewin);
1376 EwinsShowDesktop(int on)
1378 EWin *const *lst, *ewin;
1381 lst = EwinListGetForDesk(&num, DesksGetCurrent());
1383 for (i = 0; i < num; i++)
1389 if (EwinIsTransient(ewin) ||
1390 ewin->state.iconified || ewin->state.donthide)
1393 ewin->state.showingdesk = 1;
1398 if (!ewin->state.showingdesk)
1401 EwinDeIconify(ewin);
1404 Mode.showing_desktop = on;
1405 EWMH_SetShowingDesktop(on);
1409 EwinMoveToArea(EWin * ewin, int ax, int ay)
1411 DesksFixArea(&ax, &ay);
1412 EwinMove(ewin, EoGetX(ewin) + (WinGetW(VROOT) * (ax - ewin->area_x)),
1413 EoGetY(ewin) + (WinGetH(VROOT) * (ay - ewin->area_y)));
1417 EwinOpActivate(EWin * ewin, int source, int raise)
1421 if (source == OPSRC_APP && EwinInhGetApp(ewin, focus))
1424 unshade = ewin->state.shaded /* && !ewin->state.iconified */ ;
1426 if (!ewin->state.animated && !ewin->state.iconified)
1427 DeskGotoByEwin(ewin);
1429 EwinOpRaise(ewin, source);
1430 if (ewin->state.iconified)
1431 EwinOpIconify(ewin, source, 0);
1433 EwinOpShade(ewin, source, 0);
1434 FocusToEWin(ewin, FOCUS_SET);
1438 EwinOpClose(EWin * ewin, int source __UNUSED__)
1446 gwins = ListWinGroupMembersForEwin(ewin, GROUP_ACTION_KILL,
1447 Mode.nogroup, &num);
1448 for (i = 0; i < num; i++)
1450 ICCCM_Delete(gwins[i]);
1451 SoundPlay(SOUND_WINDOW_CLOSE);
1457 EwinOpKill(EWin * ewin, int source __UNUSED__)
1459 SoundPlay(SOUND_WINDOW_CLOSE);
1464 EwinOpRaise(EWin * ewin, int source __UNUSED__)
1466 EWin **gwins = NULL;
1469 SoundPlay(SOUND_RAISE);
1470 gwins = ListWinGroupMembersForEwin(ewin, GROUP_ACTION_STACKING,
1471 Mode.nogroup, &num);
1472 for (i = 0; i < num; i++)
1473 EwinRaise(gwins[i]);
1478 EwinOpLower(EWin * ewin, int source __UNUSED__)
1480 EWin **gwins = NULL;
1483 SoundPlay(SOUND_LOWER);
1484 gwins = ListWinGroupMembersForEwin(ewin, GROUP_ACTION_STACKING,
1485 Mode.nogroup, &num);
1486 for (i = 0; i < num; i++)
1487 EwinLower(gwins[i]);
1492 EwinOpStick(EWin * ewin, int source __UNUSED__, int on)
1494 EWin **gwins = NULL;
1497 gwins = ListWinGroupMembersForEwin(ewin, GROUP_ACTION_STICK,
1498 Mode.nogroup, &num);
1499 for (i = 0; i < num; i++)
1502 EwinStick(gwins[i]);
1504 EwinUnStick(gwins[i]);
1510 EwinOpSkipLists(EWin * ewin, int source __UNUSED__, int skip)
1512 ewin->props.skip_ext_task = skip;
1513 ewin->props.skip_winlist = skip;
1514 ewin->props.skip_focuslist = skip;
1516 EwinStateUpdate(ewin);
1517 HintsSetWindowState(ewin);
1519 GNOME_SetClientList();
1521 SnapshotEwinUpdate(ewin, SNAP_USE_SKIP_LISTS);
1526 EwinOpSkipTask(EWin * ewin, int skip)
1528 ewin->props.skip_ext_task = skip;
1530 EwinStateUpdate(ewin);
1531 HintsSetWindowState(ewin);
1533 GNOME_SetClientList();
1535 SnapshotEwinUpdate(ewin, SNAP_USE_SKIP_LISTS);
1539 EwinOpSkipFocus(EWin * ewin, int skip)
1541 ewin->props.skip_focuslist = skip;
1542 EwinStateUpdate(ewin);
1543 SnapshotEwinUpdate(ewin, SNAP_USE_SKIP_LISTS);
1547 EwinOpSkipWinlist(EWin * ewin, int skip)
1549 ewin->props.skip_winlist = skip;
1550 EwinStateUpdate(ewin);
1551 SnapshotEwinUpdate(ewin, SNAP_USE_SKIP_LISTS);
1555 EwinOpNeverFocus(EWin * ewin, int on)
1557 ewin->props.never_focus = on;
1558 EwinStateUpdate(ewin);
1559 SnapshotEwinUpdate(ewin, SNAP_USE_FOCUS_NEVER);
1564 EwinOpIconify(EWin * ewin, int source __UNUSED__, int on)
1566 EWin **gwins = NULL;
1569 gwins = ListWinGroupMembersForEwin(ewin, GROUP_ACTION_ICONIFY,
1570 Mode.nogroup, &num);
1571 for (i = 0; i < num; i++)
1574 EwinIconify(gwins[i]);
1576 EwinDeIconify(gwins[i]);
1582 EwinOpShade(EWin * ewin, int source __UNUSED__, int on)
1584 EWin **gwins = NULL;
1587 gwins = ListWinGroupMembersForEwin(ewin, GROUP_ACTION_SHADE,
1588 Mode.nogroup, &num);
1589 for (i = 0; i < num; i++)
1592 EwinShade(gwins[i]);
1594 EwinUnShade(gwins[i]);
1600 EwinOpSetLayer(EWin * ewin, int source __UNUSED__, int layer)
1602 if (EoGetLayer(ewin) > layer)
1604 SoundPlay(SOUND_WINDOW_CHANGE_LAYER_DOWN);
1606 else if (EoGetLayer(ewin) < layer)
1608 SoundPlay(SOUND_WINDOW_CHANGE_LAYER_UP);
1610 EoSetLayer(ewin, layer);
1612 EwinStateUpdate(ewin);
1613 HintsSetWindowState(ewin);
1614 SnapshotEwinUpdate(ewin, SNAP_USE_LAYER);
1618 EwinOpSetBorder(EWin * ewin, int source __UNUSED__, const char *name)
1620 EWin **gwins = NULL;
1624 char shadechange = 0;
1626 b = BorderFind(name);
1632 ListWinGroupMembersForEwin(ewin, GROUP_ACTION_SET_WINDOW_BORDER,
1633 Mode.nogroup, &num);
1634 for (i = 0; i < num; i++)
1636 if (gwins[i]->state.shaded)
1644 if ((b->border.left == 0) && (b->border.right == 0)
1645 && (b->border.top == 0) && (b->border.bottom == 0))
1649 for (i = 0; i < num; i++)
1651 if (b != gwins[i]->border)
1653 SoundPlay(SOUND_WINDOW_BORDER_CHANGE);
1655 if (gwins[i]->state.shaded)
1658 EwinInstantUnShade(gwins[i]);
1660 EwinBorderChange(gwins[i], b, 1);
1662 EwinInstantShade(gwins[i], 0);
1664 SnapshotEwinUpdate(gwins[i], SNAP_USE_BORDER);
1670 EwinOpSetOpacity(EWin * ewin, int source __UNUSED__, int opacity)
1674 op = OpacityFromPercent(opacity);
1675 ewin->ewmh.opacity = op;
1676 HintsSetWindowOpacity(ewin);
1677 EwinUpdateOpacity(ewin);
1678 SnapshotEwinUpdate(ewin, SNAP_USE_OPACITY);
1682 EwinOpSetFocusedOpacity(EWin * ewin, int source __UNUSED__, int opacity)
1686 op = OpacityFromPercent(opacity);
1687 ewin->props.focused_opacity = op;
1688 EwinUpdateOpacity(ewin);
1689 SnapshotEwinUpdate(ewin, SNAP_USE_OPACITY);
1693 EwinOpMoveToDesk(EWin * ewin, int source __UNUSED__, Desk * dsk, int inc)
1695 dsk = DeskGetRelative(dsk, inc);
1697 EoSetSticky(ewin, 0);
1698 EwinMoveToDesktop(ewin, dsk);
1700 EwinBorderUpdateState(ewin);
1701 EwinStateUpdate(ewin);
1702 HintsSetWindowState(ewin);
1703 HintsSetWindowDesktop(ewin);
1704 SnapshotEwinUpdate(ewin, SNAP_USE_STICKY);
1709 EwinMoveToLinearArea(EWin * ewin, int a)
1713 AreaLinearToXY(a, &ax, &ay);
1714 EwinMoveToArea(ewin, ax, ay);
1718 EwinMoveLinearAreaBy(EWin * ewin, int a)
1720 EwinMoveToLinearArea(ewin, AreaXYToLinear(ewin->area_x, ewin->area_y) + a);
1724 EwinOpMoveToArea(EWin * ewin, int x, int y)
1726 EwinMoveToArea(ewin, x, y);
1727 SnapshotEwinUpdate(ewin, SNAP_USE_POS);
1731 #if 0 /* Not used? */
1733 doMoveWinToLinearArea(EWin * ewin, const char *params)
1739 sscanf(params, "%i", &da);
1740 EwinMoveToLinearArea(ewin, da);
1742 SnapshotEwinUpdate(ewin, SNAP_USE_POS);
1747 doMoveWinByLinearArea(EWin * ewin, const char *params)
1754 sscanf(params, "%i", &da);
1755 EwinMoveLinearAreaBy(ewin, da);
1757 SnapshotEwinUpdate(ewin, SNAP_USE_POS);
1762 #if 0 /* FIXME - Unused? */
1764 doScrollWindows(EWin * edummy __UNUSED__, const char *params)
1774 sscanf(params, "%i %i", &x, &y);
1776 lst = EwinListGetAll(&num);
1777 for (i = 0; i < num; i++)
1779 if ((lst[i]->desktop == DesksGetCurrent()) && (!lst[i]->sticky) &&
1780 (!lst[i]->floating))
1781 EwinMove(lst[i], lst[i]->x + x, lst[i]->y + y);