~sjakthol/compiz/fix-1071689

« back to all changes in this revision

Viewing changes to src/outputdevices.cpp

  • Committer: Tarmac
  • Author(s): Daniel van Vugt
  • Date: 2012-11-14 10:13:51 UTC
  • mfrom: (3465.1.10 separate-outputdevices)
  • Revision ID: tarmac-20121114101351-3ofh1j0ul8trci7x
Separate the OutputDevices class from the *screen* sources into a library 
and add some initial test cases.

This does not contain any logic changes needing review. It's just been
copied and pasted between source files to enable testing.

Approved by PS Jenkins bot, Daniel van Vugt, Sam Spilsbury.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Compiz Core: OutputDevices class
 
3
 *
 
4
 * Copyright (c) 2012 Canonical Ltd.
 
5
 * 
 
6
 * Permission is hereby granted, free of charge, to any person obtaining a
 
7
 * copy of this software and associated documentation files (the "Software"),
 
8
 * to deal in the Software without restriction, including without limitation
 
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
10
 * and/or sell copies of the Software, and to permit persons to whom the
 
11
 * Software is furnished to do so, subject to the following conditions:
 
12
 * 
 
13
 * The above copyright notice and this permission notice shall be included in
 
14
 * all copies or substantial portions of the Software.
 
15
 * 
 
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 
22
 * DEALINGS IN THE SOFTWARE.
 
23
 */
 
24
 
 
25
#include <core/option.h>
 
26
#include "outputdevices.h"
 
27
#include "core_options.h"
 
28
 
 
29
namespace compiz
 
30
{
 
31
namespace core
 
32
{
 
33
 
 
34
OutputDevices::OutputDevices() :
 
35
    outputDevs (),
 
36
    overlappingOutputs (false),
 
37
    currentOutputDev (0)
 
38
{
 
39
}
 
40
 
 
41
void
 
42
OutputDevices::setGeometryOnDevice(unsigned int const nOutput,
 
43
    int x, int y,
 
44
    const int width, const int height)
 
45
{
 
46
    if (outputDevs.size() < nOutput + 1)
 
47
        outputDevs.resize(nOutput + 1);
 
48
 
 
49
    outputDevs[nOutput].setGeometry(x, y, width, height);
 
50
}
 
51
 
 
52
void
 
53
OutputDevices::adoptDevices(unsigned int nOutput, CompSize* screen)
 
54
{
 
55
    /* make sure we have at least one output */
 
56
    if (!nOutput)
 
57
    {
 
58
        setGeometryOnDevice(nOutput, 0, 0, screen->width(), screen->height());
 
59
        nOutput++;
 
60
    }
 
61
    if (outputDevs.size() > nOutput)
 
62
        outputDevs.resize(nOutput);
 
63
 
 
64
    char str[10];
 
65
    /* set name, width, height and update rect pointers in all regions */
 
66
    for (unsigned int i = 0; i < nOutput; i++)
 
67
    {
 
68
        snprintf(str, 10, "Output %d", i);
 
69
        outputDevs[i].setId(str, i);
 
70
    }
 
71
    overlappingOutputs = false;
 
72
    setCurrentOutput (currentOutputDev);
 
73
    for (unsigned int i = 0; i < nOutput - 1; i++)
 
74
        for (unsigned int j = i + 1; j < nOutput; j++)
 
75
            if (outputDevs[i].intersects(outputDevs[j]))
 
76
                overlappingOutputs = true;
 
77
}
 
78
 
 
79
void
 
80
OutputDevices::setCurrentOutput (unsigned int outputNum)
 
81
{
 
82
    if (outputNum >= outputDevs.size ())
 
83
        outputNum = 0;
 
84
 
 
85
    currentOutputDev = outputNum;
 
86
}
 
87
 
 
88
int
 
89
OutputDevices::outputDeviceForGeometry (
 
90
        const CompWindow::Geometry& gm,
 
91
        int strategy,
 
92
        CompSize* screen) const
 
93
{
 
94
    int          overlapAreas[outputDevs.size ()];
 
95
    int          highest, seen, highestScore;
 
96
    int          x, y;
 
97
    unsigned int i;
 
98
    CompRect     geomRect;
 
99
 
 
100
    if (outputDevs.size () == 1)
 
101
        return 0;
 
102
 
 
103
 
 
104
    if (strategy == CoreOptions::OverlappingOutputsSmartMode)
 
105
    {
 
106
        int centerX, centerY;
 
107
 
 
108
        /* for smart mode, calculate the overlap of the whole rectangle
 
109
           with the output device rectangle */
 
110
        geomRect.setWidth (gm.width () + 2 * gm.border ());
 
111
        geomRect.setHeight (gm.height () + 2 * gm.border ());
 
112
 
 
113
        x = gm.x () % screen->width ();
 
114
        centerX = (x + (geomRect.width () / 2));
 
115
        if (centerX < 0)
 
116
            x += screen->width ();
 
117
        else if (centerX > screen->width ())
 
118
            x -= screen->width ();
 
119
        geomRect.setX (x);
 
120
 
 
121
        y = gm.y () % screen->height ();
 
122
        centerY = (y + (geomRect.height () / 2));
 
123
        if (centerY < 0)
 
124
            y += screen->height ();
 
125
        else if (centerY > screen->height ())
 
126
            y -= screen->height ();
 
127
        geomRect.setY (y);
 
128
    }
 
129
    else
 
130
    {
 
131
        /* for biggest/smallest modes, only use the window center to determine
 
132
           the correct output device */
 
133
        x = (gm.x () + (gm.width () / 2) + gm.border ()) % screen->width ();
 
134
        if (x < 0)
 
135
            x += screen->width ();
 
136
        y = (gm.y () + (gm.height () / 2) + gm.border ()) % screen->height ();
 
137
        if (y < 0)
 
138
            y += screen->height ();
 
139
 
 
140
        geomRect.setGeometry (x, y, 1, 1);
 
141
    }
 
142
 
 
143
    /* get amount of overlap on all output devices */
 
144
    for (i = 0; i < outputDevs.size (); i++)
 
145
    {
 
146
        CompRect overlap = outputDevs[i] & geomRect;
 
147
        overlapAreas[i] = overlap.area ();
 
148
    }
 
149
 
 
150
    /* find output with largest overlap */
 
151
    for (i = 0, highest = 0, highestScore = 0;
 
152
         i < outputDevs.size (); i++)
 
153
    {
 
154
        if (overlapAreas[i] > highestScore)
 
155
        {
 
156
            highest = i;
 
157
            highestScore = overlapAreas[i];
 
158
        }
 
159
    }
 
160
 
 
161
    /* look if the highest score is unique */
 
162
    for (i = 0, seen = 0; i < outputDevs.size (); i++)
 
163
        if (overlapAreas[i] == highestScore)
 
164
            seen++;
 
165
 
 
166
    if (seen > 1)
 
167
    {
 
168
        /* it's not unique, select one output of the matching ones and use the
 
169
           user preferred strategy for that */
 
170
        unsigned int currentSize, bestOutputSize;
 
171
        bool         searchLargest;
 
172
 
 
173
        searchLargest =
 
174
            (strategy != CoreOptions::OverlappingOutputsPreferSmallerOutput);
 
175
 
 
176
        if (searchLargest)
 
177
            bestOutputSize = 0;
 
178
        else
 
179
            bestOutputSize = UINT_MAX;
 
180
 
 
181
        for (i = 0, highest = 0; i < outputDevs.size (); i++)
 
182
            if (overlapAreas[i] == highestScore)
 
183
            {
 
184
                bool bestFit;
 
185
 
 
186
                currentSize = outputDevs[i].area ();
 
187
 
 
188
                if (searchLargest)
 
189
                    bestFit = (currentSize > bestOutputSize);
 
190
                else
 
191
                    bestFit = (currentSize < bestOutputSize);
 
192
 
 
193
                if (bestFit)
 
194
                {
 
195
                    highest = i;
 
196
                    bestOutputSize = currentSize;
 
197
                }
 
198
            }
 
199
    }
 
200
 
 
201
    return highest;
 
202
}
 
203
 
 
204
} // namespace core
 
205
} // namespace compiz
 
206