1 /*
2  * synergy -- mouse and keyboard sharing utility
3  * Copyright (C) 2012-2021 Symless Ltd.
4  * Copyright (C) 2008 Volker Lanz (vl@fidra.de)
5  *
6  * This package is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * found in the file LICENSE that should have accompanied this file.
9  *
10  * This package is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 #include "ScreenList.h"
19 
20 #include <array>
21 
22 namespace {
23 
24 /**
25  * @brief getNeightborIndexes returns indexes for server neighbors
26  * @param serverIndex server index
27  * @param width of the grid
28  * @param size of the grid
29  * @return indexes for server neighbors
30  */
getNeighborsIndexes(int serverIndex,int width,int size)31 std::array<int, 8> getNeighborsIndexes(int serverIndex, int width, int size)
32 {
33     const int UNSET        = -1;
34     const int LEFT         = 0;
35     const int RIGHT        = 1;
36     const int TOP          = 2;
37     const int BOTTOM       = 3;
38     const int TOP_LEFT     = 4;
39     const int TOP_RIGHT    = 5;
40     const int BOTTOM_RIGHT = 6;
41     const int BOTTOM_LEFT  = 7;
42 
43     std::array<int, 8> indexes = { UNSET };
44 
45     if (serverIndex >= 0 && serverIndex < size)
46     {
47         indexes[LEFT]         = (serverIndex - 1) % width != width - 1 ? (serverIndex - 1) : UNSET;
48         indexes[RIGHT]        = (serverIndex + 1) % width != 0 ? (serverIndex + 1) : UNSET;
49         indexes[TOP]          = (serverIndex - width) >= 0 ? (serverIndex - width) : UNSET;
50         indexes[BOTTOM]       = (serverIndex + width) < size ? (serverIndex + width) : UNSET;
51         indexes[TOP_LEFT]     = (indexes[TOP] != UNSET && indexes[LEFT] != UNSET) ? indexes[TOP] - 1 : UNSET;
52         indexes[TOP_RIGHT]    = (indexes[TOP] != UNSET && indexes[RIGHT] != UNSET) ? indexes[TOP] + 1 : UNSET;
53         indexes[BOTTOM_RIGHT] = (indexes[BOTTOM] != UNSET && indexes[RIGHT] != UNSET) ? indexes[BOTTOM] + 1 : UNSET;
54         indexes[BOTTOM_LEFT]  = (indexes[BOTTOM] != UNSET && indexes[LEFT] != UNSET) ? indexes[BOTTOM] - 1 : UNSET;
55     }
56 
57     return indexes;
58 }
59 
60 /**
61  * @brief getServerIndex finds server and returns it's index
62  * @param screens list to find server
63  * @return server index
64  */
getServerIndex(const ScreenList & screens)65 int getServerIndex(const ScreenList& screens)
66 {
67     int serverIndex = -1;
68 
69     for (int i = 0; i < screens.size(); ++i)
70     {
71         if (screens[i].isServer()){
72             serverIndex = i;
73             break;
74         }
75     }
76 
77     return serverIndex;
78 }
79 
80 } //namespace
81 
ScreenList(int width)82 ScreenList::ScreenList(int width) :
83     QList<Screen>(),
84     m_width(width)
85 {
86 
87 }
88 
addScreenByPriority(const Screen & newScreen)89 void ScreenList::addScreenByPriority(const Screen& newScreen)
90 {
91     int serverIndex = getServerIndex(*this);
92     auto indexes = getNeighborsIndexes(serverIndex, m_width, size());
93 
94     bool isAdded = false;
95     for (const auto& index : indexes)
96     {
97         if (index >= 0 && index < size())
98         {
99             auto& screen = operator[](index);
100             if (screen.isNull())
101             {
102                 screen = newScreen;
103                 isAdded = true;
104                 break;
105             }
106         }
107     }
108 
109     if (!isAdded)
110     {
111         addScreenToFirstEmpty(newScreen);
112     }
113 }
114 
addScreenToFirstEmpty(const Screen & newScreen)115 void ScreenList::addScreenToFirstEmpty(const Screen& newScreen)
116 {
117     for (int i = 0; i < size(); ++i)
118     {
119         auto& screen = operator[](i);
120         if (screen.isNull())
121         {
122             screen = newScreen;
123             break;
124         }
125     }
126 }
127 
128