]>
Commit | Line | Data |
---|---|---|
e6728433 | 1 | Index: plugins/minimize.c |
2 | =================================================================== | |
3 | RCS file: /cvs/xorg/app/compiz/plugins/minimize.c,v | |
4 | retrieving revision 1.3 | |
5 | diff -u -r1.3 minimize.c | |
6 | --- plugins/minimize.c 31 Mar 2006 11:22:34 -0000 1.3 | |
7 | +++ plugins/minimize.c 1 Apr 2006 16:20:55 -0000 | |
8 | @@ -26,6 +26,7 @@ | |
9 | #include <X11/Xatom.h> | |
10 | ||
11 | #include <stdlib.h> | |
12 | +#include <stdio.h> | |
13 | #include <string.h> | |
14 | #include <math.h> | |
15 | ||
16 | @@ -41,6 +42,8 @@ | |
17 | #define MIN_TIMESTEP_MAX 50.0f | |
18 | #define MIN_TIMESTEP_PRECISION 0.1f | |
19 | ||
20 | +#define FAKE_ICON_SIZE 4 | |
21 | + | |
22 | static char *winType[] = { | |
23 | "Toolbar", | |
24 | "Utility", | |
25 | @@ -61,7 +64,9 @@ | |
26 | #define MIN_SCREEN_OPTION_SPEED 0 | |
27 | #define MIN_SCREEN_OPTION_TIMESTEP 1 | |
28 | #define MIN_SCREEN_OPTION_WINDOW_TYPE 2 | |
29 | -#define MIN_SCREEN_OPTION_NUM 3 | |
30 | +#define MIN_SCREEN_OPTION_ON_CREATE 3 | |
31 | +#define MIN_SCREEN_OPTION_CENTER 4 | |
32 | +#define MIN_SCREEN_OPTION_NUM 5 | |
33 | ||
34 | typedef struct _MinScreen { | |
35 | int windowPrivateIndex; | |
36 | @@ -81,6 +86,8 @@ | |
37 | unsigned int wMask; | |
38 | ||
39 | int moreAdjust; | |
40 | + Bool scaleInNewWindows; | |
41 | + Bool scaleFromCenter; | |
42 | } MinScreen; | |
43 | ||
44 | typedef struct _MinWindow { | |
45 | @@ -95,6 +102,7 @@ | |
46 | int state, newState; | |
47 | ||
48 | int unmapCnt; | |
49 | + int destroyCnt; | |
50 | } MinWindow; | |
51 | ||
52 | #define GET_MIN_DISPLAY(d) \ | |
53 | @@ -119,6 +127,23 @@ | |
54 | ||
55 | #define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption)) | |
56 | ||
57 | +static Bool | |
58 | +getMousePointerXY(CompScreen *s, short *x, short *y) | |
59 | +{ | |
60 | + Window w1, w2; | |
61 | + int xp, yp, xj, yj; | |
62 | + unsigned int m; | |
63 | + | |
64 | + if (XQueryPointer (s->display->display, s->root, &w1, &w2, &xj, &yj, &xp, &yp, &m)) | |
65 | + { | |
66 | + *x = xp; | |
67 | + *y = yp; | |
68 | + return TRUE; | |
69 | + } | |
70 | + | |
71 | + return FALSE; | |
72 | +} | |
73 | + | |
74 | static CompOption * | |
75 | minGetScreenOptions (CompScreen *screen, | |
76 | int *count) | |
77 | @@ -164,6 +189,19 @@ | |
78 | ms->wMask = compWindowTypeMaskFromStringList (&o->value); | |
79 | return TRUE; | |
80 | } | |
81 | + break; | |
82 | + case MIN_SCREEN_OPTION_ON_CREATE: | |
83 | + if (compSetBoolOption (o, value)) | |
84 | + { | |
85 | + ms->scaleInNewWindows = o->value.b; | |
86 | + return TRUE; | |
87 | + } | |
88 | + case MIN_SCREEN_OPTION_CENTER: | |
89 | + if (compSetBoolOption (o, value)) | |
90 | + { | |
91 | + ms->scaleFromCenter = o->value.b; | |
92 | + return TRUE; | |
93 | + } | |
94 | default: | |
95 | break; | |
96 | } | |
97 | @@ -210,8 +248,22 @@ | |
98 | o->value.list.value[i].s = strdup (winType[i]); | |
99 | o->rest.s.string = windowTypeString; | |
100 | o->rest.s.nString = nWindowTypeString; | |
101 | - | |
102 | ms->wMask = compWindowTypeMaskFromStringList (&o->value); | |
103 | + | |
104 | + o = &ms->opt[MIN_SCREEN_OPTION_ON_CREATE]; | |
105 | + o->name = "zoom_created_windows"; | |
106 | + o->shortDesc = "Zoom Created Windows"; | |
107 | + o->longDesc = "Zooms created windows in from cursor/center"; | |
108 | + o->type = CompOptionTypeBool; | |
109 | + o->value.b = TRUE; | |
110 | + | |
111 | + o = &ms->opt[MIN_SCREEN_OPTION_CENTER]; | |
112 | + o->name = "zoom_created_windows_from_center"; | |
113 | + o->shortDesc = "Zoom Created Windows from Center"; | |
114 | + o->longDesc = "Zooms created windows in from center instead of cursor"; | |
115 | + o->type = CompOptionTypeBool; | |
116 | + o->value.b = FALSE; | |
117 | + | |
118 | } | |
119 | ||
120 | static Bool | |
121 | @@ -286,7 +338,7 @@ | |
122 | ||
123 | MIN_WINDOW (w); | |
124 | ||
125 | - if (mw->newState == IconicState) | |
126 | + if (mw->newState == IconicState || mw->newState == WithdrawnState) | |
127 | { | |
128 | x1 = mw->icon.x; | |
129 | y1 = mw->icon.y; | |
130 | @@ -357,6 +409,11 @@ | |
131 | mw->ty = y1 - w->attrib.y; | |
132 | mw->xScale = xScale; | |
133 | mw->yScale = yScale; | |
134 | + if (mw->destroyCnt) | |
135 | + { | |
136 | + destroyWindow (w); | |
137 | + mw->destroyCnt--; | |
138 | + } | |
139 | ||
140 | return 0; | |
141 | } | |
142 | @@ -531,6 +588,21 @@ | |
143 | } | |
144 | } | |
145 | break; | |
146 | + case DestroyNotify: | |
147 | + w = findWindowAtDisplay (d, event->xunmap.window); | |
148 | + /* mark it for zooming out */ | |
149 | + if (w) | |
150 | + { | |
151 | + MIN_SCREEN (w->screen); | |
152 | + if (ms->wMask & w->type) | |
153 | + { | |
154 | + MIN_WINDOW(w); | |
155 | + mw->destroyCnt++; | |
156 | + w->destroyRefCnt++; | |
157 | + addWindowDamage(w); | |
158 | + } | |
159 | + } | |
160 | + break; | |
161 | case UnmapNotify: | |
162 | w = findWindowAtDisplay (d, event->xunmap.window); | |
163 | if (w) | |
164 | @@ -564,13 +636,39 @@ | |
165 | else /* X -> Withdrawn */ | |
166 | { | |
167 | MIN_WINDOW (w); | |
168 | - | |
169 | - if (mw->state == IconicState) | |
170 | - { | |
171 | - (*w->screen->setWindowScale) (w, 1.0f, 1.0f); | |
172 | - mw->state = NormalState; | |
173 | - } | |
174 | - } | |
175 | + if (ms->wMask & w->type) | |
176 | + { | |
177 | + if (mw->state == IconicState) | |
178 | + { | |
179 | + (*w->screen->setWindowScale) (w, 1.0f, 1.0f); | |
180 | + } | |
181 | + | |
182 | + mw->state = NormalState; | |
183 | + mw->newState = WithdrawnState; | |
184 | + | |
185 | + /* let's zoom windows on hide */ | |
186 | + if (getMousePointerXY (w->screen, &mw->icon.x, &mw->icon.y) && | |
187 | + ms->scaleInNewWindows && (ms->wMask & w->type)) | |
188 | + { | |
189 | + mw->icon.width = FAKE_ICON_SIZE; | |
190 | + mw->icon.height = FAKE_ICON_SIZE; | |
191 | + mw->icon.x -= FAKE_ICON_SIZE/2; | |
192 | + mw->icon.y -= FAKE_ICON_SIZE/2; | |
193 | + | |
194 | + if (ms->scaleFromCenter) | |
195 | + { | |
196 | + mw->icon.x = w->attrib.x + w->attrib.width/2 - FAKE_ICON_SIZE/2; | |
197 | + mw->icon.y = w->attrib.y + w->attrib.height/2 - FAKE_ICON_SIZE/2; | |
198 | + } | |
199 | + | |
200 | + mw->adjust = TRUE; | |
201 | + ms->moreAdjust = TRUE; | |
202 | + mw->unmapCnt++; | |
203 | + w->unmapRefCnt++; | |
204 | + addWindowDamage (w); | |
205 | + } | |
206 | + } | |
207 | + } | |
208 | } | |
209 | default: | |
210 | break; | |
211 | @@ -630,6 +728,33 @@ | |
212 | (*w->screen->setWindowScale) (w, 1.0f, 1.0f); | |
213 | } | |
214 | } | |
215 | + else if (mw->state != NormalState) | |
216 | + { | |
217 | + if (getMousePointerXY(w->screen,&mw->icon.x,&mw->icon.y) && ms->scaleInNewWindows) | |
218 | + { | |
219 | + mw->icon.width = FAKE_ICON_SIZE; | |
220 | + mw->icon.height = FAKE_ICON_SIZE; | |
221 | + mw->icon.x -= FAKE_ICON_SIZE/2; | |
222 | + mw->icon.y -= FAKE_ICON_SIZE/2; | |
223 | + | |
224 | + if (ms->scaleFromCenter) | |
225 | + { | |
226 | + mw->icon.x = w->attrib.x + w->attrib.width/2 - FAKE_ICON_SIZE/2; | |
227 | + mw->icon.y = w->attrib.y + w->attrib.height/2 - FAKE_ICON_SIZE/2; | |
228 | + } | |
229 | + | |
230 | + mw->tx = mw->icon.x-w->attrib.x; | |
231 | + mw->ty = mw->icon.y-w->attrib.y; | |
232 | + mw->xScale = ((float)FAKE_ICON_SIZE) / w->attrib.width; | |
233 | + mw->yScale = ((float)FAKE_ICON_SIZE) / w->attrib.height; | |
234 | + | |
235 | + mw->state = IconicState; /* we're doing this as a hack, it may not be necessary */ | |
236 | + mw->newState = NormalState; | |
237 | + mw->adjust = TRUE; | |
238 | + ms->moreAdjust = TRUE; | |
239 | + addWindowDamage (w); | |
240 | + } | |
241 | + } | |
242 | ||
243 | mw->newState = NormalState; | |
244 | } | |
245 | @@ -649,7 +774,7 @@ | |
246 | MIN_SCREEN (w->screen); | |
247 | MIN_WINDOW (w); | |
248 | ||
249 | - if (mw->unmapCnt) | |
250 | + if (mw->unmapCnt || mw->destroyCnt) | |
251 | return FALSE; | |
252 | ||
253 | UNWRAP (ms, w->screen, focusWindow); | |
254 | @@ -723,6 +848,8 @@ | |
255 | ||
256 | ms->speed = MIN_SPEED_DEFAULT; | |
257 | ms->timestep = MIN_TIMESTEP_DEFAULT; | |
258 | + ms->scaleInNewWindows = TRUE; | |
259 | + ms->scaleFromCenter = FALSE; | |
260 | ||
261 | minScreenInitOptions (ms); | |
262 | ||
263 | @@ -775,11 +902,40 @@ | |
264 | mw->xScaleVelocity = mw->yScaleVelocity = 1.0f; | |
265 | ||
266 | mw->unmapCnt = 0; | |
267 | + mw->destroyCnt = 0; | |
268 | ||
269 | mw->state = mw->newState = minGetWindowState (w); | |
270 | ||
271 | w->privates[ms->windowPrivateIndex].ptr = mw; | |
272 | ||
273 | + /* use a 'virtual' icon of 32x32 at mpx-16,mpy-16 */ | |
274 | + /* TODO consider changing this to a configurable thing somehow */ | |
275 | + if (w->type & ms->wMask && ms->scaleInNewWindows && mw->state == NormalState) | |
276 | + { | |
277 | + if (getMousePointerXY (w->screen, &mw->icon.x, &mw->icon.y)) | |
278 | + { | |
279 | + mw->icon.width = FAKE_ICON_SIZE; | |
280 | + mw->icon.height = FAKE_ICON_SIZE; | |
281 | + mw->icon.x -= FAKE_ICON_SIZE / 2; | |
282 | + mw->icon.y -= FAKE_ICON_SIZE / 2; | |
283 | + if (ms->scaleFromCenter) | |
284 | + { | |
285 | + mw->icon.x = w->attrib.x + w->attrib.width/2 - FAKE_ICON_SIZE/2; | |
286 | + mw->icon.y = w->attrib.y + w->attrib.height/2 - FAKE_ICON_SIZE/2; | |
287 | + } | |
288 | + | |
289 | + mw->tx = mw->icon.x - w->attrib.x; | |
290 | + mw->ty = mw->icon.y - w->attrib.y; | |
291 | + mw->xScale = ((float)FAKE_ICON_SIZE) / w->attrib.width; | |
292 | + mw->yScale = ((float)FAKE_ICON_SIZE) / w->attrib.height; | |
293 | + mw->state = IconicState; /* we're doing this as a hack, it may not be necessary */ | |
294 | + mw->newState = NormalState; | |
295 | + mw->adjust=TRUE; | |
296 | + ms->moreAdjust=TRUE; | |
297 | + addWindowDamage (w); | |
298 | + } | |
299 | + } | |
300 | + | |
301 | return TRUE; | |
302 | } | |
303 |