Better error message
[notion/jeffpc.git] / ioncore / screen-notify.c
blob1f52b6ea95458a5d124af7721ea081ccf6521d2c
1 /*
2 * ion/ioncore/screen-notify.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
7 */
9 #include <string.h>
11 #include <libtu/minmax.h>
12 #include <libmainloop/defer.h>
14 #include "common.h"
15 #include "global.h"
16 #include "infowin.h"
17 #include "activity.h"
18 #include "tags.h"
19 #include "gr.h"
20 #include "gr-util.h"
21 #include "stacking.h"
22 #include "names.h"
23 #include "screen.h"
24 #include "screen-notify.h"
25 #include "strings.h"
28 /*{{{ Generic stuff */
31 static WInfoWin *do_get_notifywin(WScreen *scr, Watch *watch, uint pos,
32 char *style)
35 WInfoWin *iw=(WInfoWin*)(watch->obj);
36 WFitParams fp;
38 if(iw==NULL){
39 WMPlexAttachParams param=MPLEXATTACHPARAMS_INIT;
41 param.flags=(MPLEX_ATTACH_UNNUMBERED|
42 MPLEX_ATTACH_SIZEPOLICY|
43 MPLEX_ATTACH_GEOM|
44 MPLEX_ATTACH_LEVEL|
45 MPLEX_ATTACH_PASSIVE);
46 param.level=STACKING_LEVEL_ON_TOP;
48 param.geom.x=0;
49 param.geom.y=0;
50 param.geom.w=1;
51 param.geom.h=1;
53 switch(pos){
54 case MPLEX_STDISP_TL:
55 param.szplcy=SIZEPOLICY_GRAVITY_NORTHWEST;
56 param.geom.x=0;
57 break;
59 case MPLEX_STDISP_TR:
60 param.szplcy=SIZEPOLICY_GRAVITY_NORTHEAST;
61 param.geom.x=REGION_GEOM(scr).w-1;
62 break;
64 case MPLEX_STDISP_BL:
65 param.szplcy=SIZEPOLICY_GRAVITY_SOUTHWEST;
66 param.geom.x=0;
67 param.geom.y=REGION_GEOM(scr).h-1;
68 break;
70 case MPLEX_STDISP_BR:
71 param.szplcy=SIZEPOLICY_GRAVITY_SOUTHEAST;
72 param.geom.x=REGION_GEOM(scr).w-1;
73 param.geom.y=REGION_GEOM(scr).h-1;
74 break;
78 iw=(WInfoWin*)mplex_do_attach_new(&scr->mplex, &param,
79 (WRegionCreateFn*)create_infowin,
80 style);
82 if(iw!=NULL)
83 watch_setup(watch, (Obj*)iw, NULL);
86 return iw;
90 static void do_unnotify(Watch *watch)
92 Obj *iw=watch->obj;
93 if(iw!=NULL){
94 watch_reset(watch);
95 mainloop_defer_destroy((Obj*)iw);
100 /*}}}*/
103 /*{{{ Notifywin */
106 static WInfoWin *get_notifywin(WScreen *scr)
108 WRegion *stdisp=NULL;
109 WMPlexSTDispInfo info;
110 uint pos=MPLEX_STDISP_TL;
112 mplex_get_stdisp(&scr->mplex, &stdisp, &info);
113 if(stdisp!=NULL)
114 pos=info.pos;
116 return do_get_notifywin(scr, &scr->notifywin_watch, pos, "actnotify");
120 void screen_notify(WScreen *scr, const char *str)
122 WInfoWin *iw=get_notifywin(scr);
124 if(iw!=NULL){
125 int maxw=REGION_GEOM(scr).w/3;
126 infowin_set_text(iw, str, maxw);
131 void screen_unnotify(WScreen *scr)
133 do_unnotify(&scr->notifywin_watch);
137 static bool ws_mapped(WScreen *scr, WRegion *reg)
139 while(1){
140 WRegion *mgr=REGION_MANAGER(reg);
142 if(mgr==NULL)
143 return FALSE;
145 if(mgr==(WRegion*)scr)
146 return REGION_IS_MAPPED(reg);
148 reg=mgr;
153 static void screen_managed_activity(WScreen *scr)
155 char *notstr=NULL;
156 WRegion *reg;
157 ObjListIterTmp tmp;
158 PtrListIterTmp tmp2;
159 ObjList *actlist=ioncore_activity_list();
160 WInfoWin *iw=NULL;
161 PtrList *found=NULL;
162 int nfound=0, nadded=0;
163 int w=0, maxw=REGION_GEOM(scr).w/4;
165 /* Lisäksi minimipituus (10ex tms.), ja sen yli menevät jätetään
166 * pois (+ n)
168 FOR_ALL_ON_OBJLIST(WRegion*, reg, actlist, tmp){
169 if(region_screen_of(reg)!=scr || ws_mapped(scr, reg))
170 continue;
171 if(region_name(reg)==NULL)
172 continue;
173 if(ptrlist_insert_last(&found, reg))
174 nfound++;
177 if(found==NULL)
178 goto unnotify;
180 iw=get_notifywin(scr);
182 if(iw==NULL)
183 return;
185 if(iw->brush==NULL)
186 goto unnotify;
188 notstr=scopy(TR("act: "));
190 if(notstr==NULL)
191 goto unnotify;
193 FOR_ALL_ON_PTRLIST(WRegion*, reg, found, tmp2){
194 const char *nm=region_name(reg);
195 char *nstr=NULL, *label=NULL;
197 w=grbrush_get_text_width(iw->brush, notstr, strlen(notstr));
199 if(w>=maxw)
200 break;
202 label=grbrush_make_label(iw->brush, nm, maxw-w);
203 if(label!=NULL){
204 nstr=(nadded>0
205 ? scat3(notstr, ", ", label)
206 : scat(notstr, label));
208 if(nstr!=NULL){
209 free(notstr);
210 notstr=nstr;
211 nadded++;
213 free(label);
217 if(nfound > nadded){
218 char *nstr=NULL;
220 libtu_asprintf(&nstr, "%s +%d", notstr, nfound-nadded);
222 if(nstr!=NULL){
223 free(notstr);
224 notstr=nstr;
228 ptrlist_clear(&found);
230 infowin_set_text(iw, notstr, 0);
232 free(notstr);
234 return;
236 unnotify:
237 screen_unnotify(scr);
241 static void screen_do_update_notifywin(WScreen *scr)
243 if(ioncore_g.screen_notify)
244 screen_managed_activity(scr);
245 else
246 screen_unnotify(scr);
250 /*}}}*/
253 /*{{{ Infowin */
256 static WInfoWin *get_infowin(WScreen *scr)
258 WRegion *stdisp=NULL;
259 WMPlexSTDispInfo info;
260 uint pos=MPLEX_STDISP_TR;
262 mplex_get_stdisp(&scr->mplex, &stdisp, &info);
263 if(stdisp!=NULL && info.pos==MPLEX_STDISP_TR)
264 pos=MPLEX_STDISP_BR;
266 return do_get_notifywin(scr, &scr->infowin_watch, pos, "tab-info");
270 void screen_windowinfo(WScreen *scr, const char *str)
272 WInfoWin *iw=get_infowin(scr);
274 if(iw!=NULL){
275 int maxw=REGION_GEOM(scr).w/3;
276 infowin_set_text(iw, str, maxw);
281 void screen_nowindowinfo(WScreen *scr)
283 do_unnotify(&scr->infowin_watch);
287 GR_DEFATTR(active);
288 GR_DEFATTR(inactive);
289 GR_DEFATTR(selected);
290 GR_DEFATTR(tagged);
291 GR_DEFATTR(not_tagged);
292 GR_DEFATTR(not_dragged);
293 GR_DEFATTR(activity);
294 GR_DEFATTR(no_activity);
297 static void init_attr()
299 GR_ALLOCATTR_BEGIN;
300 GR_ALLOCATTR(active);
301 GR_ALLOCATTR(inactive);
302 GR_ALLOCATTR(selected);
303 GR_ALLOCATTR(tagged);
304 GR_ALLOCATTR(not_tagged);
305 GR_ALLOCATTR(not_dragged);
306 GR_ALLOCATTR(no_activity);
307 GR_ALLOCATTR(activity);
308 GR_ALLOCATTR_END;
312 static void screen_do_update_infowin(WScreen *scr)
314 WRegion *reg=mplex_mx_current(&(scr->mplex));
315 bool tag=(reg!=NULL && region_is_tagged(reg));
316 bool act=(reg!=NULL && region_is_activity_r(reg) && !REGION_IS_ACTIVE(scr));
317 bool sac=REGION_IS_ACTIVE(scr);
319 if(tag || act){
320 const char *n=region_displayname(reg);
321 WInfoWin *iw;
323 screen_windowinfo(scr, n);
325 iw=(WInfoWin*)scr->infowin_watch.obj;
327 if(iw!=NULL){
328 GrStyleSpec *spec=infowin_stylespec(iw);
330 init_attr();
332 gr_stylespec_unalloc(spec);
334 gr_stylespec_set(spec, GR_ATTR(selected));
335 gr_stylespec_set(spec, GR_ATTR(not_dragged));
336 gr_stylespec_set(spec, sac ? GR_ATTR(active) : GR_ATTR(inactive));
337 gr_stylespec_set(spec, tag ? GR_ATTR(tagged) : GR_ATTR(not_tagged));
338 gr_stylespec_set(spec, act ? GR_ATTR(activity) : GR_ATTR(no_activity));
341 }else{
342 screen_nowindowinfo(scr);
348 /*}}}*/
351 /*{{{ Notification callbacks and deferred updates*/
354 void screen_update_infowin(WScreen *scr)
356 mainloop_defer_action((Obj*)scr,
357 (WDeferredAction*)screen_do_update_infowin);
361 void screen_update_notifywin(WScreen *scr)
363 mainloop_defer_action((Obj*)scr,
364 (WDeferredAction*)screen_do_update_notifywin);
368 void screen_managed_notify(WScreen *scr, WRegion *reg, WRegionNotify how)
370 if(how==ioncore_g.notifies.tag)
371 screen_update_infowin(scr);
375 void ioncore_screen_activity_notify(WRegion *reg, WRegionNotify how)
377 WScreen *scr=region_screen_of(reg);
378 if(scr!=NULL){
379 if(how==ioncore_g.notifies.activity){
380 screen_update_notifywin(region_screen_of(reg));
381 }else if(how==ioncore_g.notifies.name){
382 if(region_is_activity(reg))
383 screen_update_notifywin(scr);
384 if((WRegion*)scr==REGION_MANAGER(reg))
385 screen_do_update_infowin(scr);
391 /*}}}*/