1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
/* XGGeometry - Utility functions that calculate in device space
Copyright (C) 2002 Free Software Foundation, Inc.
Written by: Willem Oudshoorn <woudshoo@xs4all.nl>
This file is part of the GNU Objective C User Interface Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; see the file COPYING.LIB.
If not, see <http://www.gnu.org/licenses/> or write to the
Free Software Foundation, 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "config.h"
#include <Foundation/NSDebug.h>
#include "xlib/XGGeometry.h"
#include "x11/XGServer.h"
/**
* Returns the area that is accessible in the underlying drawable
* of win.
*
* Accessible means that we can use XPutPixel and XGetPixel
* on all the points in the result.
* If the window uses a backingstore this will be the size
* of the underlying drawable, but if the window does not
* use backing store and the window is partly outside the screen
* it will be the part of the window that falls inside the screen.
*
* NOTE:
* Unfortunately, the gswindow_device_t does not contain a reference
* to the XDisplay it is displayed on and we need it.
*/
XRectangle
accessibleRectForWindow (gswindow_device_t* win)
{
Display* xdpy = [XGServer xDisplay];
Window root;
Window ignoreWindow;
int x, y;
unsigned int w, h;
int ignoreInt;
unsigned int ignoreUInt;
XRectangle winRect;
if (!XGetGeometry (xdpy, GET_XDRAWABLE (win),
&root,
&x, &y,
&w, &h,
&ignoreUInt,
&ignoreUInt))
{
NSDebugLLog (@"XGGeometry", @"invalid Drawable in gswindow_device");
return XGMakeRect (0, 0, 0, 0);
}
winRect = XGMakeRect (0, 0, w, h);
if (win->buffer)
{
return winRect;
}
// we do not have backing store, so clip it to the screen.
if (!XGetGeometry (xdpy, root,
&root,
&ignoreInt, &ignoreInt,
&w, &h,
&ignoreUInt, &ignoreUInt))
{
NSDebugLLog (@"XGGeometry", @"could not determine size of root");
return XGMakeRect (0, 0, 0, 0);
}
if (!XTranslateCoordinates (xdpy,
root,
GET_XDRAWABLE (win),
0, 0,
&x, &y,
&ignoreWindow))
{
NSDebugLLog (@"XGGeometry", @"could not determine position of device");
return XGMakeRect (0, 0, 0, 0);
}
return XGIntersectionRect (winRect, XGMakeRect (x, y, w, h));
}
/**
*
* POST CONDITIONS
* winA and winB are unmodified
* rectA and rectB have the same size
* rectA is an accessible rectangle in winA
* rectB is an accessible rectangle in winB
* rectA is a subrectangle of the argument rectA
* rectB is a subrectangle of the argument rectB
* the size of RectA and rectB are maximal with respect to the conditions above.
*
* USAGE
* typical usage will be in copy operations between one gswindow_device to
* another gswindow_device. This because the result will be the maximal
* region that we are able to copy without generating X-protocol errors
* or segfaults.
*/
void
clipXRectsForCopying (gswindow_device_t* winA, XRectangle* rectA,
gswindow_device_t* winB, XRectangle* rectB)
{
XPoint shiftA, shiftB;
// First make A smaller.
shiftA.x = rectA->x;
shiftA.y = rectA->y;
*rectA = XGIntersectionRect (*rectA, accessibleRectForWindow (winA));
// update size of B with the size of A
rectB->x += rectA->x - shiftA.x;
rectB->y += rectA->y - shiftA.y;
rectB->width = MIN (rectA->width, rectB->width);
rectB->height = MIN (rectA->height, rectB->height);
// now make B smaller
shiftB.x = rectB->x;
shiftB.y = rectB->y;
*rectB = XGIntersectionRect (*rectB, accessibleRectForWindow (winB));
// and update size of A with size of B
rectA->x += rectB->x - shiftB.x;
rectA->y += rectB->y - shiftB.y;
rectA->width = rectB->width;
rectA->height = rectB->height;
}
|