105b261ecSmrg/* 2ed6184dfSmrg * Xephyr - A kdrive X server that runs in a host X window. 305b261ecSmrg * Authored by Matthew Allum <mallum@openedhand.com> 435c4bbdfSmrg * 535c4bbdfSmrg * Copyright © 2004 Nokia 605b261ecSmrg * 705b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its 805b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that 905b261ecSmrg * the above copyright notice appear in all copies and that both that 1005b261ecSmrg * copyright notice and this permission notice appear in supporting 1105b261ecSmrg * documentation, and that the name of Nokia not be used in 1205b261ecSmrg * advertising or publicity pertaining to distribution of the software without 1305b261ecSmrg * specific, written prior permission. Nokia makes no 1405b261ecSmrg * representations about the suitability of this software for any purpose. It 1505b261ecSmrg * is provided "as is" without express or implied warranty. 1605b261ecSmrg * 1705b261ecSmrg * NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1805b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1905b261ecSmrg * EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR 2005b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 2105b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 2205b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 2305b261ecSmrg * PERFORMANCE OF THIS SOFTWARE. 2405b261ecSmrg */ 2505b261ecSmrg 261b5d61b8Smrg#ifdef HAVE_DIX_CONFIG_H 271b5d61b8Smrg#include <dix-config.h> 2805b261ecSmrg#endif 2935c4bbdfSmrg 3035c4bbdfSmrg#include <xcb/xcb_keysyms.h> 3135c4bbdfSmrg#include <X11/keysym.h> 3235c4bbdfSmrg 3305b261ecSmrg#include "ephyr.h" 3405b261ecSmrg 3505b261ecSmrg#include "inputstr.h" 364642e01fSmrg#include "scrnintstr.h" 374642e01fSmrg#include "ephyrlog.h" 384642e01fSmrg 3935c4bbdfSmrg#ifdef GLAMOR 4035c4bbdfSmrg#include "glamor.h" 4135c4bbdfSmrg#endif 4235c4bbdfSmrg#include "ephyr_glamor_glx.h" 431b5d61b8Smrg#include "glx_extinit.h" 446747b715Smrg#include "xkbsrv.h" 456747b715Smrg 4635c4bbdfSmrgextern Bool ephyr_glamor; 474642e01fSmrg 4805b261ecSmrgKdKeyboardInfo *ephyrKbd; 4905b261ecSmrgKdPointerInfo *ephyrMouse; 5035c4bbdfSmrgBool ephyrNoDRI = FALSE; 5135c4bbdfSmrgBool ephyrNoXV = FALSE; 5205b261ecSmrg 5305b261ecSmrgstatic int mouseState = 0; 5435c4bbdfSmrgstatic Rotation ephyrRandr = RR_Rotate_0; 5505b261ecSmrg 5605b261ecSmrgtypedef struct _EphyrInputPrivate { 5735c4bbdfSmrg Bool enabled; 5805b261ecSmrg} EphyrKbdPrivate, EphyrPointerPrivate; 5905b261ecSmrg 6035c4bbdfSmrgBool EphyrWantGrayScale = 0; 6135c4bbdfSmrgBool EphyrWantResize = 0; 6235c4bbdfSmrgBool EphyrWantNoHostGrab = 0; 634642e01fSmrg 6405b261ecSmrgBool 6535c4bbdfSmrgephyrInitialize(KdCardInfo * card, EphyrPriv * priv) 6605b261ecSmrg{ 6735c4bbdfSmrg OsSignal(SIGUSR1, hostx_handle_signal); 6835c4bbdfSmrg 6935c4bbdfSmrg priv->base = 0; 7035c4bbdfSmrg priv->bytes_per_line = 0; 7135c4bbdfSmrg return TRUE; 7205b261ecSmrg} 7305b261ecSmrg 7405b261ecSmrgBool 7535c4bbdfSmrgephyrCardInit(KdCardInfo * card) 7605b261ecSmrg{ 7735c4bbdfSmrg EphyrPriv *priv; 7835c4bbdfSmrg 7935c4bbdfSmrg priv = (EphyrPriv *) malloc(sizeof(EphyrPriv)); 8035c4bbdfSmrg if (!priv) 8135c4bbdfSmrg return FALSE; 8235c4bbdfSmrg 8335c4bbdfSmrg if (!ephyrInitialize(card, priv)) { 8435c4bbdfSmrg free(priv); 8535c4bbdfSmrg return FALSE; 8605b261ecSmrg } 8735c4bbdfSmrg card->driver = priv; 8835c4bbdfSmrg 8935c4bbdfSmrg return TRUE; 9005b261ecSmrg} 9105b261ecSmrg 9205b261ecSmrgBool 9335c4bbdfSmrgephyrScreenInitialize(KdScreenInfo *screen) 9405b261ecSmrg{ 9535c4bbdfSmrg EphyrScrPriv *scrpriv = screen->driver; 9635c4bbdfSmrg int x = 0, y = 0; 9735c4bbdfSmrg int width = 640, height = 480; 9835c4bbdfSmrg CARD32 redMask, greenMask, blueMask; 9935c4bbdfSmrg 10035c4bbdfSmrg if (hostx_want_screen_geometry(screen, &width, &height, &x, &y) 10135c4bbdfSmrg || !screen->width || !screen->height) { 10235c4bbdfSmrg screen->width = width; 10335c4bbdfSmrg screen->height = height; 10435c4bbdfSmrg screen->x = x; 10535c4bbdfSmrg screen->y = y; 10605b261ecSmrg } 10705b261ecSmrg 10835c4bbdfSmrg if (EphyrWantGrayScale) 10935c4bbdfSmrg screen->fb.depth = 8; 11005b261ecSmrg 11135c4bbdfSmrg if (screen->fb.depth && screen->fb.depth != hostx_get_depth()) { 11235c4bbdfSmrg if (screen->fb.depth < hostx_get_depth() 11335c4bbdfSmrg && (screen->fb.depth == 24 || screen->fb.depth == 16 11435c4bbdfSmrg || screen->fb.depth == 8)) { 11535c4bbdfSmrg scrpriv->server_depth = screen->fb.depth; 11635c4bbdfSmrg } 11735c4bbdfSmrg else 11835c4bbdfSmrg ErrorF 11935c4bbdfSmrg ("\nXephyr: requested screen depth not supported, setting to match hosts.\n"); 12005b261ecSmrg } 12105b261ecSmrg 12235c4bbdfSmrg screen->fb.depth = hostx_get_server_depth(screen); 12335c4bbdfSmrg screen->rate = 72; 12435c4bbdfSmrg 12535c4bbdfSmrg if (screen->fb.depth <= 8) { 12635c4bbdfSmrg if (EphyrWantGrayScale) 12735c4bbdfSmrg screen->fb.visuals = ((1 << StaticGray) | (1 << GrayScale)); 12835c4bbdfSmrg else 12935c4bbdfSmrg screen->fb.visuals = ((1 << StaticGray) | 13035c4bbdfSmrg (1 << GrayScale) | 13135c4bbdfSmrg (1 << StaticColor) | 13235c4bbdfSmrg (1 << PseudoColor) | 13335c4bbdfSmrg (1 << TrueColor) | (1 << DirectColor)); 13435c4bbdfSmrg 13535c4bbdfSmrg screen->fb.redMask = 0x00; 13635c4bbdfSmrg screen->fb.greenMask = 0x00; 13735c4bbdfSmrg screen->fb.blueMask = 0x00; 13835c4bbdfSmrg screen->fb.depth = 8; 13935c4bbdfSmrg screen->fb.bitsPerPixel = 8; 14035c4bbdfSmrg } 14135c4bbdfSmrg else { 14235c4bbdfSmrg screen->fb.visuals = (1 << TrueColor); 14305b261ecSmrg 14435c4bbdfSmrg if (screen->fb.depth <= 15) { 14535c4bbdfSmrg screen->fb.depth = 15; 14635c4bbdfSmrg screen->fb.bitsPerPixel = 16; 14735c4bbdfSmrg } 14835c4bbdfSmrg else if (screen->fb.depth <= 16) { 14935c4bbdfSmrg screen->fb.depth = 16; 15035c4bbdfSmrg screen->fb.bitsPerPixel = 16; 15135c4bbdfSmrg } 15235c4bbdfSmrg else if (screen->fb.depth <= 24) { 15335c4bbdfSmrg screen->fb.depth = 24; 15435c4bbdfSmrg screen->fb.bitsPerPixel = 32; 15535c4bbdfSmrg } 15635c4bbdfSmrg else if (screen->fb.depth <= 30) { 15735c4bbdfSmrg screen->fb.depth = 30; 15835c4bbdfSmrg screen->fb.bitsPerPixel = 32; 15935c4bbdfSmrg } 16035c4bbdfSmrg else { 16135c4bbdfSmrg ErrorF("\nXephyr: Unsupported screen depth %d\n", screen->fb.depth); 16235c4bbdfSmrg return FALSE; 16335c4bbdfSmrg } 16405b261ecSmrg 16535c4bbdfSmrg hostx_get_visual_masks(screen, &redMask, &greenMask, &blueMask); 16605b261ecSmrg 16735c4bbdfSmrg screen->fb.redMask = (Pixel) redMask; 16835c4bbdfSmrg screen->fb.greenMask = (Pixel) greenMask; 16935c4bbdfSmrg screen->fb.blueMask = (Pixel) blueMask; 17005b261ecSmrg 17105b261ecSmrg } 17205b261ecSmrg 17335c4bbdfSmrg scrpriv->randr = screen->randr; 17435c4bbdfSmrg 17535c4bbdfSmrg return ephyrMapFramebuffer(screen); 17605b261ecSmrg} 17735c4bbdfSmrg 17835c4bbdfSmrgvoid * 17935c4bbdfSmrgephyrWindowLinear(ScreenPtr pScreen, 18035c4bbdfSmrg CARD32 row, 18135c4bbdfSmrg CARD32 offset, int mode, CARD32 *size, void *closure) 18205b261ecSmrg{ 18335c4bbdfSmrg KdScreenPriv(pScreen); 18435c4bbdfSmrg EphyrPriv *priv = pScreenPriv->card->driver; 18535c4bbdfSmrg 18635c4bbdfSmrg if (!pScreenPriv->enabled) 18735c4bbdfSmrg return 0; 18835c4bbdfSmrg 18935c4bbdfSmrg *size = priv->bytes_per_line; 19035c4bbdfSmrg return priv->base + row * priv->bytes_per_line + offset; 19105b261ecSmrg} 19205b261ecSmrg 1936747b715Smrg/** 1946747b715Smrg * Figure out display buffer size. If fakexa is enabled, allocate a larger 1956747b715Smrg * buffer so that fakexa has space to put offscreen pixmaps. 1966747b715Smrg */ 1976747b715Smrgint 19835c4bbdfSmrgephyrBufferHeight(KdScreenInfo * screen) 1996747b715Smrg{ 2006747b715Smrg int buffer_height; 20135c4bbdfSmrg 2026747b715Smrg if (ephyrFuncs.initAccel == NULL) 20335c4bbdfSmrg buffer_height = screen->height; 2046747b715Smrg else 20535c4bbdfSmrg buffer_height = 3 * screen->height; 2066747b715Smrg return buffer_height; 2076747b715Smrg} 2086747b715Smrg 20905b261ecSmrgBool 21035c4bbdfSmrgephyrMapFramebuffer(KdScreenInfo * screen) 21105b261ecSmrg{ 21235c4bbdfSmrg EphyrScrPriv *scrpriv = screen->driver; 21335c4bbdfSmrg EphyrPriv *priv = screen->card->driver; 21435c4bbdfSmrg KdPointerMatrix m; 21535c4bbdfSmrg int buffer_height; 21635c4bbdfSmrg 21735c4bbdfSmrg EPHYR_LOG("screen->width: %d, screen->height: %d index=%d", 21835c4bbdfSmrg screen->width, screen->height, screen->mynum); 21935c4bbdfSmrg 22035c4bbdfSmrg /* 22135c4bbdfSmrg * Use the rotation last applied to ourselves (in the Xephyr case the fb 222ed6184dfSmrg * coordinate system moves independently of the pointer coordinate system). 22335c4bbdfSmrg */ 22435c4bbdfSmrg KdComputePointerMatrix(&m, ephyrRandr, screen->width, screen->height); 22535c4bbdfSmrg KdSetPointerMatrix(&m); 22635c4bbdfSmrg 22735c4bbdfSmrg buffer_height = ephyrBufferHeight(screen); 22835c4bbdfSmrg 22935c4bbdfSmrg priv->base = 23035c4bbdfSmrg hostx_screen_init(screen, screen->x, screen->y, 23135c4bbdfSmrg screen->width, screen->height, buffer_height, 23235c4bbdfSmrg &priv->bytes_per_line, &screen->fb.bitsPerPixel); 23335c4bbdfSmrg 23435c4bbdfSmrg if ((scrpriv->randr & RR_Rotate_0) && !(scrpriv->randr & RR_Reflect_All)) { 23535c4bbdfSmrg scrpriv->shadow = FALSE; 23635c4bbdfSmrg 23735c4bbdfSmrg screen->fb.byteStride = priv->bytes_per_line; 23835c4bbdfSmrg screen->fb.pixelStride = screen->width; 23935c4bbdfSmrg screen->fb.frameBuffer = (CARD8 *) (priv->base); 24005b261ecSmrg } 24135c4bbdfSmrg else { 24235c4bbdfSmrg /* Rotated/Reflected so we need to use shadow fb */ 24335c4bbdfSmrg scrpriv->shadow = TRUE; 24435c4bbdfSmrg 24535c4bbdfSmrg EPHYR_LOG("allocing shadow"); 24635c4bbdfSmrg 24735c4bbdfSmrg KdShadowFbAlloc(screen, 24835c4bbdfSmrg scrpriv->randr & (RR_Rotate_90 | RR_Rotate_270)); 24905b261ecSmrg } 25035c4bbdfSmrg 25135c4bbdfSmrg return TRUE; 25205b261ecSmrg} 25305b261ecSmrg 25405b261ecSmrgvoid 25535c4bbdfSmrgephyrSetScreenSizes(ScreenPtr pScreen) 25605b261ecSmrg{ 25735c4bbdfSmrg KdScreenPriv(pScreen); 25835c4bbdfSmrg KdScreenInfo *screen = pScreenPriv->screen; 25935c4bbdfSmrg EphyrScrPriv *scrpriv = screen->driver; 26035c4bbdfSmrg 26135c4bbdfSmrg if (scrpriv->randr & (RR_Rotate_0 | RR_Rotate_180)) { 26235c4bbdfSmrg pScreen->width = screen->width; 26335c4bbdfSmrg pScreen->height = screen->height; 26435c4bbdfSmrg pScreen->mmWidth = screen->width_mm; 26535c4bbdfSmrg pScreen->mmHeight = screen->height_mm; 26605b261ecSmrg } 26735c4bbdfSmrg else { 26835c4bbdfSmrg pScreen->width = screen->height; 26935c4bbdfSmrg pScreen->height = screen->width; 27035c4bbdfSmrg pScreen->mmWidth = screen->height_mm; 27135c4bbdfSmrg pScreen->mmHeight = screen->width_mm; 27205b261ecSmrg } 27305b261ecSmrg} 27405b261ecSmrg 27505b261ecSmrgBool 27635c4bbdfSmrgephyrUnmapFramebuffer(KdScreenInfo * screen) 27705b261ecSmrg{ 27835c4bbdfSmrg EphyrScrPriv *scrpriv = screen->driver; 27905b261ecSmrg 28035c4bbdfSmrg if (scrpriv->shadow) 28135c4bbdfSmrg KdShadowFbFree(screen); 28205b261ecSmrg 28335c4bbdfSmrg /* Note, priv->base will get freed when XImage recreated */ 2844642e01fSmrg 28535c4bbdfSmrg return TRUE; 28635c4bbdfSmrg} 2874642e01fSmrg 28835c4bbdfSmrgvoid 28935c4bbdfSmrgephyrShadowUpdate(ScreenPtr pScreen, shadowBufPtr pBuf) 29035c4bbdfSmrg{ 29135c4bbdfSmrg KdScreenPriv(pScreen); 29235c4bbdfSmrg KdScreenInfo *screen = pScreenPriv->screen; 2934642e01fSmrg 29435c4bbdfSmrg EPHYR_LOG("slow paint"); 2954642e01fSmrg 29635c4bbdfSmrg /* FIXME: Slow Rotated/Reflected updates could be much 297ed6184dfSmrg * much faster efficiently updating via transforming 29835c4bbdfSmrg * pBuf->pDamage regions 29935c4bbdfSmrg */ 30035c4bbdfSmrg shadowUpdateRotatePacked(pScreen, pBuf); 30135c4bbdfSmrg hostx_paint_rect(screen, 0, 0, 0, 0, screen->width, screen->height); 30235c4bbdfSmrg} 3034642e01fSmrg 30435c4bbdfSmrgstatic void 30535c4bbdfSmrgephyrInternalDamageRedisplay(ScreenPtr pScreen) 30635c4bbdfSmrg{ 30735c4bbdfSmrg KdScreenPriv(pScreen); 30835c4bbdfSmrg KdScreenInfo *screen = pScreenPriv->screen; 30935c4bbdfSmrg EphyrScrPriv *scrpriv = screen->driver; 31035c4bbdfSmrg RegionPtr pRegion; 31135c4bbdfSmrg 31235c4bbdfSmrg if (!scrpriv || !scrpriv->pDamage) 31335c4bbdfSmrg return; 31435c4bbdfSmrg 31535c4bbdfSmrg pRegion = DamageRegion(scrpriv->pDamage); 31635c4bbdfSmrg 31735c4bbdfSmrg if (RegionNotEmpty(pRegion)) { 31835c4bbdfSmrg int nbox; 31935c4bbdfSmrg BoxPtr pbox; 32035c4bbdfSmrg 32135c4bbdfSmrg if (ephyr_glamor) { 32235c4bbdfSmrg ephyr_glamor_damage_redisplay(scrpriv->glamor, pRegion); 32335c4bbdfSmrg } else { 32435c4bbdfSmrg nbox = RegionNumRects(pRegion); 32535c4bbdfSmrg pbox = RegionRects(pRegion); 32635c4bbdfSmrg 32735c4bbdfSmrg while (nbox--) { 32835c4bbdfSmrg hostx_paint_rect(screen, 32935c4bbdfSmrg pbox->x1, pbox->y1, 33035c4bbdfSmrg pbox->x1, pbox->y1, 33135c4bbdfSmrg pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); 33235c4bbdfSmrg pbox++; 33335c4bbdfSmrg } 3344642e01fSmrg } 33535c4bbdfSmrg DamageEmpty(scrpriv->pDamage); 33605b261ecSmrg } 33705b261ecSmrg} 33805b261ecSmrg 33905b261ecSmrgstatic void 3401b5d61b8SmrgephyrXcbProcessEvents(Bool queued_only); 34135c4bbdfSmrg 3421b5d61b8Smrgstatic Bool 3431b5d61b8SmrgephyrEventWorkProc(ClientPtr client, void *closure) 3441b5d61b8Smrg{ 3451b5d61b8Smrg ephyrXcbProcessEvents(TRUE); 3461b5d61b8Smrg return TRUE; 34705b261ecSmrg} 34805b261ecSmrg 34905b261ecSmrgstatic void 3501b5d61b8SmrgephyrScreenBlockHandler(ScreenPtr pScreen, void *timeout) 35105b261ecSmrg{ 3521b5d61b8Smrg KdScreenPriv(pScreen); 3531b5d61b8Smrg KdScreenInfo *screen = pScreenPriv->screen; 3541b5d61b8Smrg EphyrScrPriv *scrpriv = screen->driver; 3551b5d61b8Smrg 3561b5d61b8Smrg pScreen->BlockHandler = scrpriv->BlockHandler; 3571b5d61b8Smrg (*pScreen->BlockHandler)(pScreen, timeout); 3581b5d61b8Smrg scrpriv->BlockHandler = pScreen->BlockHandler; 3591b5d61b8Smrg pScreen->BlockHandler = ephyrScreenBlockHandler; 3601b5d61b8Smrg 3611b5d61b8Smrg if (scrpriv->pDamage) 3621b5d61b8Smrg ephyrInternalDamageRedisplay(pScreen); 3631b5d61b8Smrg 3641b5d61b8Smrg if (hostx_has_queued_event()) { 3651b5d61b8Smrg if (!QueueWorkProc(ephyrEventWorkProc, NULL, NULL)) 3661b5d61b8Smrg FatalError("cannot queue event processing in ephyr block handler"); 3671b5d61b8Smrg AdjustWaitForDelay(timeout, 0); 3681b5d61b8Smrg } 36905b261ecSmrg} 37005b261ecSmrg 37105b261ecSmrgBool 37235c4bbdfSmrgephyrSetInternalDamage(ScreenPtr pScreen) 37305b261ecSmrg{ 37435c4bbdfSmrg KdScreenPriv(pScreen); 37535c4bbdfSmrg KdScreenInfo *screen = pScreenPriv->screen; 37635c4bbdfSmrg EphyrScrPriv *scrpriv = screen->driver; 37735c4bbdfSmrg PixmapPtr pPixmap = NULL; 37835c4bbdfSmrg 37935c4bbdfSmrg scrpriv->pDamage = DamageCreate((DamageReportFunc) 0, 38035c4bbdfSmrg (DamageDestroyFunc) 0, 38135c4bbdfSmrg DamageReportNone, TRUE, pScreen, pScreen); 38235c4bbdfSmrg 38335c4bbdfSmrg pPixmap = (*pScreen->GetScreenPixmap) (pScreen); 38435c4bbdfSmrg 38535c4bbdfSmrg DamageRegister(&pPixmap->drawable, scrpriv->pDamage); 38635c4bbdfSmrg 38735c4bbdfSmrg return TRUE; 38805b261ecSmrg} 38905b261ecSmrg 39005b261ecSmrgvoid 39135c4bbdfSmrgephyrUnsetInternalDamage(ScreenPtr pScreen) 39205b261ecSmrg{ 39335c4bbdfSmrg KdScreenPriv(pScreen); 39435c4bbdfSmrg KdScreenInfo *screen = pScreenPriv->screen; 39535c4bbdfSmrg EphyrScrPriv *scrpriv = screen->driver; 39635c4bbdfSmrg 39735c4bbdfSmrg DamageDestroy(scrpriv->pDamage); 3981b5d61b8Smrg scrpriv->pDamage = NULL; 39905b261ecSmrg} 40005b261ecSmrg 40105b261ecSmrg#ifdef RANDR 40205b261ecSmrgBool 40335c4bbdfSmrgephyrRandRGetInfo(ScreenPtr pScreen, Rotation * rotations) 40405b261ecSmrg{ 40535c4bbdfSmrg KdScreenPriv(pScreen); 40635c4bbdfSmrg KdScreenInfo *screen = pScreenPriv->screen; 40735c4bbdfSmrg EphyrScrPriv *scrpriv = screen->driver; 40835c4bbdfSmrg RRScreenSizePtr pSize; 40935c4bbdfSmrg Rotation randr; 41035c4bbdfSmrg int n = 0; 41135c4bbdfSmrg 41235c4bbdfSmrg struct { 41335c4bbdfSmrg int width, height; 41435c4bbdfSmrg } sizes[] = { 41535c4bbdfSmrg {1600, 1200}, 41635c4bbdfSmrg {1400, 1050}, 41735c4bbdfSmrg {1280, 960}, 41835c4bbdfSmrg {1280, 1024}, 41935c4bbdfSmrg {1152, 864}, 42035c4bbdfSmrg {1024, 768}, 42135c4bbdfSmrg {832, 624}, 42235c4bbdfSmrg {800, 600}, 42335c4bbdfSmrg {720, 400}, 42435c4bbdfSmrg {480, 640}, 42535c4bbdfSmrg {640, 480}, 42635c4bbdfSmrg {640, 400}, 42735c4bbdfSmrg {320, 240}, 42835c4bbdfSmrg {240, 320}, 42935c4bbdfSmrg {160, 160}, 43035c4bbdfSmrg {0, 0} 43105b261ecSmrg }; 4324642e01fSmrg 43335c4bbdfSmrg EPHYR_LOG("mark"); 43435c4bbdfSmrg 43535c4bbdfSmrg *rotations = RR_Rotate_All | RR_Reflect_All; 43635c4bbdfSmrg 43735c4bbdfSmrg if (!hostx_want_preexisting_window(screen) 43835c4bbdfSmrg && !hostx_want_fullscreen()) { /* only if no -parent switch */ 43935c4bbdfSmrg while (sizes[n].width != 0 && sizes[n].height != 0) { 44035c4bbdfSmrg RRRegisterSize(pScreen, 44135c4bbdfSmrg sizes[n].width, 44235c4bbdfSmrg sizes[n].height, 44335c4bbdfSmrg (sizes[n].width * screen->width_mm) / screen->width, 44435c4bbdfSmrg (sizes[n].height * screen->height_mm) / 44535c4bbdfSmrg screen->height); 44635c4bbdfSmrg n++; 44735c4bbdfSmrg } 44805b261ecSmrg } 44935c4bbdfSmrg 45035c4bbdfSmrg pSize = RRRegisterSize(pScreen, 45135c4bbdfSmrg screen->width, 45235c4bbdfSmrg screen->height, screen->width_mm, screen->height_mm); 45335c4bbdfSmrg 45435c4bbdfSmrg randr = KdSubRotation(scrpriv->randr, screen->randr); 45535c4bbdfSmrg 45635c4bbdfSmrg RRSetCurrentConfig(pScreen, randr, 0, pSize); 45735c4bbdfSmrg 45835c4bbdfSmrg return TRUE; 45905b261ecSmrg} 46005b261ecSmrg 46105b261ecSmrgBool 46235c4bbdfSmrgephyrRandRSetConfig(ScreenPtr pScreen, 46335c4bbdfSmrg Rotation randr, int rate, RRScreenSizePtr pSize) 46405b261ecSmrg{ 46535c4bbdfSmrg KdScreenPriv(pScreen); 46635c4bbdfSmrg KdScreenInfo *screen = pScreenPriv->screen; 46735c4bbdfSmrg EphyrScrPriv *scrpriv = screen->driver; 46835c4bbdfSmrg Bool wasEnabled = pScreenPriv->enabled; 46935c4bbdfSmrg EphyrScrPriv oldscr; 47035c4bbdfSmrg int oldwidth, oldheight, oldmmwidth, oldmmheight; 47135c4bbdfSmrg Bool oldshadow; 47235c4bbdfSmrg int newwidth, newheight; 47335c4bbdfSmrg 47435c4bbdfSmrg if (screen->randr & (RR_Rotate_0 | RR_Rotate_180)) { 47535c4bbdfSmrg newwidth = pSize->width; 47635c4bbdfSmrg newheight = pSize->height; 47705b261ecSmrg } 47835c4bbdfSmrg else { 47935c4bbdfSmrg newwidth = pSize->height; 48035c4bbdfSmrg newheight = pSize->width; 48105b261ecSmrg } 48235c4bbdfSmrg 48335c4bbdfSmrg if (wasEnabled) 48435c4bbdfSmrg KdDisableScreen(pScreen); 48535c4bbdfSmrg 48635c4bbdfSmrg oldscr = *scrpriv; 48735c4bbdfSmrg 48835c4bbdfSmrg oldwidth = screen->width; 48935c4bbdfSmrg oldheight = screen->height; 49035c4bbdfSmrg oldmmwidth = pScreen->mmWidth; 49135c4bbdfSmrg oldmmheight = pScreen->mmHeight; 49235c4bbdfSmrg oldshadow = scrpriv->shadow; 49335c4bbdfSmrg 49435c4bbdfSmrg /* 49535c4bbdfSmrg * Set new configuration 49635c4bbdfSmrg */ 49735c4bbdfSmrg 49835c4bbdfSmrg /* 49935c4bbdfSmrg * We need to store the rotation value for pointer coords transformation; 50035c4bbdfSmrg * though initially the pointer and fb rotation are identical, when we map 50135c4bbdfSmrg * the fb, the screen will be reinitialized and return into an unrotated 50235c4bbdfSmrg * state (presumably the HW is taking care of the rotation of the fb), but the 50335c4bbdfSmrg * pointer still needs to be transformed. 50435c4bbdfSmrg */ 50535c4bbdfSmrg ephyrRandr = KdAddRotation(screen->randr, randr); 50635c4bbdfSmrg scrpriv->randr = ephyrRandr; 50735c4bbdfSmrg 50835c4bbdfSmrg ephyrUnmapFramebuffer(screen); 50935c4bbdfSmrg 51035c4bbdfSmrg screen->width = newwidth; 51135c4bbdfSmrg screen->height = newheight; 51235c4bbdfSmrg 5131b5d61b8Smrg scrpriv->win_width = screen->width; 5141b5d61b8Smrg scrpriv->win_height = screen->height; 5151b5d61b8Smrg#ifdef GLAMOR 5161b5d61b8Smrg ephyr_glamor_set_window_size(scrpriv->glamor, 5171b5d61b8Smrg scrpriv->win_width, 5181b5d61b8Smrg scrpriv->win_height); 5191b5d61b8Smrg#endif 5201b5d61b8Smrg 52135c4bbdfSmrg if (!ephyrMapFramebuffer(screen)) 52235c4bbdfSmrg goto bail4; 52335c4bbdfSmrg 52435c4bbdfSmrg /* FIXME below should go in own call */ 52535c4bbdfSmrg 52635c4bbdfSmrg if (oldshadow) 52735c4bbdfSmrg KdShadowUnset(screen->pScreen); 52835c4bbdfSmrg else 52935c4bbdfSmrg ephyrUnsetInternalDamage(screen->pScreen); 53035c4bbdfSmrg 5311b5d61b8Smrg ephyrSetScreenSizes(screen->pScreen); 5321b5d61b8Smrg 53335c4bbdfSmrg if (scrpriv->shadow) { 53435c4bbdfSmrg if (!KdShadowSet(screen->pScreen, 53535c4bbdfSmrg scrpriv->randr, ephyrShadowUpdate, ephyrWindowLinear)) 53635c4bbdfSmrg goto bail4; 53705b261ecSmrg } 53835c4bbdfSmrg else { 5391b5d61b8Smrg#ifdef GLAMOR 5401b5d61b8Smrg if (ephyr_glamor) 5411b5d61b8Smrg ephyr_glamor_create_screen_resources(pScreen); 5421b5d61b8Smrg#endif 54335c4bbdfSmrg /* Without shadow fb ( non rotated ) we need 54435c4bbdfSmrg * to use damage to efficiently update display 54535c4bbdfSmrg * via signal regions what to copy from 'fb'. 54635c4bbdfSmrg */ 54735c4bbdfSmrg if (!ephyrSetInternalDamage(screen->pScreen)) 54835c4bbdfSmrg goto bail4; 54905b261ecSmrg } 55035c4bbdfSmrg 55135c4bbdfSmrg /* 55235c4bbdfSmrg * Set frame buffer mapping 55335c4bbdfSmrg */ 55435c4bbdfSmrg (*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap(pScreen), 55535c4bbdfSmrg pScreen->width, 55635c4bbdfSmrg pScreen->height, 55735c4bbdfSmrg screen->fb.depth, 55835c4bbdfSmrg screen->fb.bitsPerPixel, 55935c4bbdfSmrg screen->fb.byteStride, 56035c4bbdfSmrg screen->fb.frameBuffer); 56135c4bbdfSmrg 56235c4bbdfSmrg /* set the subpixel order */ 56335c4bbdfSmrg 56435c4bbdfSmrg KdSetSubpixelOrder(pScreen, scrpriv->randr); 56535c4bbdfSmrg 56635c4bbdfSmrg if (wasEnabled) 56735c4bbdfSmrg KdEnableScreen(pScreen); 56835c4bbdfSmrg 56935c4bbdfSmrg RRScreenSizeNotify(pScreen); 57035c4bbdfSmrg 57135c4bbdfSmrg return TRUE; 57235c4bbdfSmrg 57305b261ecSmrg bail4: 57435c4bbdfSmrg EPHYR_LOG("bailed"); 57535c4bbdfSmrg 57635c4bbdfSmrg ephyrUnmapFramebuffer(screen); 57735c4bbdfSmrg *scrpriv = oldscr; 57835c4bbdfSmrg (void) ephyrMapFramebuffer(screen); 57935c4bbdfSmrg 58035c4bbdfSmrg pScreen->width = oldwidth; 58135c4bbdfSmrg pScreen->height = oldheight; 58235c4bbdfSmrg pScreen->mmWidth = oldmmwidth; 58335c4bbdfSmrg pScreen->mmHeight = oldmmheight; 58435c4bbdfSmrg 58535c4bbdfSmrg if (wasEnabled) 58635c4bbdfSmrg KdEnableScreen(pScreen); 58735c4bbdfSmrg return FALSE; 58805b261ecSmrg} 58905b261ecSmrg 59005b261ecSmrgBool 59135c4bbdfSmrgephyrRandRInit(ScreenPtr pScreen) 59205b261ecSmrg{ 59335c4bbdfSmrg rrScrPrivPtr pScrPriv; 59435c4bbdfSmrg 59535c4bbdfSmrg if (!RRScreenInit(pScreen)) 59635c4bbdfSmrg return FALSE; 59735c4bbdfSmrg 59835c4bbdfSmrg pScrPriv = rrGetScrPriv(pScreen); 59935c4bbdfSmrg pScrPriv->rrGetInfo = ephyrRandRGetInfo; 60035c4bbdfSmrg pScrPriv->rrSetConfig = ephyrRandRSetConfig; 60135c4bbdfSmrg return TRUE; 60235c4bbdfSmrg} 60335c4bbdfSmrg 60435c4bbdfSmrgstatic Bool 60535c4bbdfSmrgephyrResizeScreen (ScreenPtr pScreen, 60635c4bbdfSmrg int newwidth, 60735c4bbdfSmrg int newheight) 60835c4bbdfSmrg{ 60935c4bbdfSmrg KdScreenPriv(pScreen); 61035c4bbdfSmrg KdScreenInfo *screen = pScreenPriv->screen; 61135c4bbdfSmrg RRScreenSize size = {0}; 61235c4bbdfSmrg Bool ret; 61335c4bbdfSmrg int t; 61435c4bbdfSmrg 61535c4bbdfSmrg if (screen->randr & (RR_Rotate_90|RR_Rotate_270)) { 61635c4bbdfSmrg t = newwidth; 61735c4bbdfSmrg newwidth = newheight; 61835c4bbdfSmrg newheight = t; 61935c4bbdfSmrg } 62035c4bbdfSmrg 62135c4bbdfSmrg if (newwidth == screen->width && newheight == screen->height) { 62235c4bbdfSmrg return FALSE; 62335c4bbdfSmrg } 62435c4bbdfSmrg 62535c4bbdfSmrg size.width = newwidth; 62635c4bbdfSmrg size.height = newheight; 62735c4bbdfSmrg 6281b5d61b8Smrg hostx_size_set_from_configure(TRUE); 62935c4bbdfSmrg ret = ephyrRandRSetConfig (pScreen, screen->randr, 0, &size); 6301b5d61b8Smrg hostx_size_set_from_configure(FALSE); 63135c4bbdfSmrg if (ret) { 63235c4bbdfSmrg RROutputPtr output; 63335c4bbdfSmrg 63435c4bbdfSmrg output = RRFirstOutput(pScreen); 63535c4bbdfSmrg if (!output) 63635c4bbdfSmrg return FALSE; 63735c4bbdfSmrg RROutputSetModes(output, NULL, 0, 0); 63835c4bbdfSmrg } 63935c4bbdfSmrg 64035c4bbdfSmrg return ret; 64105b261ecSmrg} 64205b261ecSmrg#endif 64305b261ecSmrg 64405b261ecSmrgBool 64535c4bbdfSmrgephyrCreateColormap(ColormapPtr pmap) 64605b261ecSmrg{ 64735c4bbdfSmrg return fbInitializeColormap(pmap); 64805b261ecSmrg} 64905b261ecSmrg 65005b261ecSmrgBool 65135c4bbdfSmrgephyrInitScreen(ScreenPtr pScreen) 65205b261ecSmrg{ 65335c4bbdfSmrg KdScreenPriv(pScreen); 65435c4bbdfSmrg KdScreenInfo *screen = pScreenPriv->screen; 65535c4bbdfSmrg 65635c4bbdfSmrg EPHYR_LOG("pScreen->myNum:%d\n", pScreen->myNum); 65735c4bbdfSmrg hostx_set_screen_number(screen, pScreen->myNum); 65835c4bbdfSmrg if (EphyrWantNoHostGrab) { 65935c4bbdfSmrg hostx_set_win_title(screen, "xephyr"); 66035c4bbdfSmrg } else { 66135c4bbdfSmrg hostx_set_win_title(screen, "(ctrl+shift grabs mouse and keyboard)"); 66235c4bbdfSmrg } 66335c4bbdfSmrg pScreen->CreateColormap = ephyrCreateColormap; 6644642e01fSmrg 6654642e01fSmrg#ifdef XV 66635c4bbdfSmrg if (!ephyrNoXV) { 66735c4bbdfSmrg if (ephyr_glamor) 66835c4bbdfSmrg ephyr_glamor_xv_init(pScreen); 66935c4bbdfSmrg else if (!ephyrInitVideo(pScreen)) { 67035c4bbdfSmrg EPHYR_LOG_ERROR("failed to initialize xvideo\n"); 67135c4bbdfSmrg } 67235c4bbdfSmrg else { 67335c4bbdfSmrg EPHYR_LOG("initialized xvideo okay\n"); 67435c4bbdfSmrg } 67535c4bbdfSmrg } 6764642e01fSmrg#endif /*XV*/ 6774642e01fSmrg 67835c4bbdfSmrg return TRUE; 67905b261ecSmrg} 68005b261ecSmrg 68135c4bbdfSmrg 68205b261ecSmrgBool 68335c4bbdfSmrgephyrFinishInitScreen(ScreenPtr pScreen) 68405b261ecSmrg{ 6851b5d61b8Smrg KdScreenPriv(pScreen); 6861b5d61b8Smrg KdScreenInfo *screen = pScreenPriv->screen; 6871b5d61b8Smrg EphyrScrPriv *scrpriv = screen->driver; 6881b5d61b8Smrg 68935c4bbdfSmrg /* FIXME: Calling this even if not using shadow. 69035c4bbdfSmrg * Seems harmless enough. But may be safer elsewhere. 69135c4bbdfSmrg */ 69235c4bbdfSmrg if (!shadowSetup(pScreen)) 69335c4bbdfSmrg return FALSE; 6944642e01fSmrg 69505b261ecSmrg#ifdef RANDR 69635c4bbdfSmrg if (!ephyrRandRInit(pScreen)) 69735c4bbdfSmrg return FALSE; 69805b261ecSmrg#endif 6994642e01fSmrg 7001b5d61b8Smrg scrpriv->BlockHandler = pScreen->BlockHandler; 7011b5d61b8Smrg pScreen->BlockHandler = ephyrScreenBlockHandler; 7021b5d61b8Smrg 70335c4bbdfSmrg return TRUE; 70405b261ecSmrg} 70505b261ecSmrg 70635c4bbdfSmrg/** 70735c4bbdfSmrg * Called by kdrive after calling down the 70835c4bbdfSmrg * pScreen->CreateScreenResources() chain, this gives us a chance to 70935c4bbdfSmrg * make any pixmaps after the screen and all extensions have been 71035c4bbdfSmrg * initialized. 71135c4bbdfSmrg */ 71205b261ecSmrgBool 71335c4bbdfSmrgephyrCreateResources(ScreenPtr pScreen) 71405b261ecSmrg{ 71535c4bbdfSmrg KdScreenPriv(pScreen); 71635c4bbdfSmrg KdScreenInfo *screen = pScreenPriv->screen; 71735c4bbdfSmrg EphyrScrPriv *scrpriv = screen->driver; 71835c4bbdfSmrg 71935c4bbdfSmrg EPHYR_LOG("mark pScreen=%p mynum=%d shadow=%d", 72035c4bbdfSmrg pScreen, pScreen->myNum, scrpriv->shadow); 72135c4bbdfSmrg 72235c4bbdfSmrg if (scrpriv->shadow) 72335c4bbdfSmrg return KdShadowSet(pScreen, 72435c4bbdfSmrg scrpriv->randr, 72535c4bbdfSmrg ephyrShadowUpdate, ephyrWindowLinear); 72635c4bbdfSmrg else { 72735c4bbdfSmrg#ifdef GLAMOR 7281b5d61b8Smrg if (ephyr_glamor) { 7291b5d61b8Smrg if (!ephyr_glamor_create_screen_resources(pScreen)) 7301b5d61b8Smrg return FALSE; 7311b5d61b8Smrg } 73235c4bbdfSmrg#endif 73335c4bbdfSmrg return ephyrSetInternalDamage(pScreen); 73435c4bbdfSmrg } 73505b261ecSmrg} 73605b261ecSmrg 73705b261ecSmrgvoid 73835c4bbdfSmrgephyrScreenFini(KdScreenInfo * screen) 73905b261ecSmrg{ 74035c4bbdfSmrg EphyrScrPriv *scrpriv = screen->driver; 74135c4bbdfSmrg 7424642e01fSmrg if (scrpriv->shadow) { 74335c4bbdfSmrg KdShadowFbFree(screen); 7444642e01fSmrg } 7451b5d61b8Smrg scrpriv->BlockHandler = NULL; 74605b261ecSmrg} 74705b261ecSmrg 74835c4bbdfSmrgvoid 74935c4bbdfSmrgephyrCloseScreen(ScreenPtr pScreen) 75035c4bbdfSmrg{ 75135c4bbdfSmrg ephyrUnsetInternalDamage(pScreen); 75235c4bbdfSmrg} 75335c4bbdfSmrg 75435c4bbdfSmrg/* 75505b261ecSmrg * Port of Mark McLoughlin's Xnest fix for focus in + modifier bug. 75605b261ecSmrg * See https://bugs.freedesktop.org/show_bug.cgi?id=3030 75705b261ecSmrg */ 75805b261ecSmrgvoid 75905b261ecSmrgephyrUpdateModifierState(unsigned int state) 76005b261ecSmrg{ 76105b261ecSmrg 76235c4bbdfSmrg DeviceIntPtr pDev = inputInfo.keyboard; 76335c4bbdfSmrg KeyClassPtr keyc = pDev->key; 76435c4bbdfSmrg int i; 76535c4bbdfSmrg CARD8 mask; 76635c4bbdfSmrg int xkb_state; 7676747b715Smrg 76835c4bbdfSmrg if (!pDev) 76935c4bbdfSmrg return; 7706747b715Smrg 77135c4bbdfSmrg xkb_state = XkbStateFieldFromRec(&pDev->key->xkbInfo->state); 77235c4bbdfSmrg state = state & 0xff; 7736747b715Smrg 77435c4bbdfSmrg if (xkb_state == state) 77535c4bbdfSmrg return; 7766747b715Smrg 77735c4bbdfSmrg for (i = 0, mask = 1; i < 8; i++, mask <<= 1) { 77835c4bbdfSmrg int key; 77905b261ecSmrg 780ed6184dfSmrg /* Modifier is down, but shouldn't be */ 78135c4bbdfSmrg if ((xkb_state & mask) && !(state & mask)) { 78235c4bbdfSmrg int count = keyc->modifierKeyCount[i]; 7834642e01fSmrg 78435c4bbdfSmrg for (key = 0; key < MAP_LENGTH; key++) 78535c4bbdfSmrg if (keyc->xkbInfo->desc->map->modmap[key] & mask) { 78635c4bbdfSmrg if (mask == XCB_MOD_MASK_LOCK) { 78735c4bbdfSmrg KdEnqueueKeyboardEvent(ephyrKbd, key, FALSE); 78835c4bbdfSmrg KdEnqueueKeyboardEvent(ephyrKbd, key, TRUE); 78935c4bbdfSmrg } 79035c4bbdfSmrg else if (key_is_down(pDev, key, KEY_PROCESSED)) 79135c4bbdfSmrg KdEnqueueKeyboardEvent(ephyrKbd, key, TRUE); 7924642e01fSmrg 79335c4bbdfSmrg if (--count == 0) 79435c4bbdfSmrg break; 79535c4bbdfSmrg } 79635c4bbdfSmrg } 7974642e01fSmrg 798ed6184dfSmrg /* Modifier should be down, but isn't */ 79935c4bbdfSmrg if (!(xkb_state & mask) && (state & mask)) 80035c4bbdfSmrg for (key = 0; key < MAP_LENGTH; key++) 80135c4bbdfSmrg if (keyc->xkbInfo->desc->map->modmap[key] & mask) { 80235c4bbdfSmrg KdEnqueueKeyboardEvent(ephyrKbd, key, FALSE); 80335c4bbdfSmrg if (mask == XCB_MOD_MASK_LOCK) 80435c4bbdfSmrg KdEnqueueKeyboardEvent(ephyrKbd, key, TRUE); 80535c4bbdfSmrg break; 80635c4bbdfSmrg } 80735c4bbdfSmrg } 8084642e01fSmrg} 8094642e01fSmrg 8104642e01fSmrgstatic Bool 8114642e01fSmrgephyrCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y) 8124642e01fSmrg{ 81335c4bbdfSmrg return FALSE; 8144642e01fSmrg} 8154642e01fSmrg 8164642e01fSmrgstatic void 81735c4bbdfSmrgephyrCrossScreen(ScreenPtr pScreen, Bool entering) 8184642e01fSmrg{ 8194642e01fSmrg} 8204642e01fSmrg 82135c4bbdfSmrgScreenPtr ephyrCursorScreen; /* screen containing the cursor */ 8224642e01fSmrg 8234642e01fSmrgstatic void 82435c4bbdfSmrgephyrWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 8254642e01fSmrg{ 8261b5d61b8Smrg input_lock(); 82735c4bbdfSmrg ephyrCursorScreen = pScreen; 82835c4bbdfSmrg miPointerWarpCursor(inputInfo.pointer, pScreen, x, y); 82935c4bbdfSmrg 8301b5d61b8Smrg input_unlock(); 8314642e01fSmrg} 8324642e01fSmrg 83335c4bbdfSmrgmiPointerScreenFuncRec ephyrPointerScreenFuncs = { 83435c4bbdfSmrg ephyrCursorOffScreen, 83535c4bbdfSmrg ephyrCrossScreen, 83635c4bbdfSmrg ephyrWarpCursor, 8374642e01fSmrg}; 8384642e01fSmrg 83935c4bbdfSmrgstatic KdScreenInfo * 84035c4bbdfSmrgscreen_from_window(Window w) 84105b261ecSmrg{ 84235c4bbdfSmrg int i = 0; 84335c4bbdfSmrg 84435c4bbdfSmrg for (i = 0; i < screenInfo.numScreens; i++) { 84535c4bbdfSmrg ScreenPtr pScreen = screenInfo.screens[i]; 84635c4bbdfSmrg KdPrivScreenPtr kdscrpriv = KdGetScreenPriv(pScreen); 84735c4bbdfSmrg KdScreenInfo *screen = kdscrpriv->screen; 84835c4bbdfSmrg EphyrScrPriv *scrpriv = screen->driver; 84935c4bbdfSmrg 85035c4bbdfSmrg if (scrpriv->win == w 85135c4bbdfSmrg || scrpriv->peer_win == w 85235c4bbdfSmrg || scrpriv->win_pre_existing == w) { 85335c4bbdfSmrg return screen; 85435c4bbdfSmrg } 85535c4bbdfSmrg } 85635c4bbdfSmrg 85735c4bbdfSmrg return NULL; 85835c4bbdfSmrg} 85935c4bbdfSmrg 86035c4bbdfSmrgstatic void 86135c4bbdfSmrgephyrProcessErrorEvent(xcb_generic_event_t *xev) 86235c4bbdfSmrg{ 86335c4bbdfSmrg xcb_generic_error_t *e = (xcb_generic_error_t *)xev; 86435c4bbdfSmrg 86535c4bbdfSmrg FatalError("X11 error\n" 86635c4bbdfSmrg "Error code: %hhu\n" 86735c4bbdfSmrg "Sequence number: %hu\n" 86835c4bbdfSmrg "Major code: %hhu\tMinor code: %hu\n" 86935c4bbdfSmrg "Error value: %u\n", 87035c4bbdfSmrg e->error_code, 87135c4bbdfSmrg e->sequence, 87235c4bbdfSmrg e->major_code, e->minor_code, 87335c4bbdfSmrg e->resource_id); 87435c4bbdfSmrg} 87535c4bbdfSmrg 87635c4bbdfSmrgstatic void 87735c4bbdfSmrgephyrProcessExpose(xcb_generic_event_t *xev) 87835c4bbdfSmrg{ 87935c4bbdfSmrg xcb_expose_event_t *expose = (xcb_expose_event_t *)xev; 88035c4bbdfSmrg KdScreenInfo *screen = screen_from_window(expose->window); 88135c4bbdfSmrg EphyrScrPriv *scrpriv = screen->driver; 88235c4bbdfSmrg 88335c4bbdfSmrg /* Wait for the last expose event in a series of cliprects 88435c4bbdfSmrg * to actually paint our screen. 88535c4bbdfSmrg */ 88635c4bbdfSmrg if (expose->count != 0) 88735c4bbdfSmrg return; 88835c4bbdfSmrg 88935c4bbdfSmrg if (scrpriv) { 89035c4bbdfSmrg hostx_paint_rect(scrpriv->screen, 0, 0, 0, 0, 89135c4bbdfSmrg scrpriv->win_width, 89235c4bbdfSmrg scrpriv->win_height); 89335c4bbdfSmrg } else { 89435c4bbdfSmrg EPHYR_LOG_ERROR("failed to get host screen\n"); 89535c4bbdfSmrg } 89635c4bbdfSmrg} 89735c4bbdfSmrg 89835c4bbdfSmrgstatic void 89935c4bbdfSmrgephyrProcessMouseMotion(xcb_generic_event_t *xev) 90035c4bbdfSmrg{ 90135c4bbdfSmrg xcb_motion_notify_event_t *motion = (xcb_motion_notify_event_t *)xev; 90235c4bbdfSmrg KdScreenInfo *screen = screen_from_window(motion->event); 90335c4bbdfSmrg 90435c4bbdfSmrg if (!ephyrMouse || 90535c4bbdfSmrg !((EphyrPointerPrivate *) ephyrMouse->driverPrivate)->enabled) { 90635c4bbdfSmrg EPHYR_LOG("skipping mouse motion:%d\n", screen->pScreen->myNum); 90735c4bbdfSmrg return; 90835c4bbdfSmrg } 90935c4bbdfSmrg 91035c4bbdfSmrg if (ephyrCursorScreen != screen->pScreen) { 91135c4bbdfSmrg EPHYR_LOG("warping mouse cursor. " 91235c4bbdfSmrg "cur_screen:%d, motion_screen:%d\n", 91335c4bbdfSmrg ephyrCursorScreen->myNum, screen->pScreen->myNum); 91435c4bbdfSmrg ephyrWarpCursor(inputInfo.pointer, screen->pScreen, 91535c4bbdfSmrg motion->event_x, motion->event_y); 91635c4bbdfSmrg } 91735c4bbdfSmrg else { 91835c4bbdfSmrg int x = 0, y = 0; 91935c4bbdfSmrg 92035c4bbdfSmrg EPHYR_LOG("enqueuing mouse motion:%d\n", screen->pScreen->myNum); 92135c4bbdfSmrg x = motion->event_x; 92235c4bbdfSmrg y = motion->event_y; 92335c4bbdfSmrg EPHYR_LOG("initial (x,y):(%d,%d)\n", x, y); 92405b261ecSmrg 92535c4bbdfSmrg /* convert coords into desktop-wide coordinates. 92635c4bbdfSmrg * fill_pointer_events will convert that back to 92735c4bbdfSmrg * per-screen coordinates where needed */ 92835c4bbdfSmrg x += screen->pScreen->x; 92935c4bbdfSmrg y += screen->pScreen->y; 93035c4bbdfSmrg 93135c4bbdfSmrg KdEnqueuePointerEvent(ephyrMouse, mouseState | KD_POINTER_DESKTOP, x, y, 0); 93235c4bbdfSmrg } 93335c4bbdfSmrg} 93435c4bbdfSmrg 93535c4bbdfSmrgstatic void 93635c4bbdfSmrgephyrProcessButtonPress(xcb_generic_event_t *xev) 93735c4bbdfSmrg{ 93835c4bbdfSmrg xcb_button_press_event_t *button = (xcb_button_press_event_t *)xev; 93935c4bbdfSmrg 94035c4bbdfSmrg if (!ephyrMouse || 94135c4bbdfSmrg !((EphyrPointerPrivate *) ephyrMouse->driverPrivate)->enabled) { 94235c4bbdfSmrg EPHYR_LOG("skipping mouse press:%d\n", screen_from_window(button->event)->pScreen->myNum); 94335c4bbdfSmrg return; 94435c4bbdfSmrg } 94535c4bbdfSmrg 94635c4bbdfSmrg ephyrUpdateModifierState(button->state); 94735c4bbdfSmrg /* This is a bit hacky. will break for button 5 ( defined as 0x10 ) 94835c4bbdfSmrg * Check KD_BUTTON defines in kdrive.h 94935c4bbdfSmrg */ 95035c4bbdfSmrg mouseState |= 1 << (button->detail - 1); 95135c4bbdfSmrg 95235c4bbdfSmrg EPHYR_LOG("enqueuing mouse press:%d\n", screen_from_window(button->event)->pScreen->myNum); 95335c4bbdfSmrg KdEnqueuePointerEvent(ephyrMouse, mouseState | KD_MOUSE_DELTA, 0, 0, 0); 95435c4bbdfSmrg} 95535c4bbdfSmrg 95635c4bbdfSmrgstatic void 95735c4bbdfSmrgephyrProcessButtonRelease(xcb_generic_event_t *xev) 95835c4bbdfSmrg{ 95935c4bbdfSmrg xcb_button_press_event_t *button = (xcb_button_press_event_t *)xev; 96035c4bbdfSmrg 96135c4bbdfSmrg if (!ephyrMouse || 96235c4bbdfSmrg !((EphyrPointerPrivate *) ephyrMouse->driverPrivate)->enabled) { 96335c4bbdfSmrg return; 96435c4bbdfSmrg } 96535c4bbdfSmrg 96635c4bbdfSmrg ephyrUpdateModifierState(button->state); 96735c4bbdfSmrg mouseState &= ~(1 << (button->detail - 1)); 96835c4bbdfSmrg 96935c4bbdfSmrg EPHYR_LOG("enqueuing mouse release:%d\n", screen_from_window(button->event)->pScreen->myNum); 97035c4bbdfSmrg KdEnqueuePointerEvent(ephyrMouse, mouseState | KD_MOUSE_DELTA, 0, 0, 0); 97135c4bbdfSmrg} 97235c4bbdfSmrg 97335c4bbdfSmrg/* Xephyr wants ctrl+shift to grab the window, but that conflicts with 97435c4bbdfSmrg ctrl+alt+shift key combos. Remember the modifier state on key presses and 97535c4bbdfSmrg releases, if mod1 is pressed, we need ctrl, shift and mod1 released 97635c4bbdfSmrg before we allow a shift-ctrl grab activation. 97735c4bbdfSmrg 97835c4bbdfSmrg note: a key event contains the mask _before_ the current key takes 97935c4bbdfSmrg effect, so mod1_was_down will be reset on the first key press after all 98035c4bbdfSmrg three were released, not on the last release. That'd require some more 98135c4bbdfSmrg effort. 98235c4bbdfSmrg */ 98335c4bbdfSmrgstatic int 98435c4bbdfSmrgephyrUpdateGrabModifierState(int state) 98535c4bbdfSmrg{ 98635c4bbdfSmrg static int mod1_was_down = 0; 98735c4bbdfSmrg 98835c4bbdfSmrg if ((state & (XCB_MOD_MASK_CONTROL|XCB_MOD_MASK_SHIFT|XCB_MOD_MASK_1)) == 0) 98935c4bbdfSmrg mod1_was_down = 0; 99035c4bbdfSmrg else if (state & XCB_MOD_MASK_1) 99135c4bbdfSmrg mod1_was_down = 1; 99235c4bbdfSmrg 99335c4bbdfSmrg return mod1_was_down; 99435c4bbdfSmrg} 99535c4bbdfSmrg 99635c4bbdfSmrgstatic void 99735c4bbdfSmrgephyrProcessKeyPress(xcb_generic_event_t *xev) 99835c4bbdfSmrg{ 99935c4bbdfSmrg xcb_key_press_event_t *key = (xcb_key_press_event_t *)xev; 100035c4bbdfSmrg 100135c4bbdfSmrg if (!ephyrKbd || 100235c4bbdfSmrg !((EphyrKbdPrivate *) ephyrKbd->driverPrivate)->enabled) { 100335c4bbdfSmrg return; 100435c4bbdfSmrg } 100535c4bbdfSmrg 100635c4bbdfSmrg ephyrUpdateGrabModifierState(key->state); 100735c4bbdfSmrg ephyrUpdateModifierState(key->state); 100835c4bbdfSmrg KdEnqueueKeyboardEvent(ephyrKbd, key->detail, FALSE); 100935c4bbdfSmrg} 101035c4bbdfSmrg 101135c4bbdfSmrgstatic void 101235c4bbdfSmrgephyrProcessKeyRelease(xcb_generic_event_t *xev) 101335c4bbdfSmrg{ 101435c4bbdfSmrg xcb_connection_t *conn = hostx_get_xcbconn(); 101535c4bbdfSmrg xcb_key_release_event_t *key = (xcb_key_release_event_t *)xev; 101635c4bbdfSmrg static xcb_key_symbols_t *keysyms; 101735c4bbdfSmrg static int grabbed_screen = -1; 101835c4bbdfSmrg int mod1_down = ephyrUpdateGrabModifierState(key->state); 101935c4bbdfSmrg 102035c4bbdfSmrg if (!keysyms) 102135c4bbdfSmrg keysyms = xcb_key_symbols_alloc(conn); 102235c4bbdfSmrg 102335c4bbdfSmrg if (!EphyrWantNoHostGrab && 102435c4bbdfSmrg (((xcb_key_symbols_get_keysym(keysyms, key->detail, 0) == XK_Shift_L 102535c4bbdfSmrg || xcb_key_symbols_get_keysym(keysyms, key->detail, 0) == XK_Shift_R) 102635c4bbdfSmrg && (key->state & XCB_MOD_MASK_CONTROL)) || 102735c4bbdfSmrg ((xcb_key_symbols_get_keysym(keysyms, key->detail, 0) == XK_Control_L 102835c4bbdfSmrg || xcb_key_symbols_get_keysym(keysyms, key->detail, 0) == XK_Control_R) 102935c4bbdfSmrg && (key->state & XCB_MOD_MASK_SHIFT)))) { 103035c4bbdfSmrg KdScreenInfo *screen = screen_from_window(key->event); 103135c4bbdfSmrg EphyrScrPriv *scrpriv = screen->driver; 103235c4bbdfSmrg 103335c4bbdfSmrg if (grabbed_screen != -1) { 103435c4bbdfSmrg xcb_ungrab_keyboard(conn, XCB_TIME_CURRENT_TIME); 103535c4bbdfSmrg xcb_ungrab_pointer(conn, XCB_TIME_CURRENT_TIME); 103635c4bbdfSmrg grabbed_screen = -1; 103735c4bbdfSmrg hostx_set_win_title(screen, 103835c4bbdfSmrg "(ctrl+shift grabs mouse and keyboard)"); 103935c4bbdfSmrg } 104035c4bbdfSmrg else if (!mod1_down) { 104135c4bbdfSmrg /* Attempt grab */ 104235c4bbdfSmrg xcb_grab_keyboard_cookie_t kbgrabc = 104335c4bbdfSmrg xcb_grab_keyboard(conn, 104435c4bbdfSmrg TRUE, 104535c4bbdfSmrg scrpriv->win, 104635c4bbdfSmrg XCB_TIME_CURRENT_TIME, 104735c4bbdfSmrg XCB_GRAB_MODE_ASYNC, 104835c4bbdfSmrg XCB_GRAB_MODE_ASYNC); 104935c4bbdfSmrg xcb_grab_keyboard_reply_t *kbgrabr; 105035c4bbdfSmrg xcb_grab_pointer_cookie_t pgrabc = 105135c4bbdfSmrg xcb_grab_pointer(conn, 105235c4bbdfSmrg TRUE, 105335c4bbdfSmrg scrpriv->win, 105435c4bbdfSmrg 0, 105535c4bbdfSmrg XCB_GRAB_MODE_ASYNC, 105635c4bbdfSmrg XCB_GRAB_MODE_ASYNC, 105735c4bbdfSmrg scrpriv->win, 105835c4bbdfSmrg XCB_NONE, 105935c4bbdfSmrg XCB_TIME_CURRENT_TIME); 106035c4bbdfSmrg xcb_grab_pointer_reply_t *pgrabr; 106135c4bbdfSmrg kbgrabr = xcb_grab_keyboard_reply(conn, kbgrabc, NULL); 106235c4bbdfSmrg if (!kbgrabr || kbgrabr->status != XCB_GRAB_STATUS_SUCCESS) { 106335c4bbdfSmrg xcb_discard_reply(conn, pgrabc.sequence); 106435c4bbdfSmrg xcb_ungrab_pointer(conn, XCB_TIME_CURRENT_TIME); 106535c4bbdfSmrg } else { 106635c4bbdfSmrg pgrabr = xcb_grab_pointer_reply(conn, pgrabc, NULL); 106735c4bbdfSmrg if (!pgrabr || pgrabr->status != XCB_GRAB_STATUS_SUCCESS) 106835c4bbdfSmrg { 106935c4bbdfSmrg xcb_ungrab_keyboard(conn, 107035c4bbdfSmrg XCB_TIME_CURRENT_TIME); 107135c4bbdfSmrg } else { 107235c4bbdfSmrg grabbed_screen = scrpriv->mynum; 107335c4bbdfSmrg hostx_set_win_title 107435c4bbdfSmrg (screen, 107535c4bbdfSmrg "(ctrl+shift releases mouse and keyboard)"); 107635c4bbdfSmrg } 107735c4bbdfSmrg } 107835c4bbdfSmrg } 107935c4bbdfSmrg } 108035c4bbdfSmrg 108135c4bbdfSmrg if (!ephyrKbd || 108235c4bbdfSmrg !((EphyrKbdPrivate *) ephyrKbd->driverPrivate)->enabled) { 108335c4bbdfSmrg return; 108435c4bbdfSmrg } 108535c4bbdfSmrg 108635c4bbdfSmrg /* Still send the release event even if above has happened server 108735c4bbdfSmrg * will get confused with just an up event. Maybe it would be 108835c4bbdfSmrg * better to just block shift+ctrls getting to kdrive all 108935c4bbdfSmrg * together. 109035c4bbdfSmrg */ 109135c4bbdfSmrg ephyrUpdateModifierState(key->state); 109235c4bbdfSmrg KdEnqueueKeyboardEvent(ephyrKbd, key->detail, TRUE); 109335c4bbdfSmrg} 109435c4bbdfSmrg 109535c4bbdfSmrgstatic void 109635c4bbdfSmrgephyrProcessConfigureNotify(xcb_generic_event_t *xev) 109735c4bbdfSmrg{ 109835c4bbdfSmrg xcb_configure_notify_event_t *configure = 109935c4bbdfSmrg (xcb_configure_notify_event_t *)xev; 110035c4bbdfSmrg KdScreenInfo *screen = screen_from_window(configure->window); 110135c4bbdfSmrg EphyrScrPriv *scrpriv = screen->driver; 110235c4bbdfSmrg 110335c4bbdfSmrg if (!scrpriv || 110435c4bbdfSmrg (scrpriv->win_pre_existing == None && !EphyrWantResize)) { 110535c4bbdfSmrg return; 110605b261ecSmrg } 110735c4bbdfSmrg 110835c4bbdfSmrg#ifdef RANDR 110935c4bbdfSmrg ephyrResizeScreen(screen->pScreen, configure->width, configure->height); 111035c4bbdfSmrg#endif /* RANDR */ 111105b261ecSmrg} 111205b261ecSmrg 11131b5d61b8Smrgstatic void 11141b5d61b8SmrgephyrXcbProcessEvents(Bool queued_only) 111505b261ecSmrg{ 111635c4bbdfSmrg xcb_connection_t *conn = hostx_get_xcbconn(); 11171b5d61b8Smrg xcb_generic_event_t *expose = NULL, *configure = NULL; 111835c4bbdfSmrg 111935c4bbdfSmrg while (TRUE) { 11201b5d61b8Smrg xcb_generic_event_t *xev = hostx_get_event(queued_only); 11211b5d61b8Smrg 112235c4bbdfSmrg if (!xev) { 112335c4bbdfSmrg /* If our XCB connection has died (for example, our window was 112435c4bbdfSmrg * closed), exit now. 112535c4bbdfSmrg */ 112635c4bbdfSmrg if (xcb_connection_has_error(conn)) { 112735c4bbdfSmrg CloseWellKnownConnections(); 112835c4bbdfSmrg OsCleanup(1); 112935c4bbdfSmrg exit(1); 113035c4bbdfSmrg } 113135c4bbdfSmrg 113235c4bbdfSmrg break; 113335c4bbdfSmrg } 113435c4bbdfSmrg 113535c4bbdfSmrg switch (xev->response_type & 0x7f) { 113635c4bbdfSmrg case 0: 113735c4bbdfSmrg ephyrProcessErrorEvent(xev); 113835c4bbdfSmrg break; 113935c4bbdfSmrg 114035c4bbdfSmrg case XCB_EXPOSE: 11411b5d61b8Smrg free(expose); 11421b5d61b8Smrg expose = xev; 11431b5d61b8Smrg xev = NULL; 114435c4bbdfSmrg break; 114535c4bbdfSmrg 114635c4bbdfSmrg case XCB_MOTION_NOTIFY: 114735c4bbdfSmrg ephyrProcessMouseMotion(xev); 114835c4bbdfSmrg break; 114935c4bbdfSmrg 115035c4bbdfSmrg case XCB_KEY_PRESS: 115135c4bbdfSmrg ephyrProcessKeyPress(xev); 115235c4bbdfSmrg break; 115335c4bbdfSmrg 115435c4bbdfSmrg case XCB_KEY_RELEASE: 115535c4bbdfSmrg ephyrProcessKeyRelease(xev); 115635c4bbdfSmrg break; 115735c4bbdfSmrg 115835c4bbdfSmrg case XCB_BUTTON_PRESS: 115935c4bbdfSmrg ephyrProcessButtonPress(xev); 116035c4bbdfSmrg break; 116135c4bbdfSmrg 116235c4bbdfSmrg case XCB_BUTTON_RELEASE: 116335c4bbdfSmrg ephyrProcessButtonRelease(xev); 116435c4bbdfSmrg break; 116535c4bbdfSmrg 116635c4bbdfSmrg case XCB_CONFIGURE_NOTIFY: 11671b5d61b8Smrg free(configure); 11681b5d61b8Smrg configure = xev; 11691b5d61b8Smrg xev = NULL; 117035c4bbdfSmrg break; 117135c4bbdfSmrg } 117235c4bbdfSmrg 11731b5d61b8Smrg if (xev) { 11741b5d61b8Smrg if (ephyr_glamor) 11751b5d61b8Smrg ephyr_glamor_process_event(xev); 11761b5d61b8Smrg 11771b5d61b8Smrg free(xev); 11781b5d61b8Smrg } 11791b5d61b8Smrg } 118035c4bbdfSmrg 11811b5d61b8Smrg if (configure) { 11821b5d61b8Smrg ephyrProcessConfigureNotify(configure); 11831b5d61b8Smrg free(configure); 118435c4bbdfSmrg } 11851b5d61b8Smrg 11861b5d61b8Smrg if (expose) { 11871b5d61b8Smrg ephyrProcessExpose(expose); 11881b5d61b8Smrg free(expose); 11891b5d61b8Smrg } 11901b5d61b8Smrg} 11911b5d61b8Smrg 11921b5d61b8Smrgstatic void 11931b5d61b8SmrgephyrXcbNotify(int fd, int ready, void *data) 11941b5d61b8Smrg{ 11951b5d61b8Smrg ephyrXcbProcessEvents(FALSE); 119605b261ecSmrg} 119705b261ecSmrg 119805b261ecSmrgvoid 119935c4bbdfSmrgephyrCardFini(KdCardInfo * card) 120005b261ecSmrg{ 120135c4bbdfSmrg EphyrPriv *priv = card->driver; 120235c4bbdfSmrg 120335c4bbdfSmrg free(priv); 120435c4bbdfSmrg} 120535c4bbdfSmrg 120635c4bbdfSmrgvoid 120735c4bbdfSmrgephyrGetColors(ScreenPtr pScreen, int n, xColorItem * pdefs) 120835c4bbdfSmrg{ 120935c4bbdfSmrg /* XXX Not sure if this is right */ 121035c4bbdfSmrg 121135c4bbdfSmrg EPHYR_LOG("mark"); 121235c4bbdfSmrg 121335c4bbdfSmrg while (n--) { 121435c4bbdfSmrg pdefs->red = 0; 121535c4bbdfSmrg pdefs->green = 0; 121635c4bbdfSmrg pdefs->blue = 0; 121735c4bbdfSmrg pdefs++; 121805b261ecSmrg } 121905b261ecSmrg 122005b261ecSmrg} 122105b261ecSmrg 122205b261ecSmrgvoid 122335c4bbdfSmrgephyrPutColors(ScreenPtr pScreen, int n, xColorItem * pdefs) 122405b261ecSmrg{ 122535c4bbdfSmrg KdScreenPriv(pScreen); 122635c4bbdfSmrg KdScreenInfo *screen = pScreenPriv->screen; 122735c4bbdfSmrg EphyrScrPriv *scrpriv = screen->driver; 122835c4bbdfSmrg int min, max, p; 122935c4bbdfSmrg 123035c4bbdfSmrg /* XXX Not sure if this is right */ 123135c4bbdfSmrg 123235c4bbdfSmrg min = 256; 123335c4bbdfSmrg max = 0; 123435c4bbdfSmrg 123535c4bbdfSmrg while (n--) { 123635c4bbdfSmrg p = pdefs->pixel; 123735c4bbdfSmrg if (p < min) 123835c4bbdfSmrg min = p; 123935c4bbdfSmrg if (p > max) 124035c4bbdfSmrg max = p; 124135c4bbdfSmrg 124235c4bbdfSmrg hostx_set_cmap_entry(pScreen, p, 124335c4bbdfSmrg pdefs->red >> 8, 124435c4bbdfSmrg pdefs->green >> 8, pdefs->blue >> 8); 124535c4bbdfSmrg pdefs++; 124635c4bbdfSmrg } 124735c4bbdfSmrg if (scrpriv->pDamage) { 124835c4bbdfSmrg BoxRec box; 124935c4bbdfSmrg RegionRec region; 125035c4bbdfSmrg 125135c4bbdfSmrg box.x1 = 0; 125235c4bbdfSmrg box.y1 = 0; 125335c4bbdfSmrg box.x2 = pScreen->width; 125435c4bbdfSmrg box.y2 = pScreen->height; 125535c4bbdfSmrg RegionInit(®ion, &box, 1); 125635c4bbdfSmrg DamageReportDamage(scrpriv->pDamage, ®ion); 125735c4bbdfSmrg RegionUninit(®ion); 125805b261ecSmrg } 125905b261ecSmrg} 126005b261ecSmrg 126105b261ecSmrg/* Mouse calls */ 126205b261ecSmrg 126305b261ecSmrgstatic Status 126435c4bbdfSmrgMouseInit(KdPointerInfo * pi) 126505b261ecSmrg{ 126605b261ecSmrg pi->driverPrivate = (EphyrPointerPrivate *) 126735c4bbdfSmrg calloc(sizeof(EphyrPointerPrivate), 1); 126835c4bbdfSmrg ((EphyrPointerPrivate *) pi->driverPrivate)->enabled = FALSE; 126905b261ecSmrg pi->nAxes = 3; 127005b261ecSmrg pi->nButtons = 32; 12716747b715Smrg free(pi->name); 12726747b715Smrg pi->name = strdup("Xephyr virtual mouse"); 127335c4bbdfSmrg 127435c4bbdfSmrg /* 127535c4bbdfSmrg * Must transform pointer coords since the pointer position 127635c4bbdfSmrg * relative to the Xephyr window is controlled by the host server and 127735c4bbdfSmrg * remains constant regardless of any rotation applied to the Xephyr screen. 127835c4bbdfSmrg */ 127935c4bbdfSmrg pi->transformCoordinates = TRUE; 128035c4bbdfSmrg 128105b261ecSmrg ephyrMouse = pi; 128205b261ecSmrg return Success; 128305b261ecSmrg} 128405b261ecSmrg 128505b261ecSmrgstatic Status 128635c4bbdfSmrgMouseEnable(KdPointerInfo * pi) 128705b261ecSmrg{ 128835c4bbdfSmrg ((EphyrPointerPrivate *) pi->driverPrivate)->enabled = TRUE; 12891b5d61b8Smrg SetNotifyFd(hostx_get_fd(), ephyrXcbNotify, X_NOTIFY_READ, NULL); 129005b261ecSmrg return Success; 129105b261ecSmrg} 129205b261ecSmrg 129305b261ecSmrgstatic void 129435c4bbdfSmrgMouseDisable(KdPointerInfo * pi) 129505b261ecSmrg{ 129635c4bbdfSmrg ((EphyrPointerPrivate *) pi->driverPrivate)->enabled = FALSE; 12971b5d61b8Smrg RemoveNotifyFd(hostx_get_fd()); 129805b261ecSmrg return; 129905b261ecSmrg} 130005b261ecSmrg 130105b261ecSmrgstatic void 130235c4bbdfSmrgMouseFini(KdPointerInfo * pi) 130305b261ecSmrg{ 13041b5d61b8Smrg free(pi->driverPrivate); 130535c4bbdfSmrg ephyrMouse = NULL; 130605b261ecSmrg return; 130705b261ecSmrg} 130805b261ecSmrg 130905b261ecSmrgKdPointerDriver EphyrMouseDriver = { 131005b261ecSmrg "ephyr", 131105b261ecSmrg MouseInit, 131205b261ecSmrg MouseEnable, 131305b261ecSmrg MouseDisable, 131405b261ecSmrg MouseFini, 131505b261ecSmrg NULL, 131605b261ecSmrg}; 131705b261ecSmrg 131805b261ecSmrg/* Keyboard */ 131905b261ecSmrg 132005b261ecSmrgstatic Status 132135c4bbdfSmrgEphyrKeyboardInit(KdKeyboardInfo * ki) 132205b261ecSmrg{ 13231b5d61b8Smrg KeySymsRec keySyms; 13241b5d61b8Smrg CARD8 modmap[MAP_LENGTH]; 13251b5d61b8Smrg XkbControlsRec controls; 13261b5d61b8Smrg 132735c4bbdfSmrg ki->driverPrivate = (EphyrKbdPrivate *) 132835c4bbdfSmrg calloc(sizeof(EphyrKbdPrivate), 1); 13291b5d61b8Smrg 13301b5d61b8Smrg if (hostx_load_keymap(&keySyms, modmap, &controls)) { 13311b5d61b8Smrg XkbApplyMappingChange(ki->dixdev, &keySyms, 13321b5d61b8Smrg keySyms.minKeyCode, 13331b5d61b8Smrg keySyms.maxKeyCode - keySyms.minKeyCode + 1, 13341b5d61b8Smrg modmap, serverClient); 13351b5d61b8Smrg XkbDDXChangeControls(ki->dixdev, &controls, &controls); 13361b5d61b8Smrg free(keySyms.map); 13371b5d61b8Smrg } 13381b5d61b8Smrg 13391b5d61b8Smrg ki->minScanCode = keySyms.minKeyCode; 13401b5d61b8Smrg ki->maxScanCode = keySyms.maxKeyCode; 13411b5d61b8Smrg 13421b5d61b8Smrg if (ki->name != NULL) { 13431b5d61b8Smrg free(ki->name); 134435c4bbdfSmrg } 13451b5d61b8Smrg 134635c4bbdfSmrg ki->name = strdup("Xephyr virtual keyboard"); 134735c4bbdfSmrg ephyrKbd = ki; 134835c4bbdfSmrg return Success; 134905b261ecSmrg} 135005b261ecSmrg 135105b261ecSmrgstatic Status 135235c4bbdfSmrgEphyrKeyboardEnable(KdKeyboardInfo * ki) 135305b261ecSmrg{ 135435c4bbdfSmrg ((EphyrKbdPrivate *) ki->driverPrivate)->enabled = TRUE; 135505b261ecSmrg 135605b261ecSmrg return Success; 135705b261ecSmrg} 135805b261ecSmrg 135905b261ecSmrgstatic void 136035c4bbdfSmrgEphyrKeyboardDisable(KdKeyboardInfo * ki) 136105b261ecSmrg{ 136235c4bbdfSmrg ((EphyrKbdPrivate *) ki->driverPrivate)->enabled = FALSE; 136305b261ecSmrg} 136405b261ecSmrg 136505b261ecSmrgstatic void 136635c4bbdfSmrgEphyrKeyboardFini(KdKeyboardInfo * ki) 136705b261ecSmrg{ 13681b5d61b8Smrg free(ki->driverPrivate); 136905b261ecSmrg ephyrKbd = NULL; 137005b261ecSmrg return; 137105b261ecSmrg} 137205b261ecSmrg 137305b261ecSmrgstatic void 137435c4bbdfSmrgEphyrKeyboardLeds(KdKeyboardInfo * ki, int leds) 137505b261ecSmrg{ 137605b261ecSmrg} 137705b261ecSmrg 137805b261ecSmrgstatic void 137935c4bbdfSmrgEphyrKeyboardBell(KdKeyboardInfo * ki, int volume, int frequency, int duration) 138005b261ecSmrg{ 138105b261ecSmrg} 138205b261ecSmrg 138305b261ecSmrgKdKeyboardDriver EphyrKeyboardDriver = { 138405b261ecSmrg "ephyr", 138505b261ecSmrg EphyrKeyboardInit, 138605b261ecSmrg EphyrKeyboardEnable, 138705b261ecSmrg EphyrKeyboardLeds, 138805b261ecSmrg EphyrKeyboardBell, 138905b261ecSmrg EphyrKeyboardDisable, 139005b261ecSmrg EphyrKeyboardFini, 139105b261ecSmrg NULL, 139205b261ecSmrg}; 1393