|
|
1.1 root 1: /*-
2: * sunInit.c --
3: * Initialization functions for screen/keyboard/mouse, etc.
4: *
5: * Copyright (c) 1987 by the Regents of the University of California
6: *
7: * Permission to use, copy, modify, and distribute this
8: * software and its documentation for any purpose and without
9: * fee is hereby granted, provided that the above copyright
10: * notice appear in all copies. The University of California
11: * makes no representations about the suitability of this
12: * software for any purpose. It is provided "as is" without
13: * express or implied warranty.
14: *
15: *
16: */
17:
18: /************************************************************
19: Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA.
20:
21: All Rights Reserved
22:
23: Permission to use, copy, modify, and distribute this
24: software and its documentation for any purpose and without
25: fee is hereby granted, provided that the above copyright no-
26: tice appear in all copies and that both that copyright no-
27: tice and this permission notice appear in supporting docu-
28: mentation, and that the names of Sun or MIT not be used in
29: advertising or publicity pertaining to distribution of the
30: software without specific prior written permission. Sun and
31: M.I.T. make no representations about the suitability of this
32: software for any purpose. It is provided "as is" without any
33: express or implied warranty.
34:
35: SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
36: INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
37: NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI-
38: ABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
39: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
40: PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
41: OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
42: THE USE OR PERFORMANCE OF THIS SOFTWARE.
43:
44: ********************************************************/
45:
46: #ifndef lint
47: static char sccsid[] = "%W %G Copyright 1987 Sun Micro";
48: #endif
49:
50: #include "sun.h"
51: #include <servermd.h>
52: #include "dixstruct.h"
53: #include "dix.h"
54: #include "opaque.h"
55:
56: extern int sunMouseProc();
57: extern void sunKbdProc();
58: extern Bool sunBW2Probe();
59: extern Bool sunCG2CProbe();
60: extern Bool sunCG4CProbe();
61: extern void ProcessInputEvents();
62:
63: extern void SetInputCheck();
64: extern char *strncpy();
65: extern GCPtr CreateScratchGC();
66:
67: #define XDEVICE "XDEVICE"
68: #define PARENT "WINDOW_GFX"
69:
70: int sunSigIO = 0; /* For use with SetInputCheck */
71:
72: /* What should this *really* be? */
73: #define MOTION_BUFFER_SIZE 0
74:
75: /*-
76: *-----------------------------------------------------------------------
77: * SigIOHandler --
78: * Signal handler for SIGIO - input is available.
79: *
80: * Results:
81: * isItTimeToYield is set - ProcessInputEvents() will be called soon.
82: *
83: * Side Effects:
84: * None
85: *
86: *-----------------------------------------------------------------------
87: */
88: /*ARGSUSED*/
89: static void
90: SigIOHandler(sig, code, scp)
91: int code;
92: int sig;
93: struct sigcontext *scp;
94: {
95: sunSigIO++;
96: isItTimeToYield++;
97: }
98:
99: /*
100: * ZOIDS should only ever be defined if SUN_WINDOWS is also defined.
101: */
102: #ifdef ZOIDS
103: sunFbDataRec sunFbData[] = {
104: sunBW2Probe, "/dev/bwtwo0", neverProbed, 0, 0,
105: sunCG2CProbe, "/dev/cgtwo0", neverProbed, 0, 0,
106: sunCG4CProbe, "/dev/cgfour0", neverProbed, 0, 0,
107: };
108: #else ZOIDS
109: sunFbDataRec sunFbData[] = {
110: sunBW2Probe, "/dev/bwtwo0", neverProbed,
111: sunCG2CProbe, "/dev/cgtwo0", neverProbed,
112: sunCG4CProbe, "/dev/cgfour0", neverProbed,
113: };
114: #endif ZOIDS
115:
116: /*
117: * NUMSCREENS is the number of supported frame buffers (i.e. the number of
118: * structures in sunFbData which have an actual probeProc).
119: */
120: #define NUMSCREENS (sizeof(sunFbData)/sizeof(sunFbData[0]))
121: #define NUMDEVICES 2
122:
123: fbFd sunFbs[NUMSCREENS]; /* Space for descriptors of open frame buffers */
124:
125: static PixmapFormatRec formats[] = {
126: 1, 1, BITMAP_SCANLINE_PAD, /* 1-bit deep */
127: 8, 8, BITMAP_SCANLINE_PAD, /* 8-bit deep */
128: };
129: #define NUMFORMATS (sizeof formats)/(sizeof formats[0])
130:
131: /*-
132: *-----------------------------------------------------------------------
133: * InitOutput --
134: * Initialize screenInfo for all actually accessible framebuffers.
135: * The
136: *
137: * Results:
138: * screenInfo init proc field set
139: *
140: * Side Effects:
141: * None
142: *
143: *-----------------------------------------------------------------------
144: */
145:
146: InitOutput(pScreenInfo, argc, argv)
147: ScreenInfo *pScreenInfo;
148: int argc;
149: char **argv;
150: {
151: int i, index, ac = argc;
152: char **av = argv;
153: int nonBlockConsole = 1;
154:
155: while (ac--) {
156: if (!strcmp(*av,"-debug")) {
157: nonBlockConsole = 0;
158: break;
159: }
160: av++;
161: }
162: /*
163: * Writes to /dev/console can block - causing an
164: * excess of error messages to hang the server in
165: * deadlock. So.......
166: */
167: if (nonBlockConsole && (fcntl(2, F_SETFL, O_NDELAY) < 0)) {
168: perror("fcntl");
169: ErrorF("InitOutput: can't put stderr in non-block mode\n");
170: }
171: pScreenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
172: pScreenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
173: pScreenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
174: pScreenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
175:
176: pScreenInfo->numPixmapFormats = NUMFORMATS;
177: for (i=0; i< NUMFORMATS; i++)
178: {
179: pScreenInfo->formats[i] = formats[i];
180: }
181:
182: for (i = 0, index = 0; i < NUMSCREENS; i++) {
183: if ((* sunFbData[i].probeProc) (pScreenInfo, index, i, argc, argv)) {
184: /* This display exists OK */
185: index++;
186: } else {
187: /* This display can't be opened */
188: ;
189: }
190: }
191: if (index == 0)
192: FatalError("Can't find any displays\n");
193:
194: pScreenInfo->numScreens = index;
195:
196: sunInitCursor();
197: signal(SIGWINCH, SIG_IGN);
198: }
199:
200: /*-
201: *-----------------------------------------------------------------------
202: * InitInput --
203: * Initialize all supported input devices...what else is there
204: * besides pointer and keyboard?
205: *
206: * Results:
207: * None.
208: *
209: * Side Effects:
210: * Two DeviceRec's are allocated and registered as the system pointer
211: * and keyboard devices.
212: *
213: *-----------------------------------------------------------------------
214: */
215: /*ARGSUSED*/
216: InitInput(argc, argv)
217: int argc;
218: char **argv;
219: {
220: DevicePtr p, k;
221: static int zero = 0;
222:
223: p = AddInputDevice(sunMouseProc, TRUE);
224: k = AddInputDevice(sunKbdProc, TRUE);
225:
226: RegisterPointerDevice(p, MOTION_BUFFER_SIZE);
227: RegisterKeyboardDevice(k);
228: signal(SIGIO, SigIOHandler);
229:
230: SetInputCheck (&zero, &isItTimeToYield);
231: }
232:
233: /*-
234: *-----------------------------------------------------------------------
235: * sunQueryBestSize --
236: * Supposed to hint about good sizes for things.
237: *
238: * Results:
239: * Perhaps change *pwidth (Height irrelevant)
240: *
241: * Side Effects:
242: * None.
243: *
244: *-----------------------------------------------------------------------
245: */
246: /*ARGSUSED*/
247: void
248: sunQueryBestSize(class, pwidth, pheight)
249: int class;
250: short *pwidth;
251: short *pheight;
252: {
253: unsigned width, test;
254:
255: switch(class)
256: {
257: case CursorShape:
258: case TileShape:
259: case StippleShape:
260: width = *pwidth;
261: if (width > 0) {
262: /* Return the closes power of two not less than what they gave me */
263: test = 0x80000000;
264: /* Find the highest 1 bit in the width given */
265: while(!(test & width))
266: test >>= 1;
267: /* If their number is greater than that, bump up to the next
268: * power of two */
269: if((test - 1) & width)
270: test <<= 1;
271: *pwidth = test;
272: }
273: /* We don't care what height they use */
274: break;
275: }
276: }
277:
278: /*-
279: *-----------------------------------------------------------------------
280: * sunScreenInit --
281: * Things which must be done for all types of frame buffers...
282: * Should be called last of all.
283: *
284: * Results:
285: * None.
286: *
287: * Side Effects:
288: * The graphics context for the screen is created. The CreateGC,
289: * CreateWindow and ChangeWindowAttributes vectors are changed in
290: * the screen structure.
291: *
292: * Both a BlockHandler and a WakeupHandler are installed for the
293: * first screen. Together, these handlers implement autorepeat
294: * keystrokes on the Sun.
295: *
296: *-----------------------------------------------------------------------
297: */
298: void
299: sunScreenInit (pScreen)
300: ScreenPtr pScreen;
301: {
302: fbFd *fb;
303: DrawablePtr pDrawable;
304: extern void sunBlockHandler();
305: extern void sunWakeupHandler();
306: static autoRepeatHandlersInstalled = FALSE;
307: static ScreenPtr autoRepeatScreen;
308:
309: fb = &sunFbs[pScreen->myNum];
310:
311: /*
312: * Prepare the GC for cursor functions on this screen.
313: * Do this before setting interceptions to avoid looping when
314: * putting down the cursor...
315: */
316: pDrawable = (DrawablePtr)(pScreen->devPrivate);
317:
318: fb->pGC = CreateScratchGC (pDrawable->pScreen, pDrawable->depth);
319:
320: /*
321: * By setting graphicsExposures false, we prevent any expose events
322: * from being generated in the CopyArea requests used by the cursor
323: * routines.
324: */
325: fb->pGC->graphicsExposures = FALSE;
326:
327: /*
328: * Preserve the "regular" functions
329: */
330: fb->CreateGC = pScreen->CreateGC;
331: fb->CreateWindow = pScreen->CreateWindow;
332: fb->ChangeWindowAttributes = pScreen->ChangeWindowAttributes;
333: fb->GetImage = pScreen->GetImage;
334: fb->GetSpans = pScreen->GetSpans;
335:
336: /*
337: * Interceptions
338: */
339: pScreen->CreateGC = sunCreateGC;
340: pScreen->CreateWindow = sunCreateWindow;
341: pScreen->ChangeWindowAttributes = sunChangeWindowAttributes;
342: pScreen->QueryBestSize = sunQueryBestSize;
343: pScreen->GetImage = sunGetImage;
344: pScreen->GetSpans = sunGetSpans;
345:
346: /*
347: * Cursor functions
348: */
349: pScreen->RealizeCursor = sunRealizeCursor;
350: pScreen->UnrealizeCursor = sunUnrealizeCursor;
351: pScreen->DisplayCursor = sunDisplayCursor;
352: pScreen->SetCursorPosition = sunSetCursorPosition;
353: pScreen->CursorLimits = sunCursorLimits;
354: pScreen->PointerNonInterestBox = sunPointerNonInterestBox;
355: pScreen->ConstrainCursor = sunConstrainCursor;
356: pScreen->RecolorCursor = sunRecolorCursor;
357:
358: /*
359: * Block/Unblock handlers
360: */
361: if (autoRepeatHandlersInstalled == FALSE) {
362: autoRepeatScreen = pScreen;
363: autoRepeatHandlersInstalled = TRUE;
364: }
365:
366: if (pScreen == autoRepeatScreen) {
367: pScreen->BlockHandler = sunBlockHandler;
368: pScreen->WakeupHandler = sunWakeupHandler;
369: }
370:
371: }
372:
373: extern char *getenv();
374:
375: /*-
376: *-----------------------------------------------------------------------
377: * nthdev --
378: * Return the nth device in a colon-separated list of devices.
379: * n is 0-origin.
380: *
381: * Results:
382: * A pointer to a STATIC string which is the device name.
383: *
384: * Side Effects:
385: * None.
386: *
387: *-----------------------------------------------------------------------
388: */
389: static char *
390: nthdev (dList, n)
391: register char *dList; /* Colon-separated device names */
392: int n; /* Device number wanted */
393: {
394: char *result;
395: static char returnstring[100];
396:
397: while (n--) {
398: while (*dList && *dList != ':') {
399: dList++;
400: }
401: }
402: if (*dList) {
403: register char *cp = dList;
404:
405: while (*cp && *cp != ':') {
406: cp++;
407: }
408: result = returnstring;
409: strncpy (result, dList, cp - dList);
410: result[cp - dList] = '\0';
411: } else {
412: result = (char *)0;
413: }
414: return (result);
415: }
416:
417: /*-
418: *-----------------------------------------------------------------------
419: * sunOpenFrameBuffer --
420: * Open a frame buffer according to several rules. If running under
421: * overview and we're set up for it, use the device given in the
422: * PARENT envariable and note that the screen is under overview.
423: * Else find the device to use by looking in the sunFbData table,
424: * an XDEVICE envariable, a -dev switch or using /dev/fb if trying
425: * to open screen 0 and all else has failed.
426: *
427: * Results:
428: * The fd of the framebuffer.
429: *
430: * Side Effects:
431: *
432: *-----------------------------------------------------------------------
433: */
434: int
435: sunOpenFrameBuffer(expect, pfbType, index, fbNum, argc, argv)
436: int expect; /* The expected type of framebuffer */
437: struct fbtype *pfbType; /* Place to store the fb info */
438: int fbNum; /* Index into the sunFbData array */
439: int index; /* Screen index */
440: int argc; /* Command-line arguments... */
441: char **argv; /* ... */
442: {
443: char *name=(char *)0;
444: int i; /* Index into argument list */
445: int fd = -1; /* Descriptor to device */
446: static int devFbUsed=FALSE; /* true if /dev/fb has been used for a */
447: /* screen already */
448: static Bool inited = FALSE;
449: static char *xdevice; /* string of devices to use from environ */
450: static char *devsw; /* string of devices from args */
451:
452: sunFbs[index].parent = FALSE;
453:
454: if (!inited) {
455: xdevice = devsw = (char *)NULL;
456:
457: xdevice = getenv (XDEVICE);
458: /*
459: * Look for an argument of the form -dev <device-string>
460: * If such a one is found place the <device-string> in devsw.
461: */
462: for (i = 1; i < argc; i++) {
463: if ((strcmp(argv[i], "-dev") == 0) && (i + 1 < argc)) {
464: devsw = argv[i+1];
465: break;
466: }
467: }
468: inited = TRUE;
469: }
470:
471: /*
472: * Attempt to find a file name for the frame buffer
473: */
474:
475: /*
476: * First see if any device was given on the command line.
477: * If one was and the device is both readable and writeable,
478: * set 'name' to it, else set it to NULL.
479: */
480: if (devsw == (char *)NULL ||
481: (name = nthdev (devsw, index)) == (char *)NULL ||
482: (access (name, R_OK | W_OK) != 0) ||
483: (strcmp(name, sunFbData[fbNum].devName) != 0)) {
484: name = (char *)NULL;
485: }
486:
487: /*
488: * If we still don't have a device for this screen, check the
489: * environment variable for one. If one was given, stick its
490: * path in name and check its accessibility. If it's not
491: * properly accessible, then reset the name to NULL to force the
492: * checking of the sunFbData array.
493: */
494: if (devsw == (char *)NULL && name == (char *)NULL &&
495: xdevice != (char *)NULL &&
496: (name = nthdev(xdevice, index)) != (char *)NULL &&
497: (access (name, R_OK | W_OK) != 0)) {
498: name = (char *)NULL;
499: }
500:
501: /*
502: * Take the device given in the frame buffer description
503: * and see if it exists and is accessible. If it does/is,
504: * we will use it, as long as no other device was given.
505: */
506: if (devsw == (char *)NULL && name == (char *)NULL &&
507: access(sunFbData[fbNum].devName, (R_OK | W_OK)) == 0) {
508: name = sunFbData[fbNum].devName;
509: }
510:
511: /*
512: * If we still have nothing and have yet to use "/dev/fb" for
513: * a screen, default the name to be "/dev/fb"
514: */
515: if (devsw == (char *)NULL && name == (char *)NULL && !devFbUsed) {
516: name = "/dev/fb";
517: }
518:
519:
520: if (name != (char *) NULL && sunUseSunWindows()) {
521: #ifdef SUN_WINDOWS
522:
523: /*
524: * Running X in coexistence with SunWindows.
525: *
526: * This section of code enables X to run with SunWindows. This is
527: * accomplished by opening up screens and windows in the SunWindows
528: * style and accepting input events from them. However, since the X
529: * graphics libraries want a raw framebuffer, we open the
530: * framebuffer of the current screen and return that. So we get
531: * input from SunWindows but send output to the raw framebuffer.
532: */
533:
534: char *parent = getenv("WINDOW_PARENT");
535: struct screen sc;
536: int winFd;
537: int parentFd;
538: int framebufferFd;
539: Rect r;
540: static struct screen newScreen;
541: struct inputmask inputMask;
542: Bool keepParent = FALSE;
543:
544: /*
545: * If no device was specified on the command line, open the window
546: * specified in WINDOW_PARENT. If a device was specified, open a
547: * new screen on that device and use it as a parent window.
548: */
549:
550: if ( devsw ) {
551: bzero( (caddr_t)&newScreen, sizeof(newScreen) );
552: strcpy( newScreen.scr_fbname, name );
553: newScreen.scr_flags |= SCR_TOGGLEENABLE;
554: if ( (parentFd = win_screennew( &newScreen )) < 0 ) {
555: ErrorF( "sunOpenFrameBuffer: Can't open new screen on %s.\n",
556: name );
557: return( -1 );
558: }
559: keepParent = TRUE;
560: } else {
561: if ((parentFd = open(parent, 2, 0)) < 0) {
562: ErrorF("sunOpenFrameBuffer: Can't open parent %s.\n", parent);
563: return (-1);
564: }
565: }
566:
567: if ((winFd = win_getnewwindow()) < 0) {
568: ErrorF("sunOpenFrameBuffer: Can't open a new window.\n");
569: close( parentFd );
570: return (-1);
571: }
572:
573: /* link the new window into the window hierarchy */
574: bzero((caddr_t) & r, sizeof r);
575: win_getrect(parentFd, &r);
576: win_setrect(winFd, &r);
577: win_setlink(winFd, WL_PARENT, win_fdtonumber(parentFd));
578: win_setlink(winFd, WL_OLDERSIB, win_getlink(parentFd, WL_TOPCHILD));
579: sunFbs[index].parent = TRUE;
580:
581: /*
582: * We would like to close the parent window here, since it's no
583: * longer needed. However, in the case where the parent is really a
584: * screen, we have to keep it open, because closing a screen closes
585: * all the windows on that screen.
586: */
587:
588: if ( ! keepParent )
589: close(parentFd);
590:
591: /*
592: * Express interest in SunView mouse events. Note: the win_insert
593: * must be AFTER setting the input mask in order to receive the
594: * initial LOC_WINENTER event.
595: */
596:
597: input_imnull(&inputMask);
598: inputMask.im_flags = IM_ASCII | IM_META | IM_NEGEVENT | IM_INTRANSIT;
599:
600: #ifdef notdef
601: win_setinputcodebit(&inputMask, KBD_USE);
602: win_setinputcodebit(&inputMask, KBD_DONE);
603: #endif notdef
604: win_setinputcodebit(&inputMask, LOC_MOVE);
605: win_setinputcodebit(&inputMask, LOC_WINEXIT);
606: win_setinputcodebit(&inputMask, LOC_WINENTER);
607: win_setinputcodebit(&inputMask, MS_LEFT);
608: win_setinputcodebit(&inputMask, MS_MIDDLE);
609: win_setinputcodebit(&inputMask, MS_RIGHT);
610: win_set_pick_mask(winFd, &inputMask);
611:
612: win_insert(winFd);
613:
614: /*
615: * Determine the framebuffer name from the window's screen, then
616: * open it. Then do an FBIOGTYPE ioctl to determine its type.
617: */
618:
619: win_screenget( winFd, &sc );
620: if ((framebufferFd = open(sc.scr_fbname, O_RDWR, 0)) < 0) {
621: ErrorF("sunOpenFrameBuffer: can't open %s\n",sc.scr_fbname);
622: (void) close(winFd);
623: (void) close(parentFd);
624: return (-1);
625: }
626:
627: if (ioctl(framebufferFd, FBIOGTYPE, pfbType) < 0) {
628: perror("sunOpenFrameBuffer");
629: (void) close(framebufferFd);
630: (void) close(winFd);
631: (void) close(parentFd);
632: return (-1);
633: }
634:
635: if (pfbType->fb_type != expect) {
636: (void) close(framebufferFd);
637: (void) close(winFd);
638: (void) close(parentFd);
639: return (-1);
640: }
641:
642: /*
643: * NDELAY only applies to "input" fds, or fds that can be
644: * read. sunwindows fds are read, while frame buffer fds aren't.
645: * That's why this fcntl is in the conditional compilation section.
646: */
647:
648: if (fcntl(winFd, F_SETFL, O_NDELAY) < 0) {
649: ErrorF("Can't set O_NDELAY on %s\n",name);
650: perror("sunOpenFrameBuffer");
651: (void) close(winFd);
652: return (-1);
653: }
654:
655: fd = framebufferFd;
656: windowFd = winFd;
657: #else
658: ErrorF("Not configured to run inside SunWindows\n");
659: fd = -1;
660: #endif SUN_WINDOWS
661: } else if (name) {
662: fd = open(name, O_RDWR, 0);
663: if (fd < 0) {
664: return (-1);
665: }
666: if (ioctl(fd, FBIOGTYPE, pfbType) < 0) {
667: perror("sunOpenFrameBuffer");
668: (void) close(fd);
669: return (-1);
670: }
671: /* XXX - this is temporary 'cos the CG4 pretends its a BW2 */
672: if (strcmp(name, sunFbData[fbNum].devName) != 0 && pfbType->fb_type != expect) {
673: (void) close(fd);
674: return (-1);
675: }
676: }
677:
678: if (name && strcmp (name, "/dev/fb") == 0) {
679: devFbUsed = TRUE;
680: }
681:
682: return (fd);
683: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.