Merge lp:~3v1n0/compiz/support-desktop-average-colors into lp:compiz
- support-desktop-average-colors
- Merge into 0.9.13
Proposed by
Marco Trevisan (Treviño)
on 2017-06-30
| Status: | Merged |
|---|---|
| Approved by: | Andrea Azzarone on 2017-06-30 |
| Approved revision: | 4150 |
| Merged at revision: | 4125 |
| Proposed branch: | lp:~3v1n0/compiz/support-desktop-average-colors |
| Merge into: | lp:compiz |
| Prerequisite: | lp:~3v1n0/compiz/resize-lowgfx-fixes |
| Diff against target: |
1075 lines (+506/-96) 17 files modified
include/core/abiversion.h (+1/-1) include/core/atoms.h (+2/-0) include/core/screen.h (+7/-1) include/core/string.h (+3/-0) plugins/grid/grid.xml.in (+5/-0) plugins/grid/src/grid.cpp (+42/-9) plugins/move/move.xml.in (+10/-0) plugins/move/src/move.cpp (+142/-61) plugins/move/src/move.h (+1/-1) plugins/resize/resize.xml.in (+10/-0) plugins/resize/src/resize.cpp (+69/-18) src/atoms.cpp (+4/-0) src/event.cpp (+5/-0) src/privatescreen.h (+6/-0) src/privatescreen/tests/test-privatescreen.cpp (+2/-0) src/screen.cpp (+136/-5) src/string/src/string.cpp (+61/-0) |
| To merge this branch: | bzr merge lp:~3v1n0/compiz/support-desktop-average-colors |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Andrea Azzarone | 2017-06-30 | Approve on 2017-06-30 | |
|
Review via email:
|
|||
Commit Message
Screen: add averageColor to get the current desktop average color
We get the value from the root window and we parse it using regex.
Also use this in 'move', 'resize' and 'grid' plugins by default, doing the
appropriate lightening / darkening to make this working properly
on the desktop surface
Description of the Change
To post a comment you must log in.
lp:~3v1n0/compiz/support-desktop-average-colors
updated
on 2017-06-30
- 4150. By Marco Trevisan (Treviño) on 2017-06-30
-
move, resize: fix compilation issue in GLES platforms
lp:~3v1n0/compiz/support-desktop-average-colors
updated
on 2017-07-03
- 4151. By Marco Trevisan (Treviño) on 2017-07-03
-
move, resize: fix damaging glitches with bigger border
- 4152. By Marco Trevisan (Treviño) on 2017-07-03
-
String: fix typo in regex match check
Don't miss the values... regex_match returns true if valid
- 4153. By Marco Trevisan (Treviño) on 2017-07-03
-
move: enable glPaintOutput only if we've a window to move and damage it on init
- 4154. By Marco Trevisan (Treviño) on 2017-07-03
-
move: use the same code for damaging the moving rectangle on init and on updates
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
| 1 | === modified file 'include/core/abiversion.h' |
| 2 | --- include/core/abiversion.h 2015-10-13 11:33:31 +0000 |
| 3 | +++ include/core/abiversion.h 2017-07-03 15:16:04 +0000 |
| 4 | @@ -5,6 +5,6 @@ |
| 5 | # error Conflicting definitions of CORE_ABIVERSION |
| 6 | #endif |
| 7 | |
| 8 | -#define CORE_ABIVERSION 20151010 |
| 9 | +#define CORE_ABIVERSION 20170630 |
| 10 | |
| 11 | #endif // COMPIZ_ABIVERSION_H |
| 12 | |
| 13 | === modified file 'include/core/atoms.h' |
| 14 | --- include/core/atoms.h 2015-02-17 14:54:10 +0000 |
| 15 | +++ include/core/atoms.h 2017-07-03 15:16:04 +0000 |
| 16 | @@ -158,6 +158,8 @@ |
| 17 | |
| 18 | extern Atom startupId; |
| 19 | |
| 20 | + extern Atom gnomeRepresentativeColors; |
| 21 | + |
| 22 | void init (Display *dpy); |
| 23 | }; |
| 24 | |
| 25 | |
| 26 | === modified file 'include/core/screen.h' |
| 27 | --- include/core/screen.h 2016-04-26 12:42:39 +0000 |
| 28 | +++ include/core/screen.h 2017-07-03 15:16:04 +0000 |
| 29 | @@ -156,6 +156,8 @@ |
| 30 | virtual void addSupportedAtoms (std::vector<Atom>& atoms); |
| 31 | |
| 32 | virtual void cursorChangeNotify (const CompString& theme, int size); |
| 33 | + |
| 34 | + virtual void averageColorChangeNotify (const unsigned short *color); |
| 35 | }; |
| 36 | |
| 37 | namespace compiz { namespace private_screen { |
| 38 | @@ -221,7 +223,7 @@ |
| 39 | } |
| 40 | |
| 41 | class CompScreen : |
| 42 | - public WrapableHandler<ScreenInterface, 19>, |
| 43 | + public WrapableHandler<ScreenInterface, 20>, |
| 44 | public PluginClassStorage, // TODO should be an interface here |
| 45 | public CompSize, |
| 46 | public virtual ::compiz::DesktopWindowCount, |
| 47 | @@ -273,6 +275,8 @@ |
| 48 | std::vector<Atom>& atoms); |
| 49 | WRAPABLE_HND (18, ScreenInterface, void, cursorChangeNotify, |
| 50 | const CompString&, int); |
| 51 | + WRAPABLE_HND (19, ScreenInterface, void, averageColorChangeNotify, |
| 52 | + const unsigned short *); |
| 53 | |
| 54 | unsigned int allocPluginClassIndex (); |
| 55 | void freePluginClassIndex (unsigned int index); |
| 56 | @@ -418,6 +422,7 @@ |
| 57 | virtual CompWindow * getTopServerWindow() const = 0; |
| 58 | virtual CoreOptions& getCoreOptions() = 0; |
| 59 | virtual Colormap colormap() const = 0; |
| 60 | + virtual const unsigned short * averageColor() const = 0; |
| 61 | virtual void setCurrentDesktop (unsigned int desktop) = 0; |
| 62 | virtual Window activeWindow() const = 0; |
| 63 | virtual void updatePassiveButtonGrabs(Window serverFrame) = 0; |
| 64 | @@ -453,6 +458,7 @@ |
| 65 | virtual void _matchPropertyChanged(CompWindow *) = 0; |
| 66 | virtual void _outputChangeNotify() = 0; |
| 67 | virtual void _cursorChangeNotify(const CompString&, int) = 0; |
| 68 | + virtual void _averageColorChangeNotify(const unsigned short*) = 0; |
| 69 | }; |
| 70 | |
| 71 | #endif |
| 72 | |
| 73 | === modified file 'include/core/string.h' |
| 74 | --- include/core/string.h 2011-10-31 13:51:00 +0000 |
| 75 | +++ include/core/string.h 2017-07-03 15:16:04 +0000 |
| 76 | @@ -28,12 +28,15 @@ |
| 77 | |
| 78 | #include <string> |
| 79 | #include <list> |
| 80 | +#include <vector> |
| 81 | #include <cstdarg> |
| 82 | |
| 83 | typedef std::string CompString; |
| 84 | typedef std::list<CompString> CompStringList; |
| 85 | +typedef std::vector<CompString> CompStringVector; |
| 86 | |
| 87 | CompString compPrintf (const char *format, ...); |
| 88 | CompString compPrintf (const char *format, va_list ap); |
| 89 | +CompStringVector compGetRegexMatches (const CompString& regexStr, const CompString& string); |
| 90 | |
| 91 | #endif |
| 92 | |
| 93 | === modified file 'plugins/grid/grid.xml.in' |
| 94 | --- plugins/grid/grid.xml.in 2016-09-07 12:26:21 +0000 |
| 95 | +++ plugins/grid/grid.xml.in 2017-07-03 15:16:04 +0000 |
| 96 | @@ -569,6 +569,11 @@ |
| 97 | <default>350</default> |
| 98 | <min>0</min> |
| 99 | </option> |
| 100 | + <option name="use_desktop_average_color" type="bool"> |
| 101 | + <_short>Use Desktop average color</_short> |
| 102 | + <_long>Try to use the desktop average color if defined by your DE.</_long> |
| 103 | + <default>true</default> |
| 104 | + </option> |
| 105 | <option name="outline_color" type="color"> |
| 106 | <_short>Preview Outline Color</_short> |
| 107 | <_long>Color and opacity of the resize indicator preview outline.</_long> |
| 108 | |
| 109 | === modified file 'plugins/grid/src/grid.cpp' |
| 110 | --- plugins/grid/src/grid.cpp 2017-07-03 15:16:04 +0000 |
| 111 | +++ plugins/grid/src/grid.cpp 2017-07-03 15:16:04 +0000 |
| 112 | @@ -508,7 +508,8 @@ |
| 113 | GLVertexBuffer *streamingBuffer = GLVertexBuffer::streamingBuffer (); |
| 114 | GLfloat vertexData[12]; |
| 115 | GLushort colorData[4]; |
| 116 | - GLushort *color; |
| 117 | + unsigned short *color, *fillColor, *outlineColor; |
| 118 | + unsigned short averageFillColor[4], averageOutlineColor[4]; |
| 119 | GLboolean isBlendingEnabled; |
| 120 | bool blend = !optionGetDisableBlend (); |
| 121 | |
| 122 | @@ -527,13 +528,45 @@ |
| 123 | glEnable (GL_BLEND); |
| 124 | } |
| 125 | |
| 126 | + fillColor = optionGetFillColor (); |
| 127 | + outlineColor = optionGetOutlineColor (); |
| 128 | + |
| 129 | + if (optionGetUseDesktopAverageColor ()) |
| 130 | + { |
| 131 | + const unsigned short *averageColor = screen->averageColor (); |
| 132 | + |
| 133 | + if (averageColor) |
| 134 | + { |
| 135 | + memcpy (averageFillColor, averageColor, 4 * sizeof (unsigned short)); |
| 136 | + averageFillColor[3] = MaxUShortFloat * 0.6; |
| 137 | + fillColor = averageFillColor; |
| 138 | + |
| 139 | + // Generate a lighter color based on border to create more contrast |
| 140 | + unsigned int averageColorLevel = (averageColor[0] + averageColor[1] + averageColor[2]) / 3; |
| 141 | + unsigned short *oc = averageOutlineColor; |
| 142 | + |
| 143 | + float colorMultiplier; |
| 144 | + if (averageColorLevel > MaxUShortFloat * 0.3) |
| 145 | + colorMultiplier = 0.7; // make it darker |
| 146 | + else |
| 147 | + colorMultiplier = 2.0; // make it lighter |
| 148 | + |
| 149 | + oc[3] = averageColor[3]; |
| 150 | + oc[0] = MIN(MaxUShortFloat, ((float) averageColor[0]) * colorMultiplier) * oc[3] / MaxUShortFloat; |
| 151 | + oc[1] = MIN(MaxUShortFloat, ((float) averageColor[1]) * colorMultiplier) * oc[3] / MaxUShortFloat; |
| 152 | + oc[2] = MIN(MaxUShortFloat, ((float) averageColor[2]) * colorMultiplier) * oc[3] / MaxUShortFloat; |
| 153 | + |
| 154 | + outlineColor = averageOutlineColor; |
| 155 | + } |
| 156 | + } |
| 157 | + |
| 158 | for (iter = animations.begin (); iter != animations.end () && animating; ++iter) |
| 159 | { |
| 160 | Animation& anim = *iter; |
| 161 | |
| 162 | float curve = powf (CURVE_ANIMATION, -anim.progress); |
| 163 | - float alpha = blend ? (optionGetFillColorAlpha () / MaxUShortFloat) * anim.opacity : 0.85; |
| 164 | - color = optionGetFillColor (); |
| 165 | + float alpha = blend ? (fillColor[3] / MaxUShortFloat) * anim.opacity : 0.85; |
| 166 | + color = fillColor; |
| 167 | |
| 168 | colorData[0] = alpha * color[0]; |
| 169 | colorData[1] = alpha * color[1]; |
| 170 | @@ -570,8 +603,8 @@ |
| 171 | anim.currentRect.height () - 2); |
| 172 | |
| 173 | /* draw outline */ |
| 174 | - alpha = blend ? (optionGetOutlineColorAlpha () / MaxUShortFloat) * anim.opacity : 1; |
| 175 | - color = optionGetOutlineColor (); |
| 176 | + alpha = blend ? (outlineColor[3] / MaxUShortFloat) * anim.opacity : 1; |
| 177 | + color = outlineColor; |
| 178 | |
| 179 | colorData[0] = alpha * color[0]; |
| 180 | colorData[1] = alpha * color[1]; |
| 181 | @@ -603,8 +636,8 @@ |
| 182 | if (!animating) |
| 183 | { |
| 184 | /* draw filled rectangle */ |
| 185 | - float alpha = blend ? optionGetFillColorAlpha () / MaxUShortFloat : 0.85; |
| 186 | - color = optionGetFillColor (); |
| 187 | + float alpha = blend ? fillColor[3] / MaxUShortFloat : 0.85; |
| 188 | + color = fillColor; |
| 189 | |
| 190 | colorData[0] = alpha * color[0]; |
| 191 | colorData[1] = alpha * color[1]; |
| 192 | @@ -638,8 +671,8 @@ |
| 193 | rect.height () - 2); |
| 194 | |
| 195 | /* draw outline */ |
| 196 | - alpha = optionGetOutlineColorAlpha () / MaxUShortFloat; |
| 197 | - color = optionGetOutlineColor (); |
| 198 | + alpha = outlineColor[3] / MaxUShortFloat; |
| 199 | + color = outlineColor; |
| 200 | |
| 201 | colorData[0] = alpha * color[0]; |
| 202 | colorData[1] = alpha * color[1]; |
| 203 | |
| 204 | === modified file 'plugins/move/move.xml.in' |
| 205 | --- plugins/move/move.xml.in 2016-09-07 12:25:04 +0000 |
| 206 | +++ plugins/move/move.xml.in 2017-07-03 15:16:04 +0000 |
| 207 | @@ -92,6 +92,16 @@ |
| 208 | <_name>Rectangle</_name> |
| 209 | </desc> |
| 210 | </option> |
| 211 | + <option name="increase_border_contrast" type="bool"> |
| 212 | + <_short>Use a double-border in 'Rectangle' and 'Outline' modes</_short> |
| 213 | + <_long>Increase the contrast of the border using a lighter color.</_long> |
| 214 | + <default>true</default> |
| 215 | + </option> |
| 216 | + <option name="use_desktop_average_color" type="bool"> |
| 217 | + <_short>Use Desktop average colors</_short> |
| 218 | + <_long>Try to use the desktop average color if defined by your DE (overrides custom colors).</_long> |
| 219 | + <default>true</default> |
| 220 | + </option> |
| 221 | <option name="border_color" type="color"> |
| 222 | <_short>Border Color</_short> |
| 223 | <_long>Border color used for outline and rectangle moving modes</_long> |
| 224 | |
| 225 | === modified file 'plugins/move/src/move.cpp' |
| 226 | --- plugins/move/src/move.cpp 2017-07-03 15:16:04 +0000 |
| 227 | +++ plugins/move/src/move.cpp 2017-07-03 15:16:04 +0000 |
| 228 | @@ -34,6 +34,9 @@ |
| 229 | |
| 230 | COMPIZ_PLUGIN_20090315 (move, MovePluginVTable) |
| 231 | |
| 232 | +static const int defaultBorderWidth = 2; |
| 233 | +static const int biggerBorderWidthMultiplier = 2; |
| 234 | + |
| 235 | static bool |
| 236 | moveInitiate (CompAction *action, |
| 237 | CompAction::State state, |
| 238 | @@ -43,14 +46,6 @@ |
| 239 | |
| 240 | MOVE_SCREEN (screen); |
| 241 | |
| 242 | - if (ms->optionGetMode () != MoveOptions::ModeNormal) |
| 243 | - { |
| 244 | - ms->gScreen->glPaintOutputSetEnabled (ms, true); |
| 245 | - ms->paintRect = true; |
| 246 | - ms->rectX = 0; |
| 247 | - ms->rectY = 0; |
| 248 | - } |
| 249 | - |
| 250 | Window xid = CompOption::getIntOptionNamed (options, "window"); |
| 251 | |
| 252 | w = screen->findWindow (xid); |
| 253 | @@ -150,6 +145,19 @@ |
| 254 | s->warpPointer (xRoot - pointerX, yRoot - pointerY); |
| 255 | } |
| 256 | |
| 257 | + if (ms->optionGetMode () != MoveOptions::ModeNormal) |
| 258 | + { |
| 259 | + Box box; |
| 260 | + |
| 261 | + ms->gScreen->glPaintOutputSetEnabled (ms, true); |
| 262 | + ms->paintRect = true; |
| 263 | + ms->rectX = 0; |
| 264 | + ms->rectY = 0; |
| 265 | + |
| 266 | + if (ms->getMovingRectangle (&box)) |
| 267 | + ms->damageMovingRectangle (&box); |
| 268 | + } |
| 269 | + |
| 270 | if (ms->moveOpacity != OPAQUE) |
| 271 | { |
| 272 | MOVE_WINDOW (w); |
| 273 | @@ -797,6 +805,61 @@ |
| 274 | return true; |
| 275 | } |
| 276 | |
| 277 | +bool |
| 278 | +MoveScreen::damageMovingRectangle (BoxPtr pBox) |
| 279 | +{ |
| 280 | + CompRegion damageRegion; |
| 281 | + int borderWidth; |
| 282 | + |
| 283 | + if (!cScreen || !pBox) |
| 284 | + return false; |
| 285 | + |
| 286 | + borderWidth = defaultBorderWidth; |
| 287 | + |
| 288 | + if (optionGetIncreaseBorderContrast ()) |
| 289 | + borderWidth *= biggerBorderWidthMultiplier; |
| 290 | + |
| 291 | + if (optionGetMode () == MoveOptions::ModeRectangle) |
| 292 | + { |
| 293 | + CompRect damage (pBox->x1 - borderWidth, |
| 294 | + pBox->y1 - borderWidth, |
| 295 | + pBox->x2 - pBox->x1 + borderWidth * 2, |
| 296 | + pBox->y2 - pBox->y1 + borderWidth * 2); |
| 297 | + damageRegion += damage; |
| 298 | + } |
| 299 | + else if (optionGetMode () == MoveOptions::ModeOutline) |
| 300 | + { |
| 301 | + // Top |
| 302 | + damageRegion += CompRect (pBox->x1 - borderWidth, |
| 303 | + pBox->y1 - borderWidth, |
| 304 | + pBox->x2 - pBox->x1 + borderWidth * 2, |
| 305 | + borderWidth * 2); |
| 306 | + // Right |
| 307 | + damageRegion += CompRect (pBox->x2 - borderWidth, |
| 308 | + pBox->y1 - borderWidth, |
| 309 | + borderWidth + borderWidth / 2, |
| 310 | + pBox->y2 - pBox->y1 + borderWidth * 2); |
| 311 | + // Bottom |
| 312 | + damageRegion += CompRect (pBox->x1 - borderWidth, |
| 313 | + pBox->y2 - borderWidth, |
| 314 | + pBox->x2 - pBox->x1 + borderWidth * 2, |
| 315 | + borderWidth * 2); |
| 316 | + // Left |
| 317 | + damageRegion += CompRect (pBox->x1 - borderWidth, |
| 318 | + pBox->y1 - borderWidth, |
| 319 | + borderWidth + borderWidth / 2, |
| 320 | + pBox->y2 - pBox->y1 + borderWidth * 2); |
| 321 | + } |
| 322 | + |
| 323 | + if (!damageRegion.isEmpty ()) |
| 324 | + { |
| 325 | + cScreen->damageRegion (damageRegion); |
| 326 | + return true; |
| 327 | + } |
| 328 | + |
| 329 | + return false; |
| 330 | +} |
| 331 | + |
| 332 | bool MoveScreen::glPaintOutput (const GLScreenPaintAttrib &attrib, |
| 333 | const GLMatrix &transform, |
| 334 | const CompRegion ®ion, |
| 335 | @@ -833,11 +896,31 @@ |
| 336 | const float MaxUShortFloat = MaxUShort; |
| 337 | GLVertexBuffer *streamingBuffer = GLVertexBuffer::streamingBuffer (); |
| 338 | GLMatrix sTransform (transform); |
| 339 | + bool usingAverageColors = false; |
| 340 | |
| 341 | GLfloat vertexData[12]; |
| 342 | GLfloat vertexData2[24]; |
| 343 | - GLushort fc[4], bc[4]; |
| 344 | + GLushort fc[4], bc[4], averageFillColor[4]; |
| 345 | GLint origSrc, origDst; |
| 346 | +#ifdef USE_GLES |
| 347 | + GLint origSrcAlpha, origDstAlpha; |
| 348 | +#endif |
| 349 | + |
| 350 | + if (optionGetUseDesktopAverageColor ()) |
| 351 | + { |
| 352 | + const unsigned short *averageColor = screen->averageColor (); |
| 353 | + |
| 354 | + if (averageColor) |
| 355 | + { |
| 356 | + usingAverageColors = true; |
| 357 | + borderColor = const_cast<unsigned short *>(averageColor); |
| 358 | + memcpy (averageFillColor, averageColor, 4 * sizeof (unsigned short)); |
| 359 | + averageFillColor[3] = MaxUShort * 0.6; |
| 360 | + |
| 361 | + if (fillColor) |
| 362 | + fillColor = averageFillColor; |
| 363 | + } |
| 364 | + } |
| 365 | |
| 366 | bool blend = optionGetBlend (); |
| 367 | |
| 368 | @@ -850,7 +933,6 @@ |
| 369 | if (blend) |
| 370 | { |
| 371 | #ifdef USE_GLES |
| 372 | - GLint origSrcAlpha, origDstAlpha; |
| 373 | glGetIntegerv (GL_BLEND_SRC_RGB, &origSrc); |
| 374 | glGetIntegerv (GL_BLEND_DST_RGB, &origDst); |
| 375 | glGetIntegerv (GL_BLEND_SRC_ALPHA, &origSrcAlpha); |
| 376 | @@ -861,11 +943,6 @@ |
| 377 | #endif |
| 378 | } |
| 379 | |
| 380 | - bc[3] = blend ? ((float) borderColor[3] / MaxUShortFloat) : MaxUShortFloat; |
| 381 | - bc[0] = ((float) borderColor[0] / MaxUShortFloat) * bc[3]; |
| 382 | - bc[1] = ((float) borderColor[1] / MaxUShortFloat) * bc[3]; |
| 383 | - bc[2] = ((float) borderColor[2] / MaxUShortFloat) * bc[3]; |
| 384 | - |
| 385 | vertexData[0] = box.x1; |
| 386 | vertexData[1] = box.y1; |
| 387 | vertexData[2] = 0.0f; |
| 388 | @@ -928,59 +1005,63 @@ |
| 389 | } |
| 390 | |
| 391 | /* draw outline */ |
| 392 | - static const int borderWidth = 2; |
| 393 | - |
| 394 | - glLineWidth (borderWidth); |
| 395 | + int borderWidth = defaultBorderWidth; |
| 396 | + |
| 397 | + if (optionGetIncreaseBorderContrast() || usingAverageColors) |
| 398 | + { |
| 399 | + // Generate a lighter color based on border to create more contrast |
| 400 | + unsigned int averageColorLevel = (borderColor[0] + borderColor[1] + borderColor[2]) / 3; |
| 401 | + |
| 402 | + float colorMultiplier; |
| 403 | + if (averageColorLevel > MaxUShort * 0.3) |
| 404 | + colorMultiplier = 0.7; // make it darker |
| 405 | + else |
| 406 | + colorMultiplier = 2.0; // make it lighter |
| 407 | + |
| 408 | + bc[3] = borderColor[3]; |
| 409 | + bc[0] = MIN(MaxUShortFloat, ((float) borderColor[0]) * colorMultiplier) * bc[3] / MaxUShortFloat; |
| 410 | + bc[1] = MIN(MaxUShortFloat, ((float) borderColor[1]) * colorMultiplier) * bc[3] / MaxUShortFloat; |
| 411 | + bc[2] = MIN(MaxUShortFloat, ((float) borderColor[2]) * colorMultiplier) * bc[3] / MaxUShortFloat; |
| 412 | + |
| 413 | + if (optionGetIncreaseBorderContrast ()) |
| 414 | + { |
| 415 | + borderWidth *= biggerBorderWidthMultiplier; |
| 416 | + |
| 417 | + glLineWidth (borderWidth); |
| 418 | + streamingBuffer->begin (GL_LINES); |
| 419 | + streamingBuffer->addVertices (8, &vertexData2[0]); |
| 420 | + streamingBuffer->addColors (1, bc); |
| 421 | + streamingBuffer->end (); |
| 422 | + streamingBuffer->render (sTransform); |
| 423 | + } else if (usingAverageColors) { |
| 424 | + borderColor = bc; |
| 425 | + } |
| 426 | + } |
| 427 | + |
| 428 | + bc[3] = blend ? borderColor[3] : MaxUShortFloat; |
| 429 | + bc[0] = borderColor[0] * bc[3] / MaxUShortFloat; |
| 430 | + bc[1] = borderColor[1] * bc[3] / MaxUShortFloat; |
| 431 | + bc[2] = borderColor[2] * bc[3] / MaxUShortFloat; |
| 432 | + |
| 433 | + glLineWidth (defaultBorderWidth); |
| 434 | streamingBuffer->begin (GL_LINES); |
| 435 | - streamingBuffer->addColors (1, borderColor); |
| 436 | + streamingBuffer->addColors (1, bc); |
| 437 | streamingBuffer->addVertices (8, &vertexData2[0]); |
| 438 | streamingBuffer->end (); |
| 439 | streamingBuffer->render (sTransform); |
| 440 | |
| 441 | if (blend) |
| 442 | { |
| 443 | - glEnable (GL_BLEND); |
| 444 | - glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); |
| 445 | - } |
| 446 | - |
| 447 | - if (cScreen) |
| 448 | - { |
| 449 | - CompRegion damageRegion; |
| 450 | - |
| 451 | - if (optionGetMode () == MoveOptions::ModeOutline) |
| 452 | - { |
| 453 | - // Top |
| 454 | - damageRegion += CompRect (box.x1 - borderWidth, |
| 455 | - box.y1 - borderWidth, |
| 456 | - box.x2 - box.x1 + borderWidth * 2, |
| 457 | - borderWidth + 1); |
| 458 | - // Right |
| 459 | - damageRegion += CompRect (box.x2 - borderWidth, |
| 460 | - box.y1 - borderWidth, |
| 461 | - borderWidth + 1, |
| 462 | - box.y2 - box.y1 + borderWidth * 2); |
| 463 | - // Bottom |
| 464 | - damageRegion += CompRect (box.x1 - borderWidth, |
| 465 | - box.y2 - borderWidth, |
| 466 | - box.x2 - box.x1 + borderWidth * 2, |
| 467 | - borderWidth + 1); |
| 468 | - // Left |
| 469 | - damageRegion += CompRect (box.x1 - borderWidth, |
| 470 | - box.y1 - borderWidth, |
| 471 | - borderWidth + 1, |
| 472 | - box.y2 - box.y1 + borderWidth * 2); |
| 473 | - } |
| 474 | - else |
| 475 | - { |
| 476 | - CompRect damage (box.x1 - borderWidth, |
| 477 | - box.y1 - borderWidth, |
| 478 | - box.x2 - box.x1 + borderWidth * 2, |
| 479 | - box.y2 - box.y1 + borderWidth * 2); |
| 480 | - damageRegion += damage; |
| 481 | - } |
| 482 | - |
| 483 | - cScreen->damageRegion (damageRegion); |
| 484 | - } |
| 485 | + glDisable (GL_BLEND); |
| 486 | +#ifdef USE_GLES |
| 487 | + glBlendFuncSeparate (origSrc, origDst, |
| 488 | + origSrcAlpha, origDstAlpha); |
| 489 | +#else |
| 490 | + glBlendFunc (origSrc, origDst); |
| 491 | +#endif |
| 492 | + } |
| 493 | + |
| 494 | + damageMovingRectangle (&box); |
| 495 | |
| 496 | return true; |
| 497 | } |
| 498 | |
| 499 | === modified file 'plugins/move/src/move.h' |
| 500 | --- plugins/move/src/move.h 2017-07-03 15:16:04 +0000 |
| 501 | +++ plugins/move/src/move.h 2017-07-03 15:16:04 +0000 |
| 502 | @@ -75,7 +75,7 @@ |
| 503 | unsigned int); |
| 504 | |
| 505 | bool getMovingRectangle (BoxPtr pbox); |
| 506 | - void damageMovingRectangle (BoxPtr pbox); |
| 507 | + bool damageMovingRectangle (BoxPtr pbox); |
| 508 | bool glPaintMovingRectangle (const GLMatrix &transform, CompOutput *output, unsigned short *borderColor, unsigned short *fillColor); |
| 509 | |
| 510 | CompWindow *w; |
| 511 | |
| 512 | === modified file 'plugins/resize/resize.xml.in' |
| 513 | --- plugins/resize/resize.xml.in 2017-07-03 15:16:04 +0000 |
| 514 | +++ plugins/resize/resize.xml.in 2017-07-03 15:16:04 +0000 |
| 515 | @@ -58,6 +58,16 @@ |
| 516 | <long>Maximizes the window vertically if the top or bottom screen edge is hit while resizing</long> |
| 517 | <default>true</default> |
| 518 | </option> |
| 519 | + <option name="increase_border_contrast" type="bool"> |
| 520 | + <_short>Use a double-border in 'Rectangle' and 'Outline' modes</_short> |
| 521 | + <_long>Increase the contrast of the border using a lighter color.</_long> |
| 522 | + <default>true</default> |
| 523 | + </option> |
| 524 | + <option name="use_desktop_average_color" type="bool"> |
| 525 | + <_short>Use Desktop average colors</_short> |
| 526 | + <_long>Try to use the desktop average color if defined by your DE (overrides custom colors).</_long> |
| 527 | + <default>true</default> |
| 528 | + </option> |
| 529 | <option name="border_color" type="color"> |
| 530 | <_short>Border Color</_short> |
| 531 | <_long>Border color used for outline and rectangle resize modes</_long> |
| 532 | |
| 533 | === modified file 'plugins/resize/src/resize.cpp' |
| 534 | --- plugins/resize/src/resize.cpp 2017-07-03 15:16:04 +0000 |
| 535 | +++ plugins/resize/src/resize.cpp 2017-07-03 15:16:04 +0000 |
| 536 | @@ -70,8 +70,8 @@ |
| 537 | |
| 538 | static bool |
| 539 | resizeTerminate (CompAction *action, |
| 540 | - CompAction::State state, |
| 541 | - CompOption::Vector &options) |
| 542 | + CompAction::State state, |
| 543 | + CompOption::Vector &options) |
| 544 | { |
| 545 | RESIZE_SCREEN (screen); |
| 546 | return rs->logic.terminateResize(action, state, options); |
| 547 | @@ -87,14 +87,34 @@ |
| 548 | GLVertexBuffer *streamingBuffer = GLVertexBuffer::streamingBuffer (); |
| 549 | const unsigned short MaxUShort = std::numeric_limits <unsigned short>::max (); |
| 550 | const float MaxUShortFloat = MaxUShort; |
| 551 | + bool usingAverageColors = false; |
| 552 | |
| 553 | BoxRec box; |
| 554 | CompRegion damageRegion; |
| 555 | GLMatrix sTransform (transform); |
| 556 | GLfloat vertexData [12]; |
| 557 | GLfloat vertexData2[24]; |
| 558 | - GLint origSrc, origDst; |
| 559 | - GLushort fc[4], bc[4]; |
| 560 | + GLint origSrc, origDst; |
| 561 | +#ifdef USE_GLES |
| 562 | + GLint origSrcAlpha, origDstAlpha; |
| 563 | +#endif |
| 564 | + GLushort fc[4], bc[4], averageFillColor[4]; |
| 565 | + |
| 566 | + if (optionGetUseDesktopAverageColor ()) |
| 567 | + { |
| 568 | + const unsigned short *averageColor = screen->averageColor (); |
| 569 | + |
| 570 | + if (averageColor) |
| 571 | + { |
| 572 | + usingAverageColors = true; |
| 573 | + borderColor = const_cast<unsigned short *>(averageColor); |
| 574 | + memcpy (averageFillColor, averageColor, 4 * sizeof (unsigned short)); |
| 575 | + averageFillColor[3] = MaxUShort * 0.6; |
| 576 | + |
| 577 | + if (fillColor) |
| 578 | + fillColor = averageFillColor; |
| 579 | + } |
| 580 | + } |
| 581 | |
| 582 | bool blend = !optionGetDisableBlend (); |
| 583 | |
| 584 | @@ -107,7 +127,6 @@ |
| 585 | if (blend) |
| 586 | { |
| 587 | #ifdef USE_GLES |
| 588 | - GLint origSrcAlpha, origDstAlpha; |
| 589 | glGetIntegerv (GL_BLEND_SRC_RGB, &origSrc); |
| 590 | glGetIntegerv (GL_BLEND_DST_RGB, &origDst); |
| 591 | glGetIntegerv (GL_BLEND_SRC_ALPHA, &origSrcAlpha); |
| 592 | @@ -118,12 +137,6 @@ |
| 593 | #endif |
| 594 | } |
| 595 | |
| 596 | - /* Premultiply the alpha values */ |
| 597 | - bc[3] = blend ? ((float) borderColor[3] / MaxUShortFloat) : MaxUShortFloat; |
| 598 | - bc[0] = ((float) borderColor[0] / MaxUShortFloat) * bc[3]; |
| 599 | - bc[1] = ((float) borderColor[1] / MaxUShortFloat) * bc[3]; |
| 600 | - bc[2] = ((float) borderColor[2] / MaxUShortFloat) * bc[3]; |
| 601 | - |
| 602 | logic.getPaintRectangle (&box); |
| 603 | |
| 604 | vertexData[0] = box.x1; |
| 605 | @@ -195,10 +208,48 @@ |
| 606 | } |
| 607 | |
| 608 | /* draw outline */ |
| 609 | - static const int borderWidth = 2; |
| 610 | - glLineWidth (borderWidth); |
| 611 | + static const int defaultBorderWidth = 2; |
| 612 | + int borderWidth = defaultBorderWidth; |
| 613 | + |
| 614 | + if (optionGetIncreaseBorderContrast() || usingAverageColors) |
| 615 | + { |
| 616 | + // Generate a lighter color based on border to create more contrast |
| 617 | + unsigned int averageColorLevel = (borderColor[0] + borderColor[1] + borderColor[2]) / 3; |
| 618 | + |
| 619 | + float colorMultiplier; |
| 620 | + if (averageColorLevel > MaxUShort * 0.3) |
| 621 | + colorMultiplier = 0.7; // make it darker |
| 622 | + else |
| 623 | + colorMultiplier = 2.0; // make it lighter |
| 624 | + |
| 625 | + bc[3] = borderColor[3]; |
| 626 | + bc[0] = MIN(MaxUShortFloat, ((float) borderColor[0]) * colorMultiplier) * bc[3] / MaxUShortFloat; |
| 627 | + bc[1] = MIN(MaxUShortFloat, ((float) borderColor[1]) * colorMultiplier) * bc[3] / MaxUShortFloat; |
| 628 | + bc[2] = MIN(MaxUShortFloat, ((float) borderColor[2]) * colorMultiplier) * bc[3] / MaxUShortFloat; |
| 629 | + |
| 630 | + if (optionGetIncreaseBorderContrast ()) |
| 631 | + { |
| 632 | + borderWidth *= 2; |
| 633 | + |
| 634 | + glLineWidth (borderWidth); |
| 635 | + streamingBuffer->begin (GL_LINES); |
| 636 | + streamingBuffer->addVertices (8, &vertexData2[0]); |
| 637 | + streamingBuffer->addColors (1, bc); |
| 638 | + streamingBuffer->end (); |
| 639 | + streamingBuffer->render (sTransform); |
| 640 | + } else if (usingAverageColors) { |
| 641 | + borderColor = bc; |
| 642 | + } |
| 643 | + } |
| 644 | + |
| 645 | + bc[3] = blend ? borderColor[3] : MaxUShortFloat; |
| 646 | + bc[0] = borderColor[0] * bc[3] / MaxUShortFloat; |
| 647 | + bc[1] = borderColor[1] * bc[3] / MaxUShortFloat; |
| 648 | + bc[2] = borderColor[2] * bc[3] / MaxUShortFloat; |
| 649 | + |
| 650 | + glLineWidth (defaultBorderWidth); |
| 651 | streamingBuffer->begin (GL_LINES); |
| 652 | - streamingBuffer->addColors (1, borderColor); |
| 653 | + streamingBuffer->addColors (1, bc); |
| 654 | streamingBuffer->addVertices (8, &vertexData2[0]); |
| 655 | streamingBuffer->end (); |
| 656 | streamingBuffer->render (sTransform); |
| 657 | @@ -222,21 +273,21 @@ |
| 658 | damageRegion += CompRect (box.x1 - borderWidth, |
| 659 | box.y1 - borderWidth, |
| 660 | box.x2 - box.x1 + borderWidth * 2, |
| 661 | - borderWidth + 1); |
| 662 | + borderWidth * 2); |
| 663 | // Right |
| 664 | damageRegion += CompRect (box.x2 - borderWidth, |
| 665 | box.y1 - borderWidth, |
| 666 | - borderWidth + 1, |
| 667 | + borderWidth + borderWidth / 2, |
| 668 | box.y2 - box.y1 + borderWidth * 2); |
| 669 | // Bottom |
| 670 | damageRegion += CompRect (box.x1 - borderWidth, |
| 671 | box.y2 - borderWidth, |
| 672 | box.x2 - box.x1 + borderWidth * 2, |
| 673 | - borderWidth + 1); |
| 674 | + borderWidth * 2); |
| 675 | // Left |
| 676 | damageRegion += CompRect (box.x1 - borderWidth, |
| 677 | box.y1 - borderWidth, |
| 678 | - borderWidth + 1, |
| 679 | + borderWidth + borderWidth / 2, |
| 680 | box.y2 - box.y1 + borderWidth * 2); |
| 681 | } |
| 682 | else |
| 683 | |
| 684 | === modified file 'src/atoms.cpp' |
| 685 | --- src/atoms.cpp 2015-02-17 14:54:10 +0000 |
| 686 | +++ src/atoms.cpp 2017-07-03 15:16:04 +0000 |
| 687 | @@ -155,6 +155,8 @@ |
| 688 | |
| 689 | Atom startupId; |
| 690 | |
| 691 | + Atom gnomeRepresentativeColors; |
| 692 | + |
| 693 | void init (Display *dpy) |
| 694 | { |
| 695 | supported = XInternAtom (dpy, "_NET_SUPPORTED", 0); |
| 696 | @@ -325,5 +327,7 @@ |
| 697 | atomPair = XInternAtom (dpy, "ATOM_PAIR", 0); |
| 698 | |
| 699 | startupId = XInternAtom (dpy, "_NET_STARTUP_ID", 0); |
| 700 | + |
| 701 | + gnomeRepresentativeColors = XInternAtom (dpy, "_GNOME_BACKGROUND_REPRESENTATIVE_COLORS", 0); |
| 702 | } |
| 703 | }; |
| 704 | |
| 705 | === modified file 'src/event.cpp' |
| 706 | --- src/event.cpp 2016-05-17 02:52:07 +0000 |
| 707 | +++ src/event.cpp 2017-07-03 15:16:04 +0000 |
| 708 | @@ -1821,6 +1821,11 @@ |
| 709 | if (w) |
| 710 | w->priv->updateStartupId (); |
| 711 | } |
| 712 | + else if (event->xproperty.atom == Atoms::gnomeRepresentativeColors) |
| 713 | + { |
| 714 | + if (event->xproperty.window == privateScreen.rootWindow()) |
| 715 | + privateScreen.updateAverageColor (event->xproperty.atom); |
| 716 | + } |
| 717 | else if (event->xproperty.atom == XA_WM_CLASS) |
| 718 | { |
| 719 | w = findWindow (event->xproperty.window); |
| 720 | |
| 721 | === modified file 'src/privatescreen.h' |
| 722 | --- src/privatescreen.h 2016-05-17 02:52:07 +0000 |
| 723 | +++ src/privatescreen.h 2017-07-03 15:16:04 +0000 |
| 724 | @@ -692,6 +692,8 @@ |
| 725 | |
| 726 | void updateResources (); |
| 727 | |
| 728 | + void updateAverageColor (Atom atom); |
| 729 | + |
| 730 | Window getActiveWindow (Window root); |
| 731 | |
| 732 | void setWindowState (unsigned int state, Window id); |
| 733 | @@ -777,6 +779,8 @@ |
| 734 | unsigned int nDesktop; |
| 735 | unsigned int currentDesktop; |
| 736 | |
| 737 | + std::vector<unsigned short> averageColor; |
| 738 | + |
| 739 | CompOutput fullscreenOutput; |
| 740 | CompScreenEdge screenEdge[SCREEN_EDGE_NUM]; |
| 741 | |
| 742 | @@ -1092,6 +1096,7 @@ |
| 743 | virtual CompWindow * getTopServerWindow() const; |
| 744 | virtual CoreOptions& getCoreOptions(); |
| 745 | virtual Colormap colormap() const; |
| 746 | + virtual const unsigned short * averageColor() const; |
| 747 | virtual void setCurrentDesktop (unsigned int desktop); |
| 748 | virtual Window activeWindow() const; |
| 749 | virtual bool grabWindowIsNot(Window w) const; |
| 750 | @@ -1187,6 +1192,7 @@ |
| 751 | virtual void _matchPropertyChanged(CompWindow *); |
| 752 | virtual void _outputChangeNotify(); |
| 753 | virtual void _cursorChangeNotify(const CompString&, int); |
| 754 | + virtual void _averageColorChangeNotify(const unsigned short*); |
| 755 | |
| 756 | void grabServer (); |
| 757 | void ungrabServer (); |
| 758 | |
| 759 | === modified file 'src/privatescreen/tests/test-privatescreen.cpp' |
| 760 | --- src/privatescreen/tests/test-privatescreen.cpp 2016-04-26 12:42:39 +0000 |
| 761 | +++ src/privatescreen/tests/test-privatescreen.cpp 2017-07-03 15:16:04 +0000 |
| 762 | @@ -82,6 +82,7 @@ |
| 763 | MOCK_METHOD1(_matchPropertyChanged, void (CompWindow *)); |
| 764 | MOCK_METHOD0(_outputChangeNotify, void ()); |
| 765 | MOCK_METHOD2(_cursorChangeNotify, void (const CompString&, int)); |
| 766 | + MOCK_METHOD1(_averageColorChangeNotify, void (const unsigned short*)); |
| 767 | |
| 768 | MOCK_METHOD0(outputDevs, CompOutput::vector & ()); |
| 769 | MOCK_METHOD2(setWindowState, void (unsigned int state, Window id)); |
| 770 | @@ -199,6 +200,7 @@ |
| 771 | MOCK_CONST_METHOD0(getTopServerWindow, CompWindow * ()); |
| 772 | MOCK_METHOD0(getCoreOptions, CoreOptions& ()); |
| 773 | MOCK_CONST_METHOD0(colormap, Colormap ()); |
| 774 | + MOCK_CONST_METHOD0(averageColor, const unsigned short * ()); |
| 775 | MOCK_METHOD1(setCurrentDesktop, void (unsigned int desktop)); |
| 776 | MOCK_CONST_METHOD0(activeWindow, Window ()); |
| 777 | MOCK_CONST_METHOD1(grabWindowIsNot, bool (Window w)); |
| 778 | |
| 779 | === modified file 'src/screen.cpp' |
| 780 | --- src/screen.cpp 2016-07-28 13:43:06 +0000 |
| 781 | +++ src/screen.cpp 2017-07-03 15:16:04 +0000 |
| 782 | @@ -1427,6 +1427,113 @@ |
| 783 | screen->cursorChangeNotify (cursorTheme, cursorSize); |
| 784 | } |
| 785 | |
| 786 | +void |
| 787 | +PrivateScreen::updateAverageColor (Atom atom) |
| 788 | +{ |
| 789 | + Atom actual_type; |
| 790 | + int result, format; |
| 791 | + unsigned long n, left; |
| 792 | + unsigned char *data; |
| 793 | + |
| 794 | + auto previousAverageColor = averageColor; |
| 795 | + averageColor.clear (); |
| 796 | + |
| 797 | + result = XGetWindowProperty (dpy, root, |
| 798 | + atom, 0L, 65536, False, |
| 799 | + XA_STRING, &actual_type, &format, |
| 800 | + &n, &left, &data); |
| 801 | + |
| 802 | + if (result != Success || !data || actual_type != XA_STRING) |
| 803 | + { |
| 804 | + if (previousAverageColor != averageColor) |
| 805 | + screen->averageColorChangeNotify (averageColor.data ()); |
| 806 | + |
| 807 | + XFree (data); |
| 808 | + return; |
| 809 | + } |
| 810 | + |
| 811 | + CompString colors (reinterpret_cast<char *> (data)); |
| 812 | + bool found_valid; |
| 813 | + double r, g, b, a; |
| 814 | + found_valid = false; |
| 815 | + r = g = b = 0.0; |
| 816 | + a = 1.0; |
| 817 | + const CompString rgba_regex = R"((rgba?))" |
| 818 | + R"(\s*\(\s*([0-9]{1,3})\s*,)" |
| 819 | + R"(\s*([0-9]{1,3})\s*,)" |
| 820 | + R"(\s*([0-9]{1,3})\s*)" |
| 821 | + R"((,\s*((0*(\.[0-9]+)|1(\.0*)?)?)\s*)?\))"; |
| 822 | + |
| 823 | + std::vector<CompString> matches = compGetRegexMatches (rgba_regex, colors); |
| 824 | + |
| 825 | + if (matches.size () > 4) |
| 826 | + { |
| 827 | + try |
| 828 | + { |
| 829 | + found_valid = true; |
| 830 | + r = std::stoi (matches[2]) / 255.0; |
| 831 | + g = std::stoi (matches[3]) / 255.0; |
| 832 | + b = std::stoi (matches[4]) / 255.0; |
| 833 | + |
| 834 | + if (matches[1] == "rgba") |
| 835 | + { |
| 836 | + if (matches.size () > 6 && !matches[6].empty ()) |
| 837 | + a = std::stod (matches[6][0] == '.' ? '0'+matches[6] : matches[6]); |
| 838 | + else |
| 839 | + found_valid = false; |
| 840 | + } |
| 841 | + } catch (std::exception const& except) { |
| 842 | + found_valid = false; |
| 843 | + compLogMessage ("core", CompLogLevelWarn, "%s: failed to parse '%s' color string", |
| 844 | + except.what (), colors.c_str ()); |
| 845 | + } |
| 846 | + } else { |
| 847 | + size_t color_len = (colors.length () - 1) / 3; |
| 848 | + |
| 849 | + if (color_len > 0 && color_len <= 4) |
| 850 | + { |
| 851 | + CompString hex_regex = "#([[:xdigit:]]{" + std::to_string(color_len) + "})" + |
| 852 | + "([[:xdigit:]]{" + std::to_string(color_len) + "})" + |
| 853 | + "([[:xdigit:]]{" + std::to_string(color_len) + "})" + |
| 854 | + "([[:xdigit:]]{" + std::to_string(color_len) + "})?$"; |
| 855 | + std::vector<CompString> matches = compGetRegexMatches (hex_regex, colors); |
| 856 | + if (matches.size () == 5) |
| 857 | + { |
| 858 | + try |
| 859 | + { |
| 860 | + double max_value = static_cast<float> ((1 << (4 * color_len)) - 1); |
| 861 | + found_valid = true; |
| 862 | + r = std::stoi (matches[1], 0, 16) / max_value; |
| 863 | + g = std::stoi (matches[2], 0, 16) / max_value; |
| 864 | + b = std::stoi (matches[3], 0, 16) / max_value; |
| 865 | + |
| 866 | + if (!matches[4].empty ()) |
| 867 | + a = std::stoi (matches[4], 0, 16) / max_value; |
| 868 | + } catch (std::exception const& except) { |
| 869 | + found_valid = false; |
| 870 | + compLogMessage ("core", CompLogLevelWarn, "%s: failed to parse '%s' color string", |
| 871 | + except.what (), colors.c_str ()); |
| 872 | + } |
| 873 | + } |
| 874 | + } |
| 875 | + } |
| 876 | + |
| 877 | + if (found_valid) |
| 878 | + { |
| 879 | + const double MaxUShort = std::numeric_limits<unsigned short>::max (); |
| 880 | + averageColor.resize (4); |
| 881 | + averageColor[0] = MAX (0, MIN (r * MaxUShort, MaxUShort)); |
| 882 | + averageColor[1] = MAX (0, MIN (g * MaxUShort, MaxUShort)); |
| 883 | + averageColor[2] = MAX (0, MIN (b * MaxUShort, MaxUShort)); |
| 884 | + averageColor[3] = MAX (0, MIN (a * MaxUShort, MaxUShort)); |
| 885 | + } |
| 886 | + |
| 887 | + XFree (data); |
| 888 | + |
| 889 | + if (previousAverageColor != averageColor) |
| 890 | + screen->averageColorChangeNotify (averageColor.data ()); |
| 891 | +} |
| 892 | + |
| 893 | bool |
| 894 | CompScreen::fileToImage (CompString &name, |
| 895 | CompSize &size, |
| 896 | @@ -3153,7 +3260,7 @@ |
| 897 | } |
| 898 | |
| 899 | if ((type & cps::GrabType::KEYBOARD) && |
| 900 | - !eventManager.topGrab (cps::GrabType::KEYBOARD)) |
| 901 | + !eventManager.topGrab (cps::GrabType::KEYBOARD)) |
| 902 | { |
| 903 | status = XGrabKeyboard (dpy, |
| 904 | eventManager.getGrabWindow (), true, |
| 905 | @@ -3171,7 +3278,7 @@ |
| 906 | } |
| 907 | else |
| 908 | { |
| 909 | - XUngrabPointer (dpy, CurrentTime); |
| 910 | + XUngrabPointer (dpy, CurrentTime); |
| 911 | } |
| 912 | } |
| 913 | |
| 914 | @@ -3242,7 +3349,7 @@ |
| 915 | } |
| 916 | else |
| 917 | { |
| 918 | - XUngrabPointer (privateScreen.dpy, CurrentTime); |
| 919 | + XUngrabPointer (privateScreen.dpy, CurrentTime); |
| 920 | } |
| 921 | } |
| 922 | |
| 923 | @@ -4226,10 +4333,10 @@ |
| 924 | PrivateScreen::updateCursors (const CompString& theme, int size) |
| 925 | { |
| 926 | if (size > 0) |
| 927 | - XcursorSetDefaultSize (dpy, size); |
| 928 | + XcursorSetDefaultSize (dpy, size); |
| 929 | |
| 930 | if (!theme.empty()) |
| 931 | - XcursorSetTheme (dpy, theme.c_str()); |
| 932 | + XcursorSetTheme (dpy, theme.c_str()); |
| 933 | |
| 934 | for (auto it = begin (cursors); it != end (cursors); ++it) |
| 935 | { |
| 936 | @@ -4250,6 +4357,18 @@ |
| 937 | privateScreen.updateCursors (theme, size); |
| 938 | } |
| 939 | |
| 940 | +void |
| 941 | +CompScreen::averageColorChangeNotify (const unsigned short* color) |
| 942 | +{ |
| 943 | + WRAPABLE_HND_FUNCTN (averageColorChangeNotify, color); |
| 944 | + _averageColorChangeNotify (color); |
| 945 | +} |
| 946 | + |
| 947 | +void |
| 948 | +CompScreenImpl::_averageColorChangeNotify (const unsigned short* color) |
| 949 | +{ |
| 950 | +} |
| 951 | + |
| 952 | /* Returns default viewport for some window geometry. If the window spans |
| 953 | * more than one viewport the most appropriate viewport is returned. How the |
| 954 | * most appropriate viewport is computed can be made optional if necessary. It |
| 955 | @@ -4396,6 +4515,10 @@ |
| 956 | ScreenInterface::cursorChangeNotify (const CompString& theme, int size) |
| 957 | WRAPABLE_DEF (cursorChangeNotify, theme, size) |
| 958 | |
| 959 | +void |
| 960 | +ScreenInterface::averageColorChangeNotify (const unsigned short *color) |
| 961 | + WRAPABLE_DEF (averageColorChangeNotify, color) |
| 962 | + |
| 963 | Window |
| 964 | CompScreenImpl::root () |
| 965 | { |
| 966 | @@ -4841,6 +4964,12 @@ |
| 967 | return privateScreen.colormap; |
| 968 | } |
| 969 | |
| 970 | +const unsigned short * |
| 971 | +CompScreenImpl::averageColor() const |
| 972 | +{ |
| 973 | + return privateScreen.averageColor.data (); |
| 974 | +} |
| 975 | + |
| 976 | void |
| 977 | CompScreenImpl::setCurrentDesktop (unsigned int desktop) |
| 978 | { |
| 979 | @@ -5270,6 +5399,8 @@ |
| 980 | XIGetClientPointer (dpy, None, &clientPointerDeviceId); |
| 981 | updateResources (); |
| 982 | |
| 983 | + updateAverageColor (Atoms::gnomeRepresentativeColors); |
| 984 | + |
| 985 | /* Attempt to gain SubstructureRedirectMask */ |
| 986 | CompScreenImpl::checkForError (dpy); |
| 987 | |
| 988 | |
| 989 | === modified file 'src/string/src/string.cpp' |
| 990 | --- src/string/src/string.cpp 2012-03-23 03:37:26 +0000 |
| 991 | +++ src/string/src/string.cpp 2017-07-03 15:16:04 +0000 |
| 992 | @@ -1,5 +1,6 @@ |
| 993 | /* |
| 994 | * Copyright © 2008 Dennis Kasprzyk |
| 995 | + * Copyright © 2017 Canonical Ltd. |
| 996 | * |
| 997 | * Permission to use, copy, modify, distribute, and sell this software |
| 998 | * and its documentation for any purpose is hereby granted without |
| 999 | @@ -21,12 +22,20 @@ |
| 1000 | * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 1001 | * |
| 1002 | * Authors: Dennis Kasprzyk <onestone@compiz-fusion.org> |
| 1003 | + * Marco Trevisan <marco.trevisan@canonical.com> |
| 1004 | */ |
| 1005 | |
| 1006 | #include <cstring> |
| 1007 | #include <cstdarg> |
| 1008 | #include <cstdio> |
| 1009 | |
| 1010 | +#if defined(__GNUC__) && ((__GNUC__ < 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ < 9))) |
| 1011 | +#include <regex.h> |
| 1012 | +#else |
| 1013 | +#include <regex> |
| 1014 | +#define HAVE_CPP_REGEX |
| 1015 | +#endif |
| 1016 | + |
| 1017 | #include <core/string.h> |
| 1018 | |
| 1019 | CompString compPrintf (const char *format, ...) |
| 1020 | @@ -86,3 +95,55 @@ |
| 1021 | delete [] str; |
| 1022 | return rv; |
| 1023 | } |
| 1024 | + |
| 1025 | +CompStringVector |
| 1026 | +compGetRegexMatches(const CompString& regexStr, |
| 1027 | + const CompString& string) |
| 1028 | +{ |
| 1029 | + |
| 1030 | + CompStringVector matches; |
| 1031 | + |
| 1032 | +#ifdef HAVE_CPP_REGEX |
| 1033 | + |
| 1034 | + std::smatch subMatches; |
| 1035 | + std::regex regex(regexStr); |
| 1036 | + |
| 1037 | + if (std::regex_match(string, subMatches, regex)) |
| 1038 | + { |
| 1039 | + for (const auto& subMatch : subMatches) |
| 1040 | + matches.push_back (subMatch.str ()); |
| 1041 | + } |
| 1042 | + |
| 1043 | +#else |
| 1044 | + |
| 1045 | + regex_t regex; |
| 1046 | + int ret; |
| 1047 | + ret = regcomp (®ex, regexStr.c_str (), REG_EXTENDED); |
| 1048 | + |
| 1049 | + if (ret != 0) |
| 1050 | + return matches; |
| 1051 | + |
| 1052 | + std::vector<regmatch_t> subMatches (regex.re_nsub + 1); |
| 1053 | + ret = regexec (®ex, string.c_str (), subMatches.size (), subMatches.data (), 0); |
| 1054 | + |
| 1055 | + if (ret == REG_NOMATCH) |
| 1056 | + return matches; |
| 1057 | + |
| 1058 | + for (const auto& sub_match : subMatches) |
| 1059 | + { |
| 1060 | + if (sub_match.rm_so >= 0) |
| 1061 | + { |
| 1062 | + size_t sub_len = sub_match.rm_eo - sub_match.rm_so; |
| 1063 | + matches.push_back (string.substr (sub_match.rm_so, sub_len)); |
| 1064 | + } else { |
| 1065 | + /* We keep this empty so the clients might access to all the subs */ |
| 1066 | + matches.push_back (CompString ()); |
| 1067 | + } |
| 1068 | + } |
| 1069 | + |
| 1070 | + regfree (®ex); |
| 1071 | + |
| 1072 | +#endif |
| 1073 | + |
| 1074 | + return matches; |
| 1075 | +} |


LGTM.