1 /* $Id: desktop.c,v 1.1 2004/08/28 19:25:45 dannybackx Exp $ */
2 /*****************************************************************************/
3 /**       Copyright 1988 by Evans & Sutherland Computer Corporation,        **/
4 /**                          Salt Lake City, Utah                           **/
5 /**  Portions Copyright 1989 by the Massachusetts Institute of Technology   **/
6 /**                        Cambridge, Massachusetts                         **/
7 /**                                                                         **/
8 /**                           All Rights Reserved                           **/
9 /**                                                                         **/
10 /**    Permission to use, copy, modify, and distribute this software and    **/
11 /**    its documentation  for  any  purpose  and  without  fee is hereby    **/
12 /**    granted, provided that the above copyright notice appear  in  all    **/
13 /**    copies and that both  that  copyright  notice  and  this  permis-    **/
14 /**    sion  notice appear in supporting  documentation,  and  that  the    **/
15 /**    names of Evans & Sutherland and M.I.T. not be used in advertising    **/
16 /**    in publicity pertaining to distribution of the  software  without    **/
17 /**    specific, written prior permission.                                  **/
18 /**                                                                         **/
19 /**    EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD    **/
20 /**    TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES  OF  MERCHANT-    **/
21 /**    ABILITY  AND  FITNESS,  IN  NO  EVENT SHALL EVANS & SUTHERLAND OR    **/
22 /**    M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL  DAM-    **/
23 /**    AGES OR  ANY DAMAGES WHATSOEVER  RESULTING FROM LOSS OF USE, DATA    **/
24 /**    OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER    **/
25 /**    TORTIOUS ACTION, ARISING OUT OF OR IN  CONNECTION  WITH  THE  USE    **/
26 /**    OR PERFORMANCE OF THIS SOFTWARE.                                     **/
27 /*****************************************************************************/
28 /****************************************************************************
29  * This module is based on Twm, but has been siginificantly modified
30  * by Rob Nation
31  ****************************************************************************/
32 /***********************************************************************
33  * The rest of it is all my fault -- MLM
34  * mwm - "LessTif Window Manager"
35  ***********************************************************************/
36 
37 #include <LTconfig.h>
38 
39 #include <Xm/Xm.h>
40 #include <Xm/MwmUtil.h>
41 #include "mwm.h"
42 
43 /****************************************************************************
44  *
45  * <Desktop description>
46  *
47  ****************************************************************************/
48 
49 /*
50  * Unmaps a window on transition to a new desktop
51  */
52 static void
remove_from_desktop(ScreenInfo * scr,MwmWindow * t)53 remove_from_desktop(ScreenInfo *scr, MwmWindow *t)
54 {
55     XWindowAttributes winattrs;
56     unsigned long eventMask;
57 
58     /*
59      * Prevent the receipt of an UnmapNotify, since that would
60      * cause a transition to the Withdrawn state.
61      */
62     XGetWindowAttributes(dpy, t->w, &winattrs);
63     eventMask = winattrs.your_event_mask;
64     XSelectInput(dpy, t->w, eventMask & ~StructureNotifyMask);
65     if (t->flags & ICONIFIED)
66     {
67 	if (t->icon_pixmap_w != None)
68 	    XUnmapWindow(dpy, t->icon_pixmap_w);
69 	if (t->icon_w != None)
70 	    XUnmapWindow(dpy, t->icon_w);
71     }
72     else if (t->flags & (MAPPED | MAP_PENDING))
73     {
74 	XUnmapWindow(dpy, t->frame);
75     }
76     XSelectInput(dpy, t->w, eventMask);
77     PAGER_UpdateView(scr, t);
78 }
79 
80 /*
81  * Maps a window on transition to a new desktop
82  */
83 static void
add_to_desktop(ScreenInfo * scr,MwmWindow * t)84 add_to_desktop(ScreenInfo *scr, MwmWindow *t)
85 {
86     if (t->flags & ICONIFIED)
87     {
88 	if (t->icon_pixmap_w != None)
89 	    XMapWindow(dpy, t->icon_pixmap_w);
90 	if (t->icon_w != None)
91 	    XMapWindow(dpy, t->icon_w);
92     }
93     else if (t->flags & MAPPED)
94     {
95 	XMapWindow(dpy, t->frame);
96 	t->flags |= MAP_PENDING;
97 	XMapWindow(dpy, t->parent);
98     }
99     PAGER_UpdateView(scr, t);
100 }
101 
102 /*
103  * save the desktop state
104  */
105 void
DT_SaveState(ScreenInfo * scr)106 DT_SaveState(ScreenInfo *scr)
107 {
108     MwmWindow *t;
109     unsigned long data[1];
110 
111     for (t = scr->mwm_root.next; t != NULL; t = t->next)
112     {
113 	data[0] = (unsigned long)t->Desk;
114 	XChangeProperty(dpy, t->w, XA_WM_DESKTOP, XA_WM_DESKTOP, 32,
115 			PropModeReplace, (unsigned char *)data, 1);
116     }
117 
118     data[0] = (unsigned long)scr->current_desk;
119     XChangeProperty(dpy, scr->root_win, XA_WM_DESKTOP, XA_WM_DESKTOP, 32,
120 		    PropModeReplace, (unsigned char *)data, 1);
121 
122     XSync(dpy, 0);
123 }
124 
125 /*
126  * Move to a new desktop
127  */
128 void
DT_ChangeDesks(ScreenInfo * scr,int val1,int val2)129 DT_ChangeDesks(ScreenInfo *scr, int val1, int val2)
130 {
131     int oldDesk;
132     MwmWindow *t;
133     MwmWindow *FocusWin = 0;
134     static MwmWindow *StickyWin = 0;
135 
136     oldDesk = scr->current_desk;
137 
138     if (val1 != 0)
139     {
140 	scr->current_desk = scr->current_desk + val1;
141     }
142     else
143     {
144 	scr->current_desk = val2;
145 	if (scr->current_desk == oldDesk)
146 	    return;
147     }
148 
149     /* Scan the window list, mapping windows on the new Desk,
150      * unmapping windows on the old Desk */
151     XGrabServer(dpy);
152     for (t = scr->mwm_root.next; t != NULL; t = t->next)
153     {
154 	/* Only change mapping for non-sticky windows */
155 	if ((!(t->flags & STICKY)) && (!(t->flags & ICON_UNMAPPED)))
156 	{
157 	    if (t->Desk == oldDesk)
158 	    {
159 		if (scr->mwm_focus == t)
160 		    t->FocusDesk = oldDesk;
161 		else
162 		    t->FocusDesk = -1;
163 		remove_from_desktop(scr, t);
164 	    }
165 	    else if (t->Desk == scr->current_desk)
166 	    {
167 		add_to_desktop(scr, t);
168 		if (t->FocusDesk == scr->current_desk)
169 		{
170 		    FocusWin = t;
171 		}
172 	    }
173 	}
174 	else
175 	{
176 	    /* Window is sticky */
177 	    t->Desk = scr->current_desk;
178 	    if (scr->mwm_focus == t)
179 	    {
180 		t->FocusDesk = oldDesk;
181 		StickyWin = t;
182 	    }
183 	}
184     }
185     XUngrabServer(dpy);
186     for (t = scr->mwm_root.next; t != NULL; t = t->next)
187     {
188 	/* If its an icon, and its sticking, autoplace it so
189 	 * that it doesn't wind up on top a a stationary
190 	 * icon */
191 	if ((t->flags & STICKY) && (t->flags & ICONIFIED) &&
192 	    (!(t->flags & ICON_MOVED)) && (!(t->flags & ICON_UNMAPPED)))
193 	    ICON_AutoPlace(scr, t);
194     }
195     /* Better re-draw the pager now */
196     PAGER_Clear(scr);
197 
198     if (Mwm.keyboard_focus_policy == XmEXPLICIT)
199     {
200 	if (Mwm.auto_key_focus)
201 	{
202 	    if (FocusWin)
203 	    {
204 		WIN_SetFocusInTree(FocusWin);
205 		WIN_SetFocus(scr, FocusWin->w, FocusWin);
206 	    }
207 	    else if (StickyWin && (StickyWin->flags && STICKY))
208 	    {
209 		WIN_SetFocusInTree(StickyWin);
210 		WIN_SetFocus(scr, StickyWin->w, StickyWin);
211 	    }
212 	}
213 	else
214         {
215 	    WIN_SetFocus(scr, scr->no_focus_win, NULL);
216         }
217     }
218 }
219 
220 /*
221  * Move to a new desktop
222  */
223 void
DT_WindowChangingDesks(ScreenInfo * scr,MwmWindow * t,int val1)224 DT_WindowChangingDesks(ScreenInfo *scr, MwmWindow *t, int val1)
225 {
226     if (val1 == t->Desk)
227 	return;
228 
229     /* Scan the window list, mapping windows on the new Desk,
230      * unmapping windows on the old Desk */
231     /* Only change mapping for non-sticky windows */
232     if ((!(t->flags & STICKY)) && (!(t->flags & ICON_UNMAPPED)))
233     {
234 	if (t->Desk == scr->current_desk)
235 	{
236 	    t->Desk = val1;
237 	    remove_from_desktop(scr, t);
238 	}
239 	else if (val1 == scr->current_desk)
240 	{
241 	    t->Desk = val1;
242 	    /* If its an icon, auto-place it */
243 	    if (t->flags & ICONIFIED)
244 		ICON_AutoPlace(scr, t);
245 	    add_to_desktop(scr, t);
246 	}
247 	else
248 	    t->Desk = val1;
249 
250     }
251     /* Better re-draw the pager now */
252     PAGER_Clear(scr);
253 }
254