Bug fixes for 0.20.3 pre-release 2
[wmaker-crm.git] / src / actions.c
blobb76faaefbf500da34ddf11289eb4cca674a18edc
1 /* action.c- misc. window commands (miniaturize, hide etc.)
2 *
3 * Window Maker window manager
4 *
5 * Copyright (c) 1997, 1998 Alfredo K. Kojima
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 * USA.
22 #include "wconfig.h"
24 #include <X11/Xlib.h>
25 #include <X11/Xutil.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <math.h>
30 #include <time.h>
32 #include "WindowMaker.h"
33 #include "wcore.h"
34 #include "framewin.h"
35 #include "window.h"
36 #include "client.h"
37 #include "icon.h"
38 #include "funcs.h"
39 #include "application.h"
40 #include "actions.h"
41 #include "stacking.h"
42 #include "appicon.h"
43 #include "dock.h"
44 #include "appmenu.h"
45 #include "winspector.h"
46 #include "list.h"
47 #include "workspace.h"
49 #ifdef WMSOUND
50 #include "wmsound.h"
51 #endif
54 /****** Global Variables ******/
55 extern Time LastTimestamp;
56 extern Time LastFocusChange;
58 extern Cursor wCursor[WCUR_LAST];
60 extern WPreferences wPreferences;
62 extern Atom _XA_WM_TAKE_FOCUS;
64 /******* Local Variables *******/
65 static struct {
66 int steps;
67 int delay;
68 } shadePars[5] = {
69 {SHADE_STEPS_UF, SHADE_DELAY_UF},
70 {SHADE_STEPS_F, SHADE_DELAY_F},
71 {SHADE_STEPS_M, SHADE_DELAY_M},
72 {SHADE_STEPS_S, SHADE_DELAY_S},
73 {SHADE_STEPS_U, SHADE_DELAY_U}};
75 #define SHADE_STEPS shadePars[(int)wPreferences.shade_speed].steps
76 #define SHADE_DELAY shadePars[(int)wPreferences.shade_speed].delay
79 static int ignoreTimestamp=0;
82 #ifdef ANIMATIONS
83 static void
84 processEvents(int event_count)
86 XEvent event;
89 * This is a hack. When animations are enabled, processing of
90 * events ocurred during a animation are delayed until it's end.
91 * Calls that consider the TimeStamp, like XSetInputFocus(), will
92 * fail because the TimeStamp is too old. Then, for example, if
93 * the user changes window focus while a miniaturize animation is
94 * in course, the window will not get focus properly after the end
95 * of the animation. This tries to workaround it by passing CurrentTime
96 * as the TimeStamp for XSetInputFocus() for all events ocurred during
97 * the animation.
99 ignoreTimestamp=1;
100 while (event_count--) {
101 WMNextEvent(dpy, &event);
102 WMHandleEvent(&event);
104 ignoreTimestamp=0;
106 #endif /* ANIMATIONS */
110 *----------------------------------------------------------------------
111 * wSetFocusTo--
112 * Changes the window focus to the one passed as argument.
113 * If the window to focus is not already focused, it will be brought
114 * to the head of the list of windows. Previously focused window is
115 * unfocused.
117 * Side effects:
118 * Window list may be reordered and the window focus is changed.
120 *----------------------------------------------------------------------
122 void
123 wSetFocusTo(WScreen *scr, WWindow *wwin)
125 WWindow *focused=scr->focused_window;
126 WWindow *owner = NULL;
127 int timestamp=LastTimestamp;
128 WApplication *oapp=NULL, *napp=NULL;
129 int wasfocused;
131 LastFocusChange = timestamp;
133 if (ignoreTimestamp)
134 timestamp=CurrentTime;
136 if (focused)
137 oapp = wApplicationOf(focused->main_window);
139 if (wwin==NULL) {
140 XSetInputFocus(dpy, scr->no_focus_win, RevertToParent, timestamp);
141 if (focused) {
142 wWindowUnfocus(focused);
144 if (oapp) {
145 wAppMenuUnmap(oapp->menu);
146 #ifdef NEWAPPICON
147 wApplicationDeactivate(oapp);
148 #endif
150 return;
152 wasfocused = wwin->flags.focused;
153 napp = wApplicationOf(wwin->main_window);
155 /* remember last workspace where the app has been */
156 if (napp)
157 napp->last_workspace = wwin->screen_ptr->current_workspace;
159 if (wwin->window_flags.no_focusable)
160 return;
162 if (wwin->flags.mapped) {
163 /* install colormap if colormap mode is lock mode */
164 if (wPreferences.colormap_mode==WKF_CLICK)
165 wColormapInstallForWindow(scr, wwin);
167 /* set input focus */
168 switch (wwin->focus_mode) {
169 case WFM_NO_INPUT:
170 XSetInputFocus(dpy, scr->no_focus_win, RevertToParent, timestamp);
171 break;
173 case WFM_PASSIVE:
174 case WFM_LOCALLY_ACTIVE:
175 XSetInputFocus(dpy, wwin->client_win, RevertToParent, timestamp);
176 break;
178 case WFM_GLOBALLY_ACTIVE:
179 break;
181 XFlush(dpy);
182 if (wwin->protocols.TAKE_FOCUS) {
183 wClientSendProtocol(wwin, _XA_WM_TAKE_FOCUS, timestamp);
185 XSync(dpy, False);
186 } else {
187 XSetInputFocus(dpy, scr->no_focus_win, RevertToParent, timestamp);
190 /* if this is not the focused window focus it */
191 if (focused!=wwin) {
192 int foo=0;
194 if (wwin->client_win == focused->transient_for)
195 wwin->flags.semi_focused = 0;
196 else if (wwin->transient_for == focused->client_win)
197 focused->flags.semi_focused = 1;
199 if (wwin->transient_for
200 && wwin->transient_for == focused->transient_for) {
201 owner = wWindowFor(wwin->transient_for);
202 if (owner && owner->flags.semi_focused) {
203 foo=1;
204 /* this is to override the unfocusing of the mainwindow
205 * in the next wWindowUnfocus() and avoid flickering */
206 owner->flags.semi_focused = 0;
209 /* unfocus previous window */
210 wWindowUnfocus(focused);
211 if (foo) {
212 owner->flags.semi_focused = 1;
214 /* change the focus window list order */
215 if (wwin->prev)
216 wwin->prev->next=wwin->next;
217 if (wwin->next)
218 wwin->next->prev=wwin->prev;
220 wwin->prev = focused;
221 focused->next = wwin;
222 wwin->next = NULL;
223 scr->focused_window = wwin;
225 if (oapp && oapp != napp) {
226 wAppMenuUnmap(oapp->menu);
227 #ifdef NEWAPPICON
228 wApplicationDeactivate(oapp);
229 #endif
232 if ((owner=wWindowFor(wwin->transient_for))
233 && !owner->flags.semi_focused) {
234 owner->flags.semi_focused = 1;
235 wWindowUnfocus(owner);
237 wWindowFocus(wwin);
238 if (napp && !wasfocused) {
239 wAppMenuMap(napp->menu, wwin);
240 #ifdef NEWAPPICON
241 wApplicationActivate(napp);
242 #endif
244 XFlush(dpy);
248 void
249 wShadeWindow(WWindow *wwin)
251 XWindowAttributes attribs;
252 time_t time0 = time(NULL);
253 #ifdef ANIMATIONS
254 int y, s, w, h;
255 #endif
257 if (wwin->flags.shaded)
258 return;
260 XLowerWindow(dpy, wwin->client_win);
262 #ifdef WMSOUND
263 wSoundPlay(WMSOUND_SHADE);
264 #endif
266 #ifdef ANIMATIONS
267 if (!wwin->screen_ptr->flags.startup && !wwin->flags.skip_next_animation
268 && !wPreferences.no_animations) {
269 /* do the shading animation */
270 h = wwin->frame->core->height;
271 s = h/SHADE_STEPS;
272 if (s < 1) s=1;
273 w = wwin->frame->core->width;
274 y = wwin->frame->top_width;
275 while (h>wwin->frame->top_width+1) {
276 XMoveWindow(dpy, wwin->client_win, 0, y);
277 XResizeWindow(dpy, wwin->frame->core->window, w, h);
278 XFlush(dpy);
280 if (time(NULL)-time0 > MAX_ANIMATION_TIME)
281 break;
283 if (SHADE_DELAY > 0)
284 wusleep(SHADE_DELAY*1000L);
285 h-=s;
286 y-=s;
288 XMoveWindow(dpy, wwin->client_win, 0, wwin->frame->top_width);
290 #endif /* ANIMATIONS */
293 wwin->flags.skip_next_animation = 0;
294 XGetWindowAttributes(dpy, wwin->client_win, &attribs);
295 wwin->flags.shaded=1;
296 wwin->flags.mapped=0;
297 /* prevent window withdrawal when getting UnmapNotify */
298 XSelectInput(dpy, wwin->client_win,
299 attribs.your_event_mask & ~StructureNotifyMask);
300 XUnmapWindow(dpy, wwin->client_win);
301 XSelectInput(dpy, wwin->client_win, attribs.your_event_mask);
303 /* for the client it's just like iconification */
304 wFrameWindowResize(wwin->frame, wwin->frame->core->width,
305 wwin->frame->top_width-1);
307 wClientSetState(wwin, IconicState, None);
310 /* update window list to reflect shaded state */
311 UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_STATE);
313 #ifdef ANIMATIONS
314 if (!wwin->screen_ptr->flags.startup) {
315 /* Look at processEvents() for reason of this code. */
316 XSync(dpy, 0);
317 processEvents(XPending(dpy));
319 #endif
323 void
324 wUnshadeWindow(WWindow *wwin)
326 time_t time0 = time(NULL);
327 #ifdef ANIMATIONS
328 int y, s, w, h;
329 #endif /* ANIMATIONS */
332 if (!wwin->flags.shaded)
333 return;
335 wwin->flags.shaded=0;
336 wwin->flags.mapped=1;
337 XMapWindow(dpy, wwin->client_win);
339 #ifdef WMSOUND
340 wSoundPlay(WMSOUND_UNSHADE);
341 #endif
343 #ifdef ANIMATIONS
344 if (!wPreferences.no_animations && !wwin->flags.skip_next_animation) {
345 /* do the shading animation */
346 h = wwin->frame->top_width + wwin->frame->bottom_width;
347 y = wwin->frame->top_width - wwin->client.height;
348 s = abs(y)/SHADE_STEPS;
349 if (s<1) s=1;
350 w = wwin->frame->core->width;
351 XMoveWindow(dpy, wwin->client_win, 0, y);
352 if (s>0) {
353 while (h < wwin->client.height + wwin->frame->top_width
354 + wwin->frame->bottom_width) {
355 XResizeWindow(dpy, wwin->frame->core->window, w, h);
356 XMoveWindow(dpy, wwin->client_win, 0, y);
357 XSync(dpy, 0);
358 if (SHADE_DELAY > 0)
359 wusleep(SHADE_DELAY*2000L/3);
360 h+=s;
361 y+=s;
363 if (time(NULL)-time0 > MAX_ANIMATION_TIME)
364 break;
367 XMoveWindow(dpy, wwin->client_win, 0, wwin->frame->top_width);
369 #endif /* ANIMATIONS */
372 wwin->flags.skip_next_animation = 0;
373 wFrameWindowResize(wwin->frame, wwin->frame->core->width,
374 wwin->frame->top_width + wwin->client.height
375 + wwin->frame->bottom_width);
377 wClientSetState(wwin, NormalState, None);
379 /* if the window is focused, set the focus again as it was disabled during
380 * shading */
381 if (wwin->flags.focused)
382 wSetFocusTo(wwin->screen_ptr, wwin);
384 /* update window list to reflect unshaded state */
385 UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_STATE);
389 void
390 wMaximizeWindow(WWindow *wwin, int directions)
392 int new_width, new_height, new_x, new_y;
394 if (wwin->flags.shaded) {
395 wwin->flags.skip_next_animation = 1;
396 wUnshadeWindow(wwin);
398 wwin->flags.maximized = directions;
399 wwin->old_geometry.width = wwin->client.width;
400 wwin->old_geometry.height = wwin->client.height;
401 wwin->old_geometry.x = wwin->frame_x;
402 wwin->old_geometry.y = wwin->frame_y;
403 if (directions & MAX_HORIZONTAL) {
404 new_width = wwin->screen_ptr->scr_width-FRAME_BORDER_WIDTH*2;
406 new_x = 0;
407 if ((wPreferences.icon_yard & IY_VERT)
408 && wPreferences.no_window_over_icons) {
410 new_width -= wPreferences.icon_size;
411 if (!(wPreferences.icon_yard & IY_RIGHT))
412 new_x += wPreferences.icon_size;
414 #if 0
415 if (wPreferences.no_window_under_dock
416 && wwin->screen_ptr->dock) {
417 new_width -= wPreferences.icon_size + DOCK_EXTRA_SPACE;
418 if (!wwin->screen_ptr->dock->on_right_side)
419 new_x += wPreferences.icon_size + DOCK_EXTRA_SPACE;
421 #endif
422 if (wwin->screen_ptr->dock && !wwin->screen_ptr->dock->lowered) {
423 new_width -= wPreferences.icon_size + DOCK_EXTRA_SPACE;
424 if (!wwin->screen_ptr->dock->on_right_side)
425 new_x += wPreferences.icon_size + DOCK_EXTRA_SPACE;
427 } else {
428 new_x = wwin->frame_x;
429 new_width = wwin->frame->core->width;
432 if (directions & MAX_VERTICAL) {
433 new_height = wwin->screen_ptr->scr_height-FRAME_BORDER_WIDTH*2;
434 new_y = 0;
435 if (!(wPreferences.icon_yard & IY_VERT)
436 && wPreferences.no_window_over_icons) {
438 new_height -= wPreferences.icon_size;
440 if (wPreferences.icon_yard & IY_TOP)
441 new_y += wPreferences.icon_size;
443 } else {
444 new_y = wwin->frame_y;
445 new_height = wwin->frame->core->height;
447 new_height -= wwin->frame->top_width+wwin->frame->bottom_width;
449 wWindowConstrainSize(wwin, &new_width, &new_height);
450 wWindowConfigure(wwin, new_x, new_y, new_width, new_height);
452 #ifdef WMSOUND
453 wSoundPlay(WMSOUND_MAXIMIZE);
454 #endif
458 void
459 wUnmaximizeWindow(WWindow *wwin)
461 int restore_x, restore_y;
463 if (wwin->flags.shaded) {
464 wwin->flags.skip_next_animation = 1;
465 wUnshadeWindow(wwin);
467 restore_x = (wwin->flags.maximized & MAX_HORIZONTAL) ?
468 wwin->old_geometry.x : wwin->frame_x;
469 restore_y = (wwin->flags.maximized & MAX_VERTICAL) ?
470 wwin->old_geometry.y : wwin->frame_y;
471 wwin->flags.maximized = 0;
472 wWindowConfigure(wwin, restore_x, restore_y,
473 wwin->old_geometry.width, wwin->old_geometry.height);
475 #ifdef WMSOUND
476 wSoundPlay(WMSOUND_UNMAXIMIZE);
477 #endif
480 #ifdef ANIMATIONS
481 static void
482 animateResizeFlip(WScreen *scr, int x, int y, int w, int h,
483 int fx, int fy, int fw, int fh, int steps)
485 #define FRAMES (MINIATURIZE_ANIMATION_FRAMES_F)
486 float cx, cy, cw, ch;
487 float xstep, ystep, wstep, hstep;
488 XPoint points[5];
489 float dx, dch, midy;
490 float angle, final_angle, delta;
492 xstep = (float)(fx-x)/steps;
493 ystep = (float)(fy-y)/steps;
494 wstep = (float)(fw-w)/steps;
495 hstep = (float)(fh-h)/steps;
497 cx = (float)x;
498 cy = (float)y;
499 cw = (float)w;
500 ch = (float)h;
502 final_angle = 2*WM_PI*MINIATURIZE_ANIMATION_TWIST_F;
503 delta = (float)(final_angle/FRAMES);
504 for (angle=0;; angle+=delta) {
505 if (angle > final_angle)
506 angle = final_angle;
508 dx = (cw/10) - ((cw/5) * sin(angle));
509 dch = (ch/2) * cos(angle);
510 midy = cy + (ch/2);
512 points[0].x = cx + dx; points[0].y = midy - dch;
513 points[1].x = cx + cw - dx; points[1].y = points[0].y;
514 points[2].x = cx + cw + dx; points[2].y = midy + dch;
515 points[3].x = cx - dx; points[3].y = points[2].y;
516 points[4].x = points[0].x; points[4].y = points[0].y;
518 XGrabServer(dpy);
519 XDrawLines(dpy,scr->root_win,scr->frame_gc,points, 5, CoordModeOrigin);
520 XFlush(dpy);
521 #if (MINIATURIZE_ANIMATION_DELAY_F > 0)
522 wusleep(MINIATURIZE_ANIMATION_DELAY_F);
523 #endif
525 XDrawLines(dpy,scr->root_win,scr->frame_gc,points, 5, CoordModeOrigin);
526 XUngrabServer(dpy);
527 cx+=xstep;
528 cy+=ystep;
529 cw+=wstep;
530 ch+=hstep;
531 if (angle >= final_angle)
532 break;
535 XFlush(dpy);
537 #undef FRAMES
540 static void
541 animateResizeTwist(WScreen *scr, int x, int y, int w, int h,
542 int fx, int fy, int fw, int fh, int steps)
544 #define FRAMES (MINIATURIZE_ANIMATION_FRAMES_T)
545 float cx, cy, cw, ch;
546 float xstep, ystep, wstep, hstep;
547 XPoint points[5];
548 float angle, final_angle, a, d, delta;
550 x += w/2;
551 y += h/2;
552 fx += fw/2;
553 fy += fh/2;
555 xstep = (float)(fx-x)/steps;
556 ystep = (float)(fy-y)/steps;
557 wstep = (float)(fw-w)/steps;
558 hstep = (float)(fh-h)/steps;
560 cx = (float)x;
561 cy = (float)y;
562 cw = (float)w;
563 ch = (float)h;
565 final_angle = 2*WM_PI*MINIATURIZE_ANIMATION_TWIST_T;
566 delta = (float)(final_angle/FRAMES);
567 for (angle=0;; angle+=delta) {
568 if (angle > final_angle)
569 angle = final_angle;
571 a = atan(ch/cw);
572 d = sqrt((cw/2)*(cw/2)+(ch/2)*(ch/2));
574 points[0].x = cx+cos(angle-a)*d;
575 points[0].y = cy+sin(angle-a)*d;
576 points[1].x = cx+cos(angle+a)*d;
577 points[1].y = cy+sin(angle+a)*d;
578 points[2].x = cx+cos(angle-a+WM_PI)*d;
579 points[2].y = cy+sin(angle-a+WM_PI)*d;
580 points[3].x = cx+cos(angle+a+WM_PI)*d;
581 points[3].y = cy+sin(angle+a+WM_PI)*d;
582 points[4].x = cx+cos(angle-a)*d;
583 points[4].y = cy+sin(angle-a)*d;
584 XGrabServer(dpy);
585 XDrawLines(dpy, scr->root_win, scr->frame_gc, points, 5, CoordModeOrigin);
586 XFlush(dpy);
587 #if (MINIATURIZE_ANIMATION_DELAY_T > 0)
588 wusleep(MINIATURIZE_ANIMATION_DELAY_T);
589 #endif
591 XDrawLines(dpy, scr->root_win, scr->frame_gc, points, 5, CoordModeOrigin);
592 XUngrabServer(dpy);
593 cx+=xstep;
594 cy+=ystep;
595 cw+=wstep;
596 ch+=hstep;
597 if (angle >= final_angle)
598 break;
601 XFlush(dpy);
603 #undef FRAMES
606 static void
607 animateResizeZoom(WScreen *scr, int x, int y, int w, int h,
608 int fx, int fy, int fw, int fh, int steps)
610 #define FRAMES (MINIATURIZE_ANIMATION_FRAMES_Z)
611 float cx[FRAMES], cy[FRAMES], cw[FRAMES], ch[FRAMES];
612 float xstep, ystep, wstep, hstep;
613 int i, j;
615 xstep = (float)(fx-x)/steps;
616 ystep = (float)(fy-y)/steps;
617 wstep = (float)(fw-w)/steps;
618 hstep = (float)(fh-h)/steps;
620 for (j=0; j<FRAMES; j++) {
621 cx[j] = (float)x;
622 cy[j] = (float)y;
623 cw[j] = (float)w;
624 ch[j] = (float)h;
626 XGrabServer(dpy);
627 for (i=0; i<steps; i++) {
628 for (j=0; j<FRAMES; j++) {
629 XDrawRectangle(dpy, scr->root_win, scr->frame_gc,
630 (int)cx[j], (int)cy[j], (int)cw[j], (int)ch[j]);
632 XFlush(dpy);
633 #if (MINIATURIZE_ANIMATION_DELAY_Z > 0)
634 wusleep(MINIATURIZE_ANIMATION_DELAY_Z);
635 #endif
636 for (j=0; j<FRAMES; j++) {
637 XDrawRectangle(dpy, scr->root_win, scr->frame_gc,
638 (int)cx[j], (int)cy[j], (int)cw[j], (int)ch[j]);
639 if (j<FRAMES-1) {
640 cx[j]=cx[j+1];
641 cy[j]=cy[j+1];
642 cw[j]=cw[j+1];
643 ch[j]=ch[j+1];
644 } else {
645 cx[j]+=xstep;
646 cy[j]+=ystep;
647 cw[j]+=wstep;
648 ch[j]+=hstep;
653 for (j=0; j<FRAMES; j++) {
654 XDrawRectangle(dpy, scr->root_win, scr->frame_gc,
655 (int)cx[j], (int)cy[j], (int)cw[j], (int)ch[j]);
657 XFlush(dpy);
658 #if (MINIATURIZE_ANIMATION_DELAY_Z > 0)
659 wusleep(MINIATURIZE_ANIMATION_DELAY_Z);
660 #endif
661 for (j=0; j<FRAMES; j++) {
662 XDrawRectangle(dpy, scr->root_win, scr->frame_gc,
663 (int)cx[j], (int)cy[j], (int)cw[j], (int)ch[j]);
666 XUngrabServer(dpy);
668 #undef FRAMES
671 static void
672 animateResize(WScreen *scr, int x, int y, int w, int h,
673 int fx, int fy, int fw, int fh, int hiding)
675 int style = wPreferences.iconification_style; /* Catch the value */
676 int steps, k;
678 if (style == WIS_NONE)
679 return;
681 k = (hiding ? 2 : 3);
682 switch(style) {
683 case WIS_TWIST:
684 steps = (MINIATURIZE_ANIMATION_STEPS_T * k)/3;
685 if (steps>0)
686 animateResizeTwist(scr, x, y, w, h, fx, fy, fw, fh, steps);
687 break;
688 case WIS_FLIP:
689 steps = (MINIATURIZE_ANIMATION_STEPS_F * k)/3;
690 if (steps>0)
691 animateResizeFlip(scr, x, y, w, h, fx, fy, fw, fh, steps);
692 break;
693 case WIS_ZOOM:
694 default:
695 steps = (MINIATURIZE_ANIMATION_STEPS_Z * k)/3;
696 if (steps>0)
697 animateResizeZoom(scr, x, y, w, h, fx, fy, fw, fh, steps);
698 break;
701 #endif /* ANIMATIONS */
704 static void
705 flushExpose()
707 XEvent tmpev;
709 while (XCheckTypedEvent(dpy, Expose, &tmpev))
710 WMHandleEvent(&tmpev);
711 XSync(dpy, 0);
714 static void
715 unmapTransientsFor(WWindow *wwin)
717 WWindow *tmp;
718 XWindowAttributes attribs;
721 tmp = wwin->screen_ptr->focused_window;
722 while (tmp) {
723 /* unmap the transients for this transient */
724 if (tmp!=wwin && tmp->transient_for == wwin->client_win
725 && (tmp->flags.mapped || wwin->screen_ptr->flags.startup
726 || tmp->flags.shaded)) {
727 unmapTransientsFor(tmp);
728 XGetWindowAttributes(dpy, tmp->client_win, &attribs);
729 tmp->flags.miniaturized=1;
730 if (!tmp->flags.shaded) {
731 tmp->flags.mapped=0;
732 XSelectInput(dpy, tmp->client_win,
733 attribs.your_event_mask & ~StructureNotifyMask);
734 XUnmapWindow(dpy, tmp->client_win);
735 XSelectInput(dpy, tmp->client_win, attribs.your_event_mask);
737 XUnmapWindow(dpy, tmp->frame->core->window);
738 if (!tmp->flags.shaded)
739 wClientSetState(tmp, IconicState, None);
740 UpdateSwitchMenu(wwin->screen_ptr, tmp, ACTION_CHANGE_STATE);
742 tmp = tmp->prev;
747 static void
748 mapTransientsFor(WWindow *wwin)
750 WWindow *tmp;
752 tmp = wwin->screen_ptr->focused_window;
753 while (tmp) {
754 /* recursively map the transients for this transient */
755 if (tmp!=wwin && tmp->transient_for == wwin->client_win
756 && /*!tmp->flags.mapped*/ tmp->flags.miniaturized
757 && tmp->icon==NULL) {
758 mapTransientsFor(tmp);
759 tmp->flags.miniaturized=0;
760 if (!tmp->flags.shaded) {
761 tmp->flags.mapped=1;
762 XMapWindow(dpy, tmp->client_win);
764 XMapWindow(dpy, tmp->frame->core->window);
765 tmp->flags.semi_focused = 0;
766 if (!tmp->flags.shaded)
767 wClientSetState(tmp, NormalState, None);
768 UpdateSwitchMenu(wwin->screen_ptr, tmp, ACTION_CHANGE_STATE);
770 tmp = tmp->prev;
775 static void
776 setupIconGrabs(WIcon *icon)
778 /* setup passive grabs on the icon */
779 XGrabButton(dpy, Button1, AnyModifier, icon->core->window, True,
780 ButtonPressMask, GrabModeSync, GrabModeAsync, None, None);
781 XGrabButton(dpy, Button2, AnyModifier, icon->core->window, True,
782 ButtonPressMask, GrabModeSync, GrabModeAsync, None, None);
783 XGrabButton(dpy, Button3, AnyModifier, icon->core->window, True,
784 ButtonPressMask, GrabModeSync, GrabModeAsync, None, None);
785 XSync(dpy, 0);
789 static WWindow*
790 recursiveTransientFor(WWindow *wwin)
792 int i;
794 if (!wwin)
795 return None;
797 /* hackish way to detect transient_for cycle */
798 i = wwin->screen_ptr->window_count+1;
800 while (wwin && wwin->transient_for != None && i>0) {
801 wwin = wWindowFor(wwin->transient_for);
802 i--;
804 if (i==0 && wwin) {
805 wwarning("%s has a severely broken WM_TRANSIENT_FOR hint.",
806 wwin->frame->title);
807 return NULL;
810 return wwin;
814 static void
815 removeIconGrabs(WIcon *icon)
817 /* remove passive grabs on the icon */
818 XUngrabButton(dpy, Button1, AnyModifier, icon->core->window);
819 XUngrabButton(dpy, Button2, AnyModifier, icon->core->window);
820 XUngrabButton(dpy, Button3, AnyModifier, icon->core->window);
821 XSync(dpy, 0);
825 void
826 wIconifyWindow(WWindow *wwin)
828 XWindowAttributes attribs;
829 int present;
832 if (!XGetWindowAttributes(dpy, wwin->client_win, &attribs)) {
833 /* the window doesn't exist anymore */
834 return;
837 if (wwin->flags.miniaturized)
838 return;
840 if (wwin->transient_for!=None) {
841 WWindow *owner = wWindowFor(wwin->transient_for);
843 if (owner && owner->flags.miniaturized)
844 return;
847 present = wwin->frame->workspace==wwin->screen_ptr->current_workspace;
849 /* if the window is in another workspace, simplify process */
850 if (present) {
851 /* icon creation may take a while */
852 XGrabPointer(dpy, wwin->screen_ptr->root_win, False,
853 ButtonMotionMask|ButtonReleaseMask, GrabModeAsync,
854 GrabModeAsync, None, None, CurrentTime);
857 if (!wwin->flags.icon_moved) {
858 PlaceIcon(wwin->screen_ptr, &wwin->icon_x, &wwin->icon_y);
860 wwin->icon = wIconCreate(wwin);
862 wwin->flags.miniaturized=1;
863 wwin->flags.mapped=0;
865 /* unmap transients */
867 unmapTransientsFor(wwin);
869 if (present) {
870 #ifdef WMSOUND
871 wSoundPlay(WMSOUND_ICONIFY);
872 #endif
874 XUngrabPointer(dpy, CurrentTime);
875 /* prevent window withdrawal when getting UnmapNotify */
876 XSelectInput(dpy, wwin->client_win,
877 attribs.your_event_mask & ~StructureNotifyMask);
878 XUnmapWindow(dpy, wwin->client_win);
879 XSelectInput(dpy, wwin->client_win, attribs.your_event_mask);
880 XUnmapWindow(dpy, wwin->frame->core->window);
881 /* let all Expose events arrive so that we can repaint
882 * something before the animation starts (and the server is grabbed) */
883 XSync(dpy, 0);
884 wClientSetState(wwin, IconicState, wwin->icon->icon_win);
885 flushExpose();
886 #ifdef ANIMATIONS
887 if (!wwin->screen_ptr->flags.startup && !wwin->flags.skip_next_animation
888 && !wPreferences.no_animations) {
889 animateResize(wwin->screen_ptr, wwin->frame_x, wwin->frame_y,
890 wwin->frame->core->width, wwin->frame->core->height,
891 wwin->icon_x, wwin->icon_y,
892 wwin->icon->core->width, wwin->icon->core->height,
893 False);
895 #endif
898 wwin->flags.skip_next_animation = 0;
899 if (wwin->screen_ptr->current_workspace==wwin->frame->workspace ||
900 wwin->window_flags.omnipresent || wPreferences.sticky_icons)
901 XMapWindow(dpy, wwin->icon->core->window);
902 AddToStackList(wwin->icon->core);
903 #ifndef STRICTNS
904 wLowerFrame(wwin->icon->core);
905 #endif
907 if (present) {
908 WWindow *owner = recursiveTransientFor(wwin->screen_ptr->focused_window);
909 setupIconGrabs(wwin->icon);
910 if ((wwin->flags.focused
911 || (owner && wwin->client_win == owner->client_win))
912 && wPreferences.focus_mode==WKF_CLICK) {
913 WWindow *tmp;
915 tmp = wwin->prev;
916 while (tmp) {
917 if (!tmp->window_flags.no_focusable
918 && !(tmp->flags.hidden||tmp->flags.miniaturized))
919 break;
920 tmp = tmp->prev;
922 wSetFocusTo(wwin->screen_ptr, tmp);
923 } else if (wPreferences.focus_mode!=WKF_CLICK) {
924 wSetFocusTo(wwin->screen_ptr, NULL);
927 #ifdef ANIMATIONS
928 if (!wwin->screen_ptr->flags.startup) {
929 Window clientwin = wwin->client_win;
931 XSync(dpy, 0);
932 processEvents(XPending(dpy));
934 /* the window can disappear while doing the processEvents() */
935 if (!wWindowFor(clientwin))
936 return;
938 #endif
942 if (wwin->flags.selected)
943 wIconSelect(wwin->icon);
945 UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_STATE);
951 void
952 wDeiconifyWindow(WWindow *wwin)
954 wWindowChangeWorkspace(wwin, wwin->screen_ptr->current_workspace);
956 if (!wwin->flags.miniaturized)
957 return;
959 if (wwin->transient_for != None) {
960 WWindow *owner = recursiveTransientFor(wwin);
961 wDeiconifyWindow(owner);
962 wSetFocusTo(wwin->screen_ptr, wwin);
963 wRaiseFrame(wwin->frame->core);
964 return;
967 wwin->flags.miniaturized=0;
968 if (!wwin->flags.shaded)
969 wwin->flags.mapped=1;
971 if (wwin->icon->selected)
972 wIconSelect(wwin->icon);
974 XUnmapWindow(dpy, wwin->icon->core->window);
976 #ifdef WMSOUND
977 wSoundPlay(WMSOUND_DEICONIFY);
978 #endif
980 /* if the window is in another workspace, do it silently */
981 #ifdef ANIMATIONS
982 if (!wwin->screen_ptr->flags.startup && !wPreferences.no_animations
983 && !wwin->flags.skip_next_animation) {
984 animateResize(wwin->screen_ptr, wwin->icon_x, wwin->icon_y,
985 wwin->icon->core->width, wwin->icon->core->height,
986 wwin->frame_x, wwin->frame_y,
987 wwin->frame->core->width, wwin->frame->core->height,
988 False);
990 #endif /* ANIMATIONS */
991 wwin->flags.skip_next_animation = 0;
992 XGrabServer(dpy);
993 if (!wwin->flags.shaded) {
994 XMapWindow(dpy, wwin->client_win);
996 XMapWindow(dpy, wwin->frame->core->window);
997 wRaiseFrame(wwin->frame->core);
998 if (!wwin->flags.shaded) {
999 wClientSetState(wwin, NormalState, None);
1001 mapTransientsFor(wwin);
1002 RemoveFromStackList(wwin->icon->core);
1003 removeIconGrabs(wwin->icon);
1004 wIconDestroy(wwin->icon);
1005 wwin->icon = NULL;
1007 XUngrabServer(dpy);
1008 if (wPreferences.focus_mode==WKF_CLICK
1009 || wPreferences.focus_mode==WKF_SLOPPY)
1010 wSetFocusTo(wwin->screen_ptr, wwin);
1012 #ifdef ANIMATIONS
1013 if (!wwin->screen_ptr->flags.startup) {
1014 Window clientwin = wwin->client_win;
1016 XSync(dpy, 0);
1017 processEvents(XPending(dpy));
1019 if (!wWindowFor(clientwin))
1020 return;
1022 #endif
1024 if (wPreferences.auto_arrange_icons) {
1025 wArrangeIcons(wwin->screen_ptr, True);
1028 UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_STATE);
1034 static void
1035 hideWindow(WIcon *icon, int icon_x, int icon_y, WWindow *wwin, int animate)
1037 XWindowAttributes attribs;
1040 if (wwin->flags.miniaturized) {
1041 XUnmapWindow(dpy, wwin->icon->core->window);
1042 wwin->flags.hidden = 1;
1043 wwin->icon->mapped = 0;
1044 UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_STATE);
1045 return;
1048 if (wwin->flags.inspector_open) {
1049 WWindow *pwin = wwin->inspector->frame;
1051 XGetWindowAttributes(dpy, pwin->client_win, &attribs);
1052 pwin->flags.hidden = 1;
1053 pwin->flags.mapped = 0;
1054 /* prevent window withdrawal when getting UnmapNotify */
1055 XSelectInput(dpy, pwin->client_win,
1056 attribs.your_event_mask & ~StructureNotifyMask);
1057 XUnmapWindow(dpy, pwin->client_win);
1058 XSelectInput(dpy, pwin->client_win, attribs.your_event_mask);
1060 XUnmapWindow(dpy, pwin->frame->core->window);
1061 wClientSetState(pwin, IconicState, icon->icon_win);
1064 XGetWindowAttributes(dpy, wwin->client_win, &attribs);
1066 wwin->flags.hidden = 1;
1067 wwin->flags.mapped = 0;
1069 /* prevent window withdrawal when getting UnmapNotify */
1070 XSelectInput(dpy, wwin->client_win,
1071 attribs.your_event_mask & ~StructureNotifyMask);
1072 XUnmapWindow(dpy, wwin->client_win);
1073 XSelectInput(dpy, wwin->client_win, attribs.your_event_mask);
1075 XUnmapWindow(dpy, wwin->frame->core->window);
1076 wClientSetState(wwin, IconicState, icon->icon_win);
1077 flushExpose();
1078 #ifdef WMSOUND
1079 wSoundPlay(WMSOUND_HIDE);
1080 #endif
1081 #ifdef ANIMATIONS
1082 if (!wwin->screen_ptr->flags.startup && !wPreferences.no_animations &&
1083 !wwin->flags.skip_next_animation && animate) {
1084 animateResize(wwin->screen_ptr, wwin->frame_x, wwin->frame_y,
1085 wwin->frame->core->width, wwin->frame->core->height,
1086 icon_x, icon_y, icon->core->width, icon->core->height,
1087 True);
1089 #endif
1090 wwin->flags.skip_next_animation = 0;
1092 UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_STATE);
1097 void
1098 wHideOtherApplications(WWindow *awin)
1100 WWindow *wwin;
1101 WApplication *tapp;
1102 #ifdef REDUCE_APPICONS
1103 char *tinstance, *tclass;
1104 unsigned int brokenwin = 0, match = 0;
1105 #endif
1107 if (!awin)
1108 return;
1109 wwin = awin->screen_ptr->focused_window;
1111 #ifdef REDUCE_APPICONS
1112 if (awin->wm_instance == NULL || awin->wm_class == NULL)
1113 brokenwin++;
1114 #endif
1116 while (wwin) {
1117 if (wwin!=awin
1118 && wwin->frame->workspace == awin->screen_ptr->current_workspace
1119 && !(wwin->flags.miniaturized||wwin->flags.hidden)
1120 && !wwin->flags.internal_window
1121 && (!wwin->flags.inspector_open || wwin->inspector->frame!=awin)
1122 && !wwin->window_flags.no_hide_others) {
1124 #ifdef REDUCE_APPICONS
1125 match = 0;
1126 if (!brokenwin) {
1127 if ((tinstance = wwin->wm_instance) == NULL)
1128 tinstance = "";
1129 if ((tclass = wwin->wm_class) == NULL)
1130 tclass = "";
1131 if ((strcmp(awin->wm_instance, tinstance) == 0) &&
1132 (strcmp(awin->wm_class, tclass) == 0) )
1133 match++;
1135 #endif
1137 if (wwin->main_window==None || wwin->window_flags.no_appicon) {
1138 if (!wwin->window_flags.no_miniaturizable) {
1139 wwin->flags.skip_next_animation = 1;
1140 wIconifyWindow(wwin);
1142 } else if (wwin->main_window!=None
1143 #ifndef REDUCE_APPICONS
1144 && awin->main_window != wwin->main_window) {
1145 #else
1146 && (awin->main_window != wwin->main_window && !match)) {
1147 #endif
1148 tapp = wApplicationOf(wwin->main_window);
1149 if (tapp) {
1150 tapp->flags.skip_next_animation = 1;
1151 wHideApplication(tapp);
1152 } else {
1153 if (!wwin->window_flags.no_miniaturizable) {
1154 wwin->flags.skip_next_animation = 1;
1155 wIconifyWindow(wwin);
1160 wwin = wwin->prev;
1163 wSetFocusTo(awin->screen_ptr, awin);
1169 void
1170 wHideApplication(WApplication *wapp)
1172 #ifdef REDUCE_APPICONS
1173 WApplication *tapp;
1174 char *tinstance, *tclass;
1175 unsigned int nowmhints = 0, matchwmhints = 0, matchworkspace = 0;
1176 #endif
1177 WScreen *scr;
1178 WWindow *wlist;
1179 int hadfocus;
1181 if (!wapp) {
1182 wwarning("trying to hide a non grouped window");
1183 return;
1185 if (!wapp->main_window_desc) {
1186 wwarning("group leader not found for window group");
1187 return;
1189 #ifdef REDUCE_APPICONS
1190 if ((wapp->main_window_desc->wm_instance == NULL) ||
1191 (wapp->main_window_desc->wm_class == NULL))
1192 nowmhints++;
1193 #endif
1194 scr = wapp->main_window_desc->screen_ptr;
1195 hadfocus = 0;
1196 wlist = scr->focused_window;
1197 if (!wlist)
1198 return;
1200 if (wlist->main_window == wapp->main_window)
1201 wapp->last_focused = wlist;
1202 else
1203 wapp->last_focused = NULL;
1204 while (wlist) {
1205 #ifdef REDUCE_APPICONS
1206 matchwmhints = matchworkspace = 0;
1207 if (!nowmhints) {
1208 tapp = wApplicationOf(wlist->main_window);
1209 tinstance = tclass = NULL;
1210 if (tapp) {
1211 if (tapp->main_window_desc) {
1212 tinstance = tapp->main_window_desc->wm_instance;
1213 tclass = tapp->main_window_desc->wm_class;
1216 if (tapp == NULL || tinstance == NULL || tclass == NULL) {
1217 /* Should never reach here */
1218 tinstance = "";
1219 tclass = "";
1221 if ((strcmp(tinstance, wapp->main_window_desc->wm_instance) == 0) &&
1222 (strcmp(tclass, wapp->main_window_desc->wm_class) == 0) )
1223 matchwmhints++;
1225 if (wlist->frame) {
1226 if (wlist->frame->workspace == wapp->main_window_desc->screen_ptr->current_workspace)
1227 matchworkspace++;
1229 if ((wlist->main_window == wapp->main_window || matchwmhints) &&
1230 matchworkspace) {
1231 #ifdef I_HATE_THIS
1233 #endif
1234 #else
1235 if (wlist->main_window == wapp->main_window) {
1236 #endif
1237 if (wlist->flags.focused) {
1238 hadfocus = 1;
1240 if (wapp->app_icon)
1241 hideWindow(wapp->app_icon->icon, wapp->app_icon->x_pos,
1242 wapp->app_icon->y_pos, wlist,
1243 !wapp->flags.skip_next_animation);
1245 wlist = wlist->prev;
1248 wapp->flags.skip_next_animation = 0;
1250 if (hadfocus) {
1251 if (wPreferences.focus_mode==WKF_CLICK) {
1252 wlist = scr->focused_window;
1253 while (wlist) {
1254 if (!wlist->window_flags.no_focusable && !wlist->flags.hidden
1255 && (wlist->flags.mapped || wlist->flags.shaded))
1256 break;
1257 wlist = wlist->prev;
1259 wSetFocusTo(scr, wlist);
1260 } else {
1261 wSetFocusTo(scr, NULL);
1265 wapp->flags.hidden = 1;
1271 static void
1272 unhideWindow(WIcon *icon, int icon_x, int icon_y, WWindow *wwin, int animate,
1273 int bringToCurrentWS)
1275 if (bringToCurrentWS)
1276 wWindowChangeWorkspace(wwin, wwin->screen_ptr->current_workspace);
1278 wwin->flags.hidden=0;
1279 wwin->flags.mapped=1;
1281 #ifdef WMSOUND
1282 wSoundPlay(WMSOUND_UNHIDE);
1283 #endif
1284 #ifdef ANIMATIONS
1285 if (!wwin->screen_ptr->flags.startup && !wPreferences.no_animations
1286 && animate) {
1287 animateResize(wwin->screen_ptr, icon_x, icon_y,
1288 icon->core->width, icon->core->height,
1289 wwin->frame_x, wwin->frame_y,
1290 wwin->frame->core->width, wwin->frame->core->height,
1291 True);
1293 #endif
1294 wwin->flags.skip_next_animation = 0;
1295 XMapWindow(dpy, wwin->client_win);
1296 XMapWindow(dpy, wwin->frame->core->window);
1297 wClientSetState(wwin, NormalState, None);
1298 wRaiseFrame(wwin->frame->core);
1299 if (wwin->flags.inspector_open) {
1300 WWindow *pwin = wwin->inspector->frame;
1302 pwin->flags.hidden = 0;
1303 pwin->flags.mapped = 1;
1304 XMapWindow(dpy, pwin->client_win);
1305 XMapWindow(dpy, pwin->frame->core->window);
1306 wClientSetState(pwin, NormalState, None);
1309 UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_STATE);
1313 void
1314 wUnhideApplication(WApplication *wapp, Bool miniwindows, Bool bringToCurrentWS)
1316 WScreen *scr;
1317 WWindow *wlist, *next;
1318 WWindow *focused=NULL;
1319 #ifdef REDUCE_APPICONS
1320 char *tinstance, *tclass;
1321 unsigned int nowmhints = 0, matchwmhints = 0, matchworkspace = 0;
1322 #endif
1324 if (!wapp) {
1325 return;
1328 #ifdef REDUCE_APPICONS
1329 if ((wapp->main_window_desc->wm_class == NULL) ||
1330 (wapp->main_window_desc->wm_instance == NULL))
1331 nowmhints++;
1332 #endif
1334 scr = wapp->main_window_desc->screen_ptr;
1335 wlist = scr->focused_window;
1336 if (!wlist) return;
1337 /* goto beginning of list */
1338 while (wlist->prev)
1339 wlist = wlist->prev;
1341 while (wlist) {
1342 next = wlist->next;
1344 #ifndef REDUCE_APPICONS
1345 if (wlist->main_window == wapp->main_window) {
1346 #else
1347 matchwmhints = matchworkspace = 0;
1348 if (!nowmhints) {
1349 if ((tinstance = wlist->wm_instance) == NULL)
1350 tinstance = "";
1351 if ((tclass = wlist->wm_class) == NULL)
1352 tclass = "";
1353 if ((strcmp(tinstance, wapp->main_window_desc->wm_instance) == 0)
1354 && (strcmp(tclass, wapp->main_window_desc->wm_class) == 0) )
1355 matchwmhints++;
1357 if (wlist->frame) {
1358 if (wlist->frame->workspace == wapp->main_window_desc->screen_ptr->current_workspace)
1359 matchworkspace++;
1362 if ((wlist->main_window == wapp->main_window || matchwmhints) &&
1363 matchworkspace) {
1364 #endif
1365 if (wlist->flags.focused)
1366 focused = wlist;
1367 else if (!focused || !focused->flags.focused)
1368 focused = wlist;
1370 if (wlist->flags.miniaturized && wlist->icon) {
1371 if (bringToCurrentWS || wPreferences.sticky_icons
1372 || wlist->frame->workspace == scr->current_workspace) {
1373 if (!wlist->icon->mapped) {
1374 XMapWindow(dpy, wlist->icon->core->window);
1375 wlist->icon->mapped = 1;
1377 wlist->flags.hidden = 0;
1378 UpdateSwitchMenu(scr, wlist, ACTION_CHANGE_STATE);
1379 if (wlist->frame->workspace != scr->current_workspace)
1380 wWindowChangeWorkspace(wlist, scr->current_workspace);
1382 if (miniwindows) {
1383 wDeiconifyWindow(wlist);
1385 } else if (wlist->flags.hidden) {
1386 unhideWindow(wapp->app_icon->icon, wapp->app_icon->x_pos,
1387 wapp->app_icon->y_pos, wlist,
1388 !wapp->flags.skip_next_animation,
1389 bringToCurrentWS);
1390 } else {
1391 if (bringToCurrentWS
1392 && wlist->frame->workspace != scr->current_workspace) {
1393 wWindowChangeWorkspace(wlist, scr->current_workspace);
1395 wRaiseFrame(wlist->frame->core);
1398 wlist = next;
1401 wapp->flags.skip_next_animation = 0;
1402 wapp->flags.hidden = 0;
1404 if (focused)
1405 wSetFocusTo(scr, focused);
1406 else if (wapp->last_focused && wapp->last_focused->flags.mapped)
1407 wSetFocusTo(scr, wapp->last_focused);
1408 wapp->last_focused = NULL;
1409 if (wPreferences.auto_arrange_icons) {
1410 wArrangeIcons(scr, True);
1416 void
1417 wShowAllWindows(WScreen *scr)
1419 WWindow *wwin, *old_foc;
1420 WApplication *wapp;
1422 old_foc = wwin = scr->focused_window;
1423 while (wwin) {
1424 if (!wwin->flags.internal_window &&
1425 (scr->current_workspace == wwin->frame->workspace
1426 || wwin->window_flags.omnipresent)) {
1427 if (wwin->flags.miniaturized) {
1428 wwin->flags.skip_next_animation = 1;
1429 wDeiconifyWindow(wwin);
1430 } else if (wwin->flags.hidden) {
1431 wapp = wApplicationOf(wwin->main_window);
1432 if (wapp) {
1433 wUnhideApplication(wapp, False, False);
1434 } else {
1435 wwin->flags.skip_next_animation = 1;
1436 wDeiconifyWindow(wwin);
1440 wwin = wwin->prev;
1442 wSetFocusTo(scr, old_foc);
1443 /*wRaiseFrame(old_foc->frame->core);*/
1447 void
1448 wRefreshDesktop(WScreen *scr)
1450 Window win;
1451 XSetWindowAttributes attr;
1453 attr.backing_store = NotUseful;
1454 attr.save_under = False;
1455 win = XCreateWindow(dpy, scr->root_win, 0, 0, scr->scr_width,
1456 scr->scr_height, 0, CopyFromParent, CopyFromParent,
1457 (Visual *)CopyFromParent, CWBackingStore|CWSaveUnder,
1458 &attr);
1459 XMapRaised(dpy, win);
1460 XDestroyWindow(dpy, win);
1461 XFlush(dpy);
1465 void
1466 wArrangeIcons(WScreen *scr, Bool arrangeAll)
1468 WWindow *wwin;
1469 WAppIcon *aicon;
1470 int pf; /* primary axis */
1471 int sf; /* secondary axis */
1472 int fullW;
1473 int fullH;
1474 int pi, si;
1475 int sx1, sx2, sy1, sy2; /* screen boundary */
1476 int sw, sh;
1477 int xo, yo;
1478 int xs, ys;
1479 int isize = wPreferences.icon_size;
1482 * Find out screen boundaries.
1484 sx1 = 0;
1485 sy1 = 0;
1486 sx2 = scr->scr_width;
1487 sy2 = scr->scr_height;
1488 if (scr->dock) {
1489 if (scr->dock->on_right_side)
1490 sx2 -= isize + DOCK_EXTRA_SPACE;
1491 else
1492 sx1 += isize + DOCK_EXTRA_SPACE;
1495 sw = isize * (scr->scr_width/isize);
1496 sh = isize * (scr->scr_height/isize);
1497 fullW = (sx2-sx1)/isize;
1498 fullH = (sy2-sy1)/isize;
1500 /* icon yard boundaries */
1501 if (wPreferences.icon_yard & IY_VERT) {
1502 pf = fullH;
1503 sf = fullW;
1504 } else {
1505 pf = fullW;
1506 sf = fullH;
1508 if (wPreferences.icon_yard & IY_RIGHT) {
1509 xo = sx2 - isize;
1510 xs = -1;
1511 } else {
1512 xo = sx1;
1513 xs = 1;
1515 if (wPreferences.icon_yard & IY_TOP) {
1516 yo = sy1;
1517 ys = 1;
1518 } else {
1519 yo = sy2 - isize;
1520 ys = -1;
1523 /* arrange icons putting the most recently focused window
1524 * as the last icon */
1525 #define X ((wPreferences.icon_yard & IY_VERT) ? xo + xs*(si*isize)\
1526 : xo + xs*(pi*isize))
1527 #define Y ((wPreferences.icon_yard & IY_VERT) ? yo + ys*(pi*isize)\
1528 : yo + ys*(si*isize))
1530 /* arrange application icons */
1531 aicon = scr->app_icon_list;
1532 /* reverse them to avoid unnecessarily sliding of icons */
1533 while (aicon && aicon->next)
1534 aicon = aicon->next;
1536 pi = 0;
1537 si = 0;
1538 while (aicon) {
1539 if (!aicon->docked) {
1540 if (aicon->x_pos != X || aicon->y_pos != Y) {
1541 #ifdef ANIMATIONS
1542 if (!wPreferences.no_animations) {
1543 SlideWindow(aicon->icon->core->window, aicon->x_pos, aicon->y_pos,
1544 X, Y);
1546 #endif /* ANIMATIONS */
1548 wAppIconMove(aicon, X, Y);
1549 pi++;
1551 /* we reversed the order so we use prev */
1552 aicon = aicon->prev;
1553 if (pi >= pf) {
1554 pi=0;
1555 si++;
1559 /* arrange miniwindows */
1561 wwin = scr->focused_window;
1562 /* reverse them to avoid unnecessarily shuffling */
1563 while (wwin && wwin->prev)
1564 wwin = wwin->prev;
1566 while (wwin) {
1567 if (wwin->icon && wwin->flags.miniaturized &&
1568 (wwin->frame->workspace==scr->current_workspace ||
1569 wwin->window_flags.omnipresent ||
1570 wPreferences.sticky_icons)) {
1572 if (arrangeAll || !wwin->flags.icon_moved) {
1573 if (wwin->icon_x != X || wwin->icon_y != Y) {
1574 #ifdef ANIMATIONS
1575 if (wPreferences.no_animations) {
1576 XMoveWindow(dpy, wwin->icon->core->window, X, Y);
1577 } else {
1578 SlideWindow(wwin->icon->core->window, wwin->icon_x,
1579 wwin->icon_y, X, Y);
1581 #else
1582 XMoveWindow(dpy, wwin->icon->core->window, X, Y);
1583 #endif /* ANIMATIONS */
1585 wwin->icon_x = X;
1586 wwin->icon_y = Y;
1587 wwin->flags.icon_moved = 0;
1588 pi++;
1591 /* we reversed the order, so we use next */
1592 wwin = wwin->next;
1593 if (pi >= pf) {
1594 pi=0;
1595 si++;
1601 void
1602 wSelectWindow(WWindow *wwin, Bool flag)
1604 WScreen *scr = wwin->screen_ptr;
1605 if (flag) {
1606 wwin->flags.selected = 1;
1607 XSetWindowBorder(dpy, wwin->frame->core->window, scr->white_pixel);
1608 scr->selected_windows = list_cons(wwin, scr->selected_windows);
1609 } else {
1610 wwin->flags.selected = 0;
1611 XSetWindowBorder(dpy, wwin->frame->core->window,
1612 scr->frame_border_pixel);
1613 scr->selected_windows = list_remove_elem(scr->selected_windows, wwin);
1618 void
1619 wMakeWindowVisible(WWindow *wwin)
1621 wWorkspaceChange(wwin->screen_ptr, wwin->frame->workspace);
1623 if (wwin->flags.shaded) {
1624 wUnshadeWindow(wwin);
1626 if (wwin->flags.hidden) {
1627 wUnhideApplication(wApplicationOf(wwin->main_window), False, False);
1628 } else if (wwin->flags.miniaturized) {
1629 wDeiconifyWindow(wwin);
1630 } else {
1631 wSetFocusTo(wwin->screen_ptr, wwin);
1632 wRaiseFrame(wwin->frame->core);