1// Drawing mixins
2
3// generic drawing of more complex things
4
5@function _widget_edge($c:$borders_edge) {
6// outer highlight "used" on most widgets
7  @if $c == none { @return none; }
8  @else { @return 0 1px $c; }
9}
10
11@mixin _shadows($list...) {
12//
13// Helper mixin to stack up to box-shadows;
14//
15  $shadows: null;
16
17  @each $shadow in $list {
18    @if $shadow!=none { $shadows: $shadows, $shadow; }
19  }
20
21  box-shadow: $shadows;
22}
23
24// entries  // Yaru change: we detached focus from selection
25@function entry_focus_border($fc:$focus_border_color) {
26  @if $variant == 'light' { @return $fc; }
27  @else { @return $focus_border_color }
28}
29
30@function entry_focus_shadow($fc:$focus_border_color) { @return inset 0 0 0 1px $fc; }  // Yaru change: we detached focus from selection
31
32@mixin entry($t, $fc:$focus_border_color, $edge: none) {  // Yaru change: we detached focus from selection
33//
34// Entries drawing function
35//
36// $t: entry type
37// $fc: focus color
38// $edge: set to none to not draw the bottom edge or specify a color to not
39//        use the default one
40//
41// possible $t values:
42// normal, focus, insensitive, backdrop, backdrop-insensitive, osd, osd-focus, osd-backdrop;
43//
44
45  $_blank_edge: if($edge == none, none, 0 1px transparentize($edge, 1));
46  $_entry_edge: if($edge == none, none, _widget_edge($edge));
47
48  @if $t==normal {
49    color: $text_color;
50    border-color: $borders_color;
51    background-color: $base_color;
52    @include _shadows(entry_focus_shadow(transparentize($fc, 1)), $_entry_edge);
53    // for the transition to work the number of shadows in different states needs to match, hence the transparent shadow here.
54  }
55  @if $t==focus {
56    @include _shadows(entry_focus_shadow($fc), $_entry_edge);
57    border-color: entry_focus_border($fc);
58  }
59  @if $t==insensitive {
60    color: $insensitive_fg_color;
61    border-color: $borders_color;
62    background-color: $insensitive_bg_color;
63    box-shadow: $_entry_edge;
64  }
65  @if $t==backdrop {
66    color: $backdrop_text_color;
67    border-color: $backdrop_borders_color;
68    background-color: $backdrop_base_color;
69    box-shadow: $_blank_edge;
70  }
71  @if $t==backdrop-insensitive {
72    color: $backdrop_insensitive_color;
73    border-color: $backdrop_borders_color;
74    background-color: $insensitive_bg_color;
75    box-shadow: $_blank_edge;
76  }
77  @if $t==osd {
78    color: $osd_text_color;
79    border-color: $osd_borders_color;
80    background-color: transparentize(opacify($osd_borders_color, 1), 0.5);
81    background-clip: padding-box;
82    box-shadow: none;
83    text-shadow: 0 1px black;
84    -gtk-icon-shadow: 0 1px black;
85  }
86  @if $t==osd-focus {
87    color: $osd_text_color;
88    border-color: $selected_bg_color;
89    background-color: transparentize(opacify($osd_borders_color, 1), 0.5);
90    background-clip: padding-box;
91    box-shadow: entry_focus_shadow($fc);
92    text-shadow: 0 1px black;
93    -gtk-icon-shadow: 0 1px black;
94  }
95  @if $t==osd-insensitive {
96    color: $osd_insensitive_fg_color;
97    border-color: $osd_borders_color;
98    background-color: $osd_insensitive_bg_color;
99    background-clip: padding-box;
100    box-shadow: none;
101    text-shadow: none;
102    -gtk-icon-shadow: none;
103  }
104  @if $t==osd-backdrop {
105    color: $osd_text_color;
106    border-color: $osd_borders_color;
107    background-color: transparentize(opacify($osd_borders_color, 1), 0.5);
108    background-clip: padding-box;
109    box-shadow: none;
110    text-shadow: none;
111    -gtk-icon-shadow: none;
112  }
113}
114
115// buttons
116
117@function _border_color($c, $darker: false) {
118  @if $darker == true { @return darken($c, 20%); }
119  @else { @return darken($c, 10%); }
120}
121
122@function _text_shadow_color ($tc: $fg_color, $bg: $bg_color) {
123//
124// calculate the color of text shadows
125//
126// $tc is the text color
127// $bg is the background color
128//
129  $_lbg: lightness($bg)/100%;
130  @if lightness($tc)<50% { @return transparentize(white, 1-$_lbg/($_lbg*1.3)); }
131  @else { @return transparentize(black, $_lbg*0.8); }
132}
133
134@function _button_hilight_color($c) {
135//
136// calculate the right top hilight color for buttons
137//
138// $c: base color;
139//
140  @if lightness($c)>95% { @return white; }
141  @else if lightness($c)>90% { @return transparentize(white, 0.2); }
142  @else if lightness($c)>80% { @return transparentize(white, 0.5); }
143  @else if lightness($c)>50% { @return transparentize(white, 0.8); }
144  @else if lightness($c)>40% { @return transparentize(white, 0.9); }
145  @else { @return transparentize(white, 0.98); }
146}
147
148@mixin _button_text_shadow ($tc:$fg_color, $bg:$bg_color) {
149//
150// helper function for the text emboss effect
151//
152// $tc is the optional text color, not the shadow color
153//
154// TODO: this functions needs a way to deal with special cases
155//
156
157  $_shadow: _text_shadow_color($tc, $bg);
158
159  @if lightness($tc)<50% {
160    text-shadow: 0 1px $_shadow;
161    -gtk-icon-shadow: 0 1px $_shadow;
162  }
163  @else {
164    text-shadow: 0 -1px $_shadow;
165    -gtk-icon-shadow: 0 -1px $_shadow;
166  }
167}
168
169@mixin button($t, $c:$bg_color, $tc:$fg_color, $edge: none) {
170//
171// Button drawing function
172//
173// $t:    button type,
174// $c:    base button color for colored* types
175// $tc:   optional text color for colored* types
176// $edge: set to none to not draw the bottom edge or specify a color to not
177//        use the default one
178//
179// possible $t values:
180// normal, hover, active, insensitive, insensitive-active,
181// backdrop, backdrop-active, backdrop-insensitive, backdrop-insensitive-active,
182// osd, osd-hover, osd-active, osd-insensitive, osd-backdrop, undecorated
183//
184// This mixin sets the $button_fill global variable which containts the button background-image
185//
186  $_hilight_color: _button_hilight_color($c);
187  $_button_edge: if($edge == none, none, _widget_edge($edge));
188  $_blank_edge: if($edge == none, none, _widget_edge(transparentize($edge,1)));
189  $_button_shadow: 0 1px 2px transparentize($shadow_color, 0.03);
190
191  @if $t==normal {
192  //
193  // normal button
194  //
195    color: $tc;
196    outline-color: $focus_border_color; // Yaru change: we detached focus from selection
197    border-color: if($c != $bg_color, _border_color($c), $borders_color);
198    // border-bottom-color: if($c != $bg_color, _border_color($c, true), $alt_borders_color);
199    // Yaru change: we don't want to use gradients on buttons
200    $button_fill: if($c == $bg_color, if($variant == 'light', image(lighten($c, 2%)), image(lighten($c, 4%))), image(lighten($c, 2%))) !global;
201    background-image: $button_fill;
202    @include _button_text_shadow($tc, $c);
203    @include _shadows(0 1px transparentize(black, 0.95)); // Yaru change: stronger shadows for flatter buttons
204  }
205
206  @else if $t==hover {
207  //
208  // hovered button
209  //
210    color: $tc;
211    outline-color: $focus_border_color; // Yaru change: we detached focus from selection
212    border-color: if($c != $bg_color, _border_color($c), $borders_color);
213    border-bottom-color: if($c != $bg_color, _border_color($c, true), $alt_borders_color);
214    @if $variant == 'light' {
215      $button_fill: linear-gradient(to top, $c, lighten($c, 1%) 1px) !global;
216      @include _button_text_shadow($tc, lighten($c, 6%));
217      @include _shadows(inset 0 1px _button_hilight_color(lighten($c, 6%)), $_button_edge, $_button_shadow);
218    }
219    @else {
220      $button_fill: linear-gradient(to top, darken($c,1%), lighten($c, 1%) 1px) !global;
221      @include _button_text_shadow($tc,lighten($c, 6%));
222      @include _shadows(inset 0 1px _button_hilight_color(darken($c, 2%)), $_button_edge, $_button_shadow);
223    }
224    box-shadow: 0 1px transparentize(black, if($variant=='light', 0.85, 0.9)); // Yaru change: stronger shadows for flatter buttons
225    background-image: if($c == $bg_color, if($variant == 'light', image(lighten($c, 4%)), image(lighten($c, 6%))), image(lighten($c, 4%)));
226  }
227
228  @if $t==normal-alt {
229  //
230  // normal button alternative look
231  //
232    color: $tc;
233    outline-color: $focus_border_color; // Yaru change: we detached focus from selection
234    border-color: if($c != $bg_color, _border_color($c, true), $alt_borders_color);
235    @include _button_text_shadow($tc, $c);
236    @if $variant == 'light' {
237      background-image: linear-gradient(to bottom, lighten($c, 5%) 20%, $c 90%);
238       @include _shadows(inset 0 1px _button_hilight_color(lighten($c, 6%)),
239                        $_button_edge, $_button_shadow);
240    }
241    @else {
242      background-image: linear-gradient(to bottom, darken($c, 3%) 20%, darken($c, 6%) 90%);
243      @include _shadows(inset 0 1px $_hilight_color,
244                        $_button_edge, $_button_shadow);
245    }
246    @include _shadows(0 1px transparentize(black, 0.95)); // Yaru change: stronger shadows for flatter buttons
247    background-image: image(if($variant=='light', lighten($c, 10%), $warm_gray)); // Yaru change: brighter alt
248    background-clip: padding-box; // Yaru change: fix background overflow
249  }
250
251  @else if $t==hover-alt {
252  //
253  // hovered button alternative look
254  //
255    color: $tc;
256    outline-color: $focus_border_color; // Yaru change: we detached focus from selection
257    border-color: if($c != $bg_color, _border_color($c, true), $alt_borders_color);
258    @if $variant == 'light' {
259      $button_fill: linear-gradient(to bottom, lighten($c, 9%) 10%, lighten($c, 4%) 90%) !global;
260      @include _shadows(inset 0 1px _button_hilight_color(lighten($c, 6%)),
261                        $_button_edge, $_button_shadow);
262    }
263    @else {
264      $button_fill: linear-gradient(to bottom, $c 20%, darken($c, 4%) 90%) !global;
265      @include _shadows(inset 0 1px $_hilight_color,
266                        $_button_edge, $_button_shadow);
267    }
268    background-image: image(if($variant=='light', lighten($c, 16%), lighten($warm_gray, 4%))); // Yaru change: brighter alt hover
269    box-shadow: 0 1px transparentize(black, 0.85); // Yaru change: stronger shadows for flatter buttons
270  }
271
272  @else if $t==active {
273  //
274  // pushed button
275  //
276    color: $tc;
277    outline-color: $focus_border_color; // Yaru change: we detached focus from selection
278    border-color: if($c != $bg_color, _border_color($c), $borders_color);
279    $button_fill: if($variant == 'light', image(darken($c, 14%)), image(darken($c, 9%))) !global;
280    background-image: $button_fill;
281    @include _shadows(inset 0 1px transparentize($_hilight_color, 1), $_button_edge);
282
283    text-shadow: none;
284    -gtk-icon-shadow: none;
285  }
286
287  @else if $t==insensitive {
288  //
289  // insensitive button
290  //
291    $_bg: if($c != $bg_color, mix($c, $base_color, 85%), $insensitive_bg_color);
292
293    color: if($tc != $fg_color, mix($tc, $_bg, 50%), $insensitive_fg_color);
294    border-color: if($c != $bg_color, _border_color($c), $insensitive_borders_color);
295    $button_fill: image($_bg) !global;
296    background-image: $button_fill;
297    text-shadow: none;
298    -gtk-icon-shadow: none;
299    // white with 0 alpha to avoid an ugly transition, since no color means
300    // black with 0 alpha
301    @include _shadows(inset 0 1px transparentize(white, 1), $_button_edge);
302  }
303
304  @else if $t==insensitive-active {
305  //
306  // insensitive pushed button
307  //
308    $_bg: if($variant == 'light', darken(mix($c, $base_color, 85%), 8%), darken(mix($c, $base_color, 85%), 6%));
309    $_bc: if($c != $bg_color, _border_color($c), $insensitive_borders_color);
310
311    color: if($c != $bg_color, mix($tc, $_bg, 60%), $insensitive_fg_color);
312    border-color: $_bc;
313    $button_fill: image($_bg) !global;
314    background-image: $button_fill;
315    // white with 0 alpha to avoid an ugly transition, since no color means
316    // black with 0 alpha
317    @include _shadows(inset 0 1px transparentize(white, 1), $_button_edge);
318  }
319
320  @else if $t==backdrop {
321  //
322  // backdrop button
323  //
324    $_bg: if($c != $bg_color, $c, $backdrop_bg_color);
325    $_bc: if($variant == 'light', $c, _border_color($c));
326
327    color: if($tc != $fg_color, mix($tc, $_bg, 80%), $backdrop_fg_color);
328    border-color: if($c != $bg_color, $_bc, $backdrop_borders_color);
329    $button_fill: image($_bg) !global;
330    background-image: $button_fill;
331    text-shadow: none;
332    -gtk-icon-shadow: none;
333    @include _shadows(inset 0 1px transparentize(white, 1), $_blank_edge);
334  }
335
336  @else if $t==backdrop-active {
337  //
338  // backdrop pushed button
339  //
340    $_bg: if($variant == 'light', darken(mix($c, $base_color, 85%), 8%), darken(mix($c, $base_color, 85%), 4%));
341    $_bc: if($variant == 'light', $_bg ,_border_color($c));
342
343    color: if($tc != $fg_color, mix($tc, $_bg, 80%), $backdrop_fg_color);
344    border-color: if($c != $bg_color, $_bc, $backdrop_borders_color);
345    $button_fill: image($_bg) !global;
346    background-image: $button_fill;
347    @include _shadows(inset 0 1px transparentize(white, 1), $_blank_edge);
348  }
349
350  @else if $t==backdrop-insensitive {
351  //
352  // backdrop insensitive button
353  //
354
355    $_bg: if($c != $bg_color, mix($c, $base_color, 85%), if($variant=='light', $insensitive_bg_color, lighten($insensitive_bg_color, 3%))); // Yaru change
356    $_bc: if($variant == 'light', $_bg,_border_color($c));
357
358    color: if($c != $bg_color, mix($tc, $_bg, 35%), $backdrop_insensitive_color);
359    border-color: if($c != $bg_color, $_bc, $backdrop_borders_color);
360    $button_fill: image($_bg) !global;
361    background-image: $button_fill;
362    text-shadow: none;
363    -gtk-icon-shadow: none;
364    // white with 0 alpha to avoid an ugly transition, since no color means
365    // black with 0 alpha
366    @include _shadows(inset 0 1px transparentize(white, 1), $_blank_edge);
367  }
368
369  @else if $t==backdrop-insensitive-active {
370  //
371  // backdrop insensitive pushed button
372  //
373
374    $_bg: if($variant == 'light', darken(mix($c, $base_color, 85%), 8%), darken(mix($c, $base_color, 85%), 4%));
375    $_bc: if($variant == 'light', $_bg, _border_color($c));
376
377    color: if($c != $bg_color, mix($tc, $_bg, 35%), $backdrop_insensitive_color);
378    border-color: if($c != $bg_color, $_bc, $backdrop_borders_color);
379    $button_fill: image($_bg) !global;
380    background-image: $button_fill;
381    @include _shadows(inset 0 1px transparentize(white, 1), $_blank_edge);
382  }
383
384  @else if $t==osd {
385  //
386  // normal osd button
387  //
388    $_bg: if($c != $bg_color, transparentize($c, 0.5), lighten($osd_bg_color, 9%)); // Yaru change: make osd buttons visible
389
390    color: $osd_fg_color;
391    border-color: $osd_borders_color;
392    background-color: transparent;
393    $button_fill: image($_bg) !global;
394    background-image: $button_fill;
395    background-clip: padding-box;
396    // box-shadow: inset 0 1px transparentize(white, 0.9); // Yaru change: remove the shadow
397    text-shadow: 0 1px black;
398    -gtk-icon-shadow: 0 1px black;
399    outline-color: transparentize($osd_fg_color, 0.7);
400  }
401
402  @else if $t==osd-hover {
403  //
404  // active osd button
405  //
406    $_bg: if($c != $bg_color, transparentize($c, 0.3), lighten($osd_bg_color, 12%));
407
408    color: white;
409    border-color: $osd_borders_color;
410    background-color: transparent;
411    $button_fill: image($_bg) !global;
412    background-image: $button_fill;
413    background-clip: padding-box;
414    // box-shadow: inset 0 1px transparentize(white, 0.9); // Yaru change: remove the shadow
415    text-shadow: 0 1px black;
416    -gtk-icon-shadow: 0 1px black;
417    outline-color: transparentize($osd_fg_color, 0.7);
418  }
419
420  @else if $t==osd-active {
421  //
422  // active osd button
423  //
424    $_bg: if($c != $bg_color, $c, $osd_borders_color);
425
426    color: white;
427    border-color: $osd_borders_color;
428    background-color: transparent;
429    $button_fill: image($_bg) !global;
430    background-image: $button_fill;
431    background-clip: padding-box;
432    box-shadow: none;
433    text-shadow: none;
434    -gtk-icon-shadow: none;
435    outline-color: transparentize($osd_fg_color, 0.7);
436  }
437
438  @else if $t==osd-insensitive {
439  //
440  // insensitive osd button
441  //
442    color: $osd_insensitive_fg_color;
443    border-color: $osd_borders_color;
444    background-color: transparent;
445    $button_fill: image($osd_insensitive_bg_color) !global;
446    background-image: $button_fill;
447    background-clip: padding-box;
448    box-shadow: none;
449    text-shadow: none;
450    -gtk-icon-shadow: none;
451  }
452
453  @else if $t==osd-backdrop {
454  //
455  // backdrop osd button
456  //
457    $_bg: if($c != $bg_color, transparentize($c, 0.5), $osd_bg_color);
458
459    color: $osd_fg_color;
460    border-color: $osd_borders_color;
461    background-color: transparent;
462    $button_fill: image($_bg) !global;
463    background-image: $button_fill;
464    background-clip: padding-box;
465    box-shadow: none;
466    text-shadow: none;
467    -gtk-icon-shadow: none;
468  }
469
470  @else if $t==undecorated {
471  //
472  // reset
473  //
474    border-color: transparent;
475    background-color: transparent;
476    $button_fill: none !global;
477    background-image: $button_fill;
478
479    @include _shadows(inset 0 1px transparentize(white, 1), $_blank_edge);
480
481    text-shadow: none;
482    -gtk-icon-shadow: none;
483  }
484}
485
486@mixin headerbar_fill($c:$headerbar_color, $hc:$top_hilight, $ov: none) {
487//
488// headerbar fill
489//
490// $c:  base color
491// $hc: top highlight color
492// $ov: a background layer for background shorthand (hence no commas!)
493//
494  $gradient: linear-gradient(to top, darken($c, 0%), lighten($c, 0%)); // Yaru change: no gradients
495
496  @if $variant == 'dark' { $gradient: linear-gradient(to top, lighten($c, 6%), lighten($c, 6%)); } // Yaru change: no gradients
497
498  @if $ov != none { background: $c $ov, $gradient; }
499  @else { background: $c $gradient; }
500
501  box-shadow: inset 0 1px $hc; // top highlight
502}
503
504@mixin overshoot($p, $t:normal, $c:$fg_color) {
505//
506// overshoot
507//
508// $p: position
509// $t: type
510// $c: base color
511//
512// possible $p values:
513// top, bottom, right, left
514//
515// possible $t values:
516// normal, backdrop
517//
518
519  $_small_gradient_length: 5%;
520  $_big_gradient_length: 100%;
521
522  $_position: center top;
523  $_small_gradient_size: 100% $_small_gradient_length;
524  $_big_gradient_size: 100% $_big_gradient_length;
525
526  @if $p==bottom {
527    $_position: center bottom;
528    $_linear_gradient_direction: to top;
529  }
530
531  @else if $p==right {
532    $_position: right center;
533    $_small_gradient_size: $_small_gradient_length 100%;
534    $_big_gradient_size: $_big_gradient_length 100%;
535  }
536
537  @else if $p==left {
538    $_position: left center;
539    $_small_gradient_size: $_small_gradient_length 100%;
540    $_big_gradient_size: $_big_gradient_length 100%;
541  }
542
543  $_small_gradient_color: $c;
544  $_big_gradient_color: $c;
545
546  @if $c==$fg_color {
547    $_small_gradient_color: darken($borders_color, 10%);
548    $_big_gradient_color: $fg_color;
549
550    @if $t==backdrop { $_small_gradient_color: $backdrop_borders_color; }
551  }
552
553  $_small_gradient: -gtk-gradient(radial,
554                                  $_position, 0,
555                                  $_position, 0.5,
556                                  to($_small_gradient_color),
557                                  to(transparentize($_small_gradient_color, 1)));
558
559  $_big_gradient: -gtk-gradient(radial,
560                                $_position, 0,
561                                $_position, 0.6,
562                                from(transparentize($_big_gradient_color, 0.93)),
563                                to(transparentize($_big_gradient_color, 1)));
564
565  @if $t==normal {
566    background-image: $_small_gradient, $_big_gradient;
567    background-size: $_small_gradient_size, $_big_gradient_size;
568  }
569
570  @else if $t==backdrop {
571    background-image: $_small_gradient;
572    background-size: $_small_gradient_size;
573  }
574
575  background-repeat: no-repeat;
576  background-position: $_position;
577
578  background-color: transparent; // reset some properties to be sure to not inherit them somehow
579  border: none;                  //
580  box-shadow: none;              //
581}
582
583/***************************
584 * Check and Radio buttons *
585 ***************************/
586
587 @mixin check($t, $c:$bg_color, $tc:$fg_color, $checked: false) {
588  // Check/Radio drawing function
589  //
590  // $t:        check/radio type,
591  // $c:        base button color for colored* types
592  // $tc:       optional text color for colored* types
593  // $checked:  bool to chose between checked/unchecked
594  //
595  // possible $t values:
596  // normal, hover, active, insensitive, backdrop, backdrop-insensitive
597
598  $_border_color: if($c==$checkradio_bg_color, $c, $alt_borders_color);
599  $_dim_border_color: transparentize($_border_color, if($variant == 'light', 0.3, 0.7));
600
601  @if $t==normal  { // Yaru change: no gradients, better borders
602    background-clip: if($checked, border-box, padding-box);
603    background-image: image(lighten($c, if($variant=='dark', if($c==$checkradio_bg_color, 0%, 5%), 0%)));
604    border-color: $_border_color;
605    box-shadow: 0 1px transparentize(black, 0.95);
606    color: $tc;
607  }
608
609  @if $t==hover {
610    background-image: image(if($c==$checkradio_bg_color, lighten($c, 7%), if($variant=='light', darken($c, 4%), lighten($c, 7%))));
611    border-color: if($c == $checkradio_bg_color, lighten($c, 7%), $alt_borders_color);
612  }
613
614  @if $t==active {
615    border-color: if($c==white, $_border_color, darken($c, 7%));
616    background-image: image(if($c==white, $_border_color, darken($c, 7%)));
617    box-shadow: none;
618  }
619
620  @if $t==insensitive {
621    box-shadow: none;
622    color: $insensitive_fg_color;
623    border-color: $insensitive_borders_color;
624    background-image: image($insensitive_bg_color);
625  }
626
627  @if $t==backdrop {
628    background-image: image($c);
629    border-color: $_border_color;
630    box-shadow: none;
631    color: $tc;
632  }
633
634  @if $t==backdrop-insensitive {
635    box-shadow: none;
636    color: $backdrop_fg_color;
637    border-color: $insensitive_borders_color;
638    background-image: image($insensitive_bg_color);
639  }
640}
641