1 /* action.c- misc. window commands (miniaturize, hide etc.)
3 * Window Maker window manager
5 * Copyright (c) 1997-2003 Alfredo K. Kojima
6 * Copyright (c) 1998-2003 Dan Pascu
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
27 #include <X11/Xutil.h>
34 #include "WindowMaker.h"
41 #include "application.h"
47 #include "winspector.h"
48 #include "workspace.h"
52 /****** Global Variables ******/
53 extern Time LastTimestamp;
54 extern Time LastFocusChange;
56 extern Cursor wCursor[WCUR_LAST];
58 extern WPreferences wPreferences;
60 extern Atom _XA_WM_TAKE_FOCUS;
62 extern void ProcessPendingEvents();
64 /******* Local Variables *******/
70 SHADE_STEPS_UF, SHADE_DELAY_UF}, {
71 SHADE_STEPS_F, SHADE_DELAY_F}, {
72 SHADE_STEPS_M, SHADE_DELAY_M}, {
73 SHADE_STEPS_S, SHADE_DELAY_S}, {
74 SHADE_STEPS_US, SHADE_DELAY_US}};
76 #define SHADE_STEPS shadePars[(int)wPreferences.shade_speed].steps
77 #define SHADE_DELAY shadePars[(int)wPreferences.shade_speed].delay
79 static int compareTimes(Time t1, Time t2)
85 return (diff < 60000) ? 1 : -1;
89 *----------------------------------------------------------------------
91 * Changes the window focus to the one passed as argument.
92 * If the window to focus is not already focused, it will be brought
93 * to the head of the list of windows. Previously focused window is
97 * Window list may be reordered and the window focus is changed.
99 *----------------------------------------------------------------------
101 void wSetFocusTo(WScreen * scr, WWindow * wwin)
103 static WScreen *old_scr = NULL;
105 WWindow *old_focused;
106 WWindow *focused = scr->focused_window;
107 Time timestamp = LastTimestamp;
108 WApplication *oapp = NULL, *napp = NULL;
111 if (scr->flags.ignore_focus_events || compareTimes(LastFocusChange, timestamp) > 0)
116 old_focused = old_scr->focused_window;
118 LastFocusChange = timestamp;
121 oapp = wApplicationOf(old_focused->main_window);
124 XSetInputFocus(dpy, scr->no_focus_win, RevertToParent, CurrentTime);
126 wWindowUnfocus(old_focused);
129 wAppMenuUnmap(oapp->menu);
131 wApplicationDeactivate(oapp);
135 WMPostNotificationName(WMNChangedFocus, NULL, (void *)True);
137 } else if (old_scr != scr && old_focused) {
138 wWindowUnfocus(old_focused);
141 wasfocused = wwin->flags.focused;
142 napp = wApplicationOf(wwin->main_window);
144 /* remember last workspace where the app has been */
146 /*napp->last_workspace = wwin->screen_ptr->current_workspace; */
147 napp->last_workspace = wwin->frame->workspace;
150 if (wwin->flags.mapped && !WFLAGP(wwin, no_focusable)) {
151 /* install colormap if colormap mode is lock mode */
152 if (wPreferences.colormap_mode == WCM_CLICK)
153 wColormapInstallForWindow(scr, wwin);
155 /* set input focus */
156 switch (wwin->focus_mode) {
158 XSetInputFocus(dpy, scr->no_focus_win, RevertToParent, CurrentTime);
162 case WFM_LOCALLY_ACTIVE:
163 XSetInputFocus(dpy, wwin->client_win, RevertToParent, CurrentTime);
166 case WFM_GLOBALLY_ACTIVE:
170 if (wwin->protocols.TAKE_FOCUS) {
171 wClientSendProtocol(wwin, _XA_WM_TAKE_FOCUS, timestamp);
175 XSetInputFocus(dpy, scr->no_focus_win, RevertToParent, CurrentTime);
177 if (WFLAGP(wwin, no_focusable))
180 /* if this is not the focused window focus it */
181 if (focused != wwin) {
182 /* change the focus window list order */
184 wwin->prev->next = wwin->next;
187 wwin->next->prev = wwin->prev;
189 wwin->prev = focused;
190 focused->next = wwin;
192 scr->focused_window = wwin;
194 if (oapp && oapp != napp) {
195 wAppMenuUnmap(oapp->menu);
197 wApplicationDeactivate(oapp);
202 wWindowFocus(wwin, focused);
204 if (napp && !wasfocused) {
206 wUserMenuRefreshInstances(napp->menu, wwin);
207 #endif /* USER_MENU */
209 if (wwin->flags.mapped)
210 wAppMenuMap(napp->menu, wwin);
212 wApplicationActivate(napp);
220 void wShadeWindow(WWindow * wwin)
227 if (wwin->flags.shaded)
232 XLowerWindow(dpy, wwin->client_win);
234 wSoundPlay(WSOUND_SHADE);
237 if (!wwin->screen_ptr->flags.startup && !wwin->flags.skip_next_animation && !wPreferences.no_animations) {
238 /* do the shading animation */
239 h = wwin->frame->core->height;
243 w = wwin->frame->core->width;
244 y = wwin->frame->top_width;
245 while (h > wwin->frame->top_width + 1) {
246 XMoveWindow(dpy, wwin->client_win, 0, y);
247 XResizeWindow(dpy, wwin->frame->core->window, w, h);
250 if (time(NULL) - time0 > MAX_ANIMATION_TIME)
253 if (SHADE_DELAY > 0) {
254 wusleep(SHADE_DELAY * 1000L);
261 XMoveWindow(dpy, wwin->client_win, 0, wwin->frame->top_width);
263 #endif /* ANIMATIONS */
265 wwin->flags.skip_next_animation = 0;
266 wwin->flags.shaded = 1;
267 wwin->flags.mapped = 0;
268 /* prevent window withdrawal when getting UnmapNotify */
269 XSelectInput(dpy, wwin->client_win, wwin->event_mask & ~StructureNotifyMask);
270 XUnmapWindow(dpy, wwin->client_win);
271 XSelectInput(dpy, wwin->client_win, wwin->event_mask);
273 /* for the client it's just like iconification */
274 wFrameWindowResize(wwin->frame, wwin->frame->core->width, wwin->frame->top_width - 1);
276 wwin->client.y = wwin->frame_y - wwin->client.height + wwin->frame->top_width;
277 wWindowSynthConfigureNotify(wwin);
280 wClientSetState(wwin, IconicState, None);
283 WMPostNotificationName(WMNChangedState, wwin, "shade");
286 if (!wwin->screen_ptr->flags.startup) {
287 /* Catch up with events not processed while animation was running */
288 ProcessPendingEvents();
293 void wUnshadeWindow(WWindow * wwin)
298 #endif /* ANIMATIONS */
300 if (!wwin->flags.shaded)
305 wwin->flags.shaded = 0;
306 wwin->flags.mapped = 1;
307 XMapWindow(dpy, wwin->client_win);
309 wSoundPlay(WSOUND_UNSHADE);
312 if (!wPreferences.no_animations && !wwin->flags.skip_next_animation) {
313 /* do the shading animation */
314 h = wwin->frame->top_width + wwin->frame->bottom_width;
315 y = wwin->frame->top_width - wwin->client.height;
316 s = abs(y) / SHADE_STEPS;
319 w = wwin->frame->core->width;
320 XMoveWindow(dpy, wwin->client_win, 0, y);
322 while (h < wwin->client.height + wwin->frame->top_width + wwin->frame->bottom_width) {
323 XResizeWindow(dpy, wwin->frame->core->window, w, h);
324 XMoveWindow(dpy, wwin->client_win, 0, y);
326 if (SHADE_DELAY > 0) {
327 wusleep(SHADE_DELAY * 2000L / 3);
334 if (time(NULL) - time0 > MAX_ANIMATION_TIME)
338 XMoveWindow(dpy, wwin->client_win, 0, wwin->frame->top_width);
340 #endif /* ANIMATIONS */
342 wwin->flags.skip_next_animation = 0;
343 wFrameWindowResize(wwin->frame, wwin->frame->core->width,
344 wwin->frame->top_width + wwin->client.height + wwin->frame->bottom_width);
346 wwin->client.y = wwin->frame_y + wwin->frame->top_width;
347 wWindowSynthConfigureNotify(wwin);
350 wClientSetState(wwin, NormalState, None);
352 /* if the window is focused, set the focus again as it was disabled during
354 if (wwin->flags.focused)
355 wSetFocusTo(wwin->screen_ptr, wwin);
357 WMPostNotificationName(WMNChangedState, wwin, "shade");
360 void wMaximizeWindow(WWindow * wwin, int directions)
363 unsigned int new_width, new_height;
364 int changed_h, changed_v, shrink_h, shrink_v;
365 WArea usableArea, totalArea;
367 if (!IS_RESIZABLE(wwin))
372 totalArea.x2 = wwin->screen_ptr->scr_width;
373 totalArea.y2 = wwin->screen_ptr->scr_height;
374 usableArea = totalArea;
376 if (!(directions & MAX_IGNORE_XINERAMA)) {
377 WScreen *scr = wwin->screen_ptr;
380 if (directions & MAX_KEYBOARD)
381 head = wGetHeadForWindow(wwin);
383 head = wGetHeadForPointerLocation(scr);
385 usableArea = wGetUsableAreaForHead(scr, head, &totalArea, True);
388 if (WFLAGP(wwin, full_maximize)) {
389 usableArea = totalArea;
392 if (wwin->flags.shaded) {
393 wwin->flags.skip_next_animation = 1;
394 wUnshadeWindow(wwin);
396 /* Only save directions, not kbd or xinerama hints */
397 directions &= (MAX_HORIZONTAL | MAX_VERTICAL);
399 changed_h = ((wwin->flags.maximized ^ directions) & MAX_HORIZONTAL);
400 changed_v = ((wwin->flags.maximized ^ directions) & MAX_VERTICAL);
401 shrink_h = (changed_h && (directions & MAX_HORIZONTAL) == 0);
402 shrink_v = (changed_v && (directions & MAX_VERTICAL) == 0);
404 if (wwin->flags.maximized) {
405 /* if already maximized in some direction, we only update the
406 * appropriate old x, old y coordinates. This is necessary to
407 * allow succesive maximizations in different directions without
408 * the need to first do an un-maximize (to avoid flicker).
410 if (!(wwin->flags.maximized & MAX_HORIZONTAL)) {
411 wwin->old_geometry.x = wwin->frame_x;
413 if (!(wwin->flags.maximized & MAX_VERTICAL)) {
414 wwin->old_geometry.y = wwin->frame_y;
417 wwin->old_geometry.width = wwin->client.width;
418 wwin->old_geometry.height = wwin->client.height;
419 wwin->old_geometry.x = wwin->frame_x;
420 wwin->old_geometry.y = wwin->frame_y;
422 wwin->flags.maximized = directions;
424 if (directions & MAX_HORIZONTAL) {
425 new_width = usableArea.x2 - usableArea.x1;
426 if (HAS_BORDER(wwin))
427 new_width -= FRAME_BORDER_WIDTH * 2;
428 new_x = usableArea.x1;
429 } else if (shrink_h) {
430 new_x = wwin->old_geometry.x;
431 new_width = wwin->old_geometry.width;
433 new_x = wwin->frame_x;
434 new_width = wwin->frame->core->width;
437 if (directions & MAX_VERTICAL) {
438 new_height = usableArea.y2 - usableArea.y1;
439 if (HAS_BORDER(wwin))
440 new_height -= FRAME_BORDER_WIDTH * 2;
441 new_y = usableArea.y1;
442 if (WFLAGP(wwin, full_maximize)) {
443 new_y -= wwin->frame->top_width;
444 new_height += wwin->frame->bottom_width - 1;
446 } else if (shrink_v) {
447 new_y = wwin->old_geometry.y;
448 new_height = wwin->old_geometry.height;
450 new_y = wwin->frame_y;
451 new_height = wwin->frame->core->height;
454 if (!WFLAGP(wwin, full_maximize)) {
455 new_height -= wwin->frame->top_width + wwin->frame->bottom_width;
458 wWindowConstrainSize(wwin, &new_width, &new_height);
460 wWindowCropSize(wwin, usableArea.x2 - usableArea.x1,
461 usableArea.y2 - usableArea.y1, &new_width, &new_height);
463 wWindowConfigure(wwin, new_x, new_y, new_width, new_height);
465 WMPostNotificationName(WMNChangedState, wwin, "maximize");
467 wSoundPlay(WSOUND_MAXIMIZE);
470 void wUnmaximizeWindow(WWindow * wwin)
474 if (!wwin->flags.maximized)
477 if (wwin->flags.shaded) {
478 wwin->flags.skip_next_animation = 1;
479 wUnshadeWindow(wwin);
481 x = ((wwin->flags.maximized & MAX_HORIZONTAL) && wwin->old_geometry.x) ?
482 wwin->old_geometry.x : wwin->frame_x;
483 y = ((wwin->flags.maximized & MAX_VERTICAL) && wwin->old_geometry.y) ?
484 wwin->old_geometry.y : wwin->frame_y;
485 w = wwin->old_geometry.width ? wwin->old_geometry.width : wwin->client.width;
486 h = wwin->old_geometry.height ? wwin->old_geometry.height : wwin->client.height;
488 wwin->flags.maximized = 0;
489 wWindowConfigure(wwin, x, y, w, h);
491 WMPostNotificationName(WMNChangedState, wwin, "maximize");
493 wSoundPlay(WSOUND_UNMAXIMIZE);
496 void wFullscreenWindow(WWindow * wwin)
501 if (wwin->flags.fullscreen)
504 wwin->flags.fullscreen = True;
506 wWindowConfigureBorders(wwin);
508 ChangeStackingLevel(wwin->frame->core, WMFullscreenLevel);
510 wwin->bfs_geometry.x = wwin->frame_x;
511 wwin->bfs_geometry.y = wwin->frame_y;
512 wwin->bfs_geometry.width = wwin->frame->core->width;
513 wwin->bfs_geometry.height = wwin->frame->core->height;
515 head = wGetHeadForWindow(wwin);
516 rect = wGetRectForHead(wwin->screen_ptr, head);
517 wWindowConfigure(wwin, rect.pos.x, rect.pos.y, rect.size.width, rect.size.height);
519 WMPostNotificationName(WMNChangedState, wwin, "fullscreen");
522 void wUnfullscreenWindow(WWindow * wwin)
524 if (!wwin->flags.fullscreen)
527 wwin->flags.fullscreen = False;
529 if (wwin->frame->core->stacking->window_level == WMFullscreenLevel) {
530 if (WFLAGP(wwin, sunken)) {
531 ChangeStackingLevel(wwin->frame->core, WMSunkenLevel);
532 } else if (WFLAGP(wwin, floating)) {
533 ChangeStackingLevel(wwin->frame->core, WMFloatingLevel);
535 ChangeStackingLevel(wwin->frame->core, WMNormalLevel);
539 wWindowConfigure(wwin, wwin->bfs_geometry.x, wwin->bfs_geometry.y,
540 wwin->bfs_geometry.width, wwin->bfs_geometry.height);
542 wWindowConfigureBorders(wwin);
544 // seems unnecessary, but also harmless (doesn't generate flicker) -Dan
545 wFrameWindowPaint(wwin->frame);
548 WMPostNotificationName(WMNChangedState, wwin, "fullscreen");
552 static void animateResizeFlip(WScreen * scr, int x, int y, int w, int h, int fx, int fy, int fw, int fh, int steps)
554 #define FRAMES (MINIATURIZE_ANIMATION_FRAMES_F)
555 float cx, cy, cw, ch;
556 float xstep, ystep, wstep, hstep;
559 float angle, final_angle, delta;
561 xstep = (float)(fx - x) / steps;
562 ystep = (float)(fy - y) / steps;
563 wstep = (float)(fw - w) / steps;
564 hstep = (float)(fh - h) / steps;
571 final_angle = 2 * WM_PI * MINIATURIZE_ANIMATION_TWIST_F;
572 delta = (float)(final_angle / FRAMES);
573 for (angle = 0;; angle += delta) {
574 if (angle > final_angle)
577 dx = (cw / 10) - ((cw / 5) * sin(angle));
578 dch = (ch / 2) * cos(angle);
579 midy = cy + (ch / 2);
581 points[0].x = cx + dx;
582 points[0].y = midy - dch;
583 points[1].x = cx + cw - dx;
584 points[1].y = points[0].y;
585 points[2].x = cx + cw + dx;
586 points[2].y = midy + dch;
587 points[3].x = cx - dx;
588 points[3].y = points[2].y;
589 points[4].x = points[0].x;
590 points[4].y = points[0].y;
593 XDrawLines(dpy, scr->root_win, scr->frame_gc, points, 5, CoordModeOrigin);
595 #if (MINIATURIZE_ANIMATION_DELAY_F > 0)
596 wusleep(MINIATURIZE_ANIMATION_DELAY_F);
601 XDrawLines(dpy, scr->root_win, scr->frame_gc, points, 5, CoordModeOrigin);
607 if (angle >= final_angle)
617 animateResizeTwist(WScreen * scr, int x, int y, int w, int h, int fx, int fy, int fw, int fh, int steps)
619 #define FRAMES (MINIATURIZE_ANIMATION_FRAMES_T)
620 float cx, cy, cw, ch;
621 float xstep, ystep, wstep, hstep;
623 float angle, final_angle, a, d, delta;
630 xstep = (float)(fx - x) / steps;
631 ystep = (float)(fy - y) / steps;
632 wstep = (float)(fw - w) / steps;
633 hstep = (float)(fh - h) / steps;
640 final_angle = 2 * WM_PI * MINIATURIZE_ANIMATION_TWIST_T;
641 delta = (float)(final_angle / FRAMES);
642 for (angle = 0;; angle += delta) {
643 if (angle > final_angle)
647 d = sqrt((cw / 2) * (cw / 2) + (ch / 2) * (ch / 2));
649 points[0].x = cx + cos(angle - a) * d;
650 points[0].y = cy + sin(angle - a) * d;
651 points[1].x = cx + cos(angle + a) * d;
652 points[1].y = cy + sin(angle + a) * d;
653 points[2].x = cx + cos(angle - a + WM_PI) * d;
654 points[2].y = cy + sin(angle - a + WM_PI) * d;
655 points[3].x = cx + cos(angle + a + WM_PI) * d;
656 points[3].y = cy + sin(angle + a + WM_PI) * d;
657 points[4].x = cx + cos(angle - a) * d;
658 points[4].y = cy + sin(angle - a) * d;
660 XDrawLines(dpy, scr->root_win, scr->frame_gc, points, 5, CoordModeOrigin);
662 #if (MINIATURIZE_ANIMATION_DELAY_T > 0)
663 wusleep(MINIATURIZE_ANIMATION_DELAY_T);
668 XDrawLines(dpy, scr->root_win, scr->frame_gc, points, 5, CoordModeOrigin);
674 if (angle >= final_angle)
683 static void animateResizeZoom(WScreen * scr, int x, int y, int w, int h, int fx, int fy, int fw, int fh, int steps)
685 #define FRAMES (MINIATURIZE_ANIMATION_FRAMES_Z)
686 float cx[FRAMES], cy[FRAMES], cw[FRAMES], ch[FRAMES];
687 float xstep, ystep, wstep, hstep;
690 xstep = (float)(fx - x) / steps;
691 ystep = (float)(fy - y) / steps;
692 wstep = (float)(fw - w) / steps;
693 hstep = (float)(fh - h) / steps;
695 for (j = 0; j < FRAMES; j++) {
702 for (i = 0; i < steps; i++) {
703 for (j = 0; j < FRAMES; j++) {
704 XDrawRectangle(dpy, scr->root_win, scr->frame_gc,
705 (int)cx[j], (int)cy[j], (int)cw[j], (int)ch[j]);
708 #if (MINIATURIZE_ANIMATION_DELAY_Z > 0)
709 wusleep(MINIATURIZE_ANIMATION_DELAY_Z);
713 for (j = 0; j < FRAMES; j++) {
714 XDrawRectangle(dpy, scr->root_win, scr->frame_gc,
715 (int)cx[j], (int)cy[j], (int)cw[j], (int)ch[j]);
716 if (j < FRAMES - 1) {
730 for (j = 0; j < FRAMES; j++) {
731 XDrawRectangle(dpy, scr->root_win, scr->frame_gc, (int)cx[j], (int)cy[j], (int)cw[j], (int)ch[j]);
734 #if (MINIATURIZE_ANIMATION_DELAY_Z > 0)
735 wusleep(MINIATURIZE_ANIMATION_DELAY_Z);
739 for (j = 0; j < FRAMES; j++) {
740 XDrawRectangle(dpy, scr->root_win, scr->frame_gc, (int)cx[j], (int)cy[j], (int)cw[j], (int)ch[j]);
748 void animateResize(WScreen * scr, int x, int y, int w, int h, int fx, int fy, int fw, int fh, int hiding)
750 int style = wPreferences.iconification_style; /* Catch the value */
753 if (style == WIS_NONE)
756 if (style == WIS_RANDOM) {
760 k = (hiding ? 2 : 3);
764 steps = (MINIATURIZE_ANIMATION_STEPS_T * k) / 3;
766 animateResizeTwist(scr, x, y, w, h, fx, fy, fw, fh, steps);
769 steps = (MINIATURIZE_ANIMATION_STEPS_F * k) / 3;
771 animateResizeFlip(scr, x, y, w, h, fx, fy, fw, fh, steps);
775 steps = (MINIATURIZE_ANIMATION_STEPS_Z * k) / 3;
777 animateResizeZoom(scr, x, y, w, h, fx, fy, fw, fh, steps);
781 #endif /* ANIMATIONS */
783 static void flushExpose()
787 while (XCheckTypedEvent(dpy, Expose, &tmpev))
788 WMHandleEvent(&tmpev);
792 static void unmapTransientsFor(WWindow * wwin)
796 tmp = wwin->screen_ptr->focused_window;
798 /* unmap the transients for this transient */
799 if (tmp != wwin && tmp->transient_for == wwin->client_win
800 && (tmp->flags.mapped || wwin->screen_ptr->flags.startup || tmp->flags.shaded)) {
801 unmapTransientsFor(tmp);
802 tmp->flags.miniaturized = 1;
803 if (!tmp->flags.shaded) {
806 XUnmapWindow(dpy, tmp->frame->core->window);
809 if (!tmp->flags.shaded)
811 wClientSetState(tmp, IconicState, None);
813 WMPostNotificationName(WMNChangedState, tmp, "iconify-transient");
819 static void mapTransientsFor(WWindow * wwin)
823 tmp = wwin->screen_ptr->focused_window;
825 /* recursively map the transients for this transient */
826 if (tmp != wwin && tmp->transient_for == wwin->client_win && /*!tmp->flags.mapped */ tmp->flags.miniaturized
827 && tmp->icon == NULL) {
828 mapTransientsFor(tmp);
829 tmp->flags.miniaturized = 0;
830 if (!tmp->flags.shaded) {
833 XMapWindow(dpy, tmp->frame->core->window);
835 tmp->flags.semi_focused = 0;
837 if (!tmp->flags.shaded)
839 wClientSetState(tmp, NormalState, None);
841 WMPostNotificationName(WMNChangedState, tmp, "iconify-transient");
848 static void setupIconGrabs(WIcon * icon)
850 /* setup passive grabs on the icon */
851 XGrabButton(dpy, Button1, AnyModifier, icon->core->window, True,
852 ButtonPressMask, GrabModeSync, GrabModeAsync, None, None);
853 XGrabButton(dpy, Button2, AnyModifier, icon->core->window, True,
854 ButtonPressMask, GrabModeSync, GrabModeAsync, None, None);
855 XGrabButton(dpy, Button3, AnyModifier, icon->core->window, True,
856 ButtonPressMask, GrabModeSync, GrabModeAsync, None, None);
861 static WWindow *recursiveTransientFor(WWindow * wwin)
868 /* hackish way to detect transient_for cycle */
869 i = wwin->screen_ptr->window_count + 1;
871 while (wwin && wwin->transient_for != None && i > 0) {
872 wwin = wWindowFor(wwin->transient_for);
875 if (i == 0 && wwin) {
876 wwarning("%s has a severely broken WM_TRANSIENT_FOR hint.", wwin->frame->title);
884 static void removeIconGrabs(WIcon * icon)
886 /* remove passive grabs on the icon */
887 XUngrabButton(dpy, Button1, AnyModifier, icon->core->window);
888 XUngrabButton(dpy, Button2, AnyModifier, icon->core->window);
889 XUngrabButton(dpy, Button3, AnyModifier, icon->core->window);
894 void wIconifyWindow(WWindow * wwin)
896 XWindowAttributes attribs;
899 if (!XGetWindowAttributes(dpy, wwin->client_win, &attribs)) {
900 /* the window doesn't exist anymore */
904 if (wwin->flags.miniaturized) {
908 if (wwin->transient_for != None && wwin->transient_for != wwin->screen_ptr->root_win) {
909 WWindow *owner = wWindowFor(wwin->transient_for);
911 if (owner && owner->flags.miniaturized)
915 present = wwin->frame->workspace == wwin->screen_ptr->current_workspace;
917 /* if the window is in another workspace, simplify process */
919 /* icon creation may take a while */
920 XGrabPointer(dpy, wwin->screen_ptr->root_win, False,
921 ButtonMotionMask | ButtonReleaseMask, GrabModeAsync,
922 GrabModeAsync, None, None, CurrentTime);
925 if (!wPreferences.disable_miniwindows
927 && !wwin->flags.net_handle_icon
930 if (!wwin->flags.icon_moved) {
931 PlaceIcon(wwin->screen_ptr, &wwin->icon_x, &wwin->icon_y, wGetHeadForWindow(wwin));
933 wwin->icon = wIconCreate(wwin);
935 wwin->icon->mapped = 1;
938 wwin->flags.miniaturized = 1;
939 wwin->flags.mapped = 0;
941 /* unmap transients */
943 unmapTransientsFor(wwin);
946 wSoundPlay(WSOUND_ICONIFY);
948 XUngrabPointer(dpy, CurrentTime);
950 /* let all Expose events arrive so that we can repaint
951 * something before the animation starts (and the server is grabbed) */
954 if (wPreferences.disable_miniwindows
956 || wwin->flags.net_handle_icon
959 wClientSetState(wwin, IconicState, None);
961 wClientSetState(wwin, IconicState, wwin->icon->icon_win);
965 if (!wwin->screen_ptr->flags.startup && !wwin->flags.skip_next_animation
966 && !wPreferences.no_animations) {
969 if (!wPreferences.disable_miniwindows
971 && !wwin->flags.net_handle_icon
976 iw = wwin->icon->core->width;
977 ih = wwin->icon->core->height;
980 if (wwin->flags.net_handle_icon) {
990 iw = wwin->screen_ptr->scr_width;
991 ih = wwin->screen_ptr->scr_height;
994 animateResize(wwin->screen_ptr, wwin->frame_x, wwin->frame_y,
995 wwin->frame->core->width, wwin->frame->core->height, ix, iy, iw, ih, False);
1000 wwin->flags.skip_next_animation = 0;
1002 if (!wPreferences.disable_miniwindows
1004 && !wwin->flags.net_handle_icon
1008 if (wwin->screen_ptr->current_workspace == wwin->frame->workspace ||
1009 IS_OMNIPRESENT(wwin) || wPreferences.sticky_icons)
1011 XMapWindow(dpy, wwin->icon->core->window);
1013 AddToStackList(wwin->icon->core);
1015 wLowerFrame(wwin->icon->core);
1019 WWindow *owner = recursiveTransientFor(wwin->screen_ptr->focused_window);
1022 * It doesn't seem to be working and causes button event hangup
1023 * when deiconifying a transient window.
1024 setupIconGrabs(wwin->icon);
1026 if ((wwin->flags.focused || (owner && wwin->client_win == owner->client_win))
1027 && wPreferences.focus_mode == WKF_CLICK) {
1032 if (!WFLAGP(tmp, no_focusable)
1033 && !(tmp->flags.hidden || tmp->flags.miniaturized)
1034 && (wwin->frame->workspace == tmp->frame->workspace))
1038 wSetFocusTo(wwin->screen_ptr, tmp);
1039 } else if (wPreferences.focus_mode != WKF_CLICK) {
1040 wSetFocusTo(wwin->screen_ptr, NULL);
1043 if (!wwin->screen_ptr->flags.startup) {
1044 /* Catch up with events not processed while animation was running */
1045 Window clientwin = wwin->client_win;
1047 ProcessPendingEvents();
1049 /* the window can disappear while ProcessPendingEvents() runs */
1050 if (!wWindowFor(clientwin)) {
1057 /* maybe we want to do this regardless of net_handle_icon
1058 * it seems to me we might break behaviour this way.
1060 if (wwin->flags.selected && !wPreferences.disable_miniwindows
1062 && !wwin->flags.net_handle_icon
1065 wIconSelect(wwin->icon);
1067 WMPostNotificationName(WMNChangedState, wwin, "iconify");
1070 void wDeiconifyWindow(WWindow * wwin)
1073 /* we're hiding for show_desktop */
1074 int netwm_hidden = wwin->flags.net_show_desktop &&
1075 wwin->frame->workspace != wwin->screen_ptr->current_workspace;
1077 int netwm_hidden = False;
1081 wWindowChangeWorkspace(wwin, wwin->screen_ptr->current_workspace);
1083 if (!wwin->flags.miniaturized)
1086 if (wwin->transient_for != None && wwin->transient_for != wwin->screen_ptr->root_win) {
1087 WWindow *owner = recursiveTransientFor(wwin);
1089 if (owner && owner->flags.miniaturized) {
1090 wDeiconifyWindow(owner);
1091 wSetFocusTo(wwin->screen_ptr, wwin);
1092 wRaiseFrame(wwin->frame->core);
1097 wwin->flags.miniaturized = 0;
1099 if (!netwm_hidden && !wwin->flags.shaded) {
1100 wwin->flags.mapped = 1;
1103 if (!netwm_hidden || wPreferences.sticky_icons) {
1104 /* maybe we want to do this regardless of net_handle_icon
1105 * it seems to me we might break behaviour this way.
1107 if (!wPreferences.disable_miniwindows
1109 && !wwin->flags.net_handle_icon
1111 && wwin->icon != NULL) {
1112 if (wwin->icon->selected)
1113 wIconSelect(wwin->icon);
1115 XUnmapWindow(dpy, wwin->icon->core->window);
1120 wSoundPlay(WSOUND_DEICONIFY);
1122 /* if the window is in another workspace, do it silently */
1123 if (!netwm_hidden) {
1125 if (!wwin->screen_ptr->flags.startup && !wPreferences.no_animations
1126 && !wwin->flags.skip_next_animation && wwin->icon != NULL) {
1129 if (!wPreferences.disable_miniwindows
1131 && !wwin->flags.net_handle_icon
1136 iw = wwin->icon->core->width;
1137 ih = wwin->icon->core->height;
1140 if (wwin->flags.net_handle_icon) {
1150 iw = wwin->screen_ptr->scr_width;
1151 ih = wwin->screen_ptr->scr_height;
1154 animateResize(wwin->screen_ptr, ix, iy, iw, ih,
1155 wwin->frame_x, wwin->frame_y,
1156 wwin->frame->core->width, wwin->frame->core->height, False);
1158 #endif /* ANIMATIONS */
1159 wwin->flags.skip_next_animation = 0;
1161 if (!wwin->flags.shaded) {
1162 XMapWindow(dpy, wwin->client_win);
1164 XMapWindow(dpy, wwin->frame->core->window);
1165 wRaiseFrame(wwin->frame->core);
1166 if (!wwin->flags.shaded) {
1167 wClientSetState(wwin, NormalState, None);
1169 mapTransientsFor(wwin);
1172 if (!wPreferences.disable_miniwindows && wwin->icon != NULL
1174 && !wwin->flags.net_handle_icon
1177 RemoveFromStackList(wwin->icon->core);
1178 /* removeIconGrabs(wwin->icon); */
1179 wIconDestroy(wwin->icon);
1183 if (!netwm_hidden) {
1186 wSetFocusTo(wwin->screen_ptr, wwin);
1189 if (!wwin->screen_ptr->flags.startup) {
1190 /* Catch up with events not processed while animation was running */
1191 Window clientwin = wwin->client_win;
1193 ProcessPendingEvents();
1195 /* the window can disappear while ProcessPendingEvents() runs */
1196 if (!wWindowFor(clientwin)) {
1203 if (wPreferences.auto_arrange_icons) {
1204 wArrangeIcons(wwin->screen_ptr, True);
1207 WMPostNotificationName(WMNChangedState, wwin, "iconify");
1209 /* In case we were shaded and iconified, also unshade */
1211 wUnshadeWindow(wwin);
1214 static void hideWindow(WIcon * icon, int icon_x, int icon_y, WWindow * wwin, int animate)
1216 if (wwin->flags.miniaturized) {
1218 XUnmapWindow(dpy, wwin->icon->core->window);
1219 wwin->icon->mapped = 0;
1221 wwin->flags.hidden = 1;
1223 WMPostNotificationName(WMNChangedState, wwin, "hide");
1227 if (wwin->flags.inspector_open) {
1228 wHideInspectorForWindow(wwin);
1231 wwin->flags.hidden = 1;
1234 wClientSetState(wwin, IconicState, icon->icon_win);
1236 wSoundPlay(WSOUND_HIDE);
1238 if (!wwin->screen_ptr->flags.startup && !wPreferences.no_animations &&
1239 !wwin->flags.skip_next_animation && animate) {
1240 animateResize(wwin->screen_ptr, wwin->frame_x, wwin->frame_y,
1241 wwin->frame->core->width, wwin->frame->core->height,
1242 icon_x, icon_y, icon->core->width, icon->core->height, True);
1245 wwin->flags.skip_next_animation = 0;
1247 WMPostNotificationName(WMNChangedState, wwin, "hide");
1250 void wHideOtherApplications(WWindow * awin)
1257 wwin = awin->screen_ptr->focused_window;
1261 && wwin->frame->workspace == awin->screen_ptr->current_workspace
1262 && !(wwin->flags.miniaturized || wwin->flags.hidden)
1263 && !wwin->flags.internal_window
1264 && wGetWindowOfInspectorForWindow(wwin) != awin && !WFLAGP(wwin, no_hide_others)) {
1266 if (wwin->main_window == None || WFLAGP(wwin, no_appicon)) {
1267 if (!WFLAGP(wwin, no_miniaturizable)) {
1268 wwin->flags.skip_next_animation = 1;
1269 wIconifyWindow(wwin);
1271 } else if (wwin->main_window != None && awin->main_window != wwin->main_window) {
1272 tapp = wApplicationOf(wwin->main_window);
1274 tapp->flags.skip_next_animation = 1;
1275 wHideApplication(tapp);
1277 if (!WFLAGP(wwin, no_miniaturizable)) {
1278 wwin->flags.skip_next_animation = 1;
1279 wIconifyWindow(wwin);
1287 wSetFocusTo(awin->screen_ptr, awin);
1291 void wHideApplication(WApplication * wapp)
1299 wwarning("trying to hide a non grouped window");
1302 if (!wapp->main_window_desc) {
1303 wwarning("group leader not found for window group");
1306 scr = wapp->main_window_desc->screen_ptr;
1308 wlist = scr->focused_window;
1312 if (wlist->main_window == wapp->main_window)
1313 wapp->last_focused = wlist;
1315 wapp->last_focused = NULL;
1317 animate = !wapp->flags.skip_next_animation;
1320 if (wlist->main_window == wapp->main_window) {
1321 if (wlist->flags.focused) {
1324 if (wapp->app_icon) {
1325 hideWindow(wapp->app_icon->icon, wapp->app_icon->x_pos,
1326 wapp->app_icon->y_pos, wlist, animate);
1330 wlist = wlist->prev;
1333 wapp->flags.skip_next_animation = 0;
1336 if (wPreferences.focus_mode == WKF_CLICK) {
1337 wlist = scr->focused_window;
1339 if (!WFLAGP(wlist, no_focusable) && !wlist->flags.hidden
1340 && (wlist->flags.mapped || wlist->flags.shaded))
1342 wlist = wlist->prev;
1344 wSetFocusTo(scr, wlist);
1346 wSetFocusTo(scr, NULL);
1350 wapp->flags.hidden = 1;
1352 if (wPreferences.auto_arrange_icons) {
1353 wArrangeIcons(scr, True);
1357 wAppIconPaint(wapp->app_icon);
1361 static void unhideWindow(WIcon * icon, int icon_x, int icon_y, WWindow * wwin, int animate, int bringToCurrentWS)
1363 if (bringToCurrentWS)
1364 wWindowChangeWorkspace(wwin, wwin->screen_ptr->current_workspace);
1366 wwin->flags.hidden = 0;
1368 wSoundPlay(WSOUND_UNHIDE);
1370 if (!wwin->screen_ptr->flags.startup && !wPreferences.no_animations && animate) {
1371 animateResize(wwin->screen_ptr, icon_x, icon_y,
1372 icon->core->width, icon->core->height,
1373 wwin->frame_x, wwin->frame_y,
1374 wwin->frame->core->width, wwin->frame->core->height, True);
1377 wwin->flags.skip_next_animation = 0;
1378 if (wwin->screen_ptr->current_workspace == wwin->frame->workspace) {
1379 XMapWindow(dpy, wwin->client_win);
1380 XMapWindow(dpy, wwin->frame->core->window);
1381 wClientSetState(wwin, NormalState, None);
1382 wwin->flags.mapped = 1;
1383 wRaiseFrame(wwin->frame->core);
1385 if (wwin->flags.inspector_open) {
1386 wUnhideInspectorForWindow(wwin);
1389 WMPostNotificationName(WMNChangedState, wwin, "hide");
1392 void wUnhideApplication(WApplication * wapp, Bool miniwindows, Bool bringToCurrentWS)
1395 WWindow *wlist, *next;
1396 WWindow *focused = NULL;
1402 scr = wapp->main_window_desc->screen_ptr;
1403 wlist = scr->focused_window;
1407 /* goto beginning of list */
1409 wlist = wlist->prev;
1411 animate = !wapp->flags.skip_next_animation;
1416 if (wlist->main_window == wapp->main_window) {
1417 if (wlist->flags.focused)
1419 else if (!focused || !focused->flags.focused)
1422 if (wlist->flags.miniaturized) {
1423 if ((bringToCurrentWS || wPreferences.sticky_icons ||
1424 wlist->frame->workspace == scr->current_workspace) && wlist->icon) {
1425 if (!wlist->icon->mapped) {
1428 PlaceIcon(scr, &x, &y, wGetHeadForWindow(wlist));
1429 if (wlist->icon_x != x || wlist->icon_y != y) {
1430 XMoveWindow(dpy, wlist->icon->core->window, x, y);
1434 XMapWindow(dpy, wlist->icon->core->window);
1435 wlist->icon->mapped = 1;
1437 wRaiseFrame(wlist->icon->core);
1439 if (bringToCurrentWS)
1440 wWindowChangeWorkspace(wlist, scr->current_workspace);
1441 wlist->flags.hidden = 0;
1442 if (miniwindows && wlist->frame->workspace == scr->current_workspace) {
1443 wDeiconifyWindow(wlist);
1445 WMPostNotificationName(WMNChangedState, wlist, "hide");
1446 } else if (wlist->flags.shaded) {
1447 if (bringToCurrentWS)
1448 wWindowChangeWorkspace(wlist, scr->current_workspace);
1449 wlist->flags.hidden = 0;
1450 if (wlist->frame->workspace == scr->current_workspace) {
1451 XMapWindow(dpy, wlist->frame->core->window);
1453 wUnshadeWindow(wlist);
1454 wRaiseFrame(wlist->frame->core);
1457 WMPostNotificationName(WMNChangedState, wlist, "hide");
1458 } else if (wlist->flags.hidden) {
1459 unhideWindow(wapp->app_icon->icon, wapp->app_icon->x_pos,
1460 wapp->app_icon->y_pos, wlist, animate, bringToCurrentWS);
1463 if (bringToCurrentWS && wlist->frame->workspace != scr->current_workspace) {
1464 wWindowChangeWorkspace(wlist, scr->current_workspace);
1466 wRaiseFrame(wlist->frame->core);
1472 wapp->flags.skip_next_animation = 0;
1473 wapp->flags.hidden = 0;
1475 if (wapp->last_focused && wapp->last_focused->flags.mapped) {
1476 wRaiseFrame(wapp->last_focused->frame->core);
1477 wSetFocusTo(scr, wapp->last_focused);
1478 } else if (focused) {
1479 wSetFocusTo(scr, focused);
1481 wapp->last_focused = NULL;
1482 if (wPreferences.auto_arrange_icons) {
1483 wArrangeIcons(scr, True);
1486 wAppIconPaint(wapp->app_icon);
1490 void wShowAllWindows(WScreen * scr)
1492 WWindow *wwin, *old_foc;
1495 old_foc = wwin = scr->focused_window;
1497 if (!wwin->flags.internal_window &&
1498 (scr->current_workspace == wwin->frame->workspace || IS_OMNIPRESENT(wwin))) {
1499 if (wwin->flags.miniaturized) {
1500 wwin->flags.skip_next_animation = 1;
1501 wDeiconifyWindow(wwin);
1502 } else if (wwin->flags.hidden) {
1503 wapp = wApplicationOf(wwin->main_window);
1505 wUnhideApplication(wapp, False, False);
1507 wwin->flags.skip_next_animation = 1;
1508 wDeiconifyWindow(wwin);
1514 wSetFocusTo(scr, old_foc);
1515 /*wRaiseFrame(old_foc->frame->core); */
1518 void wRefreshDesktop(WScreen * scr)
1521 XSetWindowAttributes attr;
1523 attr.backing_store = NotUseful;
1524 attr.save_under = False;
1525 win = XCreateWindow(dpy, scr->root_win, 0, 0, scr->scr_width,
1526 scr->scr_height, 0, CopyFromParent, CopyFromParent,
1527 (Visual *) CopyFromParent, CWBackingStore | CWSaveUnder, &attr);
1528 XMapRaised(dpy, win);
1529 XDestroyWindow(dpy, win);
1533 void wArrangeIcons(WScreen * scr, Bool arrangeAll)
1539 const int heads = wXineramaHeads(scr);
1542 int pf; /* primary axis */
1543 int sf; /* secondary axis */
1547 int sx1, sx2, sy1, sy2; /* screen boundary */
1553 int isize = wPreferences.icon_size;
1555 vars = (struct HeadVars *)wmalloc(sizeof(struct HeadVars) * heads);
1557 for (head = 0; head < heads; ++head) {
1559 WMRect rect = wGetRectForHead(scr, head);
1561 WArea area = wGetUsableAreaForHead(scr, head, NULL, False);
1562 WMRect rect = wmkrect(area.x1, area.y1, area.x2 - area.x1, area.y2 - area.y1);
1565 vars[head].pi = vars[head].si = 0;
1566 vars[head].sx1 = rect.pos.x;
1567 vars[head].sy1 = rect.pos.y;
1568 vars[head].sw = rect.size.width;
1569 vars[head].sh = rect.size.height;
1570 vars[head].sx2 = vars[head].sx1 + vars[head].sw;
1571 vars[head].sy2 = vars[head].sy1 + vars[head].sh;
1575 if (scr->dock->on_right_side)
1576 vars[head].sx2 -= isize + DOCK_EXTRA_SPACE;
1578 vars[head].sx1 += isize + DOCK_EXTRA_SPACE;
1582 vars[head].sw = isize * (vars[head].sw / isize);
1583 vars[head].sh = isize * (vars[head].sh / isize);
1584 vars[head].fullW = (vars[head].sx2 - vars[head].sx1) / isize;
1585 vars[head].fullH = (vars[head].sy2 - vars[head].sy1) / isize;
1587 /* icon yard boundaries */
1588 if (wPreferences.icon_yard & IY_VERT) {
1589 vars[head].pf = vars[head].fullH;
1590 vars[head].sf = vars[head].fullW;
1592 vars[head].pf = vars[head].fullW;
1593 vars[head].sf = vars[head].fullH;
1595 if (wPreferences.icon_yard & IY_RIGHT) {
1596 vars[head].xo = vars[head].sx2 - isize;
1599 vars[head].xo = vars[head].sx1;
1602 if (wPreferences.icon_yard & IY_TOP) {
1603 vars[head].yo = vars[head].sy1;
1606 vars[head].yo = vars[head].sy2 - isize;
1611 #define X ((wPreferences.icon_yard & IY_VERT) \
1612 ? vars[head].xo + vars[head].xs*(vars[head].si*isize) \
1613 : vars[head].xo + vars[head].xs*(vars[head].pi*isize))
1615 #define Y ((wPreferences.icon_yard & IY_VERT) \
1616 ? vars[head].yo + vars[head].ys*(vars[head].pi*isize) \
1617 : vars[head].yo + vars[head].ys*(vars[head].si*isize))
1619 /* arrange application icons */
1620 aicon = scr->app_icon_list;
1621 /* reverse them to avoid unnecessarily sliding of icons */
1622 while (aicon && aicon->next)
1623 aicon = aicon->next;
1626 if (!aicon->docked) {
1627 /* CHECK: can icon be NULL here ? */
1628 /* The intention here is to place the AppIcon on the head that
1629 * contains most of the applications _main_ window. */
1630 head = wGetHeadForWindow(aicon->icon->owner);
1632 if (aicon->x_pos != X || aicon->y_pos != Y) {
1634 if (!wPreferences.no_animations) {
1635 SlideWindow(aicon->icon->core->window, aicon->x_pos, aicon->y_pos, X, Y);
1637 #endif /* ANIMATIONS */
1639 wAppIconMove(aicon, X, Y);
1641 if (vars[head].pi >= vars[head].pf) {
1646 aicon = aicon->prev;
1649 /* arrange miniwindows */
1650 wwin = scr->focused_window;
1651 /* reverse them to avoid unnecessarily shuffling */
1652 while (wwin && wwin->prev)
1656 if (wwin->icon && wwin->flags.miniaturized && !wwin->flags.hidden &&
1657 (wwin->frame->workspace == scr->current_workspace ||
1658 IS_OMNIPRESENT(wwin) || wPreferences.sticky_icons)) {
1660 head = wGetHeadForWindow(wwin);
1662 if (arrangeAll || !wwin->flags.icon_moved) {
1663 if (wwin->icon_x != X || wwin->icon_y != Y) {
1665 if (wPreferences.no_animations) {
1666 XMoveWindow(dpy, wwin->icon->core->window, X, Y);
1668 SlideWindow(wwin->icon->core->window, wwin->icon_x,
1669 wwin->icon_y, X, Y);
1672 XMoveWindow(dpy, wwin->icon->core->window, X, Y);
1673 #endif /* ANIMATIONS */
1679 if (vars[head].pi >= vars[head].pf) {
1686 wwin->flags.icon_moved = 0;
1688 /* we reversed the order, so we use next */
1696 void wArrangeIcons(WScreen * scr, Bool arrangeAll)
1700 int pf; /* primary axis */
1701 int sf; /* secondary axis */
1705 int sx1, sx2, sy1, sy2; /* screen boundary */
1709 int isize = wPreferences.icon_size;
1712 * Find out screen boundaries.
1716 * Allows each head to have miniwindows
1718 WMRect rect = wGetRectForHead(scr, wGetHeadForPointerLocation(scr));
1722 sw = rect.size.width;
1723 sh = rect.size.height;
1727 if (scr->dock->on_right_side)
1728 sx2 -= isize + DOCK_EXTRA_SPACE;
1730 sx1 += isize + DOCK_EXTRA_SPACE;
1733 sw = isize * (scr->scr_width / isize);
1734 sh = isize * (scr->scr_height / isize);
1736 sw = isize * (sw / isize);
1737 sh = isize * (sh / isize);
1739 fullW = (sx2 - sx1) / isize;
1740 fullH = (sy2 - sy1) / isize;
1742 /* icon yard boundaries */
1743 if (wPreferences.icon_yard & IY_VERT) {
1750 if (wPreferences.icon_yard & IY_RIGHT) {
1757 if (wPreferences.icon_yard & IY_TOP) {
1765 /* arrange icons putting the most recently focused window
1766 * as the last icon */
1767 #define X ((wPreferences.icon_yard & IY_VERT) ? xo + xs*(si*isize)\
1768 : xo + xs*(pi*isize))
1769 #define Y ((wPreferences.icon_yard & IY_VERT) ? yo + ys*(pi*isize)\
1770 : yo + ys*(si*isize))
1772 /* arrange application icons */
1773 aicon = scr->app_icon_list;
1774 /* reverse them to avoid unnecessarily sliding of icons */
1775 while (aicon && aicon->next)
1776 aicon = aicon->next;
1781 if (!aicon->docked) {
1782 if (aicon->x_pos != X || aicon->y_pos != Y) {
1784 if (!wPreferences.no_animations) {
1785 SlideWindow(aicon->icon->core->window, aicon->x_pos, aicon->y_pos, X, Y);
1787 #endif /* ANIMATIONS */
1789 wAppIconMove(aicon, X, Y);
1792 /* we reversed the order so we use prev */
1793 aicon = aicon->prev;
1800 /* arrange miniwindows */
1802 wwin = scr->focused_window;
1803 /* reverse them to avoid unnecessarily shuffling */
1804 while (wwin && wwin->prev)
1808 if (wwin->icon && wwin->flags.miniaturized && !wwin->flags.hidden &&
1809 (wwin->frame->workspace == scr->current_workspace ||
1810 IS_OMNIPRESENT(wwin) || wPreferences.sticky_icons)) {
1812 if (arrangeAll || !wwin->flags.icon_moved) {
1813 if (wwin->icon_x != X || wwin->icon_y != Y) {
1815 if (wPreferences.no_animations) {
1816 XMoveWindow(dpy, wwin->icon->core->window, X, Y);
1818 SlideWindow(wwin->icon->core->window, wwin->icon_x,
1819 wwin->icon_y, X, Y);
1822 XMoveWindow(dpy, wwin->icon->core->window, X, Y);
1823 #endif /* ANIMATIONS */
1831 wwin->flags.icon_moved = 0;
1833 /* we reversed the order, so we use next */
1843 void wSelectWindow(WWindow * wwin, Bool flag)
1845 WScreen *scr = wwin->screen_ptr;
1848 wwin->flags.selected = 1;
1849 XSetWindowBorder(dpy, wwin->frame->core->window, scr->white_pixel);
1851 if (!HAS_BORDER(wwin)) {
1852 XSetWindowBorderWidth(dpy, wwin->frame->core->window, FRAME_BORDER_WIDTH);
1855 if (!scr->selected_windows)
1856 scr->selected_windows = WMCreateArray(4);
1857 WMAddToArray(scr->selected_windows, wwin);
1859 wwin->flags.selected = 0;
1860 XSetWindowBorder(dpy, wwin->frame->core->window, scr->frame_border_pixel);
1862 if (!HAS_BORDER(wwin)) {
1863 XSetWindowBorderWidth(dpy, wwin->frame->core->window, 0);
1866 if (scr->selected_windows) {
1867 WMRemoveFromArray(scr->selected_windows, wwin);
1872 void wMakeWindowVisible(WWindow * wwin)
1874 if (wwin->frame->workspace != wwin->screen_ptr->current_workspace)
1875 wWorkspaceChange(wwin->screen_ptr, wwin->frame->workspace);
1877 if (wwin->flags.shaded) {
1878 wUnshadeWindow(wwin);
1880 if (wwin->flags.hidden) {
1883 app = wApplicationOf(wwin->main_window);
1885 /* trick to get focus to this window */
1886 app->last_focused = wwin;
1887 wUnhideApplication(app, False, False);
1890 if (wwin->flags.miniaturized) {
1891 wDeiconifyWindow(wwin);
1893 if (!WFLAGP(wwin, no_focusable))
1894 wSetFocusTo(wwin->screen_ptr, wwin);
1895 wRaiseFrame(wwin->frame->core);