First import
[xorg_rtime.git] / xorg-server-1.4 / hw / xgl / glx / xglx.c
blob92974f0d4d8629b11276634e8faa8e6b3dba6832
1 /*
2 * Copyright © 2004 David Reveman
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of
9 * David Reveman not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior permission.
11 * David Reveman makes no representations about the suitability of this
12 * software for any purpose. It is provided "as is" without express or
13 * implied warranty.
15 * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17 * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Author: David Reveman <davidr@novell.com>
26 #include "xglx.h"
28 #include <X11/extensions/Xrandr.h>
29 #include <X11/cursorfont.h>
31 #include <glitz-glx.h>
33 #ifdef GLXEXT
34 #include "xglglxext.h"
35 #endif
37 #include "inputstr.h"
38 #include "cursorstr.h"
39 #include "mipointer.h"
41 #ifdef RANDR
42 #include "randrstr.h"
43 #endif
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <unistd.h>
48 #include <signal.h>
49 #include <math.h>
51 #ifdef XKB
52 #include <X11/extensions/XKB.h>
53 #include <xkbsrv.h>
54 #include <X11/extensions/XKBconfig.h>
56 extern Bool
57 XkbQueryExtension (Display *dpy,
58 int *opcodeReturn,
59 int *eventBaseReturn,
60 int *errorBaseReturn,
61 int *majorRtrn,
62 int *minorRtrn);
64 extern XkbDescPtr
65 XkbGetKeyboard (Display *dpy,
66 unsigned int which,
67 unsigned int deviceSpec);
69 extern Status
70 XkbGetControls (Display *dpy,
71 unsigned long which,
72 XkbDescPtr desc);
74 #ifndef XKB_BASE_DIRECTORY
75 #define XKB_BASE_DIRECTORY "/usr/lib/X11/xkb/"
76 #endif
77 #ifndef XKB_CONFIG_FILE
78 #define XKB_CONFIG_FILE "X0-config.keyboard"
79 #endif
80 #ifndef XKB_DFLT_RULES_FILE
81 #define XKB_DFLT_RULES_FILE "xorg"
82 #endif
83 #ifndef XKB_DFLT_KB_LAYOUT
84 #define XKB_DFLT_KB_LAYOUT "us"
85 #endif
86 #ifndef XKB_DFLT_KB_MODEL
87 #define XKB_DFLT_KB_MODEL "pc101"
88 #endif
89 #ifndef XKB_DFLT_KB_VARIANT
90 #define XKB_DFLT_KB_VARIANT NULL
91 #endif
92 #ifndef XKB_DFLT_KB_OPTIONS
93 #define XKB_DFLT_KB_OPTIONS NULL
94 #endif
96 #endif
98 #define XGLX_DEFAULT_SCREEN_WIDTH 800
99 #define XGLX_DEFAULT_SCREEN_HEIGHT 600
101 typedef struct _xglxScreen {
102 Window win, root;
103 Colormap colormap;
104 Bool fullscreen;
105 CloseScreenProcPtr CloseScreen;
106 } xglxScreenRec, *xglxScreenPtr;
108 int xglxScreenGeneration = -1;
109 int xglxScreenPrivateIndex;
111 #define XGLX_GET_SCREEN_PRIV(pScreen) \
112 ((xglxScreenPtr) (pScreen)->devPrivates[xglxScreenPrivateIndex].ptr)
114 #define XGLX_SET_SCREEN_PRIV(pScreen, v) \
115 ((pScreen)->devPrivates[xglxScreenPrivateIndex].ptr = (pointer) v)
117 #define XGLX_SCREEN_PRIV(pScreen) \
118 xglxScreenPtr pScreenPriv = XGLX_GET_SCREEN_PRIV (pScreen)
120 typedef struct _xglxCursor {
121 Cursor cursor;
122 } xglxCursorRec, *xglxCursorPtr;
124 #define XGLX_GET_CURSOR_PRIV(pCursor, pScreen) \
125 ((xglxCursorPtr) (pCursor)->devPriv[(pScreen)->myNum])
127 #define XGLX_SET_CURSOR_PRIV(pCursor, pScreen, v) \
128 ((pCursor)->devPriv[(pScreen)->myNum] = (pointer) v)
130 #define XGLX_CURSOR_PRIV(pCursor, pScreen) \
131 xglxCursorPtr pCursorPriv = XGLX_GET_CURSOR_PRIV (pCursor, pScreen)
133 static char *xDisplayName = 0;
134 static Display *xdisplay = 0;
135 static int xscreen;
136 static CARD32 lastEventTime = 0;
137 static ScreenPtr currentScreen = 0;
138 static Bool softCursor = FALSE;
139 static Bool fullscreen = TRUE;
141 static Bool randrExtension = FALSE;
142 static int randrEvent, randrError;
144 static glitz_drawable_format_t *xglxScreenFormat = 0;
146 static Bool
147 xglxAllocatePrivates (ScreenPtr pScreen)
149 xglxScreenPtr pScreenPriv;
151 if (xglxScreenGeneration != serverGeneration)
153 xglxScreenPrivateIndex = AllocateScreenPrivateIndex ();
154 if (xglxScreenPrivateIndex < 0)
155 return FALSE;
157 xglxScreenGeneration = serverGeneration;
160 pScreenPriv = xalloc (sizeof (xglxScreenRec));
161 if (!pScreenPriv)
162 return FALSE;
164 XGLX_SET_SCREEN_PRIV (pScreen, pScreenPriv);
166 return TRUE;
169 #ifdef RANDR
171 #define DEFAULT_REFRESH_RATE 50
173 static Bool
174 xglxRandRGetInfo (ScreenPtr pScreen,
175 Rotation *rotations)
177 RRScreenSizePtr pSize;
179 *rotations = RR_Rotate_0;
181 if (randrExtension)
183 XRRScreenConfiguration *xconfig;
184 XRRScreenSize *sizes;
185 int nSizes, currentSize = 0;
186 short *rates, currentRate;
187 int nRates, i, j;
189 XGLX_SCREEN_PRIV (pScreen);
191 xconfig = XRRGetScreenInfo (xdisplay, pScreenPriv->root);
192 sizes = XRRConfigSizes (xconfig, &nSizes);
193 currentRate = XRRConfigCurrentRate (xconfig);
195 if (pScreenPriv->fullscreen)
197 Rotation rotation;
199 currentSize = XRRConfigCurrentConfiguration (xconfig, &rotation);
201 for (i = 0; i < nSizes; i++)
203 pSize = RRRegisterSize (pScreen,
204 sizes[i].width,
205 sizes[i].height,
206 sizes[i].mwidth,
207 sizes[i].mheight);
209 rates = XRRConfigRates (xconfig, i, &nRates);
211 for (j = 0; j < nRates; j++)
213 RRRegisterRate (pScreen, pSize, rates[j]);
215 if (i == currentSize && rates[j] == currentRate)
216 RRSetCurrentConfig (pScreen, RR_Rotate_0, currentRate,
217 pSize);
221 else
223 pSize = RRRegisterSize (pScreen,
224 pScreen->width,
225 pScreen->height,
226 pScreen->mmWidth,
227 pScreen->mmHeight);
229 for (i = 0; i < nSizes; i++)
231 rates = XRRConfigRates (xconfig, i, &nRates);
233 for (j = 0; j < nRates; j++)
235 RRRegisterRate (pScreen, pSize, rates[j]);
237 if (rates[j] == currentRate)
238 RRSetCurrentConfig (pScreen, RR_Rotate_0, currentRate,
239 pSize);
244 XRRFreeScreenConfigInfo (xconfig);
246 else
248 pSize = RRRegisterSize (pScreen,
249 pScreen->width,
250 pScreen->height,
251 pScreen->mmWidth,
252 pScreen->mmHeight);
254 RRRegisterRate (pScreen, pSize, DEFAULT_REFRESH_RATE);
255 RRSetCurrentConfig (pScreen, RR_Rotate_0, DEFAULT_REFRESH_RATE, pSize);
258 return TRUE;
261 static Bool
262 xglxRandRSetConfig (ScreenPtr pScreen,
263 Rotation rotations,
264 int rate,
265 RRScreenSizePtr pSize)
267 if (randrExtension)
269 XRRScreenConfiguration *xconfig;
270 XRRScreenSize *sizes;
271 int nSizes, currentSize;
272 int i, size = -1;
273 int status = RRSetConfigFailed;
274 Rotation rotation;
276 XGLX_SCREEN_PRIV (pScreen);
278 xconfig = XRRGetScreenInfo (xdisplay, pScreenPriv->root);
279 sizes = XRRConfigSizes (xconfig, &nSizes);
280 currentSize = XRRConfigCurrentConfiguration (xconfig, &rotation);
282 for (i = 0; i < nSizes; i++)
284 if (pScreenPriv->fullscreen)
286 if (sizes[i].width == pSize->width &&
287 sizes[i].height == pSize->height &&
288 sizes[i].mwidth == pSize->mmWidth &&
289 sizes[i].mheight == pSize->mmHeight)
291 size = i;
292 break;
295 else
297 short *rates;
298 int nRates, j;
300 rates = XRRConfigRates (xconfig, i, &nRates);
302 for (j = 0; j < nRates; j++)
304 if (rates[j] == rate)
306 size = i;
307 if (i >= currentSize)
308 break;
314 if (size >= 0)
315 status = XRRSetScreenConfigAndRate (xdisplay,
316 xconfig,
317 pScreenPriv->root,
318 size,
319 RR_Rotate_0,
320 rate,
321 CurrentTime);
323 XRRFreeScreenConfigInfo (xconfig);
325 if (status == RRSetConfigSuccess)
327 PixmapPtr pPixmap;
329 pPixmap = (*pScreen->GetScreenPixmap) (pScreen);
331 if (pScreenPriv->fullscreen)
333 XGL_PIXMAP_PRIV (pPixmap);
335 xglSetRootClip (pScreen, FALSE);
337 XResizeWindow (xdisplay, pScreenPriv->win,
338 pSize->width, pSize->height);
340 glitz_drawable_update_size (pPixmapPriv->drawable,
341 pSize->width, pSize->height);
343 pScreen->width = pSize->width;
344 pScreen->height = pSize->height;
345 pScreen->mmWidth = pSize->mmWidth;
346 pScreen->mmHeight = pSize->mmHeight;
348 (*pScreen->ModifyPixmapHeader) (pPixmap,
349 pScreen->width,
350 pScreen->height,
351 pPixmap->drawable.depth,
352 pPixmap->drawable.bitsPerPixel,
353 0, 0);
355 xglSetRootClip (pScreen, TRUE);
358 return TRUE;
362 return FALSE;
365 static Bool
366 xglxRandRInit (ScreenPtr pScreen)
368 rrScrPrivPtr pScrPriv;
370 if (!RRScreenInit (pScreen))
371 return FALSE;
373 pScrPriv = rrGetScrPriv (pScreen);
374 pScrPriv->rrGetInfo = xglxRandRGetInfo;
375 pScrPriv->rrSetConfig = xglxRandRSetConfig;
377 return TRUE;
380 #endif
382 static void
383 xglxConstrainCursor (ScreenPtr pScreen,
384 BoxPtr pBox)
388 static void
389 xglxCursorLimits (ScreenPtr pScreen,
390 CursorPtr pCursor,
391 BoxPtr pHotBox,
392 BoxPtr pTopLeftBox)
394 *pTopLeftBox = *pHotBox;
397 static Bool
398 xglxDisplayCursor (ScreenPtr pScreen,
399 CursorPtr pCursor)
401 XGLX_SCREEN_PRIV (pScreen);
402 XGLX_CURSOR_PRIV (pCursor, pScreen);
404 XDefineCursor (xdisplay, pScreenPriv->win, pCursorPriv->cursor);
406 return TRUE;
409 #ifdef ARGB_CURSOR
411 static Bool
412 xglxARGBCursorSupport (void);
414 static Cursor
415 xglxCreateARGBCursor (ScreenPtr pScreen,
416 CursorPtr pCursor);
418 #endif
420 static Bool
421 xglxRealizeCursor (ScreenPtr pScreen,
422 CursorPtr pCursor)
424 xglxCursorPtr pCursorPriv;
425 XImage *ximage;
426 Pixmap source, mask;
427 XColor fgColor, bgColor;
428 XlibGC xgc;
429 unsigned long valuemask;
430 XGCValues values;
432 XGLX_SCREEN_PRIV (pScreen);
434 valuemask = GCForeground | GCBackground;
436 values.foreground = 1L;
437 values.background = 0L;
439 pCursorPriv = xalloc (sizeof (xglxCursorRec));
440 if (!pCursorPriv)
441 return FALSE;
443 XGLX_SET_CURSOR_PRIV (pCursor, pScreen, pCursorPriv);
445 #ifdef ARGB_CURSOR
446 if (pCursor->bits->argb)
448 pCursorPriv->cursor = xglxCreateARGBCursor (pScreen, pCursor);
449 if (pCursorPriv->cursor)
450 return TRUE;
452 #endif
454 source = XCreatePixmap (xdisplay,
455 pScreenPriv->win,
456 pCursor->bits->width,
457 pCursor->bits->height,
460 mask = XCreatePixmap (xdisplay,
461 pScreenPriv->win,
462 pCursor->bits->width,
463 pCursor->bits->height,
466 xgc = XCreateGC (xdisplay, source, valuemask, &values);
468 ximage = XCreateImage (xdisplay,
469 DefaultVisual (xdisplay, xscreen),
470 1, XYBitmap, 0,
471 (char *) pCursor->bits->source,
472 pCursor->bits->width,
473 pCursor->bits->height,
474 BitmapPad (xdisplay), 0);
476 XPutImage (xdisplay, source, xgc, ximage,
477 0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height);
479 XFree (ximage);
481 ximage = XCreateImage (xdisplay,
482 DefaultVisual (xdisplay, xscreen),
483 1, XYBitmap, 0,
484 (char *) pCursor->bits->mask,
485 pCursor->bits->width,
486 pCursor->bits->height,
487 BitmapPad (xdisplay), 0);
489 XPutImage (xdisplay, mask, xgc, ximage,
490 0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height);
492 XFree (ximage);
493 XFreeGC (xdisplay, xgc);
495 fgColor.red = pCursor->foreRed;
496 fgColor.green = pCursor->foreGreen;
497 fgColor.blue = pCursor->foreBlue;
499 bgColor.red = pCursor->backRed;
500 bgColor.green = pCursor->backGreen;
501 bgColor.blue = pCursor->backBlue;
503 pCursorPriv->cursor =
504 XCreatePixmapCursor (xdisplay, source, mask, &fgColor, &bgColor,
505 pCursor->bits->xhot, pCursor->bits->yhot);
507 XFreePixmap (xdisplay, mask);
508 XFreePixmap (xdisplay, source);
510 return TRUE;
513 static Bool
514 xglxUnrealizeCursor (ScreenPtr pScreen,
515 CursorPtr pCursor)
517 XGLX_CURSOR_PRIV (pCursor, pScreen);
519 XFreeCursor (xdisplay, pCursorPriv->cursor);
520 xfree (pCursorPriv);
522 return TRUE;
525 static void
526 xglxRecolorCursor (ScreenPtr pScreen,
527 CursorPtr pCursor,
528 Bool displayed)
530 XColor fgColor, bgColor;
532 XGLX_CURSOR_PRIV (pCursor, pScreen);
534 fgColor.red = pCursor->foreRed;
535 fgColor.green = pCursor->foreGreen;
536 fgColor.blue = pCursor->foreBlue;
538 bgColor.red = pCursor->backRed;
539 bgColor.green = pCursor->backGreen;
540 bgColor.blue = pCursor->backBlue;
542 XRecolorCursor (xdisplay, pCursorPriv->cursor, &fgColor, &bgColor);
545 static Bool
546 xglxSetCursorPosition (ScreenPtr pScreen,
547 int x,
548 int y,
549 Bool generateEvent)
551 XGLX_SCREEN_PRIV (pScreen);
553 XWarpPointer (xdisplay, pScreenPriv->win, pScreenPriv->win,
554 0, 0, 0, 0, x, y);
556 return TRUE;
559 static Bool
560 xglxCloseScreen (int index,
561 ScreenPtr pScreen)
563 glitz_drawable_t *drawable;
565 XGLX_SCREEN_PRIV (pScreen);
567 drawable = XGL_GET_SCREEN_PRIV (pScreen)->drawable;
568 if (drawable)
569 glitz_drawable_destroy (drawable);
571 xglClearVisualTypes ();
573 if (pScreenPriv->win)
574 XDestroyWindow (xdisplay, pScreenPriv->win);
576 if (pScreenPriv->colormap)
577 XFreeColormap (xdisplay, pScreenPriv->colormap);
579 XGL_SCREEN_UNWRAP (CloseScreen);
580 xfree (pScreenPriv);
582 return (*pScreen->CloseScreen) (index, pScreen);
585 static Bool
586 xglxCursorOffScreen (ScreenPtr *ppScreen, int *x, int *y)
588 return FALSE;
591 static void
592 xglxCrossScreen (ScreenPtr pScreen, Bool entering)
596 static void
597 xglxWarpCursor (ScreenPtr pScreen, int x, int y)
599 miPointerWarpCursor (pScreen, x, y);
602 miPointerScreenFuncRec xglxPointerScreenFuncs = {
603 xglxCursorOffScreen,
604 xglxCrossScreen,
605 xglxWarpCursor
608 static Bool
609 xglxScreenInit (int index,
610 ScreenPtr pScreen,
611 int argc,
612 char **argv)
614 XSetWindowAttributes xswa;
615 XWMHints *wmHints;
616 XSizeHints *normalHints;
617 XClassHint *classHint;
618 xglxScreenPtr pScreenPriv;
619 XVisualInfo *vinfo;
620 XEvent xevent;
621 glitz_drawable_format_t *format;
622 glitz_drawable_t *drawable;
624 format = xglxScreenFormat;
626 if (!xglxAllocatePrivates (pScreen))
627 return FALSE;
629 currentScreen = pScreen;
631 pScreenPriv = XGLX_GET_SCREEN_PRIV (pScreen);
633 pScreenPriv->root = RootWindow (xdisplay, xscreen);
634 pScreenPriv->fullscreen = fullscreen;
636 vinfo = glitz_glx_get_visual_info_from_format (xdisplay, xscreen, format);
637 if (!vinfo)
639 ErrorF ("[%d] no visual info from format\n", index);
640 return FALSE;
643 pScreenPriv->colormap =
644 XCreateColormap (xdisplay, pScreenPriv->root, vinfo->visual,
645 AllocNone);
647 if (XRRQueryExtension (xdisplay, &randrEvent, &randrError))
648 randrExtension = TRUE;
650 if (fullscreen)
652 xglScreenInfo.width = DisplayWidth (xdisplay, xscreen);
653 xglScreenInfo.height = DisplayHeight (xdisplay, xscreen);
654 xglScreenInfo.widthMm = DisplayWidthMM (xdisplay, xscreen);
655 xglScreenInfo.heightMm = DisplayHeightMM (xdisplay, xscreen);
657 if (randrExtension)
659 XRRScreenConfiguration *xconfig;
660 Rotation rotation;
661 XRRScreenSize *sizes;
662 int nSizes, currentSize;
664 xconfig = XRRGetScreenInfo (xdisplay, pScreenPriv->root);
665 currentSize = XRRConfigCurrentConfiguration (xconfig, &rotation);
666 sizes = XRRConfigSizes (xconfig, &nSizes);
668 xglScreenInfo.width = sizes[currentSize].width;
669 xglScreenInfo.height = sizes[currentSize].height;
670 xglScreenInfo.widthMm = sizes[currentSize].mwidth;
671 xglScreenInfo.heightMm = sizes[currentSize].mheight;
673 XRRFreeScreenConfigInfo (xconfig);
676 else if (xglScreenInfo.width == 0 || xglScreenInfo.height == 0)
678 xglScreenInfo.width = XGLX_DEFAULT_SCREEN_WIDTH;
679 xglScreenInfo.height = XGLX_DEFAULT_SCREEN_HEIGHT;
682 xswa.colormap = pScreenPriv->colormap;
684 pScreenPriv->win =
685 XCreateWindow (xdisplay, pScreenPriv->root, 0, 0,
686 xglScreenInfo.width, xglScreenInfo.height, 0,
687 vinfo->depth, InputOutput, vinfo->visual,
688 CWColormap, &xswa);
690 XFree (vinfo);
692 normalHints = XAllocSizeHints ();
693 normalHints->flags = PMinSize | PMaxSize | PSize;
694 normalHints->min_width = xglScreenInfo.width;
695 normalHints->min_height = xglScreenInfo.height;
696 normalHints->max_width = xglScreenInfo.width;
697 normalHints->max_height = xglScreenInfo.height;
699 if (fullscreen)
701 normalHints->x = 0;
702 normalHints->y = 0;
703 normalHints->flags |= PPosition;
706 classHint = XAllocClassHint ();
707 classHint->res_name = "xglx";
708 classHint->res_class = "Xglx";
710 wmHints = XAllocWMHints ();
711 wmHints->flags = InputHint;
712 wmHints->input = TRUE;
714 Xutf8SetWMProperties (xdisplay, pScreenPriv->win, "Xglx", "Xglx", 0, 0,
715 normalHints, wmHints, classHint);
717 XFree (wmHints);
718 XFree (classHint);
719 XFree (normalHints);
721 drawable = glitz_glx_create_drawable_for_window (xdisplay, xscreen,
722 format, pScreenPriv->win,
723 xglScreenInfo.width,
724 xglScreenInfo.height);
725 if (!drawable)
727 ErrorF ("[%d] couldn't create glitz drawable for window\n", index);
728 return FALSE;
731 XSelectInput (xdisplay, pScreenPriv->win,
732 ButtonPressMask | ButtonReleaseMask |
733 KeyPressMask | KeyReleaseMask | EnterWindowMask |
734 PointerMotionMask | ExposureMask);
736 XMapWindow (xdisplay, pScreenPriv->win);
738 if (fullscreen)
740 XClientMessageEvent xev;
742 memset (&xev, 0, sizeof (xev));
744 xev.type = ClientMessage;
745 xev.message_type = XInternAtom (xdisplay, "_NET_WM_STATE", FALSE);
746 xev.display = xdisplay;
747 xev.window = pScreenPriv->win;
748 xev.format = 32;
749 xev.data.l[0] = 1;
750 xev.data.l[1] =
751 XInternAtom (xdisplay, "_NET_WM_STATE_FULLSCREEN", FALSE);
753 XSendEvent (xdisplay, pScreenPriv->root, FALSE,
754 SubstructureRedirectMask, (XEvent *) &xev);
757 xglScreenInfo.drawable = drawable;
759 if (!xglScreenInit (pScreen))
760 return FALSE;
762 #ifdef GLXEXT
763 if (!xglInitVisualConfigs (pScreen))
764 return FALSE;
765 #endif
767 XGL_SCREEN_WRAP (CloseScreen, xglxCloseScreen);
769 #ifdef ARGB_CURSOR
770 if (!xglxARGBCursorSupport ())
771 softCursor = TRUE;
772 #endif
774 if (softCursor)
776 static char data = 0;
777 XColor black, dummy;
778 Pixmap bitmap;
779 Cursor cursor;
781 if (!XAllocNamedColor (xdisplay, pScreenPriv->colormap,
782 "black", &black, &dummy))
783 return FALSE;
785 bitmap = XCreateBitmapFromData (xdisplay, pScreenPriv->win, &data,
786 1, 1);
787 if (!bitmap)
788 return FALSE;
790 cursor = XCreatePixmapCursor (xdisplay, bitmap, bitmap, &black, &black,
791 0, 0);
792 if (!cursor)
793 return FALSE;
795 XDefineCursor (xdisplay, pScreenPriv->win, cursor);
797 XFreeCursor (xdisplay, cursor);
798 XFreePixmap (xdisplay, bitmap);
799 XFreeColors (xdisplay, pScreenPriv->colormap, &black.pixel, 1, 0);
801 miDCInitialize (pScreen, &xglxPointerScreenFuncs);
803 else
805 pScreen->ConstrainCursor = xglxConstrainCursor;
806 pScreen->CursorLimits = xglxCursorLimits;
807 pScreen->DisplayCursor = xglxDisplayCursor;
808 pScreen->RealizeCursor = xglxRealizeCursor;
809 pScreen->UnrealizeCursor = xglxUnrealizeCursor;
810 pScreen->RecolorCursor = xglxRecolorCursor;
811 pScreen->SetCursorPosition = xglxSetCursorPosition;
814 if (!xglFinishScreenInit (pScreen))
815 return FALSE;
817 #ifdef RANDR
818 if (!xglxRandRInit (pScreen))
819 return FALSE;
820 #endif
822 while (XNextEvent (xdisplay, &xevent))
823 if (xevent.type == Expose)
824 break;
826 return TRUE;
829 void
830 xglxInitOutput (ScreenInfo *pScreenInfo,
831 int argc,
832 char **argv)
834 glitz_drawable_format_t *format, templ;
835 int i;
836 unsigned long mask;
837 unsigned long extraMask[] = {
838 GLITZ_FORMAT_DOUBLEBUFFER_MASK | GLITZ_FORMAT_ALPHA_SIZE_MASK,
839 GLITZ_FORMAT_DOUBLEBUFFER_MASK,
840 GLITZ_FORMAT_ALPHA_SIZE_MASK,
844 xglClearVisualTypes ();
846 xglSetPixmapFormats (pScreenInfo);
848 if (!xdisplay)
850 char *name = xDisplayName;
852 if (!name)
853 name = xglxInitXorg ();
855 xdisplay = XOpenDisplay (name);
856 if (!xdisplay)
857 FatalError ("can't open display: %s\n", name ? name : "NULL");
859 xscreen = DefaultScreen (xdisplay);
861 if (!xDisplayName)
862 XDefineCursor (xdisplay, RootWindow (xdisplay, xscreen),
863 XCreateFontCursor (xdisplay, XC_watch));
866 templ.samples = 1;
867 templ.doublebuffer = 1;
868 templ.color.fourcc = GLITZ_FOURCC_RGB;
869 templ.color.alpha_size = 8;
871 mask = GLITZ_FORMAT_SAMPLES_MASK | GLITZ_FORMAT_FOURCC_MASK;
873 for (i = 0; i < sizeof (extraMask) / sizeof (extraMask[0]); i++)
875 format = glitz_glx_find_window_format (xdisplay, xscreen,
876 mask | extraMask[i],
877 &templ, 0);
878 if (format)
879 break;
882 if (!format)
883 FatalError ("no visual format found");
885 xglScreenInfo.depth =
886 format->color.red_size +
887 format->color.green_size +
888 format->color.blue_size;
890 xglSetVisualTypes (xglScreenInfo.depth,
891 (1 << TrueColor),
892 format->color.red_size,
893 format->color.green_size,
894 format->color.blue_size);
896 xglxScreenFormat = format;
898 AddScreen (xglxScreenInit, argc, argv);
901 static Bool
902 xglxExposurePredicate (Display *xdisplay,
903 XEvent *xevent,
904 char *args)
906 return (xevent->type == Expose);
909 static Bool
910 xglxNotExposurePredicate (Display *xdisplay,
911 XEvent *xevent,
912 char *args)
914 return (xevent->type != Expose);
917 static int
918 xglxWindowExposures (WindowPtr pWin,
919 pointer pReg)
921 ScreenPtr pScreen = pWin->drawable.pScreen;
922 RegionRec ClipList;
924 if (HasBorder (pWin))
926 REGION_INIT (pScreen, &ClipList, NullBox, 0);
927 REGION_SUBTRACT (pScreen, &ClipList, &pWin->borderClip,
928 &pWin->winSize);
929 REGION_INTERSECT (pScreen, &ClipList, &ClipList, (RegionPtr) pReg);
930 (*pScreen->PaintWindowBorder) (pWin, &ClipList, PW_BORDER);
931 REGION_UNINIT (pScreen, &ClipList);
934 REGION_INIT (pScreen, &ClipList, NullBox, 0);
935 REGION_INTERSECT (pScreen, &ClipList, &pWin->clipList, (RegionPtr) pReg);
936 (*pScreen->WindowExposures) (pWin, &ClipList, NullRegion);
937 REGION_UNINIT (pScreen, &ClipList);
939 return WT_WALKCHILDREN;
942 static void
943 xglxBlockHandler (pointer blockData,
944 OSTimePtr pTimeout,
945 pointer pReadMask)
947 XEvent X;
948 RegionRec region;
949 BoxRec box;
951 XGL_SCREEN_PRIV (currentScreen);
953 while (XCheckIfEvent (xdisplay, &X, xglxExposurePredicate, NULL))
955 ScreenPtr pScreen = currentScreen;
957 box.x1 = X.xexpose.x;
958 box.y1 = X.xexpose.y;
959 box.x2 = box.x1 + X.xexpose.width;
960 box.y2 = box.y1 + X.xexpose.height;
962 REGION_INIT (currentScreen, &region, &box, 1);
964 WalkTree (pScreen, xglxWindowExposures, &region);
966 REGION_UNINIT (pScreen, &region);
969 if (!xglSyncSurface (&pScreenPriv->pScreenPixmap->drawable))
970 FatalError (XGL_SW_FAILURE_STRING);
972 glitz_surface_flush (pScreenPriv->surface);
973 glitz_drawable_flush (pScreenPriv->drawable);
975 XFlush (xdisplay);
978 static void
979 xglxWakeupHandler (pointer blockData,
980 int result,
981 pointer pReadMask)
983 ScreenPtr pScreen = currentScreen;
984 XEvent X;
985 xEvent x;
987 while (XCheckIfEvent (xdisplay, &X, xglxNotExposurePredicate, NULL))
989 switch (X.type) {
990 case KeyPress:
991 x.u.u.type = KeyPress;
992 x.u.u.detail = X.xkey.keycode;
993 x.u.keyButtonPointer.time = lastEventTime = GetTimeInMillis ();
994 mieqEnqueue (&x);
995 break;
996 case KeyRelease:
997 x.u.u.type = KeyRelease;
998 x.u.u.detail = X.xkey.keycode;
999 x.u.keyButtonPointer.time = lastEventTime = GetTimeInMillis ();
1000 mieqEnqueue (&x);
1001 break;
1002 case ButtonPress:
1003 x.u.u.type = ButtonPress;
1004 x.u.u.detail = X.xbutton.button;
1005 x.u.keyButtonPointer.time = lastEventTime = GetTimeInMillis ();
1006 mieqEnqueue (&x);
1007 break;
1008 case ButtonRelease:
1009 x.u.u.type = ButtonRelease;
1010 x.u.u.detail = X.xbutton.button;
1011 x.u.keyButtonPointer.time = lastEventTime = GetTimeInMillis ();
1012 mieqEnqueue (&x);
1013 break;
1014 case MotionNotify:
1015 x.u.u.type = MotionNotify;
1016 x.u.u.detail = 0;
1017 x.u.keyButtonPointer.rootX = X.xmotion.x;
1018 x.u.keyButtonPointer.rootY = X.xmotion.y;
1019 x.u.keyButtonPointer.time = lastEventTime = GetTimeInMillis ();
1020 miPointerAbsoluteCursor (X.xmotion.x, X.xmotion.y, lastEventTime);
1021 mieqEnqueue (&x);
1022 break;
1023 case EnterNotify:
1024 if (X.xcrossing.detail != NotifyInferior) {
1025 if (pScreen) {
1026 NewCurrentScreen (pScreen, X.xcrossing.x, X.xcrossing.y);
1027 x.u.u.type = MotionNotify;
1028 x.u.u.detail = 0;
1029 x.u.keyButtonPointer.rootX = X.xcrossing.x;
1030 x.u.keyButtonPointer.rootY = X.xcrossing.y;
1031 x.u.keyButtonPointer.time = lastEventTime =
1032 GetTimeInMillis ();
1033 mieqEnqueue (&x);
1036 break;
1037 default:
1038 break;
1043 static void
1044 xglxBell (int volume,
1045 DeviceIntPtr pDev,
1046 pointer ctrl,
1047 int cls)
1049 XBell (xdisplay, volume);
1052 static void
1053 xglxKbdCtrl (DeviceIntPtr pDev,
1054 KeybdCtrl *ctrl)
1056 unsigned long valueMask;
1057 XKeyboardControl values;
1058 int i;
1060 valueMask = KBKeyClickPercent | KBBellPercent | KBBellPitch |
1061 KBBellDuration | KBAutoRepeatMode;
1063 values.key_click_percent = ctrl->click;
1064 values.bell_percent = ctrl->bell;
1065 values.bell_pitch = ctrl->bell_pitch;
1066 values.bell_duration = ctrl->bell_duration;
1067 values.auto_repeat_mode = (ctrl->autoRepeat) ? AutoRepeatModeOn :
1068 AutoRepeatModeOff;
1070 XChangeKeyboardControl (xdisplay, valueMask, &values);
1072 valueMask = KBLed | KBLedMode;
1074 for (i = 1; i <= 32; i++)
1076 values.led = i;
1077 values.led_mode = (ctrl->leds & (1 << (i - 1))) ? LedModeOn :
1078 LedModeOff;
1080 XChangeKeyboardControl (xdisplay, valueMask, &values);
1084 static int
1085 xglxKeybdProc (DeviceIntPtr pDevice,
1086 int onoff)
1088 Bool ret = FALSE;
1089 DevicePtr pDev = (DevicePtr) pDevice;
1091 if (!pDev)
1092 return BadImplementation;
1094 switch (onoff) {
1095 case DEVICE_INIT: {
1096 XModifierKeymap *xmodMap;
1097 KeySym *xkeyMap;
1098 int minKeyCode, maxKeyCode, mapWidth, i, j;
1099 KeySymsRec xglxKeySyms;
1100 CARD8 xglxModMap[256];
1101 XKeyboardState values;
1103 #ifdef _XSERVER64
1104 KeySym64 *xkeyMap64;
1105 int len;
1106 #endif
1108 #ifdef XKB
1109 Bool xkbExtension = FALSE;
1110 int xkbOp, xkbEvent, xkbError, xkbMajor, xkbMinor;
1111 #endif
1113 if (pDev != LookupKeyboardDevice ())
1114 return !Success;
1116 xmodMap = XGetModifierMapping (xdisplay);
1118 XDisplayKeycodes (xdisplay, &minKeyCode, &maxKeyCode);
1120 #ifdef _XSERVER64
1121 xkeyMap64 = XGetKeyboardMapping (xdisplay,
1122 minKeyCode,
1123 maxKeyCode - minKeyCode + 1,
1124 &mapWidth);
1126 len = (maxKeyCode - minKeyCode + 1) * mapWidth;
1127 xkeyMap = (KeySym *) xalloc (len * sizeof (KeySym));
1128 for (i = 0; i < len; ++i)
1129 xkeyMap[i] = xkeyMap64[i];
1131 XFree (xkeyMap64);
1132 #else
1133 xkeyMap = XGetKeyboardMapping (xdisplay,
1134 minKeyCode,
1135 maxKeyCode - minKeyCode + 1,
1136 &mapWidth);
1137 #endif
1139 memset (xglxModMap, 0, 256);
1141 for (j = 0; j < 8; j++)
1143 for (i = 0; i < xmodMap->max_keypermod; i++)
1145 CARD8 keyCode;
1147 keyCode = xmodMap->modifiermap[j * xmodMap->max_keypermod + i];
1148 if (keyCode)
1149 xglxModMap[keyCode] |= 1 << j;
1153 XFreeModifiermap (xmodMap);
1155 xglxKeySyms.minKeyCode = minKeyCode;
1156 xglxKeySyms.maxKeyCode = maxKeyCode;
1157 xglxKeySyms.mapWidth = mapWidth;
1158 xglxKeySyms.map = xkeyMap;
1160 #ifdef XKB
1161 if (!noXkbExtension)
1162 xkbExtension = XkbQueryExtension (xdisplay,
1163 &xkbOp, &xkbEvent, &xkbError,
1164 &xkbMajor, &xkbMinor);
1166 if (xkbExtension)
1168 XkbDescPtr desc;
1169 char *rules, *model, *layout, *variants, *options;
1171 desc = XkbGetKeyboard (xdisplay,
1172 XkbGBN_AllComponentsMask,
1173 XkbUseCoreKbd);
1175 if (desc && desc->geom)
1177 XkbComponentNamesRec names;
1178 FILE *file;
1180 rules = XKB_DFLT_RULES_FILE;
1181 model = XKB_DFLT_KB_MODEL;
1182 layout = XKB_DFLT_KB_LAYOUT;
1183 variants = XKB_DFLT_KB_VARIANT;
1184 options = XKB_DFLT_KB_OPTIONS;
1186 XkbGetControls (xdisplay, XkbAllControlsMask, desc);
1188 memset (&names, 0, sizeof (XkbComponentNamesRec));
1190 XkbSetRulesDflts (rules, model, layout, variants, options);
1192 ret = XkbInitKeyboardDeviceStruct ((pointer) pDev,
1193 &names,
1194 &xglxKeySyms,
1195 xglxModMap,
1196 xglxBell,
1197 xglxKbdCtrl);
1199 if (ret)
1200 XkbDDXChangeControls ((pointer) pDev, desc->ctrls,
1201 desc->ctrls);
1203 XkbFreeKeyboard (desc, 0, False);
1206 #endif
1208 if (!ret)
1210 XGetKeyboardControl (xdisplay, &values);
1212 memmove (defaultKeyboardControl.autoRepeats,
1213 values.auto_repeats, sizeof (values.auto_repeats));
1215 ret = InitKeyboardDeviceStruct (pDev,
1216 &xglxKeySyms,
1217 xglxModMap,
1218 xglxBell,
1219 xglxKbdCtrl);
1222 #ifdef _XSERVER64
1223 xfree (xkeyMap);
1224 #else
1225 XFree (xkeyMap);
1226 #endif
1228 if (!ret)
1229 return BadImplementation;
1231 } break;
1232 case DEVICE_ON:
1233 pDev->on = TRUE;
1234 break;
1235 case DEVICE_OFF:
1236 case DEVICE_CLOSE:
1237 pDev->on = FALSE;
1238 break;
1241 return Success;
1244 Bool
1245 xglxLegalModifier (unsigned int key,
1246 DeviceIntPtr pDev)
1248 return TRUE;
1251 void
1252 xglxProcessInputEvents (void)
1254 mieqProcessInputEvents ();
1255 miPointerUpdate ();
1258 void
1259 xglxInitInput (int argc,
1260 char **argv)
1262 DeviceIntPtr pKeyboard, pPointer;
1264 pPointer = AddInputDevice (xglMouseProc, TRUE);
1265 pKeyboard = AddInputDevice (xglxKeybdProc, TRUE);
1267 RegisterPointerDevice (pPointer);
1268 RegisterKeyboardDevice (pKeyboard);
1270 miRegisterPointerDevice (screenInfo.screens[0], pPointer);
1271 mieqInit (&pKeyboard->public, &pPointer->public);
1273 AddEnabledDevice (XConnectionNumber (xdisplay));
1275 RegisterBlockAndWakeupHandlers (xglxBlockHandler,
1276 xglxWakeupHandler,
1277 NULL);
1280 void
1281 xglxUseMsg (void)
1283 ErrorF ("-screen WIDTH[/WIDTHMM]xHEIGHT[/HEIGHTMM] "
1284 "specify screen characteristics\n");
1285 ErrorF ("-fullscreen run fullscreen\n");
1286 ErrorF ("-display string display name of the real server\n");
1287 ErrorF ("-softcursor force software cursor\n");
1289 if (!xDisplayName)
1290 xglxUseXorgMsg ();
1294 xglxProcessArgument (int argc,
1295 char **argv,
1296 int i)
1298 static Bool checkDisplayName = FALSE;
1300 if (!checkDisplayName)
1302 char *display = ":0";
1303 int j;
1305 for (j = i; j < argc; j++)
1307 if (!strcmp (argv[j], "-display"))
1309 if (++j < argc)
1310 xDisplayName = argv[j];
1312 break;
1314 else if (argv[j][0] == ':')
1316 display = argv[j];
1320 if (!xDisplayName)
1321 xDisplayName = getenv ("DISPLAY");
1323 if (xDisplayName)
1325 int n;
1327 n = strspn (xDisplayName, ":0123456789");
1328 if (strncmp (xDisplayName, display, n) == 0)
1329 xDisplayName = 0;
1332 if (xDisplayName)
1333 fullscreen = FALSE;
1335 checkDisplayName = TRUE;
1338 if (!strcmp (argv[i], "-screen"))
1340 if ((i + 1) < argc)
1342 xglParseScreen (argv[i + 1]);
1344 else
1345 return 1;
1347 return 2;
1349 else if (!strcmp (argv[i], "-fullscreen"))
1351 fullscreen = TRUE;
1352 return 1;
1354 else if (!strcmp (argv[i], "-display"))
1356 if (++i < argc)
1357 return 2;
1359 return 0;
1361 else if (!strcmp (argv[i], "-softcursor"))
1363 softCursor = TRUE;
1364 return 1;
1366 else if (!xDisplayName)
1368 return xglxProcessXorgArgument (argc, argv, i);
1371 return 0;
1374 void
1375 xglxAbort (void)
1377 xglxAbortXorg ();
1380 void
1381 xglxGiveUp (void)
1383 AbortDDX ();
1386 void
1387 xglxOsVendorInit (void)
1391 #ifdef ARGB_CURSOR
1393 #include <X11/extensions/Xrender.h>
1395 static Bool
1396 xglxARGBCursorSupport (void)
1398 int renderMajor, renderMinor;
1400 if (!XRenderQueryVersion (xdisplay, &renderMajor, &renderMinor))
1401 renderMajor = renderMinor = -1;
1403 return (renderMajor > 0 || renderMinor > 4);
1406 static Cursor
1407 xglxCreateARGBCursor (ScreenPtr pScreen,
1408 CursorPtr pCursor)
1410 Pixmap xpixmap;
1411 XlibGC xgc;
1412 XImage *ximage;
1413 XRenderPictFormat *xformat;
1414 Picture xpicture;
1415 Cursor cursor;
1417 XGLX_SCREEN_PRIV (pScreen);
1419 xpixmap = XCreatePixmap (xdisplay,
1420 pScreenPriv->win,
1421 pCursor->bits->width,
1422 pCursor->bits->height,
1423 32);
1425 xgc = XCreateGC (xdisplay, xpixmap, 0, NULL);
1427 ximage = XCreateImage (xdisplay,
1428 DefaultVisual (xdisplay, xscreen),
1429 32, ZPixmap, 0,
1430 (char *) pCursor->bits->argb,
1431 pCursor->bits->width,
1432 pCursor->bits->height,
1433 32, pCursor->bits->width * 4);
1435 XPutImage (xdisplay, xpixmap, xgc, ximage,
1436 0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height);
1438 XFree (ximage);
1439 XFreeGC (xdisplay, xgc);
1441 xformat = XRenderFindStandardFormat (xdisplay, PictStandardARGB32);
1442 xpicture = XRenderCreatePicture (xdisplay, xpixmap, xformat, 0, 0);
1444 cursor = XRenderCreateCursor (xdisplay, xpicture,
1445 pCursor->bits->xhot,
1446 pCursor->bits->yhot);
1448 XRenderFreePicture (xdisplay, xpicture);
1449 XFreePixmap (xdisplay, xpixmap);
1451 return cursor;
1454 #endif