1 /****************************************************************************
2 * This module is based on Twm, but has been siginificantly modified
3 * by Rob Nation
4 *
5 * later modified slightly for BowMan
6 * by Bo Yang
7 *
8 * later modified even more slightly for AfterStep
9 * by Frank Fejes
10 ****************************************************************************/
11 /*****************************************************************************/
12 /** Copyright 1988 by Evans & Sutherland Computer Corporation, **/
13 /** Salt Lake City, Utah **/
14 /** Portions Copyright 1989 by the Massachusetts Institute of Technology **/
15 /** Cambridge, Massachusetts **/
16 /** **/
17 /** All Rights Reserved **/
18 /** **/
19 /** Permission to use, copy, modify, and distribute this software and **/
20 /** its documentation for any purpose and without fee is hereby **/
21 /** granted, provided that the above copyright notice appear in all **/
22 /** copies and that both that copyright notice and this permis- **/
23 /** sion notice appear in supporting documentation, and that the **/
24 /** names of Evans & Sutherland and M.I.T. not be used in advertising **/
25 /** in publicity pertaining to distribution of the software without **/
26 /** specific, written prior permission. **/
27 /** **/
28 /** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/
29 /** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/
30 /** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/
31 /** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/
32 /** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/
33 /** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/
34 /** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/
35 /** OR PERFORMANCE OF THIS SOFTWARE. **/
36 /*****************************************************************************/
37 /***********************************************************************
38 *
39 * afterstep menu code
40 *
41 ***********************************************************************/
42
43 #include "../configure.h"
44
45 #include <stdio.h>
46 #include <signal.h>
47 #include <string.h>
48 #include <ctype.h>
49 #include <unistd.h>
50 #include <limits.h>
51
52 #include "afterstep.h"
53 #include "menus.h"
54 #include "misc.h"
55 #include "parse.h"
56 #include "screen.h"
57 #include "module.h"
58
59 #ifndef SHADE_ANIMATION_STEPS
60 #define SHADE_ANIMATION_STEPS 15
61 #endif
62
63 extern XEvent Event;
64 extern ASWindow *Tmp_win;
65 extern int menuFromFrameOrWindowOrTitlebar;
66 extern DoHandlePageing;
67
68 extern char **g_argv;
69
70 /***********************************************************************
71 *
72 * Procedure:
73 * ExecuteFunction - execute a afterstep built in function
74 *
75 * Inputs:
76 * func - the function to execute
77 * action - the menu action to execute
78 * w - the window to execute this function on
79 * tmp_win - the afterstep window structure
80 * event - the event that caused the function
81 * context - the context in which the button was pressed
82 * val1,val2 - the distances to move in a scroll operation
83 *
84 ***********************************************************************/
ExecuteFunction(int func,char * action,Window in_w,ASWindow * tmp_win,XEvent * eventp,unsigned long context,long val1,long val2,int val1_unit,int val2_unit,MenuRoot * menu,int Module)85 void ExecuteFunction(int func,char *action, Window in_w, ASWindow *tmp_win,
86 XEvent *eventp, unsigned long context,long val1,long val2,
87 int val1_unit, int val2_unit, MenuRoot *menu, int Module)
88 {
89 ASWindow *t,*temp,*tmp=NULL;
90 char *junk, *junkC;
91 unsigned long junkN;
92 int junkD;
93 int x,y;
94 Window w;
95 #ifndef NON_VIRTUAL
96 int delta_x,delta_y;
97 #endif
98 int warp_x=0,warp_y=0;
99 #ifndef NO_PAGER
100 Pixel TextColor,BackColor;
101 Pixmap BackPixmap;
102 #endif
103
104 /* Defer Execution may wish to alter this value */
105 w = in_w;
106
107 switch (func)
108 {
109 case F_NOP:
110 case F_TITLE:
111 break;
112
113 case F_BEEP:
114 XBell(dpy, Scr.screen);
115 break;
116
117 case F_RESIZE:
118 if (DeferExecution(eventp,&w,&tmp_win,&context, MOVE, ButtonPress))
119 break;
120
121 if(tmp_win == NULL)
122 break;
123 if(check_allowed_function2(func,tmp_win) == 0)
124 {
125 XBell(dpy, Scr.screen);
126 break;
127 }
128 tmp_win->flags &= ~MAXIMIZED;
129 resize_window(w,tmp_win,val1,val2,val1_unit,val2_unit);
130 break;
131
132 case F_MOVE:
133 if (DeferExecution(eventp,&w,&tmp_win,&context, MOVE,ButtonPress))
134 break;
135
136 if(tmp_win == NULL)
137 break;
138
139 move_window(eventp,w,tmp_win,context,val1,val2,val1_unit,val2_unit);
140 break;
141
142 #ifndef NON_VIRTUAL
143 case F_SCROLL:
144 if((val1 > -100000)&&(val1 < 100000))
145 x=Scr.Vx + val1*val1_unit/100;
146 else
147 x = Scr.Vx + (val1/1000)*val1_unit/100;
148
149 if((val2 > -100000)&&(val2 < 100000))
150 y=Scr.Vy + val2*val2_unit/100;
151 else
152 y = Scr.Vy + (val2/1000)*val2_unit/100;
153
154 if(((val1 <= -100000)||(val1 >= 100000))&&(x>Scr.VxMax))
155 {
156 x = 0;
157 y += Scr.MyDisplayHeight;
158 if(y > Scr.VyMax)
159 y=0;
160 }
161 if(((val1 <= -100000)||(val1 >= 100000))&&(x<0))
162 {
163 x = Scr.VxMax;
164 y -= Scr.MyDisplayHeight;
165 if(y < 0)
166 y=Scr.VyMax;
167 }
168 if(((val2 <= -100000)||(val2>= 100000))&&(y>Scr.VyMax))
169 {
170 y = 0;
171 x += Scr.MyDisplayWidth;
172 if(x > Scr.VxMax)
173 x=0;
174 }
175 if(((val2 <= -100000)||(val2>= 100000))&&(y<0))
176 {
177 y = Scr.VyMax;
178 x -= Scr.MyDisplayWidth;
179 if(x < 0)
180 x=Scr.VxMax;
181 }
182 MoveViewport(x,y,True);
183 break;
184 #endif
185 case F_MOVECURSOR:
186 XQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild,
187 &x,&y,&JunkX, &JunkY, &JunkMask);
188 #ifndef NON_VIRTUAL
189 delta_x = 0;
190 delta_y = 0;
191 warp_x = 0;
192 warp_y = 0;
193 if(x >= Scr.MyDisplayWidth -2)
194 {
195 delta_x = Scr.EdgeScrollX;
196 warp_x = Scr.EdgeScrollX - 4;
197 }
198 if(y>= Scr.MyDisplayHeight -2)
199 {
200 delta_y = Scr.EdgeScrollY;
201 warp_y = Scr.EdgeScrollY - 4;
202 }
203 if(x < 2)
204 {
205 delta_x = -Scr.EdgeScrollX;
206 warp_x = -Scr.EdgeScrollX + 4;
207 }
208 if(y < 2)
209 {
210 delta_y = -Scr.EdgeScrollY;
211 warp_y = -Scr.EdgeScrollY + 4;
212 }
213 if(Scr.Vx + delta_x < 0)
214 delta_x = -Scr.Vx;
215 if(Scr.Vy + delta_y < 0)
216 delta_y = -Scr.Vy;
217 if(Scr.Vx + delta_x > Scr.VxMax)
218 delta_x = Scr.VxMax - Scr.Vx;
219 if(Scr.Vy + delta_y > Scr.VyMax)
220 delta_y = Scr.VyMax - Scr.Vy;
221 if((delta_x!=0)||(delta_y!=0))
222 {
223 MoveViewport(Scr.Vx + delta_x,Scr.Vy+delta_y,True);
224 XWarpPointer(dpy, Scr.Root, Scr.Root, 0, 0, Scr.MyDisplayWidth,
225 Scr.MyDisplayHeight,
226 x - warp_x,
227 y - warp_y);
228 }
229 #endif
230 XWarpPointer(dpy, Scr.Root, Scr.Root, 0, 0, Scr.MyDisplayWidth,
231 Scr.MyDisplayHeight, x + val1*val1_unit/100-warp_x,
232 y+val2*val2_unit/100 - warp_y);
233
234 break;
235 case F_ICONIFY:
236 if (DeferExecution(eventp,&w,&tmp_win,&context, SELECT, ButtonRelease))
237 break;
238
239 if(tmp_win == NULL)
240 break;
241 if (tmp_win->flags & ICONIFIED)
242 {
243 if(val1 <=0)
244 DeIconify(tmp_win);
245 }
246 else
247 {
248 if(check_allowed_function2(func,tmp_win) == 0)
249 {
250 XBell(dpy, Scr.screen);
251 break;
252 }
253 if(val1 >=0)
254 {
255 if(check_allowed_function2(func,tmp_win) == 0)
256 {
257 XBell(dpy, Scr.screen);
258 break;
259 }
260 Iconify(tmp_win,eventp->xbutton.x_root-5,eventp->xbutton.y_root-5);
261 }
262 }
263 break;
264
265 case F_RAISE:
266 if (DeferExecution(eventp,&w,&tmp_win,&context, SELECT,ButtonRelease))
267 break;
268
269 if(tmp_win)
270 RaiseWindow(tmp_win);
271 break;
272
273 case F_PUTONTOP:
274 if (DeferExecution(eventp,&w,&tmp_win,&context, SELECT,ButtonRelease))
275 break;
276
277 if(tmp_win->flags & STAYSONTOP_FLAG)
278 tmp_win->flags &= ~STAYSONTOP_FLAG;
279 else
280 tmp_win->flags |= STAYSONTOP_FLAG;
281 /* put the window to its new place above or below ontop windows */
282 if(tmp_win)
283 RaiseWindow(tmp_win);
284 break;
285
286 case F_LOWER:
287 if (DeferExecution(eventp,&w,&tmp_win,&context, SELECT, ButtonRelease))
288 break;
289
290 if(tmp_win == NULL)
291 break;
292 LowerWindow(tmp_win);
293
294 tmp_win->flags &= ~ONTOP;
295 break;
296
297 case F_DESTROY:
298 if (DeferExecution(eventp,&w,&tmp_win,&context, DESTROY, ButtonRelease))
299 break;
300
301 if(tmp_win == NULL)
302 break;
303 if(check_allowed_function2(func,tmp_win) == 0)
304 {
305 XBell(dpy, Scr.screen);
306 break;
307 }
308 #ifndef NO_PAGER
309 /* Dont delete the pager - it crashes the program! */
310 if((tmp_win->w == Scr.Pager_w)||(tmp_win == Scr.ASPager))
311 break;
312 #endif
313
314 if (XGetGeometry(dpy, tmp_win->w, &JunkRoot, &JunkX, &JunkY,
315 &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth) == 0)
316 Destroy(tmp_win);
317 else
318 XKillClient(dpy, tmp_win->w);
319 XSync(dpy,0);
320 break;
321
322 case F_DELETE:
323 if (DeferExecution(eventp,&w,&tmp_win,&context, DESTROY,ButtonRelease))
324 break;
325
326 if(tmp_win == NULL)
327 break;
328 if(check_allowed_function2(func,tmp_win) == 0)
329 {
330 XBell(dpy, Scr.screen);
331 break;
332 }
333
334 #ifndef NO_PAGER
335 /* Dont delete the pager - it crashes the program! */
336 if((tmp_win->w == Scr.Pager_w)||(tmp_win == Scr.ASPager))
337 break;
338 #endif
339 if (tmp_win->flags & DoesWmDeleteWindow)
340 {
341 send_clientmessage (tmp_win->w, _XA_WM_DELETE_WINDOW, CurrentTime);
342 break;
343 }
344 else
345 XBell (dpy, Scr.screen);
346 XSync(dpy,0);
347 break;
348
349 case F_CLOSE:
350 if (DeferExecution(eventp,&w,&tmp_win,&context, DESTROY,ButtonRelease))
351 break;
352
353 if(tmp_win == NULL)
354 break;
355 if(check_allowed_function2(func,tmp_win) == 0)
356 {
357 XBell(dpy, Scr.screen);
358 break;
359 }
360
361 #ifndef NO_PAGER
362 /* Dont delete the pager - it crashes the program! */
363 if((tmp_win->w == Scr.Pager_w)||(tmp_win == Scr.ASPager))
364 break;
365 #endif
366 if (tmp_win->flags & DoesWmDeleteWindow)
367 {
368 send_clientmessage (tmp_win->w, _XA_WM_DELETE_WINDOW, CurrentTime);
369 break;
370 }
371 else if (XGetGeometry(dpy, tmp_win->w, &JunkRoot, &JunkX, &JunkY,
372 &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth) == 0)
373 Destroy(tmp_win);
374 else
375 XKillClient(dpy, tmp_win->w);
376 XSync(dpy,0);
377 break;
378
379 case F_RESTART:
380 ClosePipes();
381 ResetShade(tmp);
382 Done(1, action);
383 break;
384
385 case F_EXEC:
386 XGrabPointer(dpy, Scr.Root, True,
387 ButtonPressMask | ButtonReleaseMask,
388 GrabModeAsync, GrabModeAsync,
389 Scr.Root, Scr.ASCursors[WAIT], CurrentTime);
390 XSync (dpy,0);
391
392 if (!(fork())) /* child process */
393 if (execl("/bin/sh", "/bin/sh", "-c", action, (char *)0)==-1)
394 exit(100);
395 XUngrabPointer(dpy,CurrentTime);
396 XSync (dpy,0);
397 break;
398
399 case F_REFRESH:
400 {
401 XSetWindowAttributes attributes;
402 unsigned long valuemask;
403
404 valuemask = (CWBackPixel);
405 attributes.background_pixel = Scr.StdColors.fore;
406 attributes.backing_store = NotUseful;
407 w = XCreateWindow (dpy, Scr.Root, 0, 0,
408 (unsigned int) Scr.MyDisplayWidth,
409 (unsigned int) Scr.MyDisplayHeight,
410 (unsigned int) 0,
411 CopyFromParent, (unsigned int) CopyFromParent,
412 (Visual *) CopyFromParent, valuemask,
413 &attributes);
414 XMapWindow (dpy, w);
415 XDestroyWindow (dpy, w);
416 XFlush (dpy);
417 }
418 break;
419
420 case F_STICK:
421 /* stick/unstick a window */
422 if (DeferExecution(eventp,&w,&tmp_win,&context,SELECT,ButtonRelease))
423 break;
424
425 if(tmp_win == NULL)
426 break;
427
428 if(tmp_win->flags & STICKY)
429 {
430 tmp_win->flags &= ~STICKY;
431 if(tmp_win->BackPixel == Scr.StickyColors.back)
432 {
433 tmp_win->ReliefPixel = Scr.StdRelief.fore;
434 tmp_win->ShadowPixel = Scr.StdRelief.back;
435 tmp_win->BackPixel = Scr.StdColors.back;
436 }
437 if(tmp_win->TextPixel == Scr.StickyColors.fore)
438 tmp_win->TextPixel = Scr.StdColors.fore;
439 }
440 else
441 {
442 tmp_win->flags |=STICKY;
443 if(tmp_win->BackPixel == Scr.StdColors.back)
444 {
445 tmp_win->BackPixel = Scr.StickyColors.back;
446 tmp_win->ShadowPixel = Scr.StickyRelief.back;
447 tmp_win->ReliefPixel = Scr.StickyRelief.fore;
448 }
449 if(tmp_win->TextPixel == Scr.StdColors.fore)
450 tmp_win->TextPixel = Scr.StickyColors.fore;
451 }
452 if(Scr.Hilite != tmp_win)
453 {
454 /* Need to make SetBorder change the window back color */
455 temp=Scr.Hilite;
456 SetBorder(tmp_win,True,True,True,None);
457 SetBorder(tmp_win,False,True,True,None);
458 SetBorder(temp,True,True,True,None);
459 }
460 BroadcastConfig(M_CONFIGURE_WINDOW,tmp_win);
461 #ifndef NO_PAGER
462 MoveResizePagerView(tmp_win);
463
464 /* Need to re-draw pager_view in case the window
465 * is unsticking */
466 if(Scr.Hilite == tmp_win)
467 {
468 TextColor = Scr.HiColors.fore;
469 BackPixmap= Scr.gray_pixmap;
470 BackColor = Scr.HiColors.back;
471 }
472 else
473 {
474 TextColor = Scr.StdColors.fore;
475 BackPixmap = Scr.light_gray_pixmap;
476 BackColor = Scr.StdColors.back;
477 }
478 if(Scr.d_depth < 2)
479 XSetWindowBackgroundPixmap(dpy,tmp_win->pager_view,BackPixmap);
480 else
481 XSetWindowBackground(dpy,tmp_win->pager_view,BackColor);
482 XClearWindow(dpy,tmp_win->pager_view);
483 if((tmp_win->icon_name != NULL)&&(Scr.PagerFont.height > 0))
484 {
485 NewFontAndColor(Scr.PagerFont.font->fid,TextColor,BackColor);
486 XDrawString (dpy, tmp_win->pager_view,Scr.FontGC,2,Scr.PagerFont.y+2,
487 tmp_win->icon_name, strlen(tmp_win->icon_name));
488 }
489 #endif
490 break;
491
492 #ifndef NON_VIRTUAL
493 case F_GOTO_PAGE:
494 /* back up 1 virtual desktop page */
495 x=val1*Scr.MyDisplayWidth;
496 y=val2*Scr.MyDisplayHeight;
497 MoveViewport(x,y,True);
498 break;
499 #endif
500 #ifndef NON_VIRTUAL
501 case F_TOGGLE_PAGE:
502 if (DoHandlePageing)
503 {
504 DoHandlePageing = 0;
505 Broadcast(M_TOGGLE_PAGING,1,0,0,0,0,0,0,0);
506 }
507 else
508 {
509 DoHandlePageing = 1;
510 Broadcast(M_TOGGLE_PAGING,1,1,0,0,0,0,0,0);
511 }
512 checkPanFrames();
513 break;
514 #endif
515
516 case F_CIRCULATE_UP:
517 t=Circulate(tmp_win,action,UP);
518 if(t)FocusOn(t,0,True);
519 break;
520
521 case F_CIRCULATE_DOWN:
522 t=Circulate(tmp_win,action,DOWN);
523 if(t)FocusOn(t,0,True);
524 break;
525
526 case F_WARP:
527 t=Circulate(tmp_win,action,DOWN);
528 if((t)&&(t->flags & ICONIFIED))
529 {
530 FocusOn(t,0,False);
531 DeIconify(t);
532 }
533 if(t)FocusOn(t,0,True);
534 break;
535
536 case F_WAIT:
537 {
538 Bool done = False;
539 if(val1 == 0)
540 val1 = 1;
541 while(!done)
542 {
543 if(My_XNextEvent(dpy, &Event))
544 {
545 DispatchEvent ();
546 if(Event.type == MapNotify)
547 {
548 if((Tmp_win)&&(matchWildcards(action,Tmp_win->name)==True))
549 done = True;
550 if((Tmp_win)&&(Tmp_win->class.res_class)&&
551 (matchWildcards(action,Tmp_win->class.res_class)==True))
552 done = True;
553 if((Tmp_win)&&(Tmp_win->class.res_name)&&
554 (matchWildcards(action,Tmp_win->class.res_name)==True))
555 done = True;
556 }
557 }
558 }
559 }
560 XSync(dpy,0);
561 break;
562 case F_RAISE_IT:
563 if(val1 != 0)
564 {
565 FocusOn((ASWindow *)val1,0,False);
566 if (((ASWindow *)(val1))->flags & ICONIFIED)
567 {
568 DeIconify((ASWindow *)val1);
569 FocusOn((ASWindow *)val1,0,False);
570 }
571 }
572
573 break;
574 case F_FOCUS:
575 if (DeferExecution(eventp,&w,&tmp_win,&context,SELECT,ButtonRelease))
576 break;
577 FocusOn(tmp_win,0,False);
578 break;
579
580 case F_CHANGE_WINDOWS_DESK:
581 if (DeferExecution(eventp,&w,&tmp_win,&context,SELECT,ButtonRelease))
582 break;
583 if(tmp_win == NULL)
584 break;
585
586 changeWindowsDesk(tmp_win,val1);
587 break;
588 case F_DESK:
589 changeDesks(val1,val2);
590 break;
591 case F_MODULE:
592 if(eventp->type != KeyPress)
593 UngrabEm();
594 if(tmp_win)
595 executeModule(action, (FILE *)NULL,(char **)tmp_win->w,(int *)context);
596 else
597 executeModule(action, (FILE *)NULL,(char **)0, (int *)context);
598 /* If we execute a module, don't wait for buttons to come up,
599 * that way, a pop-up menu could be implemented */
600 Module = 0;
601 break;
602
603 case F_RAISELOWER:
604 if (DeferExecution(eventp,&w,&tmp_win,&context, SELECT,ButtonRelease))
605 break;
606 if(tmp_win == NULL)
607 break;
608
609 if(tmp_win->flags & VISIBLE) /*|| (tmp_win->flags & MAXIMIZED)) fsf */
610 {
611 tmp_win->flags &= ~ONTOP;
612 LowerWindow(tmp_win);
613 }
614 else
615 {
616 RaiseWindow(tmp_win);
617 }
618 break;
619
620 case F_POPUP:
621 ActiveItem = NULL;
622 ActiveMenu = NULL;
623 menuFromFrameOrWindowOrTitlebar = FALSE;
624 do_menu(menu);
625 break;
626
627 case F_MAXIMIZE:
628 if (DeferExecution(eventp,&w,&tmp_win,&context, SELECT,ButtonRelease))
629 break;
630 if(tmp_win == NULL)
631 break;
632
633 if(check_allowed_function2(func,tmp_win) == 0)
634 {
635 XBell(dpy, Scr.screen);
636 break;
637 }
638 Maximize(tmp_win,val1,val2,val1_unit,val2_unit);
639 break;
640
641 case F_SHADE:
642 if (DeferExecution(eventp,&w,&tmp_win,&context, SELECT,ButtonRelease))
643 break;
644 if(tmp_win == NULL)
645 break;
646
647 if(check_allowed_function2(func,tmp_win) == 0)
648 {
649 XBell(dpy, Scr.screen);
650 break;
651 }
652 Shade(tmp_win);
653 break;
654
655 case F_QUIT:
656 Done(0, NULL);
657 break;
658
659 case F_WINDOWLIST:
660 do_windowList(val1,val2);
661 break;
662
663 case F_FUNCTION:
664 ComplexFunction(w, tmp_win, eventp, context,menu);
665 break;
666
667 case F_QUICKIE:
668 QuickRestart();
669 break;
670 case F_SEND_WINDOW_LIST:
671 if(Module >= 0)
672 {
673 SendPacket(Module,M_TOGGLE_PAGING,1,DoHandlePageing,0,0,0,0,0,0);
674 SendPacket(Module,M_NEW_DESK,1,Scr.CurrentDesk,0,0,0,0,0,0);
675 SendPacket(Module,M_NEW_PAGE,3,Scr.Vx,Scr.Vy,Scr.CurrentDesk,
676 0,0,0,0);
677 /* if(Scr.Hilite != NULL)
678 SendPacket(Module,M_FOCUS_CHANGE,3,Scr.Hilite->w,Scr.Hilite->frame,
679 (unsigned long)Scr.Hilite,0,0,0,0);
680 else
681 SendPacket(Module,M_FOCUS_CHANGE,3,0,0,0,0,0,0,0);
682 */
683 for (t = Scr.ASRoot.next; t != NULL; t = t->next)
684 {
685 SendConfig(Module,M_CONFIGURE_WINDOW,t);
686 SendName(Module,M_WINDOW_NAME,t->w,t->frame,
687 (unsigned long)t,t->name);
688 SendName(Module,M_ICON_NAME,t->w,t->frame,
689 (unsigned long)t,t->icon_name);
690 SendName(Module,M_RES_CLASS,t->w,t->frame,
691 (unsigned long)t,t->class.res_class);
692 SendName(Module,M_RES_NAME,t->w,t->frame,
693 (unsigned long)t,t->class.res_name);
694
695 if((t->flags & ICONIFIED)&&(!(t->flags & ICON_UNMAPPED)))
696 SendPacket(Module,M_ICONIFY,7,t->w,t->frame,
697 (unsigned long)t,
698 t->icon_x_loc,t->icon_y_loc,
699 t->icon_p_width,
700 t->icon_p_height);
701 if((t->flags & ICONIFIED) && (t->flags & ICON_UNMAPPED))
702 SendPacket(Module,M_ICONIFY,7,t->w,t->frame,
703 (unsigned long)t,0,0,0,0);
704 }
705 /* if(Scr.Hilite == NULL)
706 {
707 Broadcast(M_FOCUS_CHANGE,3,0,0,0,0,0,0,0);
708 }
709 else
710 {
711 Broadcast(M_FOCUS_CHANGE,3,Scr.Hilite->w,
712 Scr.Hilite->frame,(unsigned long)Scr.Hilite,0,0,0,0);
713 }
714 */
715 SendPacket(Module,M_END_WINDOWLIST,0,0,0,0,0,0,0,0);
716 }
717 }
718
719 /* Only wait for an all-buttons-up condition after calls from
720 * regular built-ins, not from complex-functions or modules. */
721 if(Module == -1)
722 WaitForButtonsUp();
723
724 return;
725 }
726
Circulate(ASWindow * tmp_win,char * action,Bool Direction)727 ASWindow *Circulate(ASWindow *tmp_win, char *action,Bool Direction)
728 {
729 ASWindow *t,*selected;
730 long best, worst, high;
731
732 if (action && (*action == '\0')) action = NULL;
733
734 best = LONG_MIN;
735 for (t = Scr.ASRoot.next; t != NULL; t = t->next)
736 {
737 if ((t->circulate_sequence > best)
738 && (t->Desk == Scr.CurrentDesk)
739 && ! (t->flags & CIRCULATESKIP)
740 && (!(Scr.flags & CirculateSkipIcons) || !(t->flags & ICONIFIED))
741 && (t->flags & BORDER))
742 {
743 best = t->circulate_sequence;
744 tmp_win = t;
745 }
746 }
747 if (tmp_win == NULL) return NULL;
748
749 if (Direction == DOWN)
750 {
751 best = high = LONG_MAX; /* down: find smallest circulate_sequence */
752 worst = LONG_MIN;
753 }
754 else
755 {
756 best = high = LONG_MIN; /* up: find largest circulate_sequence */
757 worst = LONG_MAX;
758 tmp_win->circulate_sequence = LONG_MIN; /* but ignore current */
759 }
760 selected = tmp_win;
761 for (t = Scr.ASRoot.next; t != NULL; t = t->next)
762 {
763 if (Direction == DOWN)
764 {
765 if (t->circulate_sequence > worst) worst = t->circulate_sequence;
766 if (t->circulate_sequence >= best) continue;
767 }
768 else
769 {
770 if ((t != tmp_win) && (t->circulate_sequence < worst))
771 worst = t->circulate_sequence;
772 if (t->circulate_sequence <= best) continue;
773 }
774 high = t->circulate_sequence;
775
776 if ((t->Desk != Scr.CurrentDesk) || (t->flags & CIRCULATESKIP)) continue;
777
778 /* optional skip over icons */
779 if ((t->flags & ICONIFIED) && (Scr.flags & CirculateSkipIcons)) continue;
780 if ( !(t->flags & BORDER)) continue;
781
782 /* Make CirculateUp and CirculateDown take args. by Y.NOMURA */
783 if (action && !matchWildcards(action, t->name)
784 && !matchWildcards(action, t->icon_name) && t->class.res_name
785 && !matchWildcards(action, t->class.res_name)) continue;
786
787 best = t->circulate_sequence;
788 selected = t;
789 }
790 if(Direction == DOWN)
791 selected->circulate_sequence = worst + 1;
792 else
793 {
794 tmp_win->circulate_sequence = worst - 1;
795 selected->circulate_sequence = high + 1;
796 }
797
798 return selected;
799 }
800
801
802 /***********************************************************************
803 *
804 * Procedure:
805 * DeferExecution - defer the execution of a function to the
806 * next button press if the context is C_ROOT
807 *
808 * Inputs:
809 * eventp - pointer to XEvent to patch up
810 * w - pointer to Window to patch up
811 * tmp_win - pointer to ASWindow Structure to patch up
812 * context - the context in which the mouse button was pressed
813 * func - the function to defer
814 * cursor - the cursor to display while waiting
815 * finishEvent - ButtonRelease or ButtonPress; tells what kind of event to
816 * terminate on.
817 *
818 ***********************************************************************/
DeferExecution(XEvent * eventp,Window * w,ASWindow ** tmp_win,unsigned long * context,int cursor,int FinishEvent)819 int DeferExecution(XEvent *eventp, Window *w,ASWindow **tmp_win,
820 unsigned long *context, int cursor, int FinishEvent)
821
822 {
823 int done;
824 int finished = 0;
825 Window dummy;
826 Window original_w;
827
828 original_w = *w;
829
830 if((*context != C_ROOT)&&(*context != C_NO_CONTEXT))
831 {
832 if((FinishEvent == ButtonPress)||((FinishEvent == ButtonRelease) &&
833 (eventp->type != ButtonPress)))
834 {
835 return FALSE;
836 }
837 }
838 if(!GrabEm(cursor))
839 {
840 XBell(dpy,Scr.screen);
841 return True;
842 }
843
844 while (!finished)
845 {
846 done = 0;
847 /* block until there is an event */
848 XMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask |
849 ExposureMask | KeyPressMask |
850 ButtonMotionMask| PointerMotionMask/* | EnterWindowMask |
851 LeaveWindowMask*/, eventp);
852 StashEventTime(eventp);
853
854 if(eventp->type == KeyPress)
855 Keyboard_shortcuts(eventp,FinishEvent);
856 if(eventp->type == FinishEvent)
857 finished = 1;
858 if(eventp->type == ButtonPress)
859 {
860 XAllowEvents(dpy,ReplayPointer,CurrentTime);
861 done = 1;
862 }
863 if(eventp->type == ButtonRelease)
864 done = 1;
865 if(eventp->type == KeyPress)
866 done = 1;
867
868 if(!done)
869 {
870 DispatchEvent();
871 }
872 }
873
874 *w = eventp->xany.window;
875 if(((*w == Scr.Root)||(*w == Scr.NoFocusWin))
876 && (eventp->xbutton.subwindow != (Window)0))
877 {
878 *w = eventp->xbutton.subwindow;
879 eventp->xany.window = *w;
880 }
881 if (*w == Scr.Root)
882 {
883 *context = C_ROOT;
884 XBell(dpy,Scr.screen);
885 UngrabEm();
886 return TRUE;
887 }
888 if (XFindContext (dpy, *w, ASContext, (caddr_t *)tmp_win) == XCNOENT)
889 {
890 *tmp_win = NULL;
891 XBell(dpy,Scr.screen);
892 UngrabEm();
893 return (TRUE);
894 }
895
896 if(*w == (*tmp_win)->Parent)
897 *w = (*tmp_win)->w;
898
899 if(original_w == (*tmp_win)->Parent)
900 original_w = (*tmp_win)->w;
901
902 /* this ugly mess attempts to ensure that the release and press
903 * are in the same window. */
904 /* the windows are considered the same if any one of these is found true:
905 - the window IDs are identical
906 - the original window is Scr.Root, None, or NoFocusWin
907 - the original window is the client window and the current window
908 is the frame window
909 */
910 /* if ((*w != original_w) && (original_w != Scr.Root) &&
911 (original_w != None) && (original_w != Scr.NoFocusWin) &&
912 (*w != (*tmp_win)->frame) && (original_w != (*tmp_win)->w))
913 {
914 *context = C_ROOT;
915 XBell(dpy,Scr.screen);
916 UngrabEm();
917 return TRUE;
918 }
919 */
920 *context = GetContext(*tmp_win,eventp,&dummy);
921
922 UngrabEm();
923 return FALSE;
924 }
925
926
927 /****************************************************************************
928 *
929 * This is used to tell applications which windows on the screen are
930 * top level appication windows, and which windows are the icon windows
931 * that go with them.
932 *
933 ****************************************************************************/
SetMapStateProp(ASWindow * tmp_win,int state)934 void SetMapStateProp(ASWindow *tmp_win, int state)
935 {
936 unsigned long data[2]; /* "suggested" by ICCCM version 1 */
937
938 data[0] = (unsigned long) state;
939 data[1] = (unsigned long) tmp_win->icon_pixmap_w;
940
941 XChangeProperty (dpy, tmp_win->w, _XA_WM_STATE, _XA_WM_STATE, 32,
942 PropModeReplace, (unsigned char *) data, 2);
943 return;
944 }
945
946
947 /***************************************************************************
948 *
949 * Moves the viewport within thwe virtual desktop
950 *
951 ***************************************************************************/
952 #ifndef NON_VIRTUAL
MoveViewport(int newx,int newy,Bool grab)953 void MoveViewport(int newx, int newy, Bool grab)
954 {
955 ASWindow *t;
956 int deltax,deltay;
957
958 if(grab)
959 XGrabServer(dpy);
960
961
962 if(newx > Scr.VxMax)
963 newx = Scr.VxMax;
964 if(newy > Scr.VyMax)
965 newy = Scr.VyMax;
966 if(newx <0)
967 newx = 0;
968 if(newy <0)
969 newy = 0;
970
971 deltay = Scr.Vy - newy;
972 deltax = Scr.Vx - newx;
973
974 Scr.Vx = newx;
975 Scr.Vy = newy;
976 Broadcast(M_NEW_PAGE,3,Scr.Vx,Scr.Vy,Scr.CurrentDesk,0,0,0,0);
977
978 if((deltax!=0)||(deltay!=0))
979 {
980 for (t = Scr.ASRoot.next; t != NULL; t = t->next)
981 {
982 /* If the window is iconified, and sticky Icons is set,
983 * then the window should essentially be sticky */
984 if(!((t->flags & ICONIFIED)&&(Scr.flags & StickyIcons)) &&
985 (!(t->flags & STICKY)))
986 {
987 if(!(Scr.flags & StickyIcons))
988 {
989 t->icon_x_loc += deltax;
990 t->icon_y_loc += deltay;
991 if(t->icon_pixmap_w != None)
992 XMoveWindow(dpy,t->icon_pixmap_w,t->icon_x_loc,
993 t->icon_y_loc);
994 if(!(t->flags &ICON_UNMAPPED))
995 Broadcast(M_ICON_LOCATION,7,t->w,t->frame,
996 (unsigned long)t,
997 t->icon_x_loc,t->icon_y_loc,
998 t->icon_p_width,
999 t->icon_p_height);
1000 }
1001 }
1002 if(!(t->flags & STICKY))
1003 SetupFrame (t, t->frame_x+ deltax, t->frame_y + deltay,
1004 t->frame_width, t->frame_height,FALSE);
1005 }
1006 for (t = Scr.ASRoot.next; t != NULL; t = t->next)
1007 {
1008 /* If its an icon, and its sticking, autoplace it so
1009 * that it doesn't wind up on top a a stationary
1010 * icon */
1011 if(((t->flags & STICKY)||(Scr.flags & StickyIcons))&&
1012 (t->flags & ICONIFIED)&&(!(t->flags & ICON_MOVED))&&
1013 (!(t->flags & ICON_UNMAPPED)))
1014 AutoPlace(t);
1015 }
1016
1017 }
1018 /* fix up the viewport indicator */
1019 MoveResizeViewPortIndicator();
1020 #ifndef NON_VIRTUAL
1021 checkPanFrames();
1022
1023 /* do this with PanFrames too ??? HEDU */
1024 while(XCheckTypedEvent(dpy,MotionNotify,&Event))
1025 StashEventTime(&Event);
1026 #endif
1027 UpdateVisibility();
1028 if(grab)
1029 XUngrabServer(dpy);
1030 }
1031 #endif
1032
1033
1034 /**************************************************************************
1035 *
1036 * Moves focus to specified window
1037 *
1038 *************************************************************************/
FocusOn(ASWindow * t,int DeIconifyOnly,Bool circulating)1039 void FocusOn(ASWindow *t,int DeIconifyOnly, Bool circulating)
1040 {
1041 #ifndef NON_VIRTUAL
1042 int dx,dy;
1043 int cx,cy;
1044 #endif
1045 int x,y;
1046
1047 if(t == (ASWindow *)0)
1048 return;
1049
1050 if(t->Desk != Scr.CurrentDesk)
1051 {
1052 changeDesks(0,t->Desk);
1053 }
1054
1055 #ifndef NON_VIRTUAL
1056 if(t->flags & ICONIFIED)
1057 {
1058 cx = t->icon_x_loc + t->icon_p_width/2;
1059 cy = t->icon_y_loc + t->icon_p_height/2;
1060 }
1061 else
1062 {
1063 cx = t->frame_x + t->frame_width/2;
1064 cy = t->frame_y + t->frame_height/2;
1065 }
1066
1067 /* Put center of window on the visible screen */
1068 if((!DeIconifyOnly)&&(Scr.flags & CenterOnCirculate))
1069 {
1070 dx = cx - Scr.MyDisplayWidth/2 + Scr.Vx;
1071 dy = cy - Scr.MyDisplayHeight/2 + Scr.Vy;
1072 }
1073 else
1074 {
1075 dx = (cx + Scr.Vx)/Scr.MyDisplayWidth*Scr.MyDisplayWidth;
1076 dy = (cy +Scr.Vy)/Scr.MyDisplayHeight*Scr.MyDisplayHeight;
1077 }
1078 MoveViewport(dx,dy,True);
1079 #endif
1080
1081 if(t->flags & ICONIFIED)
1082 {
1083 x = t->icon_x_loc + t->icon_p_width/2;
1084 y = t->icon_y_loc + t->icon_p_height/2;
1085 }
1086 else
1087 {
1088 x = t->frame_x;
1089 y = t->frame_y;
1090 }
1091 if(!(Scr.flags & ClickToFocus))
1092 XWarpPointer(dpy, None, Scr.Root, 0, 0, 0, 0, x+2,y+2);
1093 RaiseWindow(t);
1094
1095 /* If the window is still not visible, make it visible! */
1096 if(((t->frame_x + t->frame_width)< 0)||(t->frame_y + t->frame_height < 0)||
1097 (t->frame_x >Scr.MyDisplayWidth)||(t->frame_y>Scr.MyDisplayHeight))
1098 {
1099 SetupFrame(t,0,0,t->frame_width, t->frame_height,False);
1100 if(!(Scr.flags & ClickToFocus))
1101 XWarpPointer(dpy, None, Scr.Root, 0, 0, 0, 0, 2,2);
1102 }
1103 UngrabEm();
1104 SetFocus(t->w,t,circulating);
1105 }
1106
1107
1108
1109 /***********************************************************************
1110 *
1111 * Procedure:
1112 * (Un)Maximize a window.
1113 *
1114 ***********************************************************************/
Maximize(ASWindow * tmp_win,int val1,int val2,int val1_unit,int val2_unit)1115 void Maximize(ASWindow *tmp_win,int val1,int val2,
1116 int val1_unit,int val2_unit)
1117 {
1118 int new_width, new_height,new_x,new_y;
1119
1120 if (tmp_win->flags & MAXIMIZED)
1121 {
1122 tmp_win->flags &= ~MAXIMIZED;
1123 SetupFrame(tmp_win, tmp_win->orig_x, tmp_win->orig_y, tmp_win->orig_wd,
1124 tmp_win->orig_ht,TRUE);
1125 SetBorder(tmp_win,True,True,True,None);
1126 }
1127 else
1128 {
1129 new_width = tmp_win->frame_width;
1130 new_height = tmp_win->frame_height;
1131 new_x = tmp_win->frame_x;
1132 new_y = tmp_win->frame_y;
1133 if(val1 >0)
1134 {
1135 new_width = val1*val1_unit/100-2;
1136 new_x = 0;
1137 }
1138 if(val2 >0)
1139 {
1140 new_height = val2*val2_unit/100-2;
1141 new_y = 0;
1142 }
1143 if((val1==0)&&(val2==0))
1144 {
1145 new_x = 0;
1146 new_y = 0;
1147 new_height = Scr.MyDisplayHeight-2;
1148 new_width = Scr.MyDisplayWidth-2;
1149 }
1150 tmp_win->flags |= MAXIMIZED;
1151 ConstrainSize (tmp_win, &new_width, &new_height);
1152 SetupFrame(tmp_win,new_x,new_y,new_width,new_height,TRUE);
1153 SetBorder(tmp_win,True,True,True,tmp_win->right_w[0]);
1154 }
1155 #ifndef NO_PAGER
1156 RedrawPager();
1157 #endif
1158 UpdateVisibility();
1159 /* UpdateVisibility(); */
1160 }
1161
1162 /***********************************************************************
1163 *
1164 * Procedure:
1165 * (Un)Shade a window.
1166 *
1167 ***********************************************************************/
1168 #ifdef notdef
Shade(ASWindow * tmp_win)1169 void Shade(ASWindow *tmp_win)
1170 {
1171 int new_width, new_height;
1172
1173 if ( tmp_win == NULL )
1174 return;
1175
1176 if (tmp_win->wmhints)
1177 tmp_win->wmhints->flags |= StateHint;
1178
1179 if ((tmp_win->wmhints && tmp_win->wmhints->initial_state == ZoomState)
1180 || (!tmp_win->wmhints && (tmp_win->flags & MAXIMIZED)))
1181 {
1182 tmp_win->flags &= ~MAXIMIZED;
1183 if (tmp_win->wmhints)
1184 tmp_win->wmhints->initial_state = NormalState;
1185 SetupFrame(tmp_win, tmp_win->frame_x, tmp_win->frame_y, tmp_win->orig_wd,
1186 tmp_win->orig_ht,TRUE);
1187 SetBorder(tmp_win,True,True,True,None);
1188 Broadcast(M_UNSHADE,3,tmp_win->w,tmp_win->frame,(unsigned long)tmp_win,
1189 0,0,0,0);
1190 }
1191 else
1192 {
1193 new_width = tmp_win->frame_width;
1194 new_height = 21;
1195 tmp_win->flags |= MAXIMIZED;
1196 if (tmp_win->wmhints)
1197 tmp_win->wmhints->initial_state = ZoomState;
1198
1199 SetupFrame(tmp_win,tmp_win->frame_x,tmp_win->frame_y,new_width,
1200 new_height,TRUE);
1201 Broadcast(M_SHADE,3,tmp_win->w,tmp_win->frame,(unsigned long)tmp_win,
1202 0,0,0,0);
1203 }
1204 #ifndef NO_PAGER
1205 RedrawPager();
1206 #endif
1207 }
1208 #endif /* notdef */
1209
Shade(ASWindow * tmp_win)1210 void Shade(ASWindow *tmp_win)
1211 {
1212 int new_width, new_height;
1213 XWindowAttributes winattrs;
1214 unsigned long eventMask;
1215 #ifdef SHADE_ANIMATION
1216 int y, s, w, h;
1217 #endif
1218
1219
1220 if ( tmp_win == NULL )
1221 return;
1222
1223 if (tmp_win->flags & SHADED)
1224 {
1225 /* unshade window */
1226 tmp_win->flags |= MAPPED;
1227 XMapWindow(dpy, tmp_win->w);
1228 SetMapStateProp(tmp_win, NormalState);
1229 #ifdef SHADE_ANIMATION
1230 /* do the shading animation */
1231 XMoveWindow(dpy, tmp_win->title_height, 0, -(tmp_win->frame_height-
1232 tmp_win->title_height));
1233 h = tmp_win->title_height;
1234 y = tmp_win->frame_height;
1235 s = y/SHADE_ANIMATION_STEPS;
1236 w = tmp_win->frame_width;
1237 y = -(tmp_win->frame_height-tmp_win->title_height);
1238 while (h<tmp_win->frame_height-tmp_win->title_height) {
1239 XResizeWindow(dpy, tmp_win->frame, w, h);
1240 XMoveWindow(dpy, tmp_win->w, 0, y);
1241 XSync(dpy, 0);
1242 h+=s;
1243 y+=s;
1244 }
1245 XMoveWindow(dpy, tmp_win->w, 0, 0);
1246 #endif /* SHADE_ANIMATION */
1247 XResizeWindow(dpy, tmp_win->frame, tmp_win->frame_width,
1248 tmp_win->frame_height);
1249 if((Scr.flags & StubbornIcons)||(Scr.flags & ClickToFocus))
1250 FocusOn(tmp_win,1,True);
1251 tmp_win->flags &= ~SHADED;
1252 Broadcast(M_UNSHADE,3,tmp_win->w,tmp_win->frame,(unsigned long)tmp_win,
1253 0,0,0,0);
1254 }
1255 else
1256 {
1257 tmp_win->flags |= SHADED;
1258
1259 /* can't shade a window with no titlebar */
1260 if ((!tmp_win->flags) & TITLE) return;
1261
1262 #ifdef SHADE_ANIMATION
1263 XLowerWindow(dpy, tmp_win->w);
1264 h = tmp_win->frame_height;
1265 s = h/SHADE_ANIMATION_STEPS;
1266 w = tmp_win->frame_width;
1267 y = tmp_win->title_height;
1268
1269 while (h>tmp_win->title_height) {
1270 XMoveWindow(dpy, tmp_win->w, 0, y);
1271 XResizeWindow(dpy, tmp_win->frame, w, h);
1272 XSync(dpy, 0);
1273 h-=s;
1274 y-=s;
1275 }
1276 XMoveWindow(dpy, tmp_win->w, 0, 0);
1277 #endif /* SHADE_ANIMATION */
1278 XResizeWindow(dpy, tmp_win->frame, tmp_win->frame_width,
1279 tmp_win->title_height);
1280 XGetWindowAttributes(dpy, tmp_win->w, &winattrs);
1281 eventMask = winattrs.your_event_mask;
1282
1283 /*
1284 * Prevent the receipt of an UnmapNotify, since that would
1285 * cause a transition to the Withdrawn state.
1286 */
1287 tmp_win->flags &= ~MAPPED;
1288 XSelectInput(dpy, tmp_win->w, eventMask & ~StructureNotifyMask);
1289 XUnmapWindow(dpy, tmp_win->w);
1290 XSelectInput(dpy, tmp_win->w, eventMask);
1291
1292 SetMapStateProp(tmp_win, IconicState);
1293 Broadcast(M_SHADE,3,tmp_win->w,tmp_win->frame,(unsigned long)tmp_win,
1294 0,0,0,0);
1295 }
1296 #ifndef NO_PAGER
1297 RedrawPager();
1298 #endif
1299 UpdateVisibility();
1300
1301 }
1302
1303
1304
1305 /****************************************************************************
1306 *
1307 * Reset Shaded Windows on restart
1308 * Trying to fix a problem with afterstep crashing on some systems during
1309 * restart.
1310 *
1311 ***************************************************************************/
ResetShade(ASWindow * tw)1312 void ResetShade(ASWindow *tw)
1313 {
1314 for (tw = Scr.ASRoot.next; tw != NULL; tw = tw->next)
1315 {
1316 /* if(tw->flags & MAXIMIZED && tw->wmhints && tw->wmhints->initial_state == ZoomState) */
1317 if (tw->flags & SHADED && tw->wmhints && tw->wmhints->initial_state == ZoomState)
1318 {
1319 Shade(tw);
1320 }
1321 }
1322 }
1323
1324
1325 /*****************************************************************************
1326 *
1327 * Grab the pointer and keyboard
1328 *
1329 ****************************************************************************/
GrabEm(int cursor)1330 Bool GrabEm(int cursor)
1331 {
1332 int i=0,val=0;
1333 unsigned int mask;
1334
1335 XSync(dpy,0);
1336 /* move the keyboard focus prior to grabbing the pointer to
1337 * eliminate the enterNotify and exitNotify events that go
1338 * to the windows */
1339 if(Scr.PreviousFocus == NULL)
1340 Scr.PreviousFocus = Scr.Focus;
1341 SetFocus(Scr.NoFocusWin,NULL,False);
1342 mask = ButtonPressMask|ButtonReleaseMask|ButtonMotionMask|PointerMotionMask
1343 | EnterWindowMask | LeaveWindowMask;
1344 while((i<1000)&&(val=XGrabPointer(dpy, Scr.Root, True, mask,
1345 GrabModeAsync, GrabModeAsync, Scr.Root,
1346 Scr.ASCursors[cursor], CurrentTime)!=
1347 GrabSuccess))
1348 {
1349 i++;
1350 /* If you go too fast, other windows may not get a change to release
1351 * any grab that they have. */
1352 sleep_a_little(1000);
1353 }
1354
1355 /* If we fall out of the loop without grabbing the pointer, its
1356 time to give up */
1357 XSync(dpy,0);
1358 if(val!=GrabSuccess)
1359 {
1360 return False;
1361 }
1362 return True;
1363 }
1364
1365
1366 /*****************************************************************************
1367 *
1368 * UnGrab the pointer and keyboard
1369 *
1370 ****************************************************************************/
UngrabEm()1371 void UngrabEm()
1372 {
1373 Window w;
1374
1375 XSync(dpy,0);
1376 XUngrabPointer(dpy,CurrentTime);
1377
1378 if(Scr.PreviousFocus != NULL)
1379 {
1380 w = Scr.PreviousFocus->w;
1381
1382 /* if the window still exists, focus on it */
1383 if (w)
1384 {
1385 SetFocus(w,Scr.PreviousFocus,True);
1386 }
1387 Scr.PreviousFocus = NULL;
1388 }
1389 XSync(dpy,0);
1390 }
1391
1392
1393 /*****************************************************************************
1394 *
1395 * Waits Scr.ClickTime, or until it is evident that the user is not
1396 * clicking, but is moving the cursor
1397 *
1398 ****************************************************************************/
IsClick(int x,int y,unsigned EndMask,XEvent * d)1399 Bool IsClick(int x,int y,unsigned EndMask, XEvent *d)
1400 {
1401 int xcurrent,ycurrent,total = 0;
1402
1403 xcurrent = x;
1404 ycurrent = y;
1405 while((total < Scr.ClickTime)&&
1406 (x - xcurrent < 5)&&(x - xcurrent > -5)&&
1407 (y - ycurrent < 5)&&(y - ycurrent > -5))
1408 {
1409 sleep_a_little(10000);
1410 total+=10;
1411 if(XCheckMaskEvent (dpy,EndMask, d))
1412 {
1413 StashEventTime(d);
1414 return True;
1415 }
1416 if(XCheckMaskEvent (dpy,ButtonMotionMask|PointerMotionMask, d))
1417 {
1418 xcurrent = d->xmotion.x_root;
1419 ycurrent = d->xmotion.y_root;
1420 StashEventTime(d);
1421 }
1422 }
1423 return False;
1424 }
1425
1426 /*****************************************************************************
1427 *
1428 * Builtin which determines if the button press was a click or double click...
1429 *
1430 ****************************************************************************/
ComplexFunction(Window w,ASWindow * tmp_win,XEvent * eventp,unsigned long context,MenuRoot * mr)1431 void ComplexFunction(Window w, ASWindow *tmp_win, XEvent *eventp,
1432 unsigned long context, MenuRoot *mr)
1433 {
1434 char type = MOTION;
1435 char c;
1436 XEvent *ev;
1437 MenuItem *mi;
1438 XEvent d;
1439 Bool Persist = False;
1440 Bool HaveDoubleClick = False;
1441 Bool HaveTripleClick = False;
1442 Bool NeedsTarget = False;
1443 int x, y ;
1444
1445 if(mr == NULL)
1446 return;
1447
1448 /* These built-ins require a selected window
1449 * The function code is >= 100 and < 1000
1450 * F_RESIZE
1451 * F_MOVE
1452 * F_ICONIFY
1453 * F_RAISE
1454 * F_LOWER
1455 * F_DESTROY
1456 * F_DELETE
1457 * F_STICK
1458 * F_RAISELOWER
1459 * F_MAXIMIZE
1460 * F_SHADE
1461 * F_PUTONTOP
1462 * F_FOCUS
1463 *
1464 * These do not:
1465 * The function code is < 100
1466 * F_NOP
1467 * F_TITLE
1468 * F_BEEP
1469 * F_SCROLL
1470 * F_MOVECURSOR
1471 * F_RESTART
1472 * F_EXEC
1473 * F_REFRESH
1474 * F_GOTO_PAGE
1475 * F_TOGGLE_PAGE
1476 * F_CIRCULATE_UP
1477 * F_CIRCULATE_DOWN
1478 * F_WARP
1479 * F_DESK
1480 * F_MODULE
1481 * F_POPUP
1482 * F_QUIT
1483 * F_WINDOWLIST
1484 * F_FUNCTION
1485 * F_SEND_WINDOW_LIST
1486 */
1487
1488 mi = mr->first;
1489 while(mi != NULL)
1490 {
1491 /* make lower case */
1492 c = *(mi->item);
1493 if((mi->func >= 100)&&(mi->func < 1000))
1494 NeedsTarget = True;
1495 if(isupper(c))
1496 c=tolower(c);
1497 if(c==DOUBLE_CLICK)
1498 HaveDoubleClick = True;
1499 if(c==TRIPLE_CLICK)
1500 HaveTripleClick = True;
1501 else if(c == IMMEDIATE)
1502 {
1503 if(tmp_win)
1504 w = tmp_win->frame;
1505 else
1506 w = None;
1507 ExecuteFunction(mi->func, mi->action,w,
1508 tmp_win, eventp, context,mi->val1,mi->val2,
1509 mi->val1_unit,mi->val2_unit,
1510 mi->menu,-1);
1511 }
1512 else
1513 Persist = True;
1514 mi = mi->next;
1515 }
1516
1517 if(!Persist)
1518 return;
1519
1520 /* Only defer execution if there is a possibility of needing
1521 * a window to operate on */
1522 if(NeedsTarget)
1523 {
1524 if (DeferExecution(eventp,&w,&tmp_win,&context, SELECT,ButtonPress))
1525 {
1526 WaitForButtonsUp();
1527 return;
1528 }
1529 }
1530
1531 if(!GrabEm(SELECT))
1532 {
1533 XBell(dpy,Scr.screen);
1534 return;
1535 }
1536 XQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild,
1537 &x,&y,&JunkX, &JunkY, &JunkMask);
1538
1539 /* A window has already been selected */
1540 ev = eventp;
1541
1542 /* Wait and see if we have a click, or a move */
1543 /* wait 100 msec, see if the user releases the button */
1544 if(IsClick(x,y,ButtonReleaseMask,&d))
1545 {
1546 type = CLICK;
1547 ev = &d;
1548 }
1549
1550 /* If it was a click, wait to see if its a double click */
1551 if((HaveDoubleClick) && (type == CLICK) &&
1552 (IsClick(x,y,ButtonPressMask, &d)))
1553 {
1554 type = ONE_AND_A_HALF_CLICKS;
1555 ev = &d;
1556 }
1557 if((HaveDoubleClick) && (type == ONE_AND_A_HALF_CLICKS) &&
1558 (IsClick(x,y,ButtonReleaseMask, &d)))
1559 {
1560 type = DOUBLE_CLICK;
1561 ev = &d;
1562 }
1563 if((HaveTripleClick) && (type == DOUBLE_CLICK) &&
1564 (IsClick(x,y,ButtonPressMask, &d)))
1565 {
1566 type = TWO_AND_A_HALF_CLICKS;
1567 ev = &d;
1568 }
1569 if((HaveTripleClick) && (type == TWO_AND_A_HALF_CLICKS) &&
1570 (IsClick(x,y,ButtonReleaseMask, &d)))
1571 {
1572 type = TRIPLE_CLICK;
1573 ev = &d;
1574 }
1575
1576 /* some functions operate on button release instead of
1577 * presses. These gets really weird for complex functions ... */
1578 if(eventp->type == ButtonPress)
1579 eventp->type = ButtonRelease;
1580
1581 mi = mr->first;
1582 while(mi != NULL)
1583 {
1584 /* make lower case */
1585 c = *(mi->item);
1586 if(isupper(c))
1587 c=tolower(c);
1588 if(c == type)
1589 {
1590 if(tmp_win)
1591 w = tmp_win->frame;
1592 else
1593 w = None;
1594 ExecuteFunction(mi->func, mi->action,w,
1595 tmp_win, eventp, context,
1596 mi->val1,mi->val2,
1597 mi->val1_unit,mi->val2_unit,mi->menu,-2);
1598 }
1599 mi = mi->next;
1600 }
1601 WaitForButtonsUp();
1602 UngrabEm();
1603 }
1604
1605
1606 /* For Ultrix 4.2 */
1607 #include <sys/types.h>
1608 #include <sys/time.h>
1609
1610
1611 /**************************************************************************
1612 *
1613 * Move to a new desktop
1614 *
1615 *************************************************************************/
changeDesks(int val1,int val2)1616 void changeDesks(int val1,int val2)
1617 {
1618 int oldDesk;
1619 ASWindow *t;
1620 ASWindow *FocusWin = 0;
1621 static ASWindow *StickyWin = 0;
1622
1623 oldDesk = Scr.CurrentDesk;
1624
1625 if(val1 != 0)
1626 {
1627 Scr.CurrentDesk = Scr.CurrentDesk + val1;
1628 }
1629 else
1630 {
1631 Scr.CurrentDesk = val2;
1632 if(Scr.CurrentDesk == oldDesk)
1633 return;
1634 }
1635
1636 Broadcast(M_NEW_DESK,1,Scr.CurrentDesk,0,0,0,0,0,0);
1637 /* Scan the window list, mapping windows on the new Desk,
1638 * unmapping windows on the old Desk */
1639 XGrabServer(dpy);
1640 for (t = Scr.ASRoot.next; t != NULL; t = t->next)
1641 {
1642 /* Only change mapping for non-sticky windows */
1643 if(!((t->flags & ICONIFIED)&&(Scr.flags & StickyIcons)) &&
1644 (!(t->flags & STICKY))&&(!(t->flags & ICON_UNMAPPED)))
1645 {
1646 if(t->Desk == oldDesk) {
1647 if (Scr.Focus == t)
1648 t->FocusDesk = oldDesk;
1649 else
1650 t->FocusDesk = -1;
1651 UnmapIt(t);
1652 } else if(t->Desk == Scr.CurrentDesk) {
1653 MapIt(t);
1654 if (t->FocusDesk == Scr.CurrentDesk) {
1655 FocusWin = t;
1656 }
1657 }
1658 }
1659 else
1660 {
1661 /* Window is sticky */
1662 t->Desk = Scr.CurrentDesk;
1663 if (Scr.Focus == t) {
1664 t->FocusDesk = oldDesk;
1665 StickyWin = t;
1666 }
1667 }
1668 }
1669 XUngrabServer(dpy);
1670 for (t = Scr.ASRoot.next; t != NULL; t = t->next)
1671 {
1672 /* If its an icon, and its sticking, autoplace it so
1673 * that it doesn't wind up on top a a stationary
1674 * icon */
1675 if(((t->flags & STICKY)||(Scr.flags & StickyIcons))&&
1676 (t->flags & ICONIFIED)&&(!(t->flags & ICON_MOVED))&&
1677 (!(t->flags & ICON_UNMAPPED)))
1678 AutoPlace(t);
1679 }
1680 /* Better re-draw the pager now */
1681 RedrawPager();
1682
1683 if(Scr.flags & ClickToFocus) {
1684 #ifndef NO_REMEMBER_FOCUS
1685 if (FocusWin)
1686 SetFocus(FocusWin->w, FocusWin, False);
1687 else if (StickyWin && (StickyWin->flags && STICKY))
1688 SetFocus(StickyWin->w, StickyWin, False);
1689 else
1690 #endif
1691 SetFocus(Scr.NoFocusWin, NULL, False);
1692 }
1693 CorrectStackOrder();
1694 }
1695
1696
1697
1698 /**************************************************************************
1699 *
1700 * Move to a new desktop
1701 *
1702 *************************************************************************/
changeWindowsDesk(ASWindow * t,int val1)1703 void changeWindowsDesk(ASWindow *t,int val1)
1704 {
1705 if(val1 == t->Desk)
1706 return;
1707
1708 /* Scan the window list, mapping windows on the new Desk,
1709 * unmapping windows on the old Desk */
1710 /* Only change mapping for non-sticky windows */
1711 if(!((t->flags & ICONIFIED)&&(Scr.flags & StickyIcons)) &&
1712 (!(t->flags & STICKY))&&(!(t->flags & ICON_UNMAPPED)))
1713 {
1714 if(t->Desk == Scr.CurrentDesk)
1715 {
1716 t->Desk = val1;
1717 UnmapIt(t);
1718 }
1719 else if(val1 == Scr.CurrentDesk)
1720 {
1721 t->Desk = val1;
1722 /* If its an icon, auto-place it */
1723 if(t->flags & ICONIFIED)
1724 AutoPlace(t);
1725 MapIt(t);
1726 }
1727 else
1728 t->Desk = val1;
1729
1730 }
1731 /* Better re-draw the pager now */
1732 BroadcastConfig(M_CONFIGURE_WINDOW,t);
1733 RedrawPager();
1734 CorrectStackOrder();
1735 }
1736
1737
1738 /**************************************************************************
1739 *
1740 * Unmaps a window on transition to a new desktop
1741 *
1742 *************************************************************************/
UnmapIt(ASWindow * t)1743 void UnmapIt(ASWindow *t)
1744 {
1745 XWindowAttributes winattrs;
1746 unsigned long eventMask;
1747 /*
1748 * Prevent the receipt of an UnmapNotify, since that would
1749 * cause a transition to the Withdrawn state.
1750 */
1751 XGetWindowAttributes(dpy, t->w, &winattrs);
1752 eventMask = winattrs.your_event_mask;
1753 XSelectInput(dpy, t->w, eventMask & ~StructureNotifyMask);
1754 if(t->flags & ICONIFIED)
1755 {
1756 if(t->icon_pixmap_w != None)
1757 XUnmapWindow(dpy,t->icon_pixmap_w);
1758 }
1759 else if(t->flags & (MAPPED|MAP_PENDING))
1760 {
1761 XUnmapWindow(dpy,t->frame);
1762 }
1763 XSelectInput(dpy, t->w, eventMask);
1764 MoveResizePagerView(t);
1765 }
1766
1767 /**************************************************************************
1768 *
1769 * Maps a window on transition to a new desktop
1770 *
1771 *************************************************************************/
MapIt(ASWindow * t)1772 void MapIt(ASWindow *t)
1773 {
1774 if(t->flags & ICONIFIED)
1775 {
1776 if(t->icon_pixmap_w != None)
1777 XMapWindow(dpy,t->icon_pixmap_w);
1778 }
1779 else if(t->flags & MAPPED)
1780 {
1781 XMapWindow(dpy,t->frame);
1782 t->flags |= MAP_PENDING;
1783 XMapWindow(dpy, t->Parent);
1784 }
1785 MoveResizePagerView(t);
1786 }
1787
1788 extern void InitVariables(void);
1789
QuickRestart(void)1790 void QuickRestart(void)
1791 {
1792 #ifdef M4
1793 extern char *m4_options;
1794 #endif
1795 extern char *display_name;
1796 int i;
1797 ASWindow *tmp,*next;
1798 extern unsigned PopupCount;
1799 extern int have_the_colors;
1800 MenuRoot *PopupTable[MAXPOPUPS];
1801 extern MenuRoot *ActiveMenu;
1802 extern MenuItem *ActiveItem;
1803 extern int menu_on;
1804 XEvent event;
1805
1806 PopDownMenu();
1807 PopDownMenu();
1808 UngrabEm();
1809 InstallWindowColormaps (&Scr.ASRoot); /* force reinstall */
1810
1811 ClosePipes();
1812
1813 Reborder();
1814 tmp = Scr.ASRoot.next;
1815 while (tmp != NULL)
1816 {
1817 next = tmp->next;
1818 Destroy(tmp);
1819 tmp = next;
1820 }
1821 XSync(dpy,0);
1822 for(i=0;i<PopupCount;i++)
1823 {
1824 /* The next line was commented out...readded 08/12/96 */
1825 free(PopupTable[i]);
1826 PopupTable[i] = NULL;
1827 }
1828
1829 PopupCount = 0;
1830 ActiveMenu = NULL;
1831 ActiveItem = NULL;
1832 menu_on = 0;
1833 have_the_colors = 0;
1834
1835 InitVariables();
1836
1837 #ifdef M4
1838 MakeMenus(display_name, m4_options);
1839 #else
1840 MakeMenus(display_name, NULL);
1841 #endif
1842 #ifndef NON_VIRTUAL
1843 XUnmapWindow(dpy,Scr.PanFrameLeft.win);
1844 XUnmapWindow (dpy,Scr.PanFrameRight.win);
1845 XUnmapWindow (dpy,Scr.PanFrameBottom.win);
1846 XUnmapWindow(dpy,Scr.PanFrameTop.win);
1847 Scr.PanFrameBottom.isMapped=
1848 Scr.PanFrameTop.isMapped=
1849 Scr.PanFrameLeft.isMapped=
1850 Scr.PanFrameRight.isMapped=
1851 False;
1852 #endif
1853 while(XPending(dpy))
1854 XNextEvent(dpy,&event);
1855
1856 CaptureAllWindows();
1857 #ifndef NON_VIRTUAL
1858 checkPanFrames();
1859 #endif
1860 HandleEvents();
1861
1862 }
1863