1 /*
2 * Copyright (C) 2002 Sasha Vasko <sasha at aftercode.net>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 *
18 */
19
20 #define LOCAL_DEBUG
21 #include "../configure.h"
22 #include "asapp.h"
23
24 #include <signal.h>
25 #include <sys/socket.h>
26 #include <sys/types.h>
27 #include <sys/fcntl.h>
28 #include <sys/un.h>
29
30 #include "afterstep.h"
31 #include "mystyle.h"
32 #include "screen.h"
33 #include "module.h"
34 #include "wmprops.h"
35 #include "../libAfterImage/afterimage.h"
36 #include <X11/XKBlib.h>
37 #ifdef XSHMIMAGE
38 #include <sys/ipc.h>
39 #include <sys/shm.h>
40 #include <X11/extensions/XShm.h>
41 #endif
42
43 static Bool as_X_synchronous_mode = False;
44
45 /*************************************************************************/
46 /* Scr data members access functions to be used in linking DLLs */
get_screen_width(ScreenInfo * scr)47 int get_screen_width (ScreenInfo * scr)
48 {
49 if (scr == NULL)
50 scr = ASDefaultScr;
51 return scr->MyDisplayWidth;
52 }
53
get_screen_height(ScreenInfo * scr)54 int get_screen_height (ScreenInfo * scr)
55 {
56 if (scr == NULL)
57 scr = ASDefaultScr;
58 return scr->MyDisplayHeight;
59 }
60
get_screen_current_desk(ScreenInfo * scr)61 int get_screen_current_desk (ScreenInfo * scr)
62 {
63 if (scr == NULL)
64 scr = ASDefaultScr;
65 return scr->CurrentDesk;
66 }
67
get_screen_look(ScreenInfo * scr)68 struct MyLook *get_screen_look (ScreenInfo * scr)
69 {
70 if (scr == NULL)
71 scr = ASDefaultScr;
72 return &(scr->Look);
73 }
74
get_screen_image_manager(ScreenInfo * scr)75 struct ASImageManager *get_screen_image_manager (ScreenInfo * scr)
76 {
77 if (scr == NULL)
78 scr = ASDefaultScr;
79 return scr->image_manager;
80 }
81
get_screen_font_manager(ScreenInfo * scr)82 struct ASFontManager *get_screen_font_manager (ScreenInfo * scr)
83 {
84 if (scr == NULL)
85 scr = ASDefaultScr;
86 return scr->font_manager;
87 }
88
get_screen_visual(ScreenInfo * scr)89 struct ASVisual *get_screen_visual (ScreenInfo * scr)
90 {
91 if (scr == NULL)
92 scr = ASDefaultScr;
93 return scr->asv;
94 }
95
96
get_current_screen()97 ScreenInfo *get_current_screen ()
98 {
99 return ASDefaultScr;
100 }
101
102 void
reload_screen_image_manager(ScreenInfo * scr,ASImageManager ** old_imageman)103 reload_screen_image_manager (ScreenInfo * scr,
104 ASImageManager ** old_imageman)
105 {
106 char *env_path1 = NULL, *env_path2 = NULL;
107
108 if (scr == NULL)
109 scr = ASDefaultScr;
110 if (old_imageman) {
111 *old_imageman = scr->image_manager;
112 } else if (scr->image_manager)
113 destroy_image_manager (scr->image_manager, False);
114
115 env_path1 = getenv ("IMAGE_PATH");
116 /* otherwise we'll be loading binary files as images - no good!!! */
117 /* env_path2 = getenv ("PATH"); */
118 if (env_path1 == NULL) {
119 env_path1 = env_path2;
120 env_path2 = NULL;
121 }
122 scr->image_manager =
123 create_image_manager (NULL, 2.2,
124 Environment->pixmap_path ? Environment->
125 pixmap_path : "",
126 Environment->IconThemePath ? Environment->
127 IconThemePath : "", env_path1, env_path2,
128 NULL);
129 set_xml_image_manager (scr->image_manager);
130 show_progress ("Pixmap Path changed to \"%s:%s:%s:%s\" ...",
131 Environment->pixmap_path ? Environment->pixmap_path : "",
132 Environment->IconThemePath ? Environment->
133 IconThemePath : "", env_path1 ? env_path1 : "",
134 env_path2 ? env_path2 : "");
135 }
136
137 /*************************************************************************/
138
get_Xinerama_rectangles(ScreenInfo * scr)139 void get_Xinerama_rectangles (ScreenInfo * scr)
140 {
141 #ifdef HAVE_XINERAMA
142 if (XineramaQueryExtension
143 (dpy, &(scr->XineEventBase), &(scr->XineErrorBase))) {
144 register int i;
145 XineramaScreenInfo *s;
146
147 if ((s =
148 XineramaQueryScreens (dpy,
149 &(scr->xinerama_screens_num))) != NULL) {
150 static char buf[256];
151
152 scr->xinerama_screens =
153 safemalloc (sizeof (XRectangle) * scr->xinerama_screens_num);
154 asxml_var_insert ("xroot.xinerama_screens_num",
155 scr->xinerama_screens_num);
156 for (i = 0; i < scr->xinerama_screens_num; ++i) {
157 char *append_point = &buf[0];
158
159 sprintf (append_point, "xroot.xinerama_screens[%d].", i);
160 append_point += 23;
161 while (*append_point)
162 ++append_point;
163
164 append_point[0] = 'x';
165 append_point[1] = '\0';
166 asxml_var_insert (&buf[0], s[i].x_org);
167 scr->xinerama_screens[i].x = s[i].x_org;
168
169 append_point[0] = 'y';
170 asxml_var_insert (&buf[0], s[i].y_org);
171 scr->xinerama_screens[i].y = s[i].y_org;
172
173 strcpy (append_point, "width");
174 asxml_var_insert (&buf[0], s[i].width);
175 scr->xinerama_screens[i].width = s[i].width;
176
177 strcpy (append_point, "height");
178 asxml_var_insert (&buf[0], s[i].height);
179 scr->xinerama_screens[i].height = s[i].height;
180 }
181 XFree (s);
182 }
183 } else
184 #endif
185 {
186 scr->xinerama_screens = NULL;
187 scr->xinerama_screens_num = 0;
188 asxml_var_insert ("xroot.xinerama_screens_num", 0);
189 }
190 }
191
set_synchronous_mode(Bool enable)192 Bool set_synchronous_mode (Bool enable)
193 {
194 Bool old = as_X_synchronous_mode;
195
196 XSynchronize (dpy, enable);
197 as_X_synchronous_mode = enable;
198 return old;
199 }
200
is_synchronous_request(int request_code)201 Bool is_synchronous_request (int request_code)
202 {
203 if (as_X_synchronous_mode)
204 return True;
205 switch (request_code) {
206 case X_CreateWindow:
207 case X_GetWindowAttributes:
208 case X_GetGeometry:
209 case X_QueryTree:
210 case X_InternAtom:
211 case X_GetAtomName:
212 case X_GetProperty:
213 case X_ListProperties:
214 case X_GetSelectionOwner:
215 case X_ConvertSelection:
216 case X_QueryPointer:
217 case X_GetMotionEvents:
218 case X_TranslateCoords:
219 case X_GetInputFocus:
220 case X_QueryKeymap:
221 case X_OpenFont:
222 case X_QueryFont:
223 case X_QueryTextExtents:
224 case X_ListFonts:
225 case X_ListFontsWithInfo:
226 case X_GetFontPath:
227 case X_CreatePixmap:
228 case X_CreateGC:
229 case X_GetImage:
230 case X_CreateColormap:
231 case X_CopyColormapAndFree:
232 case X_ListInstalledColormaps:
233 case X_AllocColor:
234 case X_AllocNamedColor:
235 case X_AllocColorCells:
236 case X_AllocColorPlanes:
237 case X_QueryColors:
238 case X_LookupColor:
239 case X_CreateCursor:
240 case X_CreateGlyphCursor:
241 case X_QueryBestSize:
242 case X_QueryExtension:
243 case X_ListExtensions:
244 case X_GetKeyboardMapping:
245 case X_GetKeyboardControl:
246 case X_GetPointerControl:
247 case X_GetScreenSaver:
248 case X_ListHosts:
249 case X_GetPointerMapping:
250 case X_GetModifierMapping:
251 return True;
252 break;
253 default:
254 break;
255 }
256 return False;
257 }
258
ASErrorHandler(Display * dpy,XErrorEvent * event)259 int ASErrorHandler (Display * dpy, XErrorEvent * event)
260 {
261 char *err_text;
262
263 fprintf (stderr,
264 "%s has encountered a problem interacting with X Windows :\n",
265 MyName);
266 if (event && dpy) {
267 if (event->error_code == BadWindow && ASDefaultScr->Windows != NULL)
268 if (ASDefaultScr->on_dead_window)
269 if (ASDefaultScr->on_dead_window (event->resourceid))
270 return 0;
271
272 err_text = safemalloc (128);
273 strcpy (err_text, "unknown error");
274 XGetErrorText (dpy, event->error_code, err_text, 120);
275 fprintf (stderr, " Request: %d, Error: %d(%s)\n",
276 event->request_code, event->error_code, err_text);
277 free (err_text);
278 fprintf (stderr, " in resource: 0x%lX\n", event->resourceid);
279 #ifndef __CYGWIN__
280 if (is_synchronous_request (event->request_code))
281 print_simple_backtrace ();
282 #endif
283 }
284 return 0;
285 }
286
287
init_ScreenInfo(ScreenInfo * scr)288 void init_ScreenInfo (ScreenInfo * scr)
289 {
290 if (scr) {
291 memset (scr, 0x00, sizeof (ScreenInfo));
292 scr->Look.magic = MAGIC_MYLOOK;
293 }
294 }
295
ConnectXDisplay(Display * display,ScreenInfo * scr,Bool as_manager)296 int ConnectXDisplay (Display * display, ScreenInfo * scr, Bool as_manager)
297 {
298 int width_mm, height_mm;
299 int display_dpcmx = 0, display_dpcmy = 0;
300 int button_w, button_h, mini_w, mini_h;
301
302 if (display == NULL)
303 return -1;
304
305 dpy = display;
306 set_current_X_display (display); /* for libAfterBase X Wrappers */
307
308 if (scr == NULL) {
309 if (ASDefaultScr == NULL)
310 ASDefaultScr = safecalloc (1, sizeof (ScreenInfo));
311 scr = ASDefaultScr;
312 }
313
314 init_ScreenInfo (scr);
315
316 x_fd = XConnectionNumber (dpy);
317
318 if (x_fd < 0) {
319 show_error ("failed to initialize X Windows session. Aborting!");
320 exit (1);
321 }
322 if (fcntl (x_fd, F_SETFD, 1) == -1)
323 show_warning ("close-on-exec for X Windows connection failed");
324
325 XSetErrorHandler (ASErrorHandler);
326
327 if (get_flags (MyArgs.flags, ASS_Debugging))
328 set_synchronous_mode (True);
329
330 intern_hint_atoms ();
331 intern_wmprop_atoms ();
332
333 scr->screen = DefaultScreen (dpy);
334 scr->Root = RootWindow (dpy, scr->screen);
335 if (scr->Root == None) {
336 show_error ("Screen %d is not valid. Exiting.", (int)scr->screen);
337 exit (1);
338 }
339
340 scr->NumberOfScreens = NumberOfScreens = ScreenCount (dpy);
341 scr->MyDisplayWidth = DisplayWidth (dpy, scr->screen);
342 scr->MyDisplayHeight = DisplayHeight (dpy, scr->screen);
343
344 asxml_var_insert ("xroot.width", scr->MyDisplayWidth);
345 asxml_var_insert ("xroot.height", scr->MyDisplayHeight);
346
347 width_mm = DisplayWidthMM (dpy, scr->screen);
348 height_mm = DisplayHeightMM (dpy, scr->screen);
349 asxml_var_insert ("xroot.widthmm", width_mm);
350 asxml_var_insert ("xroot.heightmm", height_mm);
351
352 display_dpcmx = (scr->MyDisplayWidth * 10) / width_mm;
353 display_dpcmy = (scr->MyDisplayHeight * 10) / height_mm;
354
355 button_w = (display_dpcmx < 50) ? 48 : 64;
356 button_h = (display_dpcmy < 50) ? 48 : 64;
357 mini_w =
358 (display_dpcmx <= 44) ? max (display_dpcmx / 2,
359 12) : display_dpcmx - 20;
360 mini_h =
361 (display_dpcmy <= 44) ? max (display_dpcmy / 2,
362 12) : display_dpcmy - 20;
363 asxml_var_insert (ASXMLVAR_IconButtonWidth, button_w);
364 asxml_var_insert (ASXMLVAR_IconButtonHeight, button_h);
365 asxml_var_insert (ASXMLVAR_IconWidth, (button_w * 3) / 4);
366 asxml_var_insert (ASXMLVAR_IconHeight, (button_h * 3) / 4);
367 asxml_var_insert (ASXMLVAR_MinipixmapWidth, mini_w);
368 asxml_var_insert (ASXMLVAR_MinipixmapHeight, mini_h);
369 asxml_var_insert (ASXMLVAR_TitleFontSize, (mini_h * 7) / 12);
370 asxml_var_insert (ASXMLVAR_MenuFontSize, (mini_h * 7) / 12 + 1);
371 asxml_var_insert ("font.size", ((mini_h * 7) / 12));
372
373 scr->CurrentDesk = -1;
374
375 scr->RootClipArea.width = scr->MyDisplayWidth;
376 scr->RootClipArea.height = scr->MyDisplayHeight;
377
378 if ((scr->wmprops =
379 setup_wmprops (scr, as_manager, 0xFFFFFFFF, NULL)) == NULL)
380 return -1;
381
382 scr->asv =
383 create_asvisual (dpy, scr->screen, DefaultDepth (dpy, scr->screen),
384 NULL);
385 if (scr->asv == NULL) {
386 show_error ("Failed to find suitable visual for screen %d. Exiting.",
387 (int)scr->screen);
388 exit (1);
389 }
390
391 scr->d_depth = scr->asv->visual_info.depth;
392
393 scr->last_Timestamp = CurrentTime;
394 scr->menu_grab_Timestamp = CurrentTime;
395
396 setup_modifiers ();
397
398 get_Xinerama_rectangles (scr);
399
400 #ifdef SHAPE
401 XShapeQueryExtension (dpy, &(scr->ShapeEventBase),
402 &(scr->ShapeErrorBase));
403 #endif /* SHAPE */
404 #ifdef XSHMIMAGE
405 scr->ShmCompletionEventType = XShmGetEventBase (dpy) + ShmCompletion;
406 #endif /* SHAPE */
407
408 init_screen_gcs (scr);
409
410 return x_fd;
411 }
412
ConnectX(ScreenInfo * scr,unsigned long event_mask)413 int ConnectX (ScreenInfo * scr, unsigned long event_mask)
414 {
415 if (!(dpy = XOpenDisplay (MyArgs.display_name))) {
416 show_error ("Can't open display \"%s\". Exiting!",
417 XDisplayName (MyArgs.display_name));
418 exit (1);
419 }
420
421 ConnectXDisplay (dpy, scr, (event_mask & SubstructureRedirectMask));
422 XSelectInput (dpy, scr->Root, event_mask);
423 return x_fd;
424 }
425
426
427 /***********************************************************************
428 * Procedure:
429 * SetupEnvironment - setup environment variables DISPLAY and HOSTDISPLAY
430 * for our children to use.
431 ************************************************************************/
make_screen_envvars(ScreenInfo * scr)432 void make_screen_envvars (ScreenInfo * scr)
433 {
434 int len;
435 char *display = ":0.0";
436 char client[MAXHOSTNAME];
437
438 /* We set environmanet vars and we keep memory used for those allocated
439 * as some OS's don't copy the environment variables properly
440 */
441 if (scr == NULL)
442 scr = ASDefaultScr;
443
444 if (scr->display_string)
445 free (scr->display_string);
446 if (scr->rdisplay_string)
447 free (scr->rdisplay_string);
448
449 /* Add a DISPLAY entry to the environment, incase we were started
450 * with afterstep -display term:0.0
451 */
452 display = XDisplayString (dpy);
453 len = strlen (display);
454 scr->display_string = safemalloc (len + 10);
455 sprintf (scr->display_string, "DISPLAY=%s", display);
456
457 /* Add a HOSTDISPLAY environment variable, which is the same as
458 * DISPLAY, unless display = :0.0 or unix:0.0, in which case the full
459 * host name will be used for ease in networking . */
460 if (scr->display_string[8] == ':'
461 || strncmp (&(scr->display_string[8]), "unix:", 5) == 0) {
462 register char *ptr = &(scr->display_string[8]);
463
464 if (*ptr != ':')
465 ptr += 5;
466 mygethostname (client, MAXHOSTNAME);
467 scr->localhost = True;
468 scr->rdisplay_string = safemalloc (len + 14 + strlen (client));
469 sprintf (scr->rdisplay_string, "HOSTDISPLAY=%s:%s", client, ptr);
470 } else { /* X Server is likely to be runnig on other computer: */
471 scr->localhost = False;
472 scr->rdisplay_string = safemalloc (len + 14);
473 sprintf (scr->rdisplay_string, "HOSTDISPLAY=%s", display);
474 }
475 }
476
init_screen_gcs(ScreenInfo * scr)477 void init_screen_gcs (ScreenInfo * scr)
478 {
479 XGCValues gcv;
480 unsigned long gcm = GCGraphicsExposures;
481
482 if (scr == NULL)
483 scr = ASDefaultScr;
484
485 gcv.graphics_exposures = False;
486
487 scr->RootGC = XCreateGC (dpy, scr->Root, gcm, &gcv);
488 scr->DrawGC = create_visual_gc (scr->asv, scr->Root, gcm, &gcv);
489 }
490
destroy_screen_gcs(ScreenInfo * scr)491 void destroy_screen_gcs (ScreenInfo * scr)
492 {
493 if (scr == NULL)
494 scr = ASDefaultScr;
495
496 if (scr->DrawGC) {
497 XFreeGC (dpy, scr->DrawGC);
498 scr->DrawGC = NULL;
499 }
500 if (scr->RootGC) {
501 XFreeGC (dpy, scr->RootGC);
502 scr->RootGC = NULL;
503 }
504 }
505
506 /* Setting up global variables nonlock_mods, and lock_mods, defined in asapp.c : */
setup_modifiers()507 void setup_modifiers ()
508 {
509 int m, i, knl;
510 char *kn;
511 KeySym ks;
512 KeyCode kc, *kp;
513 unsigned lockmask, *mp;
514 XModifierKeymap *mm = XGetModifierMapping (dpy);
515
516 lockmask = LockMask;
517 if (mm) {
518 kp = mm->modifiermap;
519 for (m = 0; m < 8; m++) {
520 for (i = 0; i < mm->max_keypermod; i++) {
521 if ((kc = *kp++)
522 && ((ks = XkbKeycodeToKeysym (dpy, kc, 0, 0)) != NoSymbol)) {
523 kn = XKeysymToString (ks);
524 knl = strlen (kn);
525 if ((knl > 6) && (mystrcasecmp (kn + knl - 4, "lock") == 0))
526 lockmask |= (1 << m);
527 }
528 }
529 }
530 XFreeModifiermap (mm);
531 }
532 /* forget shift & control locks */
533 lockmask &= ~(ShiftMask | ControlMask);
534 nonlock_mods =
535 ((ShiftMask | ControlMask | Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask
536 | Mod5Mask) & ~lockmask);
537
538 LOCAL_DEBUG_OUT ("lockmask = %X, nonlock_mods = %X", lockmask,
539 nonlock_mods);
540
541 mp = lock_mods;
542 for (m = 0, i = 1; i < MAX_LOCK_MODS; i++) {
543 if ((i & lockmask) > m)
544 m = *mp++ = (i & lockmask);
545 }
546 *mp = 0;
547 }
548
549 /****************************************************************************
550 * Pan Frames : windows for edge-scrolling
551 * the root window is surrounded by four window slices, which are InputOnly.
552 * So you can see 'through' them, but they eat the input. An EnterEvent in
553 * one of these windows causes a Paging. The windows have the according cursor
554 * pointing in the pan direction or are hidden if there is no more panning
555 * in that direction. This is mostly intended to get a panning even atop
556 * of Motif applictions, which does not work yet. It seems Motif windows
557 * eat all mouse events.
558 *
559 * Hermann Dunkel, HEDU, dunkel@cul-ipn.uni-kiel.de 1/94
560 ****************************************************************************/
init_screen_panframes(ScreenInfo * scr)561 void init_screen_panframes (ScreenInfo * scr)
562 {
563 #ifndef NO_VIRTUAL
564 XRectangle frame_rects[PAN_FRAME_SIDES];
565
566 XSetWindowAttributes attributes; /* attributes for create */
567 register int i;
568
569 if (scr == NULL)
570 scr = ASDefaultScr;
571
572 frame_rects[0].x = frame_rects[0].y = 0;
573 frame_rects[0].width = scr->MyDisplayWidth;
574 frame_rects[0].height = SCROLL_REGION;
575
576 frame_rects[1].x = scr->MyDisplayWidth - SCROLL_REGION;
577 frame_rects[1].y = SCROLL_REGION;
578 frame_rects[1].width = SCROLL_REGION;
579 frame_rects[1].height = scr->MyDisplayHeight - 2 * SCROLL_REGION;
580
581 frame_rects[2].x = 0;
582 frame_rects[2].y = scr->MyDisplayHeight - SCROLL_REGION;
583 frame_rects[2].width = scr->MyDisplayWidth;
584 frame_rects[2].height = SCROLL_REGION;
585
586 frame_rects[3].x = 0;
587 frame_rects[3].y = SCROLL_REGION;
588 frame_rects[3].width = SCROLL_REGION;
589 frame_rects[3].height = scr->MyDisplayHeight - 2 * SCROLL_REGION;
590
591 frame_rects[2].width = frame_rects[0].width = scr->MyDisplayWidth;
592 frame_rects[1].x = scr->MyDisplayWidth - SCROLL_REGION;
593 frame_rects[3].height = frame_rects[1].height =
594 scr->MyDisplayHeight - (SCROLL_REGION * 2);
595
596 attributes.event_mask = AS_PANFRAME_EVENT_MASK;
597 for (i = 0; i < PAN_FRAME_SIDES; i++) {
598 scr->PanFrame[i].win = create_screen_window (scr, None, frame_rects[i].x, frame_rects[i].y, frame_rects[i].width, frame_rects[i].height, 0, /* no border */
599 InputOnly, (CWEventMask),
600 &attributes);
601 LOCAL_DEBUG_OUT ("creating PanFrame %d(%lX) at %dx%d%+d%+d", i,
602 scr->PanFrame[i].win, frame_rects[i].width,
603 frame_rects[i].height, frame_rects[i].x,
604 frame_rects[i].y);
605 scr->PanFrame[i].isMapped = False;
606 }
607 #endif /* NO_VIRTUAL */
608 }
609
610 /***************************************************************************
611 * checkPanFrames hides PanFrames if they are on the very border of the
612 * VIRTUELL screen and EdgeWrap for that direction is off.
613 * (A special cursor for the EdgeWrap border could be nice) HEDU
614 ****************************************************************************/
check_screen_panframes(ScreenInfo * scr)615 void check_screen_panframes (ScreenInfo * scr)
616 {
617 #ifndef NO_VIRTUAL
618 int wrapX;
619 int wrapY;
620 Bool map_frame[PAN_FRAME_SIDES] = { False, False, False, False };
621 register int i;
622
623 if (scr == NULL)
624 scr = ASDefaultScr;
625
626 wrapX = get_flags (scr->Feel.flags, EdgeWrapX);
627 wrapY = get_flags (scr->Feel.flags, EdgeWrapY);
628
629 if (get_flags (scr->Feel.flags, DoHandlePageing)) {
630 if (scr->Feel.EdgeScrollY > 0) {
631 if (scr->Vy > 0 || wrapY)
632 map_frame[FR_N] = True;
633 if (scr->Vy < scr->VyMax || wrapY)
634 map_frame[FR_S] = True;
635 }
636 if (scr->Feel.EdgeScrollX > 0) {
637 if (scr->Vx < scr->VxMax || wrapX)
638 map_frame[FR_E] = True;
639 if (scr->Vx > 0 || wrapX)
640 map_frame[FR_W] = True;
641 }
642 }
643 /* Remove Pan frames if paging by edge-scroll is permanently or
644 * temporarily disabled */
645 for (i = 0; i < PAN_FRAME_SIDES; i++) {
646 if (scr->PanFrame[i].win) {
647 if (map_frame[i] != scr->PanFrame[i].isMapped) {
648 if (map_frame[i]) {
649 LOCAL_DEBUG_OUT ("mapping PanFrame %d(%lX)", i,
650 scr->PanFrame[i].win);
651 XMapRaised (dpy, scr->PanFrame[i].win);
652 } else
653 XUnmapWindow (dpy, scr->PanFrame[i].win);
654 scr->PanFrame[i].isMapped = map_frame[i];
655 }
656
657 if (map_frame[i]) {
658 /* to maintain stacking order where first mapped pan frame is the lowest window : */
659 LOCAL_DEBUG_OUT ("rasing PanFrame %d(%lX)", i,
660 scr->PanFrame[i].win);
661 XRaiseWindow (dpy, scr->PanFrame[i].win);
662 XDefineCursor (dpy, scr->PanFrame[i].win,
663 scr->Feel.cursors[ASCUR_Top + i]);
664 }
665 }
666 }
667 #endif
668 }
669
670 /****************************************************************************
671 * Gotta make sure these things are on top of everything else, or they
672 * don't work!
673 ***************************************************************************/
raise_scren_panframes(ScreenInfo * scr)674 void raise_scren_panframes (ScreenInfo * scr)
675 {
676 #ifndef NO_VIRTUAL
677 register int i;
678
679 if (scr == NULL)
680 scr = ASDefaultScr;
681 for (i = 0; i < PAN_FRAME_SIDES; i++)
682 if (scr->PanFrame[i].isMapped) {
683 LOCAL_DEBUG_OUT ("rasing PanFrame %d(%lX)", i, scr->PanFrame[i].win);
684 XRaiseWindow (dpy, scr->PanFrame[i].win);
685 }
686 #endif
687 }
688
get_lowest_panframe(ScreenInfo * scr)689 Window get_lowest_panframe (ScreenInfo * scr)
690 {
691 register int i;
692
693 if (scr == NULL)
694 scr = ASDefaultScr;
695 for (i = 0; i < PAN_FRAME_SIDES; i++)
696 if (scr->PanFrame[i].isMapped)
697 return scr->PanFrame[i].win;
698 return None;
699 }
700
701 /* utility function for geometry merging : */
merge_geometry(ASGeometry * from,ASGeometry * to)702 void merge_geometry (ASGeometry * from, ASGeometry * to)
703 {
704 if (get_flags (from->flags, WidthValue))
705 to->width = from->width;
706 if (get_flags (from->flags, HeightValue))
707 to->height = from->height;
708 if (get_flags (from->flags, XValue)) {
709 to->x = from->x;
710 if (!get_flags (from->flags, XNegative))
711 clear_flags (to->flags, XNegative);
712 }
713 if (get_flags (from->flags, YValue)) {
714 to->y = from->y;
715 if (!get_flags (from->flags, YNegative))
716 clear_flags (to->flags, YNegative);
717 }
718 to->flags |= from->flags;
719 }
720
check_desksize_sanity(ScreenInfo * scr)721 void check_desksize_sanity (ScreenInfo * scr)
722 {
723 if (scr == NULL)
724 scr = ASDefaultScr;
725
726 if (scr->VxMax <= 0)
727 scr->VxMax = 0;
728 else if (scr->VxMax < 32000 / scr->MyDisplayWidth)
729 scr->VxMax = (scr->VxMax * scr->MyDisplayWidth) - scr->MyDisplayWidth;
730
731 if (scr->VyMax <= 0)
732 scr->VyMax = 0;
733 else if (scr->VyMax < 32000 / scr->MyDisplayHeight)
734 scr->VyMax =
735 (scr->VyMax * scr->MyDisplayHeight) - scr->MyDisplayHeight;
736 }
737