]> icculus.org git repositories - mikachu/rspanel.git/blob - gui.c
iconified = flat, normal = raised, focused = sunken. this is what all panels do i...
[mikachu/rspanel.git] / gui.c
1 #include "gui.h"
2 #include "dims.h"
3 #include "xprop.h"
4 #include "icon.h"
5 #include "rspanel.h"
6
7 #include <openbox/theme.h>
8
9 static int pager_size;
10
11 static RrAppearance *background;
12 static RrAppearance *focused_task;
13 static RrAppearance *iconified_task;
14 static RrAppearance *unfocused_task;
15 static RrAppearance *normal_text;
16 static RrAppearance *iconified_text;
17 static RrAppearance *shaded_text;
18 static RrAppearance *focused_text;
19 static RrAppearance *a_icon;
20
21 /* you can edit these */
22 #define MAX_TASK_WIDTH 500
23 #define PADDING 2
24 #define ICON_SIZE ((tb->h)-(2*PADDING))
25
26 static void set_icon_geometry(screen *sc, taskbar *tb, task *tk);
27
28 #define SURF(x) with->surface.x
29 #define TEXT(x) with->texture[0].data.text.x
30 #define USE(x) (with = x)
31 #define SETTEXT(x, y, z) with->texture[0].type = RR_TEXTURE_TEXT; \
32                          with->texture[0].data.text.font = x; \
33                          with->texture[0].data.text.justify = y; \
34                          with->texture[0].data.text.ellipsize = z;
35 #define SETSHADOW(y, z, u, v) with->texture[0].data.text.shadow_offset_x = y; \
36                               with->texture[0].data.text.shadow_offset_y = z; \
37                               with->texture[0].data.text.shadow_alpha = u; \
38                               with->texture[0].data.text.shadow_color = v;
39
40 void gui_init(screen *sc)
41 {
42     XGCValues gcv;
43     RrFont *font;
44     RrAppearance *with;
45     
46     gcv.graphics_exposures = False;
47     sc->fore_gc = XCreateGC(sc->dd, sc->root, GCGraphicsExposures, &gcv);
48
49     /* We don't allow different fonts for various window states... */
50     font = RrFontOpen(sc->rr, "Candara, sans", 10,
51                       RR_FONTWEIGHT_NORMAL, RR_FONTSLANT_NORMAL);
52
53     /* this appearance will be used to draw icons */
54     a_icon = RrAppearanceNew(sc->rr, 1);
55     USE(a_icon);
56     SURF(grad) = RR_SURFACE_PARENTREL;
57     SURF(parentx) = PADDING;
58     SURF(parenty) = PADDING;
59     a_icon->texture[0].type = RR_TEXTURE_RGBA;
60
61     /* this is the appearance for the background of the panel */
62     background = RrAppearanceNew(sc->rr, 0);
63     USE(background);
64     SURF(grad) = RR_SURFACE_DIAGONAL;
65     SURF(primary) = RrColorNew(sc->rr, 170, 170, 190);
66     SURF(secondary) = RrColorNew(sc->rr, 100, 100, 160);
67
68     /* this is the appearance for unfocused tasks,
69      * text needs to be separate appearances so we can align it correctly */
70     unfocused_task = RrAppearanceNew(sc->rr, 0);
71     USE(unfocused_task);
72     SURF(parent) = background;
73     SURF(grad) = RR_SURFACE_PARENTREL;
74     SURF(relief) = RR_RELIEF_RAISED;
75
76     /* ... for iconified tasks, also used for shaded ones currently */
77     iconified_task = RrAppearanceCopy(unfocused_task);
78     USE(iconified_task);
79     SURF(relief) = RR_RELIEF_FLAT;
80     SURF(parent) = background; /* RrAppearanceCopy doesn't copy .parent */
81
82     /* ... for focused tasks */
83     focused_task = RrAppearanceNew(sc->rr, 0);
84     USE(focused_task);
85     SURF(grad) = RR_SURFACE_CROSS_DIAGONAL;
86     SURF(secondary) = RrColorNew(sc->rr, 70, 80, 110);
87     SURF(primary) = RrColorNew(sc->rr, 130, 160, 250);
88     SURF(relief) = RR_RELIEF_SUNKEN;
89
90     /* this is the text used for all normal unfocused tasks */
91     /* we don't set .parent here, but in draw_task, since we
92      * want to combine _task and _text semirandomly.
93      * XXX plz not when themes are here */
94     normal_text = RrAppearanceNew(sc->rr, 1);
95     USE(normal_text);
96     SURF(grad) = RR_SURFACE_PARENTREL;
97     SETTEXT(font, RR_JUSTIFY_LEFT, RR_ELLIPSIZE_END);
98
99     /* ... for iconified tasks */
100     iconified_text = RrAppearanceCopy(normal_text);
101     /* ... and for focused tasks, we copy this here (ie not 5 lines down)
102      * so the color isn't copied i actually don't know if that would
103      * hurt so XXX on that */
104     focused_text = RrAppearanceCopy(normal_text);
105     USE(focused_text);
106     TEXT(color) = RrColorNew(sc->rr, 230, 230, 255);
107
108     USE(normal_text);
109     TEXT(color) = RrColorNew(sc->rr, 20, 20, 40);
110
111     USE(iconified_text);
112     SETSHADOW(2, 2, 100, RrColorNew(sc->rr, 0, 0, 0));
113     TEXT(color) = RrColorNew(sc->rr, 200, 200, 200);
114
115     shaded_text = RrAppearanceCopy(normal_text);
116     USE(shaded_text);
117     TEXT(color) = RrColorNew(sc->rr, 50, 60, 90);
118 }
119
120 void gui_create_taskbar(screen *sc, taskbar *tb)
121 {
122     XSizeHints size_hints;
123     XSetWindowAttributes att;
124     XClassHint xclhints;
125
126     att.event_mask = ButtonPressMask;
127
128     /* XXX make the height conigurable */
129     tb->x = 0;
130     tb->y = sc->height - 24;
131     tb->w = sc->width;
132     tb->h = 24;
133
134     tb->win = XCreateWindow(/* display  */ sc->dd,
135                             /* parent   */ sc->root,
136                             /* x        */ tb->x,
137                             /* y        */ tb->y,
138                             /* width    */ tb->w,
139                             /* height   */ tb->h,
140                             /* border   */ 0,
141                             /* depth    */ CopyFromParent,
142                             /* class    */ InputOutput,
143                             /* visual   */ CopyFromParent,
144                             /*value mask*/ CWEventMask,
145                             /* attribs  */ &att);
146     tb->bg = None;
147
148     /* reside on ALL desktops */
149     xprop_set_num(sc, tb->win, _NET_WM_DESKTOP, 0xFFFFFFFF);
150     xprop_set_atom(sc, tb->win, _NET_WM_WINDOW_TYPE, _NET_WM_WINDOW_TYPE_DOCK);
151     xprop_set_atom(sc, tb->win, _NET_WM_STATE, _NET_WM_STATE_BELOW);
152     xprop_set_string(sc, tb->win, WM_NAME, "rspanel");
153
154     /* make sure the WM obays our window position */
155     size_hints.flags = PPosition;
156     size_hints.x = tb->x;
157     size_hints.y = tb->y;
158     /*XSetWMNormalHints (sc->dd, tb->win, &size_hints); */
159     XChangeProperty(sc->dd, tb->win, XA_WM_NORMAL_HINTS, XA_WM_SIZE_HINTS, 32,
160                     PropModeReplace, (unsigned char *)&size_hints,
161                     sizeof(XSizeHints) / 4);
162
163     xclhints.res_name = "rspanel";
164     xclhints.res_class = "RSPanel";
165     XSetClassHint(sc->dd, tb->win, &xclhints);
166
167     XMapWindow(sc->dd, tb->win);
168 }
169
170 void gui_draw_task(screen *sc, taskbar *tb, task *tk, int redraw)
171 {
172     RrAppearance *a;
173     RrAppearance *b;
174     const icon *i;
175     int icon_size = 0;
176
177     if (tk->iconified)
178         b = iconified_task;
179     else if (tk->focused)
180         b = focused_task;
181     else if (tk->shaded)
182         b = iconified_task;
183     else
184         b = unfocused_task;
185
186     if (tk->iconified)
187         a = iconified_text;
188     else if (tk->shaded)
189         a = shaded_text;
190     else if (tk->focused)
191         a = focused_text;
192     else
193         a = normal_text;
194
195     i = icon_get_best(tk->icons, tk->nicons, ICON_SIZE, ICON_SIZE);
196
197     if (i) {
198         RrTextureRGBA *d = &a_icon->texture[0].data.rgba;
199         a_icon->surface.parent = b;
200         d->width = i->width;
201         d->height = i->height;
202         d->alpha = tk->iconified ? 0x80 : tk->shaded ? 0xB0 : 0xff;
203         d->data = i->data;
204         icon_size = ICON_SIZE + PADDING;
205     }
206
207     a->surface.parent = b;
208     a->surface.parentx = icon_size + PADDING;
209     a->texture[0].data.text.string = tk->name;
210     b->surface.parentx = tk->pos_x;
211
212     RrPaintPixmap(b, tk->width, tb->h);
213     RrPaintPixmap(a, tk->width-(2*PADDING+icon_size), tb->h);
214
215     if (i) {
216         RrPaintPixmap(a_icon, ICON_SIZE, ICON_SIZE);
217         XCopyArea(sc->dd, a_icon->pixmap, b->pixmap, sc->fore_gc, 0, 0,
218                   ICON_SIZE, ICON_SIZE, PADDING, PADDING);
219     }
220
221     XCopyArea(sc->dd, a->pixmap, b->pixmap, sc->fore_gc, 0, 0,
222               tk->width-(2*PADDING+icon_size), tb->h, icon_size + PADDING, 0);
223     XCopyArea(sc->dd, b->pixmap, tb->bg, sc->fore_gc, 0, 0,
224               tk->width, tb->h, tk->pos_x, 0);
225
226     XFreePixmap(sc->dd, a->pixmap);
227     XFreePixmap(sc->dd, b->pixmap);
228     XFreePixmap(sc->dd, a_icon->pixmap);
229     if (redraw) {
230         XSetWindowBackgroundPixmap(sc->dd, tb->win, tb->bg);
231         XClearWindow(sc->dd, tb->win);
232     }
233 }
234
235 void gui_draw_taskbar(screen *sc, taskbar *tb)
236 {
237     task *tk;
238     int x, width, taskw;
239     int num_tasks = 0;
240
241 #ifdef PAGER
242     pager_draw();
243 #else
244     pager_size = TEXTPAD;
245 #endif
246
247     x = pager_size + 2;
248     width = tb->w - (pager_size + GRILL_WIDTH);
249 #warning only rerender if width changed!
250     if (tb->bg) XFreePixmap(sc->dd, tb->bg);
251     tb->bg = XCreatePixmap(sc->dd, sc->root, tb->w, tb->h, RrDepth(sc->rr));
252
253     XFreePixmap(sc->dd, RrPaintPixmap(background, tb->w, tb->h));
254     XCopyArea(sc->dd, background->pixmap, tb->bg, sc->fore_gc, 0, 0,
255               tb->w, tb->h, 0, 0);
256
257     /* find the number of visible tasks */
258     for (tk = tb->task_list; tk; tk = tk->next) {
259         if (!task_shown(tk))
260             continue;
261         num_tasks++;
262     }
263
264     if (num_tasks == 0)
265         goto clear;
266
267     taskw = width / num_tasks;
268     if (taskw > MAX_TASK_WIDTH)
269         taskw = MAX_TASK_WIDTH;
270
271     for (tk = tb->task_list; tk; tk = tk->next) {
272         if (!task_shown(tk))
273             continue;
274         tk->pos_x = x;
275         tk->width = taskw - 1;
276         gui_draw_task(sc, tb, tk, FALSE);
277         set_icon_geometry(sc, tb, tk);
278         x += taskw;
279     }
280
281 clear:
282     XSetWindowBackgroundPixmap(sc->dd, tb->win, tb->bg);
283     XClearWindow(sc->dd, tb->win);
284 }
285
286 void gui_move_taskbar(screen *sc, taskbar *tb)
287 {
288     tb->x = tb->y = 0;
289
290     if (tb->hidden)
291         tb->x = TEXTPAD - tb->w;
292
293     if (!tb->at_top)
294         tb->y = sc->height - tb->h;
295
296     XMoveWindow(sc->dd, tb->win, tb->x, tb->y);
297 }
298
299 static void set_icon_geometry(screen *sc, taskbar *tb, task *tk)
300 {
301     long coords[4];
302
303     coords[0] = tb->x + tk->pos_x;
304     coords[1] = tb->y;
305     coords[2] = MAX(tk->width, 1);
306     coords[3] = tb->h;
307
308     xprop_set_array(sc, tk->win, _NET_WM_ICON_GEOMETRY, coords, 4);
309 }