1 /*
2  * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3  * Copyright (C) 2006-2018 Kim Woelders
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to
7  * deal in the Software without restriction, including without limitation the
8  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9  * sell copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies of the Software, its documentation and marketing & publicity
14  * materials, and acknowledgment shall be given in the documentation, materials
15  * and software packages that this Software was used.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 #include "E.h"
25 #include "desktops.h"
26 #include "eobj.h"
27 #include "ewins.h"
28 #include "hints.h"
29 #include "iclass.h"
30 #include "tclass.h"
31 #include "timers.h"
32 #include "xwin.h"
33 
34 static EObj        *coord_eo = NULL;
35 
36 static void
_CoordsShow(EWin * ewin,int mode)37 _CoordsShow(EWin * ewin, int mode)
38 {
39    TextClass          *tc;
40    ImageClass         *ic;
41    char                s[256];
42    int                 md;
43    int                 x, y;
44    unsigned int        w, h;
45    int                 cx, cy, cw, ch;
46    EObj               *eo = coord_eo;
47    EImageBorder       *pad;
48    int                 bl, br, bt, bb;
49 
50    if (!Conf.movres.mode_info)
51       return;
52    if (!ewin || !ewin->state.show_coords)
53       return;
54 
55    tc = TextclassFind("COORDS", 1);
56    ic = ImageclassFind("COORDS", 1);
57    if ((!ic) || (!tc))
58       return;
59 
60    cx = cy = cw = ch = 0;
61 
62    x = ewin->shape_x;
63    y = ewin->shape_y;
64    w = (ewin->state.shaded) ? ewin->client.w : ewin->shape_w;
65    h = (ewin->state.shaded) ? ewin->client.h : ewin->shape_h;
66    ICCCM_GetIncrementalSize(ewin, w, h, &w, &h);
67 
68    switch (mode)
69      {
70      default:
71      case 0:
72 	Esnprintf(s, sizeof(s), "%i x %i (%i, %i)", w, h, x, y);
73 	break;
74      case 1:
75 	Esnprintf(s, sizeof(s), _("Focused/unfocused opacity: %d/%d %%"),
76 		  OpacityToPercent(ewin->props.focused_opacity),
77 		  OpacityToPercent(ewin->props.opacity));
78 	break;
79      }
80    TextSize(tc, 0, 0, 0, s, &cw, &ch, 17);
81    pad = ImageclassGetPadding(ic);
82    cw += pad->left + pad->right;
83    ch += pad->top + pad->bottom;
84 
85    /* Width hysteresis (hack - assuming horizontal text) */
86    cw += 8;
87    if (eo && abs(EobjGetW(eo) - cw) < 8)
88       cw = EobjGetW(eo);
89 
90    if (Mode.mode == MODE_MOVE)
91       md = Conf.movres.mode_move;
92    else
93       md = Conf.movres.mode_resize;
94 
95    if ((md == 0) || ((cw < ewin->shape_w - 2) && (ch < ewin->shape_h - 2)))
96      {
97 	if (Conf.movres.mode_info == 1)
98 	  {
99 	     switch (md)
100 	       {
101 	       case MR_OPAQUE:
102 	       case MR_TECHNICAL:
103 	       case MR_BOX:
104 	       case MR_TECH_OPAQUE:
105 		  EwinBorderGetSize(ewin, &bl, &br, &bt, &bb);
106 		  w = (ewin->state.shaded) ?
107 		     EoGetW(ewin) : ewin->shape_w + bl + br;
108 		  h = (ewin->state.shaded) ?
109 		     EoGetH(ewin) : ewin->shape_h + bt + bb;
110 		  cx = x + (w - cw) / 2 + EoGetX(EoGetDesk(ewin));
111 		  cy = y + (h - ch) / 2 + EoGetY(EoGetDesk(ewin));
112 		  break;
113 	       }
114 	  }
115      }
116 
117    if (!eo)
118      {
119 	eo = EobjWindowCreate(EOBJ_TYPE_MISC, 0, 0, 1, 1, 2, "Coord");
120 	if (!eo)
121 	   return;
122 	coord_eo = eo;
123 	eo->fade = eo->shadow = 1;
124 
125 	/* Center text (override theme) */
126 	TextclassSetJustification(tc, 512);
127      }
128 
129 #define TEST_COORD_REPARENT_TO_FRAME 0
130 #if TEST_COORD_REPARENT_TO_FRAME
131    cx -= x;
132    cy -= y;
133 #endif
134    md = cw != EobjGetW(eo) || ch != EobjGetH(eo);	/* md is change size flag */
135    EobjMoveResize(eo, cx, cy, cw, ch);
136 
137    if (!eo->shown)
138      {
139 #if TEST_COORD_REPARENT_TO_FRAME
140 	EobjReparent(eo, EoObj(ewin), cx, cy);
141 #endif
142 	EobjMap(eo, 0);
143      }
144 
145    ITApply(EobjGetWin(eo), ic, NULL, STATE_NORMAL, 1, 0, tc, NULL, s, 1);
146 
147    if (md)			/* Assuming that shape change only happens when size changes too */
148       EobjShapeUpdate(eo, 0);
149 
150    EFlush();
151 }
152 
153 void
CoordsHide(void)154 CoordsHide(void)
155 {
156    EObj               *eo = coord_eo;
157 
158    if (eo && eo->shown)
159      {
160 	EobjUnmap(eo);
161 #if TEST_COORD_REPARENT_TO_FRAME
162 	EobjReparent(eo, EoObj(DeskGet(0)), 0, 0);
163 #endif
164      }
165 }
166 
167 void
CoordsShow(EWin * ewin)168 CoordsShow(EWin * ewin)
169 {
170    _CoordsShow(ewin, 0);
171 }
172 
173 static Timer       *timer_show_op = NULL;
174 
175 static int
_CoordsHideTimeout(void * data __UNUSED__)176 _CoordsHideTimeout(void *data __UNUSED__)
177 {
178    CoordsHide();
179 
180    timer_show_op = NULL;
181    return 0;
182 }
183 
184 void
CoordsShowOpacity(EWin * ewin)185 CoordsShowOpacity(EWin * ewin)
186 {
187    EwinShapeSet(ewin);
188    ewin->state.show_coords = 1;
189    _CoordsShow(ewin, 1);
190    TIMER_DEL(timer_show_op);
191    TIMER_ADD(timer_show_op, 1000, _CoordsHideTimeout, NULL);
192 }
193