~ubuntu-branches/ubuntu/precise/xorg-server/precise-updates

« back to all changes in this revision

Viewing changes to mi/mipointer.c

  • Committer: Package Import Robot
  • Author(s): Christopher James Halse Rogers
  • Date: 2012-01-23 16:09:29 UTC
  • mfrom: (1.1.46) (0.11.34 sid)
  • Revision ID: package-import@ubuntu.com-20120123160929-k4xdb9b7xeesiukp
Tags: 2:1.11.3-0ubuntu8
* debian/patches/224_return_BadWindow_not_BadMatch.diff:
  - Fix the error values of a whole slew of window-related calls.
    Fixes some gnome-settings-daemon aborts in XLib (LP: #903973)

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
in this Software without prior written authorization from The Open Group.
24
24
*/
25
25
 
 
26
/**
 
27
 * @file
 
28
 * This file contains functions to move the pointer on the screen and/or
 
29
 * restrict its movement. These functions are divided into two sets:
 
30
 * Screen-specific functions that are used as function pointers from other
 
31
 * parts of the server (and end up heavily wrapped by e.g. animcur and
 
32
 * xfixes):
 
33
 *      miPointerConstrainCursor
 
34
 *      miPointerCursorLimits
 
35
 *      miPointerDisplayCursor
 
36
 *      miPointerRealizeCursor
 
37
 *      miPointerUnrealizeCursor
 
38
 *      miPointerSetCursorPosition
 
39
 *      miRecolorCursor
 
40
 *      miPointerDeviceInitialize
 
41
 *      miPointerDeviceCleanup
 
42
 * If wrapped, these are the last element in the wrapping chain. They may
 
43
 * call into sprite-specific code through further function pointers though.
 
44
 *
 
45
 * The second type of functions are those that are directly called by the
 
46
 * DIX, DDX and some drivers.
 
47
 */
 
48
 
26
49
#ifdef HAVE_DIX_CONFIG_H
27
50
#include <dix-config.h>
28
51
#endif
40
63
# include   "dixstruct.h"
41
64
# include   "inputstr.h"
42
65
# include   "inpututils.h"
 
66
# include   "eventstr.h"
43
67
 
44
68
DevPrivateKeyRec miPointerScreenKeyRec;
45
69
 
50
74
DevPrivateKeyRec miPointerPrivKeyRec;
51
75
 
52
76
#define MIPOINTER(dev) \
53
 
    ((!IsMaster(dev) && !dev->u.master) ? \
 
77
    (IsFloating(dev) ? \
54
78
        (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \
55
79
        (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey))
56
80
 
76
100
                                   ScreenPtr pScreen);
77
101
static void miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y);
78
102
 
79
 
static EventList* events; /* for WarpPointer MotionNotifies */
 
103
static InternalEvent* events; /* for WarpPointer MotionNotifies */
80
104
 
81
105
Bool
82
106
miPointerInitialize (ScreenPtr                  pScreen,
126
150
    return TRUE;
127
151
}
128
152
 
 
153
/**
 
154
 * Destroy screen-specific information.
 
155
 *
 
156
 * @param index Screen index of the screen in screenInfo.screens[]
 
157
 * @param pScreen The actual screen pointer
 
158
 */
129
159
static Bool
130
160
miPointerCloseScreen (int index, ScreenPtr pScreen)
131
161
{
132
 
#if 0
133
 
    miPointerPtr pPointer;
134
 
    DeviceIntPtr pDev;
135
 
#endif
136
 
 
137
162
    SetupScreen(pScreen);
138
163
 
139
 
#if 0
140
 
    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
141
 
    {
142
 
        if (DevHasCursor(pDev))
143
 
        {
144
 
            pPointer = MIPOINTER(pDev);
145
 
 
146
 
            if (pScreen == pPointer->pScreen)
147
 
                pPointer->pScreen = 0;
148
 
            if (pScreen == pPointer->pSpriteScreen)
149
 
                pPointer->pSpriteScreen = 0;
150
 
        }
151
 
    }
152
 
 
153
 
    if (MIPOINTER(inputInfo.pointer)->pScreen == pScreen)
154
 
        MIPOINTER(inputInfo.pointer)->pScreen = 0;
155
 
    if (MIPOINTER(inputInfo.pointer)->pSpriteScreen == pScreen)
156
 
        MIPOINTER(inputInfo.pointer)->pSpriteScreen = 0;
157
 
#endif
158
 
 
159
164
    pScreen->CloseScreen = pScreenPriv->CloseScreen;
160
165
    free((pointer) pScreenPriv);
161
166
    FreeEventList(events, GetMaximumEventsNum());
189
194
    miPointerPtr pPointer;
190
195
 
191
196
    /* return for keyboards */
192
 
    if ((IsMaster(pDev) && !DevHasCursor(pDev)) ||
193
 
        (!IsMaster(pDev) && pDev->u.master && !DevHasCursor(pDev->u.master)))
 
197
    if (!IsPointerDevice(pDev))
194
198
            return FALSE;
195
199
 
196
200
    pPointer = MIPOINTER(pDev);
201
205
    return TRUE;
202
206
}
203
207
 
 
208
/**
 
209
 * Set up the constraints for the given device. This function does not
 
210
 * actually constrain the cursor but merely copies the given box to the
 
211
 * internal constraint storage.
 
212
 *
 
213
 * @param pDev The device to constrain to the box
 
214
 * @param pBox The rectangle to constrain the cursor to
 
215
 * @param pScreen Used for copying screen confinement
 
216
 */
204
217
static void
205
218
miPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox)
206
219
{
212
225
    pPointer->confined = PointerConfinedToScreen(pDev);
213
226
}
214
227
 
215
 
/*ARGSUSED*/
 
228
/**
 
229
 * Should calculate the box for the given cursor, based on screen and the
 
230
 * confinement given. But we assume that whatever box is passed in is valid
 
231
 * anyway.
 
232
 *
 
233
 * @param pDev The device to calculate the cursor limits for
 
234
 * @param pScreen The screen the confinement happens on
 
235
 * @param pCursor The screen the confinement happens on
 
236
 * @param pHotBox The confinement box for the cursor
 
237
 * @param[out] pTopLeftBox The new confinement box, always *pHotBox.
 
238
 */
216
239
static void
217
240
miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
218
241
                      BoxPtr pHotBox, BoxPtr pTopLeftBox)
220
243
    *pTopLeftBox = *pHotBox;
221
244
}
222
245
 
223
 
static Bool GenerateEvent;
224
 
 
 
246
/**
 
247
 * Set the device's cursor position to the x/y position on the given screen.
 
248
 * Generates and event if required.
 
249
 *
 
250
 * This function is called from:
 
251
 *    - sprite init code to place onto initial position
 
252
 *    - the various WarpPointer implementations (core, XI, Xinerama, dmx,…)
 
253
 *    - during the cursor update path in CheckMotion
 
254
 *    - in the Xinerama part of NewCurrentScreen
 
255
 *    - when a RandR/RandR1.2 mode was applied (it may have moved the pointer, so
 
256
 *      it's set back to the original pos)
 
257
 *
 
258
 * @param pDev The device to move
 
259
 * @param pScreen The screen the device is on
 
260
 * @param x The x coordinate in per-screen coordinates
 
261
 * @param y The y coordinate in per-screen coordinates
 
262
 * @param generateEvent True if the pointer movement should generate an
 
263
 * event.
 
264
 *
 
265
 * @return TRUE in all cases
 
266
 */
225
267
static Bool
226
268
miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
227
269
                           int x, int y, Bool generateEvent)
228
270
{
229
271
    SetupScreen (pScreen);
230
 
 
231
 
    GenerateEvent = generateEvent;
 
272
    miPointerPtr pPointer = MIPOINTER(pDev);
 
273
 
 
274
    pPointer->generateEvent = generateEvent;
 
275
 
 
276
    if (pScreen->ConstrainCursorHarder)
 
277
        pScreen->ConstrainCursorHarder(pDev, pScreen, Absolute, &x, &y);
 
278
 
232
279
    /* device dependent - must pend signal and call miPointerWarpCursor */
233
280
    (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y);
234
281
    if (!generateEvent)
236
283
    return TRUE;
237
284
}
238
285
 
239
 
/* Set up sprite information for the device.
240
 
   This function will be called once for each device after it is initialized
241
 
   in the DIX.
 
286
/**
 
287
 * Set up sprite information for the device.
 
288
 * This function will be called once for each device after it is initialized
 
289
 * in the DIX.
 
290
 *
 
291
 * @param pDev The newly created device
 
292
 * @param pScreen The initial sprite scree.
242
293
 */
243
294
static Bool
244
295
miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
261
312
    pPointer->confined = FALSE;
262
313
    pPointer->x = 0;
263
314
    pPointer->y = 0;
 
315
    pPointer->generateEvent = FALSE;
264
316
 
265
317
    if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen)))
266
318
    {
272
324
    return TRUE;
273
325
}
274
326
 
275
 
/* Clean up after device.
276
 
   This function will be called once before the device is freed in the DIX
 
327
/**
 
328
 * Clean up after device.
 
329
 * This function will be called once before the device is freed in the DIX
 
330
 *
 
331
 * @param pDev The device to be removed from the server
 
332
 * @param pScreen Current screen of the device
277
333
 */
278
334
static void
279
335
miPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
280
336
{
281
337
    SetupScreen(pScreen);
282
338
 
283
 
    if (!IsMaster(pDev) && pDev->u.master)
 
339
    if (!IsMaster(pDev) && !IsFloating(pDev))
284
340
        return;
285
341
 
286
342
    (*pScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen);
289
345
}
290
346
 
291
347
 
292
 
/* Once signals are ignored, the WarpCursor function can call this */
 
348
/**
 
349
 * Warp the pointer to the given position on the given screen. May generate
 
350
 * an event, depending on whether we're coming from miPointerSetPosition.
 
351
 *
 
352
 * Once signals are ignored, the WarpCursor function can call this
 
353
 *
 
354
 * @param pDev The device to warp
 
355
 * @param pScreen Screen to warp on
 
356
 * @param x The x coordinate in per-screen coordinates
 
357
 * @param y The y coordinate in per-screen coordinates
 
358
 */
293
359
 
294
360
void
295
361
miPointerWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
306
372
        changedScreen = TRUE;
307
373
    }
308
374
 
309
 
    if (GenerateEvent)
 
375
    if (pPointer->generateEvent)
310
376
        miPointerMove (pDev, pScreen, x, y);
311
377
    else
312
378
        miPointerMoveNoEvent(pDev, pScreen, x, y);
322
388
        UpdateSpriteForScreen (pDev, pScreen) ;
323
389
}
324
390
 
325
 
/*
326
 
 * Pointer/CursorDisplay interface routines
327
 
 */
328
 
 
329
 
/*
330
 
 * miPointerUpdateSprite
 
391
/**
 
392
 * Syncronize the sprite with the cursor.
331
393
 *
332
 
 * Syncronize the sprite with the cursor - called from ProcessInputEvents
 
394
 * @param pDev The device to sync
333
395
 */
334
 
 
335
396
void
336
397
miPointerUpdateSprite (DeviceIntPtr pDev)
337
398
{
408
469
    }
409
470
}
410
471
 
 
472
/**
 
473
 * Set the device to the coordinates on the given screen.
 
474
 *
 
475
 * @param pDev The device to move
 
476
 * @param screen_no Index of the screen to move to
 
477
 * @param x The x coordinate in per-screen coordinates
 
478
 * @param y The y coordinate in per-screen coordinates
 
479
 */
411
480
void
412
481
miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y)
413
482
{
426
495
        pPointer->limits.y2 = pScreen->height;
427
496
}
428
497
 
 
498
/**
 
499
 * @return The current screen of the VCP
 
500
 */
429
501
ScreenPtr
430
502
miPointerCurrentScreen (void)
431
503
{
432
504
    return miPointerGetScreen(inputInfo.pointer);
433
505
}
434
506
 
 
507
/**
 
508
 * @return The current screen of the given device or NULL.
 
509
 */
435
510
ScreenPtr
436
511
miPointerGetScreen(DeviceIntPtr pDev)
437
512
{
469
544
     * VCP, as this may cause a non-HW rendered cursor to be rendered during
470
545
     * SIGIO. This again leads to allocs during SIGIO which leads to SIGABRT.
471
546
     */
472
 
    if ((pDev == inputInfo.pointer || (!IsMaster(pDev) && pDev->u.master == inputInfo.pointer))
 
547
    if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer
473
548
        && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
474
549
    {
475
550
        pPointer->devx = x;
483
558
    pPointer->pScreen = pScreen;
484
559
}
485
560
 
486
 
void
487
 
miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y)
 
561
/**
 
562
 * Set the devices' cursor position to the given x/y position.
 
563
 *
 
564
 * This function is called during the pointer update path in
 
565
 * GetPointerEvents and friends (and the same in the xwin DDX).
 
566
 *
 
567
 * The coordinates provided are always absolute. The parameter mode whether
 
568
 * it was relative or absolute movement that landed us at those coordinates.
 
569
 *
 
570
 * @param pDev The device to move
 
571
 * @param mode Movement mode (Absolute or Relative)
 
572
 * @param[in,out] screenx The x coordinate in desktop coordinates
 
573
 * @param[in,out] screeny The y coordinate in desktop coordinates
 
574
 */
 
575
ScreenPtr
 
576
miPointerSetPosition(DeviceIntPtr pDev, int mode, double *screenx, double *screeny)
488
577
{
489
578
    miPointerScreenPtr  pScreenPriv;
490
579
    ScreenPtr           pScreen;
491
580
    ScreenPtr           newScreen;
 
581
    int                 x, y;
 
582
    Bool                switch_screen = FALSE;
492
583
 
493
584
    miPointerPtr        pPointer; 
494
585
 
495
586
    if (!pDev || !pDev->coreEvents)
496
 
        return;
 
587
        return NULL;
497
588
 
498
589
    pPointer = MIPOINTER(pDev);
499
590
    pScreen = pPointer->pScreen;
500
591
    if (!pScreen)
501
 
        return;     /* called before ready */
502
 
 
503
 
    if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height)
 
592
        return NULL;    /* called before ready */
 
593
 
 
594
    x = trunc(*screenx);
 
595
    y = trunc(*screeny);
 
596
 
 
597
    switch_screen = !point_on_screen(pScreen, x, y);
 
598
 
 
599
    /* Switch to per-screen coordinates for CursorOffScreen and
 
600
     * Pointer->limits */
 
601
    x -= pScreen->x;
 
602
    y -= pScreen->y;
 
603
 
 
604
    if (switch_screen)
504
605
    {
505
606
        pScreenPriv = GetScreenPrivate (pScreen);
506
607
        if (!pPointer->confined)
507
608
        {
508
609
            newScreen = pScreen;
509
 
            (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, x, y);
 
610
            (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, &x, &y);
510
611
            if (newScreen != pScreen)
511
612
            {
512
613
                pScreen = newScreen;
513
614
                (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen,
514
615
                                                             FALSE);
515
 
                /* Smash the confine to the new screen */
 
616
                /* Smash the confine to the new screen */
516
617
                pPointer->limits.x2 = pScreen->width;
517
618
                pPointer->limits.y2 = pScreen->height;
518
619
            }
519
620
        }
520
621
    }
521
622
    /* Constrain the sprite to the current limits. */
522
 
    if (*x < pPointer->limits.x1)
523
 
        *x = pPointer->limits.x1;
524
 
    if (*x >= pPointer->limits.x2)
525
 
        *x = pPointer->limits.x2 - 1;
526
 
    if (*y < pPointer->limits.y1)
527
 
        *y = pPointer->limits.y1;
528
 
    if (*y >= pPointer->limits.y2)
529
 
        *y = pPointer->limits.y2 - 1;
530
 
 
531
 
    if (pPointer->x == *x && pPointer->y == *y && 
532
 
            pPointer->pScreen == pScreen) 
533
 
        return;
534
 
 
535
 
    miPointerMoveNoEvent(pDev, pScreen, *x, *y);
 
623
    if (x < pPointer->limits.x1)
 
624
        x = pPointer->limits.x1;
 
625
    if (x >= pPointer->limits.x2)
 
626
        x = pPointer->limits.x2 - 1;
 
627
    if (y < pPointer->limits.y1)
 
628
        y = pPointer->limits.y1;
 
629
    if (y >= pPointer->limits.y2)
 
630
        y = pPointer->limits.y2 - 1;
 
631
 
 
632
    if (pScreen->ConstrainCursorHarder)
 
633
       pScreen->ConstrainCursorHarder(pDev, pScreen, mode, &x, &y);
 
634
 
 
635
    if (pPointer->x != x || pPointer->y != y ||
 
636
            pPointer->pScreen != pScreen)
 
637
        miPointerMoveNoEvent(pDev, pScreen, x, y);
 
638
 
 
639
    /* Convert to desktop coordinates again */
 
640
    x += pScreen->x;
 
641
    y += pScreen->y;
 
642
 
 
643
    /* In the event we actually change screen or we get confined, we just
 
644
     * drop the float component on the floor
 
645
     * FIXME: only drop remainder for ConstrainCursorHarder, not for screen
 
646
     * crossings */
 
647
    if (x != trunc(*screenx))
 
648
        *screenx = x;
 
649
    if (y != trunc(*screeny))
 
650
        *screeny = y;
 
651
 
 
652
    return pScreen;
536
653
}
537
654
 
 
655
/**
 
656
 * Get the current position of the device in desktop coordinates.
 
657
 *
 
658
 * @param x Return value for the current x coordinate in desktop coordiates.
 
659
 * @param y Return value for the current y coordinate in desktop coordiates.
 
660
 */
538
661
void
539
662
miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y)
540
663
{
548
671
void darwinEvents_unlock(void);
549
672
#endif
550
673
 
 
674
/**
 
675
 * Move the device's pointer to the x/y coordinates on the given screen.
 
676
 * This function generates and enqueues pointer events.
 
677
 *
 
678
 * @param pDev The device to move
 
679
 * @param pScreen The screen the device is on
 
680
 * @param x The x coordinate in per-screen coordinates
 
681
 * @param y The y coordinate in per-screen coordinates
 
682
 */
551
683
void
552
684
miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
553
685
{
581
713
    darwinEvents_lock();
582
714
#endif
583
715
    for (i = 0; i < nevents; i++)
584
 
        mieqEnqueue(pDev, (InternalEvent*)events[i].event);
 
716
        mieqEnqueue(pDev, &events[i]);
585
717
#ifdef XQUARTZ
586
718
    darwinEvents_unlock();
587
719
#endif