File: XGGeometry.m

package info (click to toggle)
gnustep-back 0.32.0-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,320 kB
  • sloc: objc: 42,426; ansic: 6,623; xml: 258; makefile: 130; sh: 120
file content (142 lines) | stat: -rw-r--r-- 4,759 bytes parent folder | download | duplicates (4)
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;
}