0.51.1 pre snapshot. Be careful, it may be buggy. It fixes some bugs though.
[wmaker-crm.git] / src / actions.c
blobd889e04753b92cc72afd125c49c3fa9c9fbeac09
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.
23 #include "wconfig.h"
26 #include <X11/Xlib.h>
27 #include <X11/Xutil.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <unistd.h>
31 #include <math.h>
32 #include <time.h>
34 #include "WindowMaker.h"
35 #include "wcore.h"
36 #include "framewin.h"
37 #include "window.h"
38 #include "client.h"
39 #include "icon.h"
40 #include "funcs.h"
41 #include "application.h"
42 #include "actions.h"
43 #include "stacking.h"
44 #include "appicon.h"
45 #include "dock.h"
46 #include "appmenu.h"
47 #include "winspector.h"
48 #include "list.h"
49 #include "workspace.h"
51 #ifdef GNOME_STUFF
52 # include "gnome.h"
53 #endif
54 #ifdef KWM_HINTS
55 # include "kwm.h"
56 #endif
58 #ifdef WMSOUND
59 #include "wmsound.h"
60 #endif
63 /****** Global Variables ******/
64 extern Time LastTimestamp;
65 extern Time LastFocusChange;
67 extern Cursor wCursor[WCUR_LAST];
69 extern WPreferences wPreferences;
71 extern Atom _XA_WM_TAKE_FOCUS;
74 /******* Local Variables *******/
75 static struct {
76 int steps;
77 int delay;
78 } shadePars[5] = {
79 {SHADE_STEPS_UF, SHADE_DELAY_UF},
80 {SHADE_STEPS_F, SHADE_DELAY_F},
81 {SHADE_STEPS_M, SHADE_DELAY_M},
82 {SHADE_STEPS_S, SHADE_DELAY_S},
83 {SHADE_STEPS_U, SHADE_DELAY_U}};
85 #define SHADE_STEPS shadePars[(int)wPreferences.shade_speed].steps
86 #define SHADE_DELAY shadePars[(int)wPreferences.shade_speed].delay
89 static int ignoreTimestamp=0;
92 #ifdef ANIMATIONS
93 static void
94 processEvents(int event_count)
96 XEvent event;
99 * This is a hack. When animations are enabled, processing of
100 * events ocurred during a animation are delayed until it's end.
101 * Calls that consider the TimeStamp, like XSetInputFocus(), will
102 * fail because the TimeStamp is too old. Then, for example, if
103 * the user changes window focus while a miniaturize animation is
104 * in course, the window will not get focus properly after the end
105 * of the animation. This tries to workaround it by passing CurrentTime
106 * as the TimeStamp for XSetInputFocus() for all events ocurred during
107 * the animation.
109 ignoreTimestamp=1;
110 while (XPending(dpy) && event_count--) {
111 WMNextEvent(dpy, &event);
112 WMHandleEvent(&event);
114 ignoreTimestamp=0;
116 #endif /* ANIMATIONS */
121 *----------------------------------------------------------------------
122 * wSetFocusTo--
123 * Changes the window focus to the one passed as argument.
124 * If the window to focus is not already focused, it will be brought
125 * to the head of the list of windows. Previously focused window is
126 * unfocused.
128 * Side effects:
129 * Window list may be reordered and the window focus is changed.
131 *----------------------------------------------------------------------
133 void
134 wSetFocusTo(WScreen *scr, WWindow *wwin)
136 WWindow *focused=scr->focused_window;
137 int timestamp=LastTimestamp;
138 WApplication *oapp=NULL, *napp=NULL;
139 int wasfocused;
141 LastFocusChange = timestamp;
144 * This is a hack, because XSetInputFocus() should have a proper
145 * timestamp instead of CurrentTime but it seems that some times
146 * clients will not receive focus properly that way.
147 if (ignoreTimestamp)
149 timestamp = CurrentTime;
151 if (focused)
152 oapp = wApplicationOf(focused->main_window);
154 if (wwin == NULL) {
155 XSetInputFocus(dpy, scr->no_focus_win, RevertToParent, timestamp);
156 if (focused) {
157 wWindowUnfocus(focused);
159 if (oapp) {
160 wAppMenuUnmap(oapp->menu);
161 #ifdef NEWAPPICON
162 wApplicationDeactivate(oapp);
163 #endif
165 #ifdef KWM_HINTS
166 wKWMUpdateActiveWindowHint(scr);
167 wKWMSendEventMessage(NULL, WKWMFocusWindow);
168 #endif
169 return;
171 wasfocused = wwin->flags.focused;
172 napp = wApplicationOf(wwin->main_window);
174 /* remember last workspace where the app has been */
175 if (napp)
176 napp->last_workspace = wwin->screen_ptr->current_workspace;
178 if (wwin->flags.mapped && !WFLAGP(wwin, no_focusable)) {
179 /* install colormap if colormap mode is lock mode */
180 if (wPreferences.colormap_mode==WKF_CLICK)
181 wColormapInstallForWindow(scr, wwin);
183 /* set input focus */
184 switch (wwin->focus_mode) {
185 case WFM_NO_INPUT:
186 XSetInputFocus(dpy, scr->no_focus_win, RevertToParent, timestamp);
187 break;
189 case WFM_PASSIVE:
190 case WFM_LOCALLY_ACTIVE:
191 XSetInputFocus(dpy, wwin->client_win, RevertToParent, timestamp);
192 break;
194 case WFM_GLOBALLY_ACTIVE:
195 break;
197 XFlush(dpy);
198 if (wwin->protocols.TAKE_FOCUS) {
199 wClientSendProtocol(wwin, _XA_WM_TAKE_FOCUS, timestamp);
201 XSync(dpy, False);
202 } else {
203 XSetInputFocus(dpy, scr->no_focus_win, RevertToParent, timestamp);
206 if (WFLAGP(wwin, no_focusable))
207 return;
209 /* if this is not the focused window focus it */
210 if (focused!=wwin) {
211 /* change the focus window list order */
212 if (wwin->prev)
213 wwin->prev->next = wwin->next;
215 if (wwin->next)
216 wwin->next->prev = wwin->prev;
218 wwin->prev = focused;
219 focused->next = wwin;
220 wwin->next = NULL;
221 scr->focused_window = wwin;
223 if (oapp && oapp != napp) {
224 wAppMenuUnmap(oapp->menu);
225 #ifdef NEWAPPICON
226 wApplicationDeactivate(oapp);
227 #endif
231 wWindowFocus(wwin, focused);
233 if (napp && !wasfocused) {
234 wAppMenuMap(napp->menu, wwin);
235 #ifdef NEWAPPICON
236 wApplicationActivate(napp);
237 #endif
239 #ifdef KWM_HINTS
240 wKWMUpdateActiveWindowHint(scr);
241 wKWMSendEventMessage(wwin, WKWMFocusWindow);
242 #endif
243 XFlush(dpy);
247 void
248 wShadeWindow(WWindow *wwin)
250 time_t time0 = time(NULL);
251 #ifdef ANIMATIONS
252 int y, s, w, h;
253 #endif
255 if (wwin->flags.shaded)
256 return;
258 XLowerWindow(dpy, wwin->client_win);
260 #ifdef WMSOUND
261 wSoundPlay(WMSOUND_SHADE);
262 #endif
264 #ifdef ANIMATIONS
265 if (!wwin->screen_ptr->flags.startup && !wwin->flags.skip_next_animation
266 && !wPreferences.no_animations) {
267 /* do the shading animation */
268 h = wwin->frame->core->height;
269 s = h/SHADE_STEPS;
270 if (s < 1) s=1;
271 w = wwin->frame->core->width;
272 y = wwin->frame->top_width;
273 while (h>wwin->frame->top_width+1) {
274 XMoveWindow(dpy, wwin->client_win, 0, y);
275 XResizeWindow(dpy, wwin->frame->core->window, w, h);
276 XFlush(dpy);
278 if (time(NULL)-time0 > MAX_ANIMATION_TIME)
279 break;
281 if (SHADE_DELAY > 0)
282 wusleep(SHADE_DELAY*1000L);
283 h-=s;
284 y-=s;
286 XMoveWindow(dpy, wwin->client_win, 0, wwin->frame->top_width);
288 #endif /* ANIMATIONS */
290 wwin->flags.skip_next_animation = 0;
291 wwin->flags.shaded = 1;
292 wwin->flags.mapped = 0;
293 /* prevent window withdrawal when getting UnmapNotify */
294 XSelectInput(dpy, wwin->client_win,
295 wwin->event_mask & ~StructureNotifyMask);
296 XUnmapWindow(dpy, wwin->client_win);
297 XSelectInput(dpy, wwin->client_win, wwin->event_mask);
299 /* for the client it's just like iconification */
300 wFrameWindowResize(wwin->frame, wwin->frame->core->width,
301 wwin->frame->top_width - 1);
303 wwin->client.y = wwin->frame_y - wwin->client.height
304 + wwin->frame->top_width;
305 wWindowSynthConfigureNotify(wwin);
308 wClientSetState(wwin, IconicState, None);
311 #ifdef GNOME_STUFF
312 wGNOMEUpdateClientStateHint(wwin, False);
313 #endif
314 #ifdef KWM_HINTS
315 wKWMUpdateClientStateHint(wwin, KWMIconifiedFlag);
316 wKWMSendEventMessage(wwin, WKWMChangedClient);
317 #endif
318 /* update window list to reflect shaded state */
319 UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_STATE);
321 #ifdef ANIMATIONS
322 if (!wwin->screen_ptr->flags.startup) {
323 /* Look at processEvents() for reason of this code. */
324 XSync(dpy, 0);
325 processEvents(XPending(dpy));
327 #endif
331 void
332 wUnshadeWindow(WWindow *wwin)
334 time_t time0 = time(NULL);
335 #ifdef ANIMATIONS
336 int y, s, w, h;
337 #endif /* ANIMATIONS */
340 if (!wwin->flags.shaded)
341 return;
343 wwin->flags.shaded = 0;
344 wwin->flags.mapped = 1;
345 XMapWindow(dpy, wwin->client_win);
347 #ifdef WMSOUND
348 wSoundPlay(WMSOUND_UNSHADE);
349 #endif
351 #ifdef ANIMATIONS
352 if (!wPreferences.no_animations && !wwin->flags.skip_next_animation) {
353 /* do the shading animation */
354 h = wwin->frame->top_width + wwin->frame->bottom_width;
355 y = wwin->frame->top_width - wwin->client.height;
356 s = abs(y)/SHADE_STEPS;
357 if (s<1) s=1;
358 w = wwin->frame->core->width;
359 XMoveWindow(dpy, wwin->client_win, 0, y);
360 if (s>0) {
361 while (h < wwin->client.height + wwin->frame->top_width
362 + wwin->frame->bottom_width) {
363 XResizeWindow(dpy, wwin->frame->core->window, w, h);
364 XMoveWindow(dpy, wwin->client_win, 0, y);
365 XSync(dpy, 0);
366 if (SHADE_DELAY > 0)
367 wusleep(SHADE_DELAY*2000L/3);
368 h+=s;
369 y+=s;
371 if (time(NULL)-time0 > MAX_ANIMATION_TIME)
372 break;
375 XMoveWindow(dpy, wwin->client_win, 0, wwin->frame->top_width);
377 #endif /* ANIMATIONS */
379 wwin->flags.skip_next_animation = 0;
380 wFrameWindowResize(wwin->frame, wwin->frame->core->width,
381 wwin->frame->top_width + wwin->client.height
382 + wwin->frame->bottom_width);
384 wwin->client.y = wwin->frame_y + wwin->frame->top_width;
385 wWindowSynthConfigureNotify(wwin);
388 wClientSetState(wwin, NormalState, None);
390 /* if the window is focused, set the focus again as it was disabled during
391 * shading */
392 if (wwin->flags.focused)
393 wSetFocusTo(wwin->screen_ptr, wwin);
395 #ifdef GNOME_STUFF
396 wGNOMEUpdateClientStateHint(wwin, False);
397 #endif
398 #ifdef KWM_HINTS
399 wKWMUpdateClientStateHint(wwin, KWMIconifiedFlag);
400 wKWMSendEventMessage(wwin, WKWMChangedClient);
401 #endif
403 /* update window list to reflect unshaded state */
404 UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_STATE);
409 void
410 wMaximizeWindow(WWindow *wwin, int directions)
412 int new_width, new_height, new_x, new_y;
413 WArea usableArea = wwin->screen_ptr->totalUsableArea;
416 if (WFLAGP(wwin, no_resizable))
417 return;
419 if (wwin->flags.shaded) {
420 wwin->flags.skip_next_animation = 1;
421 wUnshadeWindow(wwin);
423 wwin->flags.maximized = directions;
424 wwin->old_geometry.width = wwin->client.width;
425 wwin->old_geometry.height = wwin->client.height;
426 wwin->old_geometry.x = wwin->frame_x;
427 wwin->old_geometry.y = wwin->frame_y;
429 #ifdef KWM_HINTS
430 wKWMUpdateClientGeometryRestore(wwin);
431 #endif
433 if (directions & MAX_HORIZONTAL) {
435 new_width = (usableArea.x2-usableArea.x1)-FRAME_BORDER_WIDTH*2;
436 new_x = usableArea.x1;
438 } else {
440 new_x = wwin->frame_x;
441 new_width = wwin->frame->core->width;
445 if (directions & MAX_VERTICAL) {
447 new_height = (usableArea.y2-usableArea.y1)-FRAME_BORDER_WIDTH*2;
448 new_y = usableArea.y1;
450 } else {
452 new_y = wwin->frame_y;
453 new_height = wwin->frame->core->height;
456 new_height -= wwin->frame->top_width+wwin->frame->bottom_width;
458 wWindowConstrainSize(wwin, &new_width, &new_height);
459 wWindowConfigure(wwin, new_x, new_y, new_width, new_height);
461 #ifdef GNOME_STUFF
462 wGNOMEUpdateClientStateHint(wwin, False);
463 #endif
464 #ifdef KWM_HINTS
465 wKWMUpdateClientStateHint(wwin, KWMMaximizedFlag);
466 wKWMSendEventMessage(wwin, WKWMChangedClient);
467 #endif
469 #ifdef WMSOUND
470 wSoundPlay(WMSOUND_MAXIMIZE);
471 #endif
475 void
476 wUnmaximizeWindow(WWindow *wwin)
478 int restore_x, restore_y;
480 if (!wwin->flags.maximized)
481 return;
483 if (wwin->flags.shaded) {
484 wwin->flags.skip_next_animation = 1;
485 wUnshadeWindow(wwin);
487 restore_x = (wwin->flags.maximized & MAX_HORIZONTAL) ?
488 wwin->old_geometry.x : wwin->frame_x;
489 restore_y = (wwin->flags.maximized & MAX_VERTICAL) ?
490 wwin->old_geometry.y : wwin->frame_y;
491 wwin->flags.maximized = 0;
492 wWindowConfigure(wwin, restore_x, restore_y,
493 wwin->old_geometry.width, wwin->old_geometry.height);
495 #ifdef GNOME_STUFF
496 wGNOMEUpdateClientStateHint(wwin, False);
497 #endif
498 #ifdef KWM_HINTS
499 wKWMUpdateClientStateHint(wwin, KWMMaximizedFlag);
500 wKWMSendEventMessage(wwin, WKWMChangedClient);
501 #endif
503 #ifdef WMSOUND
504 wSoundPlay(WMSOUND_UNMAXIMIZE);
505 #endif
508 #ifdef ANIMATIONS
509 static void
510 animateResizeFlip(WScreen *scr, int x, int y, int w, int h,
511 int fx, int fy, int fw, int fh, int steps)
513 #define FRAMES (MINIATURIZE_ANIMATION_FRAMES_F)
514 float cx, cy, cw, ch;
515 float xstep, ystep, wstep, hstep;
516 XPoint points[5];
517 float dx, dch, midy;
518 float angle, final_angle, delta;
520 xstep = (float)(fx-x)/steps;
521 ystep = (float)(fy-y)/steps;
522 wstep = (float)(fw-w)/steps;
523 hstep = (float)(fh-h)/steps;
525 cx = (float)x;
526 cy = (float)y;
527 cw = (float)w;
528 ch = (float)h;
530 final_angle = 2*WM_PI*MINIATURIZE_ANIMATION_TWIST_F;
531 delta = (float)(final_angle/FRAMES);
532 for (angle=0;; angle+=delta) {
533 if (angle > final_angle)
534 angle = final_angle;
536 dx = (cw/10) - ((cw/5) * sin(angle));
537 dch = (ch/2) * cos(angle);
538 midy = cy + (ch/2);
540 points[0].x = cx + dx; points[0].y = midy - dch;
541 points[1].x = cx + cw - dx; points[1].y = points[0].y;
542 points[2].x = cx + cw + dx; points[2].y = midy + dch;
543 points[3].x = cx - dx; points[3].y = points[2].y;
544 points[4].x = points[0].x; points[4].y = points[0].y;
546 XGrabServer(dpy);
547 XDrawLines(dpy,scr->root_win,scr->frame_gc,points, 5, CoordModeOrigin);
548 XFlush(dpy);
549 #if (MINIATURIZE_ANIMATION_DELAY_F > 0)
550 wusleep(MINIATURIZE_ANIMATION_DELAY_F);
551 #endif
553 XDrawLines(dpy,scr->root_win,scr->frame_gc,points, 5, CoordModeOrigin);
554 XUngrabServer(dpy);
555 cx+=xstep;
556 cy+=ystep;
557 cw+=wstep;
558 ch+=hstep;
559 if (angle >= final_angle)
560 break;
563 XFlush(dpy);
565 #undef FRAMES
568 static void
569 animateResizeTwist(WScreen *scr, int x, int y, int w, int h,
570 int fx, int fy, int fw, int fh, int steps)
572 #define FRAMES (MINIATURIZE_ANIMATION_FRAMES_T)
573 float cx, cy, cw, ch;
574 float xstep, ystep, wstep, hstep;
575 XPoint points[5];
576 float angle, final_angle, a, d, delta;
578 x += w/2;
579 y += h/2;
580 fx += fw/2;
581 fy += fh/2;
583 xstep = (float)(fx-x)/steps;
584 ystep = (float)(fy-y)/steps;
585 wstep = (float)(fw-w)/steps;
586 hstep = (float)(fh-h)/steps;
588 cx = (float)x;
589 cy = (float)y;
590 cw = (float)w;
591 ch = (float)h;
593 final_angle = 2*WM_PI*MINIATURIZE_ANIMATION_TWIST_T;
594 delta = (float)(final_angle/FRAMES);
595 for (angle=0;; angle+=delta) {
596 if (angle > final_angle)
597 angle = final_angle;
599 a = atan(ch/cw);
600 d = sqrt((cw/2)*(cw/2)+(ch/2)*(ch/2));
602 points[0].x = cx+cos(angle-a)*d;
603 points[0].y = cy+sin(angle-a)*d;
604 points[1].x = cx+cos(angle+a)*d;
605 points[1].y = cy+sin(angle+a)*d;
606 points[2].x = cx+cos(angle-a+WM_PI)*d;
607 points[2].y = cy+sin(angle-a+WM_PI)*d;
608 points[3].x = cx+cos(angle+a+WM_PI)*d;
609 points[3].y = cy+sin(angle+a+WM_PI)*d;
610 points[4].x = cx+cos(angle-a)*d;
611 points[4].y = cy+sin(angle-a)*d;
612 XGrabServer(dpy);
613 XDrawLines(dpy, scr->root_win, scr->frame_gc, points, 5, CoordModeOrigin);
614 XFlush(dpy);
615 #if (MINIATURIZE_ANIMATION_DELAY_T > 0)
616 wusleep(MINIATURIZE_ANIMATION_DELAY_T);
617 #endif
619 XDrawLines(dpy, scr->root_win, scr->frame_gc, points, 5, CoordModeOrigin);
620 XUngrabServer(dpy);
621 cx+=xstep;
622 cy+=ystep;
623 cw+=wstep;
624 ch+=hstep;
625 if (angle >= final_angle)
626 break;
629 XFlush(dpy);
631 #undef FRAMES
634 static void
635 animateResizeZoom(WScreen *scr, int x, int y, int w, int h,
636 int fx, int fy, int fw, int fh, int steps)
638 #define FRAMES (MINIATURIZE_ANIMATION_FRAMES_Z)
639 float cx[FRAMES], cy[FRAMES], cw[FRAMES], ch[FRAMES];
640 float xstep, ystep, wstep, hstep;
641 int i, j;
643 xstep = (float)(fx-x)/steps;
644 ystep = (float)(fy-y)/steps;
645 wstep = (float)(fw-w)/steps;
646 hstep = (float)(fh-h)/steps;
648 for (j=0; j<FRAMES; j++) {
649 cx[j] = (float)x;
650 cy[j] = (float)y;
651 cw[j] = (float)w;
652 ch[j] = (float)h;
654 XGrabServer(dpy);
655 for (i=0; i<steps; i++) {
656 for (j=0; j<FRAMES; j++) {
657 XDrawRectangle(dpy, scr->root_win, scr->frame_gc,
658 (int)cx[j], (int)cy[j], (int)cw[j], (int)ch[j]);
660 XFlush(dpy);
661 #if (MINIATURIZE_ANIMATION_DELAY_Z > 0)
662 wusleep(MINIATURIZE_ANIMATION_DELAY_Z);
663 #endif
664 for (j=0; j<FRAMES; j++) {
665 XDrawRectangle(dpy, scr->root_win, scr->frame_gc,
666 (int)cx[j], (int)cy[j], (int)cw[j], (int)ch[j]);
667 if (j<FRAMES-1) {
668 cx[j]=cx[j+1];
669 cy[j]=cy[j+1];
670 cw[j]=cw[j+1];
671 ch[j]=ch[j+1];
672 } else {
673 cx[j]+=xstep;
674 cy[j]+=ystep;
675 cw[j]+=wstep;
676 ch[j]+=hstep;
681 for (j=0; j<FRAMES; j++) {
682 XDrawRectangle(dpy, scr->root_win, scr->frame_gc,
683 (int)cx[j], (int)cy[j], (int)cw[j], (int)ch[j]);
685 XFlush(dpy);
686 #if (MINIATURIZE_ANIMATION_DELAY_Z > 0)
687 wusleep(MINIATURIZE_ANIMATION_DELAY_Z);
688 #endif
689 for (j=0; j<FRAMES; j++) {
690 XDrawRectangle(dpy, scr->root_win, scr->frame_gc,
691 (int)cx[j], (int)cy[j], (int)cw[j], (int)ch[j]);
694 XUngrabServer(dpy);
696 #undef FRAMES
699 static void
700 animateResize(WScreen *scr, int x, int y, int w, int h,
701 int fx, int fy, int fw, int fh, int hiding)
703 int style = wPreferences.iconification_style; /* Catch the value */
704 int steps, k;
706 if (style == WIS_NONE)
707 return;
709 if (style == WIS_RANDOM) {
710 style = rand()%3;
713 k = (hiding ? 2 : 3);
714 switch(style) {
715 case WIS_TWIST:
716 steps = (MINIATURIZE_ANIMATION_STEPS_T * k)/3;
717 if (steps>0)
718 animateResizeTwist(scr, x, y, w, h, fx, fy, fw, fh, steps);
719 break;
720 case WIS_FLIP:
721 steps = (MINIATURIZE_ANIMATION_STEPS_F * k)/3;
722 if (steps>0)
723 animateResizeFlip(scr, x, y, w, h, fx, fy, fw, fh, steps);
724 break;
725 case WIS_ZOOM:
726 default:
727 steps = (MINIATURIZE_ANIMATION_STEPS_Z * k)/3;
728 if (steps>0)
729 animateResizeZoom(scr, x, y, w, h, fx, fy, fw, fh, steps);
730 break;
733 #endif /* ANIMATIONS */
736 static void
737 flushExpose()
739 XEvent tmpev;
741 while (XCheckTypedEvent(dpy, Expose, &tmpev))
742 WMHandleEvent(&tmpev);
743 XSync(dpy, 0);
746 static void
747 unmapTransientsFor(WWindow *wwin)
749 WWindow *tmp;
752 tmp = wwin->screen_ptr->focused_window;
753 while (tmp) {
754 /* unmap the transients for this transient */
755 if (tmp!=wwin && tmp->transient_for == wwin->client_win
756 && (tmp->flags.mapped || wwin->screen_ptr->flags.startup
757 || tmp->flags.shaded)) {
758 unmapTransientsFor(tmp);
759 tmp->flags.miniaturized = 1;
760 if (!tmp->flags.shaded) {
761 wWindowUnmap(tmp);
762 } else {
763 XUnmapWindow(dpy, tmp->frame->core->window);
766 if (!tmp->flags.shaded)
768 wClientSetState(tmp, IconicState, None);
769 #ifdef KWM_HINTS
770 wKWMUpdateClientStateHint(tmp, KWMIconifiedFlag);
771 wKWMSendEventMessage(tmp, WKWMRemoveWindow);
772 tmp->flags.kwm_hidden_for_modules = 1;
773 #endif
775 UpdateSwitchMenu(wwin->screen_ptr, tmp, ACTION_CHANGE_STATE);
778 tmp = tmp->prev;
783 static void
784 mapTransientsFor(WWindow *wwin)
786 WWindow *tmp;
788 tmp = wwin->screen_ptr->focused_window;
789 while (tmp) {
790 /* recursively map the transients for this transient */
791 if (tmp!=wwin && tmp->transient_for == wwin->client_win
792 && /*!tmp->flags.mapped*/ tmp->flags.miniaturized
793 && tmp->icon==NULL) {
794 mapTransientsFor(tmp);
795 tmp->flags.miniaturized = 0;
796 if (!tmp->flags.shaded) {
797 wWindowMap(tmp);
798 } else {
799 XMapWindow(dpy, tmp->frame->core->window);
801 tmp->flags.semi_focused = 0;
803 if (!tmp->flags.shaded)
805 wClientSetState(tmp, NormalState, None);
806 #ifdef KWM_HINTS
807 wKWMUpdateClientStateHint(tmp, KWMIconifiedFlag);
808 if (tmp->flags.kwm_hidden_for_modules) {
809 wKWMSendEventMessage(tmp, WKWMAddWindow);
810 tmp->flags.kwm_hidden_for_modules = 0;
812 #endif
814 UpdateSwitchMenu(wwin->screen_ptr, tmp, ACTION_CHANGE_STATE);
817 tmp = tmp->prev;
821 #if 0
822 static void
823 setupIconGrabs(WIcon *icon)
825 /* setup passive grabs on the icon */
826 XGrabButton(dpy, Button1, AnyModifier, icon->core->window, True,
827 ButtonPressMask, GrabModeSync, GrabModeAsync, None, None);
828 XGrabButton(dpy, Button2, AnyModifier, icon->core->window, True,
829 ButtonPressMask, GrabModeSync, GrabModeAsync, None, None);
830 XGrabButton(dpy, Button3, AnyModifier, icon->core->window, True,
831 ButtonPressMask, GrabModeSync, GrabModeAsync, None, None);
832 XSync(dpy, 0);
834 #endif
836 static WWindow*
837 recursiveTransientFor(WWindow *wwin)
839 int i;
841 if (!wwin)
842 return None;
844 /* hackish way to detect transient_for cycle */
845 i = wwin->screen_ptr->window_count+1;
847 while (wwin && wwin->transient_for != None && i>0) {
848 wwin = wWindowFor(wwin->transient_for);
849 i--;
851 if (i==0 && wwin) {
852 wwarning("%s has a severely broken WM_TRANSIENT_FOR hint.",
853 wwin->frame->title);
854 return NULL;
857 return wwin;
860 #if 0
861 static void
862 removeIconGrabs(WIcon *icon)
864 /* remove passive grabs on the icon */
865 XUngrabButton(dpy, Button1, AnyModifier, icon->core->window);
866 XUngrabButton(dpy, Button2, AnyModifier, icon->core->window);
867 XUngrabButton(dpy, Button3, AnyModifier, icon->core->window);
868 XSync(dpy, 0);
870 #endif
872 void
873 wIconifyWindow(WWindow *wwin)
875 XWindowAttributes attribs;
876 int present;
879 if (!XGetWindowAttributes(dpy, wwin->client_win, &attribs)) {
880 /* the window doesn't exist anymore */
881 return;
884 if (wwin->flags.miniaturized) {
885 return;
889 if (wwin->transient_for!=None) {
890 WWindow *owner = wWindowFor(wwin->transient_for);
892 if (owner && owner->flags.miniaturized)
893 return;
896 present = wwin->frame->workspace==wwin->screen_ptr->current_workspace;
898 /* if the window is in another workspace, simplify process */
899 if (present) {
900 /* icon creation may take a while */
901 XGrabPointer(dpy, wwin->screen_ptr->root_win, False,
902 ButtonMotionMask|ButtonReleaseMask, GrabModeAsync,
903 GrabModeAsync, None, None, CurrentTime);
906 if (!wwin->flags.icon_moved) {
907 PlaceIcon(wwin->screen_ptr, &wwin->icon_x, &wwin->icon_y);
909 wwin->icon = wIconCreate(wwin);
911 wwin->flags.miniaturized = 1;
912 wwin->flags.mapped = 0;
914 /* unmap transients */
916 unmapTransientsFor(wwin);
918 if (present) {
919 #ifdef WMSOUND
920 wSoundPlay(WMSOUND_ICONIFY);
921 #endif
923 XUngrabPointer(dpy, CurrentTime);
924 wWindowUnmap(wwin);
925 /* let all Expose events arrive so that we can repaint
926 * something before the animation starts (and the server is grabbed) */
927 XSync(dpy, 0);
928 wClientSetState(wwin, IconicState, wwin->icon->icon_win);
929 flushExpose();
930 #ifdef ANIMATIONS
931 if (!wwin->screen_ptr->flags.startup && !wwin->flags.skip_next_animation
932 && !wPreferences.no_animations) {
933 animateResize(wwin->screen_ptr, wwin->frame_x, wwin->frame_y,
934 wwin->frame->core->width, wwin->frame->core->height,
935 wwin->icon_x, wwin->icon_y,
936 wwin->icon->core->width, wwin->icon->core->height,
937 False);
939 #endif
942 wwin->flags.skip_next_animation = 0;
943 if (wwin->screen_ptr->current_workspace==wwin->frame->workspace ||
944 IS_OMNIPRESENT(wwin) || wPreferences.sticky_icons)
946 XMapWindow(dpy, wwin->icon->core->window);
947 AddToStackList(wwin->icon->core);
949 wLowerFrame(wwin->icon->core);
951 if (present) {
952 WWindow *owner = recursiveTransientFor(wwin->screen_ptr->focused_window);
955 * It doesn't seem to be working and causes button event hangup
956 * when deiconifying a transient window.
957 setupIconGrabs(wwin->icon);
959 if ((wwin->flags.focused
960 || (owner && wwin->client_win == owner->client_win))
961 && wPreferences.focus_mode==WKF_CLICK) {
962 WWindow *tmp;
964 tmp = wwin->prev;
965 while (tmp) {
966 if (!WFLAGP(tmp, no_focusable)
967 && !(tmp->flags.hidden||tmp->flags.miniaturized))
968 break;
969 tmp = tmp->prev;
971 wSetFocusTo(wwin->screen_ptr, tmp);
972 } else if (wPreferences.focus_mode!=WKF_CLICK) {
973 wSetFocusTo(wwin->screen_ptr, NULL);
976 #ifdef ANIMATIONS
977 if (!wwin->screen_ptr->flags.startup) {
978 Window clientwin = wwin->client_win;
980 XSync(dpy, 0);
981 processEvents(XPending(dpy));
983 /* the window can disappear while doing the processEvents() */
984 if (!wWindowFor(clientwin))
985 return;
987 #endif
991 if (wwin->flags.selected)
992 wIconSelect(wwin->icon);
994 #ifdef GNOME_STUFF
995 wGNOMEUpdateClientStateHint(wwin, False);
996 #endif
997 #ifdef KWM_HINTS
998 wKWMUpdateClientStateHint(wwin, KWMIconifiedFlag);
999 wKWMSendEventMessage(wwin, WKWMChangedClient);
1000 #endif
1002 UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_STATE);
1007 void
1008 wDeiconifyWindow(WWindow *wwin)
1010 wWindowChangeWorkspace(wwin, wwin->screen_ptr->current_workspace);
1012 if (!wwin->flags.miniaturized)
1013 return;
1015 if (wwin->transient_for != None) {
1016 WWindow *owner = recursiveTransientFor(wwin);
1018 if (wwin->flags.miniaturized) {
1019 wDeiconifyWindow(owner);
1020 wSetFocusTo(wwin->screen_ptr, wwin);
1021 wRaiseFrame(wwin->frame->core);
1022 return;
1026 wwin->flags.miniaturized = 0;
1027 if (!wwin->flags.shaded)
1028 wwin->flags.mapped = 1;
1030 if (wwin->icon->selected)
1031 wIconSelect(wwin->icon);
1033 XUnmapWindow(dpy, wwin->icon->core->window);
1035 #ifdef WMSOUND
1036 wSoundPlay(WMSOUND_DEICONIFY);
1037 #endif
1039 /* if the window is in another workspace, do it silently */
1040 #ifdef ANIMATIONS
1041 if (!wwin->screen_ptr->flags.startup && !wPreferences.no_animations
1042 && !wwin->flags.skip_next_animation) {
1043 animateResize(wwin->screen_ptr, wwin->icon_x, wwin->icon_y,
1044 wwin->icon->core->width, wwin->icon->core->height,
1045 wwin->frame_x, wwin->frame_y,
1046 wwin->frame->core->width, wwin->frame->core->height,
1047 False);
1049 #endif /* ANIMATIONS */
1050 wwin->flags.skip_next_animation = 0;
1051 XGrabServer(dpy);
1052 if (!wwin->flags.shaded) {
1053 XMapWindow(dpy, wwin->client_win);
1055 XMapWindow(dpy, wwin->frame->core->window);
1056 wRaiseFrame(wwin->frame->core);
1057 if (!wwin->flags.shaded) {
1058 wClientSetState(wwin, NormalState, None);
1060 mapTransientsFor(wwin);
1061 RemoveFromStackList(wwin->icon->core);
1062 /* removeIconGrabs(wwin->icon);*/
1063 wIconDestroy(wwin->icon);
1064 wwin->icon = NULL;
1066 XUngrabServer(dpy);
1067 if (wPreferences.focus_mode==WKF_CLICK
1068 || wPreferences.focus_mode==WKF_SLOPPY)
1069 wSetFocusTo(wwin->screen_ptr, wwin);
1071 #ifdef ANIMATIONS
1072 if (!wwin->screen_ptr->flags.startup) {
1073 Window clientwin = wwin->client_win;
1075 XSync(dpy, 0);
1076 processEvents(XPending(dpy));
1078 if (!wWindowFor(clientwin))
1079 return;
1081 #endif
1083 if (wPreferences.auto_arrange_icons) {
1084 wArrangeIcons(wwin->screen_ptr, True);
1087 #ifdef GNOME_STUFF
1088 wGNOMEUpdateClientStateHint(wwin, False);
1089 #endif
1090 #ifdef KWM_HINTS
1091 wKWMUpdateClientStateHint(wwin, KWMIconifiedFlag);
1092 wKWMSendEventMessage(wwin, WKWMChangedClient);
1093 #endif
1095 UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_STATE);
1100 static void
1101 hideWindow(WIcon *icon, int icon_x, int icon_y, WWindow *wwin, int animate)
1103 if (wwin->flags.miniaturized) {
1104 XUnmapWindow(dpy, wwin->icon->core->window);
1105 wwin->flags.hidden = 1;
1106 wwin->icon->mapped = 0;
1107 #ifdef GNOME_STUFF
1108 wGNOMEUpdateClientStateHint(wwin, False);
1109 #endif
1111 UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_STATE);
1113 return;
1116 if (wwin->flags.inspector_open) {
1117 WWindow *pwin = wwin->inspector->frame;
1119 wWindowUnmap(pwin);
1120 pwin->flags.hidden = 1;
1122 wClientSetState(pwin, IconicState, icon->icon_win);
1125 wwin->flags.hidden = 1;
1126 wWindowUnmap(wwin);
1128 wClientSetState(wwin, IconicState, icon->icon_win);
1129 flushExpose();
1130 #ifdef WMSOUND
1131 wSoundPlay(WMSOUND_HIDE);
1132 #endif
1133 #ifdef ANIMATIONS
1134 if (!wwin->screen_ptr->flags.startup && !wPreferences.no_animations &&
1135 !wwin->flags.skip_next_animation && animate) {
1136 animateResize(wwin->screen_ptr, wwin->frame_x, wwin->frame_y,
1137 wwin->frame->core->width, wwin->frame->core->height,
1138 icon_x, icon_y, icon->core->width, icon->core->height,
1139 True);
1141 #endif
1142 wwin->flags.skip_next_animation = 0;
1144 #ifdef GNOME_STUFF
1145 wGNOMEUpdateClientStateHint(wwin, False);
1146 #endif
1148 UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_STATE);
1153 void
1154 wHideOtherApplications(WWindow *awin)
1156 WWindow *wwin;
1157 WApplication *tapp;
1158 #ifdef REDUCE_APPICONS
1159 char *tinstance, *tclass;
1160 unsigned int brokenwin = 0, match = 0;
1161 #endif
1163 if (!awin)
1164 return;
1165 wwin = awin->screen_ptr->focused_window;
1167 #ifdef REDUCE_APPICONS
1168 if (awin->wm_instance == NULL || awin->wm_class == NULL)
1169 brokenwin++;
1170 #endif
1172 while (wwin) {
1173 if (wwin!=awin
1174 && wwin->frame->workspace == awin->screen_ptr->current_workspace
1175 && !(wwin->flags.miniaturized||wwin->flags.hidden)
1176 && !wwin->flags.internal_window
1177 && (!wwin->flags.inspector_open || wwin->inspector->frame!=awin)
1178 && !WFLAGP(wwin, no_hide_others)) {
1180 #ifdef REDUCE_APPICONS
1181 match = 0;
1182 if (!brokenwin) {
1183 if ((tinstance = wwin->wm_instance) == NULL)
1184 tinstance = "";
1185 if ((tclass = wwin->wm_class) == NULL)
1186 tclass = "";
1187 if ((strcmp(awin->wm_instance, tinstance) == 0) &&
1188 (strcmp(awin->wm_class, tclass) == 0) )
1189 match++;
1191 #endif
1193 if (wwin->main_window==None || WFLAGP(wwin, no_appicon)) {
1194 if (!WFLAGP(wwin, no_miniaturizable)) {
1195 wwin->flags.skip_next_animation = 1;
1196 wIconifyWindow(wwin);
1198 } else if (wwin->main_window!=None
1199 #ifndef REDUCE_APPICONS
1200 && awin->main_window != wwin->main_window) {
1201 #else
1202 && (awin->main_window != wwin->main_window && !match)) {
1203 #endif
1204 tapp = wApplicationOf(wwin->main_window);
1205 if (tapp) {
1206 tapp->flags.skip_next_animation = 1;
1207 wHideApplication(tapp);
1208 } else {
1209 if (!WFLAGP(wwin, no_miniaturizable)) {
1210 wwin->flags.skip_next_animation = 1;
1211 wIconifyWindow(wwin);
1216 wwin = wwin->prev;
1219 wSetFocusTo(awin->screen_ptr, awin);
1225 void
1226 wHideApplication(WApplication *wapp)
1228 #ifdef REDUCE_APPICONS
1229 WApplication *tapp;
1230 char *tinstance, *tclass;
1231 unsigned int nowmhints = 0, matchwmhints = 0, matchworkspace = 0;
1232 #endif
1233 WScreen *scr;
1234 WWindow *wlist;
1235 int hadfocus;
1237 if (!wapp) {
1238 wwarning("trying to hide a non grouped window");
1239 return;
1241 if (!wapp->main_window_desc) {
1242 wwarning("group leader not found for window group");
1243 return;
1245 #ifdef REDUCE_APPICONS
1246 if ((wapp->main_window_desc->wm_instance == NULL) ||
1247 (wapp->main_window_desc->wm_class == NULL))
1248 nowmhints++;
1249 #endif
1250 scr = wapp->main_window_desc->screen_ptr;
1251 hadfocus = 0;
1252 wlist = scr->focused_window;
1253 if (!wlist)
1254 return;
1256 if (wlist->main_window == wapp->main_window)
1257 wapp->last_focused = wlist;
1258 else
1259 wapp->last_focused = NULL;
1260 while (wlist) {
1261 #ifdef REDUCE_APPICONS
1262 matchwmhints = matchworkspace = 0;
1263 if (!nowmhints) {
1264 tapp = wApplicationOf(wlist->main_window);
1265 tinstance = tclass = NULL;
1266 if (tapp) {
1267 if (tapp->main_window_desc) {
1268 tinstance = tapp->main_window_desc->wm_instance;
1269 tclass = tapp->main_window_desc->wm_class;
1272 if (tapp == NULL || tinstance == NULL || tclass == NULL) {
1273 /* Should never reach here */
1274 tinstance = "";
1275 tclass = "";
1277 if ((strcmp(tinstance, wapp->main_window_desc->wm_instance) == 0) &&
1278 (strcmp(tclass, wapp->main_window_desc->wm_class) == 0) )
1279 matchwmhints++;
1281 if (wlist->frame) {
1282 if (wlist->frame->workspace == wapp->main_window_desc->screen_ptr->current_workspace)
1283 matchworkspace++;
1285 if ((wlist->main_window == wapp->main_window || matchwmhints) &&
1286 matchworkspace) {
1287 #ifdef I_HATE_THIS
1289 #endif
1290 #else
1291 if (wlist->main_window == wapp->main_window) {
1292 #endif
1293 if (wlist->flags.focused) {
1294 hadfocus = 1;
1296 if (wapp->app_icon)
1297 hideWindow(wapp->app_icon->icon, wapp->app_icon->x_pos,
1298 wapp->app_icon->y_pos, wlist,
1299 !wapp->flags.skip_next_animation);
1301 wlist = wlist->prev;
1304 wapp->flags.skip_next_animation = 0;
1306 if (hadfocus) {
1307 if (wPreferences.focus_mode==WKF_CLICK) {
1308 wlist = scr->focused_window;
1309 while (wlist) {
1310 if (!WFLAGP(wlist, no_focusable) && !wlist->flags.hidden
1311 && (wlist->flags.mapped || wlist->flags.shaded))
1312 break;
1313 wlist = wlist->prev;
1315 wSetFocusTo(scr, wlist);
1316 } else {
1317 wSetFocusTo(scr, NULL);
1321 wapp->flags.hidden = 1;
1323 if(wPreferences.auto_arrange_icons) {
1324 wArrangeIcons(scr, True);
1331 static void
1332 unhideWindow(WIcon *icon, int icon_x, int icon_y, WWindow *wwin, int animate,
1333 int bringToCurrentWS)
1335 if (bringToCurrentWS)
1336 wWindowChangeWorkspace(wwin, wwin->screen_ptr->current_workspace);
1338 wwin->flags.hidden=0;
1339 wwin->flags.mapped=1;
1341 #ifdef WMSOUND
1342 wSoundPlay(WMSOUND_UNHIDE);
1343 #endif
1344 #ifdef ANIMATIONS
1345 if (!wwin->screen_ptr->flags.startup && !wPreferences.no_animations
1346 && animate) {
1347 animateResize(wwin->screen_ptr, icon_x, icon_y,
1348 icon->core->width, icon->core->height,
1349 wwin->frame_x, wwin->frame_y,
1350 wwin->frame->core->width, wwin->frame->core->height,
1351 True);
1353 #endif
1354 wwin->flags.skip_next_animation = 0;
1355 XMapWindow(dpy, wwin->client_win);
1356 XMapWindow(dpy, wwin->frame->core->window);
1357 wClientSetState(wwin, NormalState, None);
1358 wRaiseFrame(wwin->frame->core);
1359 if (wwin->flags.inspector_open) {
1360 WWindow *pwin = wwin->inspector->frame;
1362 pwin->flags.hidden = 0;
1363 pwin->flags.mapped = 1;
1364 XMapWindow(dpy, pwin->client_win);
1365 XMapWindow(dpy, pwin->frame->core->window);
1366 wClientSetState(pwin, NormalState, None);
1369 #ifdef GNOME_STUFF
1370 wGNOMEUpdateClientStateHint(wwin, False);
1371 #endif
1373 UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_STATE);
1378 void
1379 wUnhideApplication(WApplication *wapp, Bool miniwindows, Bool bringToCurrentWS)
1381 WScreen *scr;
1382 WWindow *wlist, *next;
1383 WWindow *focused=NULL;
1384 #ifdef REDUCE_APPICONS
1385 char *tinstance, *tclass;
1386 unsigned int nowmhints = 0, matchwmhints = 0, matchworkspace = 0;
1387 #endif
1389 if (!wapp) {
1390 return;
1393 #ifdef REDUCE_APPICONS
1394 if ((wapp->main_window_desc->wm_class == NULL) ||
1395 (wapp->main_window_desc->wm_instance == NULL))
1396 nowmhints++;
1397 #endif
1399 scr = wapp->main_window_desc->screen_ptr;
1400 wlist = scr->focused_window;
1401 if (!wlist) return;
1402 /* goto beginning of list */
1403 while (wlist->prev)
1404 wlist = wlist->prev;
1406 while (wlist) {
1407 next = wlist->next;
1409 #ifndef REDUCE_APPICONS
1410 if (wlist->main_window == wapp->main_window) {
1411 #else
1412 matchwmhints = matchworkspace = 0;
1413 if (!nowmhints) {
1414 if ((tinstance = wlist->wm_instance) == NULL)
1415 tinstance = "";
1416 if ((tclass = wlist->wm_class) == NULL)
1417 tclass = "";
1418 if ((strcmp(tinstance, wapp->main_window_desc->wm_instance) == 0)
1419 && (strcmp(tclass, wapp->main_window_desc->wm_class) == 0) )
1420 matchwmhints++;
1422 if (wlist->frame) {
1423 if (wlist->frame->workspace == wapp->main_window_desc->screen_ptr->current_workspace)
1424 matchworkspace++;
1427 if ((wlist->main_window == wapp->main_window || matchwmhints) &&
1428 matchworkspace) {
1429 #endif
1430 if (wlist->flags.focused)
1431 focused = wlist;
1432 else if (!focused || !focused->flags.focused)
1433 focused = wlist;
1435 if (wlist->flags.miniaturized && wlist->icon) {
1436 if (bringToCurrentWS || wPreferences.sticky_icons
1437 || wlist->frame->workspace == scr->current_workspace) {
1438 if (!wlist->icon->mapped) {
1439 XMapWindow(dpy, wlist->icon->core->window);
1440 wlist->icon->mapped = 1;
1442 wlist->flags.hidden = 0;
1444 UpdateSwitchMenu(scr, wlist, ACTION_CHANGE_STATE);
1446 if (wlist->frame->workspace != scr->current_workspace)
1447 wWindowChangeWorkspace(wlist, scr->current_workspace);
1449 if (miniwindows) {
1450 wDeiconifyWindow(wlist);
1452 } else if (wlist->flags.hidden) {
1453 unhideWindow(wapp->app_icon->icon, wapp->app_icon->x_pos,
1454 wapp->app_icon->y_pos, wlist,
1455 !wapp->flags.skip_next_animation,
1456 bringToCurrentWS);
1457 } else {
1458 if (bringToCurrentWS
1459 && wlist->frame->workspace != scr->current_workspace) {
1460 wWindowChangeWorkspace(wlist, scr->current_workspace);
1462 wRaiseFrame(wlist->frame->core);
1465 wlist = next;
1468 wapp->flags.skip_next_animation = 0;
1469 wapp->flags.hidden = 0;
1471 if (focused)
1472 wSetFocusTo(scr, focused);
1473 else if (wapp->last_focused && wapp->last_focused->flags.mapped)
1474 wSetFocusTo(scr, wapp->last_focused);
1475 wapp->last_focused = NULL;
1476 if (wPreferences.auto_arrange_icons) {
1477 wArrangeIcons(scr, True);
1483 void
1484 wShowAllWindows(WScreen *scr)
1486 WWindow *wwin, *old_foc;
1487 WApplication *wapp;
1489 old_foc = wwin = scr->focused_window;
1490 while (wwin) {
1491 if (!wwin->flags.internal_window &&
1492 (scr->current_workspace == wwin->frame->workspace
1493 || IS_OMNIPRESENT(wwin))) {
1494 if (wwin->flags.miniaturized) {
1495 wwin->flags.skip_next_animation = 1;
1496 wDeiconifyWindow(wwin);
1497 } else if (wwin->flags.hidden) {
1498 wapp = wApplicationOf(wwin->main_window);
1499 if (wapp) {
1500 wUnhideApplication(wapp, False, False);
1501 } else {
1502 wwin->flags.skip_next_animation = 1;
1503 wDeiconifyWindow(wwin);
1507 wwin = wwin->prev;
1509 wSetFocusTo(scr, old_foc);
1510 /*wRaiseFrame(old_foc->frame->core);*/
1514 void
1515 wRefreshDesktop(WScreen *scr)
1517 Window win;
1518 XSetWindowAttributes attr;
1520 attr.backing_store = NotUseful;
1521 attr.save_under = False;
1522 win = XCreateWindow(dpy, scr->root_win, 0, 0, scr->scr_width,
1523 scr->scr_height, 0, CopyFromParent, CopyFromParent,
1524 (Visual *)CopyFromParent, CWBackingStore|CWSaveUnder,
1525 &attr);
1526 XMapRaised(dpy, win);
1527 XDestroyWindow(dpy, win);
1528 XFlush(dpy);
1532 void
1533 wArrangeIcons(WScreen *scr, Bool arrangeAll)
1535 WWindow *wwin;
1536 WAppIcon *aicon;
1537 int pf; /* primary axis */
1538 int sf; /* secondary axis */
1539 int fullW;
1540 int fullH;
1541 int pi, si;
1542 int sx1, sx2, sy1, sy2; /* screen boundary */
1543 int sw, sh;
1544 int xo, yo;
1545 int xs, ys;
1546 int isize = wPreferences.icon_size;
1549 * Find out screen boundaries.
1551 sx1 = 0;
1552 sy1 = 0;
1553 sx2 = scr->scr_width;
1554 sy2 = scr->scr_height;
1555 if (scr->dock) {
1556 if (scr->dock->on_right_side)
1557 sx2 -= isize + DOCK_EXTRA_SPACE;
1558 else
1559 sx1 += isize + DOCK_EXTRA_SPACE;
1562 sw = isize * (scr->scr_width/isize);
1563 sh = isize * (scr->scr_height/isize);
1564 fullW = (sx2-sx1)/isize;
1565 fullH = (sy2-sy1)/isize;
1567 /* icon yard boundaries */
1568 if (wPreferences.icon_yard & IY_VERT) {
1569 pf = fullH;
1570 sf = fullW;
1571 } else {
1572 pf = fullW;
1573 sf = fullH;
1575 if (wPreferences.icon_yard & IY_RIGHT) {
1576 xo = sx2 - isize;
1577 xs = -1;
1578 } else {
1579 xo = sx1;
1580 xs = 1;
1582 if (wPreferences.icon_yard & IY_TOP) {
1583 yo = sy1;
1584 ys = 1;
1585 } else {
1586 yo = sy2 - isize;
1587 ys = -1;
1590 /* arrange icons putting the most recently focused window
1591 * as the last icon */
1592 #define X ((wPreferences.icon_yard & IY_VERT) ? xo + xs*(si*isize)\
1593 : xo + xs*(pi*isize))
1594 #define Y ((wPreferences.icon_yard & IY_VERT) ? yo + ys*(pi*isize)\
1595 : yo + ys*(si*isize))
1597 /* arrange application icons */
1598 aicon = scr->app_icon_list;
1599 /* reverse them to avoid unnecessarily sliding of icons */
1600 while (aicon && aicon->next)
1601 aicon = aicon->next;
1603 pi = 0;
1604 si = 0;
1605 while (aicon) {
1606 if (!aicon->docked) {
1607 if (aicon->x_pos != X || aicon->y_pos != Y) {
1608 #ifdef ANIMATIONS
1609 if (!wPreferences.no_animations) {
1610 SlideWindow(aicon->icon->core->window, aicon->x_pos, aicon->y_pos,
1611 X, Y);
1613 #endif /* ANIMATIONS */
1615 wAppIconMove(aicon, X, Y);
1616 pi++;
1618 /* we reversed the order so we use prev */
1619 aicon = aicon->prev;
1620 if (pi >= pf) {
1621 pi=0;
1622 si++;
1626 /* arrange miniwindows */
1628 wwin = scr->focused_window;
1629 /* reverse them to avoid unnecessarily shuffling */
1630 while (wwin && wwin->prev)
1631 wwin = wwin->prev;
1633 while (wwin) {
1634 if (wwin->icon && wwin->flags.miniaturized &&/*!wwin->flags.hidden &&*/
1635 (wwin->frame->workspace==scr->current_workspace ||
1636 IS_OMNIPRESENT(wwin) || wPreferences.sticky_icons)) {
1638 if (arrangeAll || !wwin->flags.icon_moved) {
1639 if (wwin->icon_x != X || wwin->icon_y != Y) {
1640 #ifdef ANIMATIONS
1641 if (wPreferences.no_animations) {
1642 XMoveWindow(dpy, wwin->icon->core->window, X, Y);
1643 } else {
1644 SlideWindow(wwin->icon->core->window, wwin->icon_x,
1645 wwin->icon_y, X, Y);
1647 #else
1648 XMoveWindow(dpy, wwin->icon->core->window, X, Y);
1649 #endif /* ANIMATIONS */
1651 wwin->icon_x = X;
1652 wwin->icon_y = Y;
1653 pi++;
1656 if (arrangeAll) {
1657 wwin->flags.icon_moved = 0;
1659 /* we reversed the order, so we use next */
1660 wwin = wwin->next;
1661 if (pi >= pf) {
1662 pi=0;
1663 si++;
1669 void
1670 wSelectWindow(WWindow *wwin, Bool flag)
1672 WScreen *scr = wwin->screen_ptr;
1673 if (flag) {
1674 wwin->flags.selected = 1;
1675 XSetWindowBorder(dpy, wwin->frame->core->window, scr->white_pixel);
1676 scr->selected_windows = list_cons(wwin, scr->selected_windows);
1677 } else {
1678 wwin->flags.selected = 0;
1679 XSetWindowBorder(dpy, wwin->frame->core->window,
1680 scr->frame_border_pixel);
1681 scr->selected_windows = list_remove_elem(scr->selected_windows, wwin);
1686 void
1687 wMakeWindowVisible(WWindow *wwin)
1689 wWorkspaceChange(wwin->screen_ptr, wwin->frame->workspace);
1691 if (wwin->flags.shaded) {
1692 wUnshadeWindow(wwin);
1694 if (wwin->flags.hidden) {
1695 WApplication *app;
1697 app = wApplicationOf(wwin->main_window);
1698 if (app)
1699 wUnhideApplication(app, False, False);
1700 } else if (wwin->flags.miniaturized) {
1701 wDeiconifyWindow(wwin);
1702 } else {
1703 wSetFocusTo(wwin->screen_ptr, wwin);
1704 wRaiseFrame(wwin->frame->core);