]> git.decadent.org.uk Git - ion3.git/blob - ioncore/screen-notify.c
[svn-upgrade] Integrating new upstream version, ion3 (20070506)
[ion3.git] / ioncore / screen-notify.c
1 /*
2  * ion/ioncore/screen-notify.c
3  *
4  * Copyright (c) Tuomo Valkonen 1999-2007. 
5  *
6  * See the included file LICENSE for details.
7  */
8
9 #include <string.h>
10
11 #include <libtu/minmax.h>
12 #include <libmainloop/defer.h>
13
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"
26
27
28 /*{{{ Generic stuff */
29
30
31 static WInfoWin *do_get_notifywin(WScreen *scr, Watch *watch, uint pos,
32                                   char *style)
33 {
34
35     WInfoWin *iw=(WInfoWin*)(watch->obj);
36     WFitParams fp;
37     
38     if(iw==NULL){
39         WMPlexAttachParams param=MPLEXATTACHPARAMS_INIT;
40         
41         param.flags=(MPLEX_ATTACH_UNNUMBERED|
42                      MPLEX_ATTACH_SIZEPOLICY|
43                      MPLEX_ATTACH_GEOM|
44                      MPLEX_ATTACH_LEVEL);
45         param.level=STACKING_LEVEL_ON_TOP;
46         
47         param.geom.x=0;
48         param.geom.y=0;
49         param.geom.w=1;
50         param.geom.h=1;
51         
52         switch(pos){
53         case MPLEX_STDISP_TL:
54             param.szplcy=SIZEPOLICY_GRAVITY_NORTHWEST;
55             param.geom.x=0;
56             break;
57             
58         case MPLEX_STDISP_TR:
59             param.szplcy=SIZEPOLICY_GRAVITY_NORTHEAST;
60             param.geom.x=REGION_GEOM(scr).w-1;
61             break;
62             
63         case MPLEX_STDISP_BL:
64             param.szplcy=SIZEPOLICY_GRAVITY_SOUTHWEST;
65             param.geom.x=0;
66             param.geom.y=REGION_GEOM(scr).h-1;
67             break;
68             
69         case MPLEX_STDISP_BR:
70             param.szplcy=SIZEPOLICY_GRAVITY_SOUTHEAST;
71             param.geom.x=REGION_GEOM(scr).w-1;
72             param.geom.y=REGION_GEOM(scr).h-1;
73             break;
74         }
75         
76
77         iw=(WInfoWin*)mplex_do_attach_new(&scr->mplex, &param,
78                                           (WRegionCreateFn*)create_infowin, 
79                                           style);
80         
81         if(iw!=NULL)
82             watch_setup(watch, (Obj*)iw, NULL);
83     }
84     
85     return iw;
86 }
87
88
89 static void do_unnotify(Watch *watch)
90 {    
91     Obj *iw=watch->obj;
92     if(iw!=NULL){
93         watch_reset(watch);
94         mainloop_defer_destroy((Obj*)iw);
95     }
96 }
97
98
99 /*}}}*/
100
101
102 /*{{{ Notifywin */
103
104
105 static WInfoWin *get_notifywin(WScreen *scr)
106 {
107     WRegion *stdisp=NULL;
108     WMPlexSTDispInfo info;
109     uint pos=MPLEX_STDISP_TL;
110     
111     mplex_get_stdisp(&scr->mplex, &stdisp, &info);
112     if(stdisp!=NULL)
113         pos=info.pos;
114     
115     return do_get_notifywin(scr, &scr->notifywin_watch, pos, "actnotify");
116 }
117
118
119 void screen_notify(WScreen *scr, const char *str)
120 {
121     WInfoWin *iw=get_notifywin(scr);
122     
123     if(iw!=NULL){
124         int maxw=REGION_GEOM(scr).w/3;
125         infowin_set_text(iw, str, maxw);
126     }
127 }
128
129
130 void screen_unnotify(WScreen *scr)
131 {
132     do_unnotify(&scr->notifywin_watch);
133 }
134
135
136 static bool ws_mapped(WScreen *scr, WRegion *reg)
137 {
138     while(1){
139         WRegion *mgr=REGION_MANAGER(reg);
140         
141         if(mgr==NULL)
142             return FALSE;
143         
144         if(mgr==(WRegion*)scr)
145             return REGION_IS_MAPPED(reg);
146         
147         reg=mgr;
148     }
149 }
150
151
152 static void screen_managed_activity(WScreen *scr)
153 {
154     char *notstr=NULL;
155     WRegion *reg;
156     ObjListIterTmp tmp;
157     PtrListIterTmp tmp2;
158     ObjList *actlist=ioncore_activity_list();
159     WInfoWin *iw=NULL;
160     PtrList *found=NULL;
161     int nfound=0, nadded=0;
162     int w=0, maxw=REGION_GEOM(scr).w/4;
163     
164     /* Lisäksi minimipituus (10ex tms.), ja sen yli menevät jätetään
165      * pois (+ n) 
166      */
167     FOR_ALL_ON_OBJLIST(WRegion*, reg, actlist, tmp){
168         if(region_screen_of(reg)!=scr || ws_mapped(scr, reg))
169             continue;
170         if(region_name(reg)==NULL)
171             continue;
172         if(ptrlist_insert_last(&found, reg))
173             nfound++;
174     }
175     
176     if(found==NULL)
177         goto unnotify;
178     
179     iw=get_notifywin(scr);
180     
181     if(iw==NULL)
182         return;
183         
184     if(iw->brush==NULL)
185         goto unnotify;
186     
187     notstr=scopy(TR("act: "));
188     
189     if(notstr==NULL)
190         goto unnotify;
191     
192     FOR_ALL_ON_PTRLIST(WRegion*, reg, found, tmp2){
193         const char *nm=region_name(reg);
194         char *nstr=NULL, *label=NULL;
195         
196         w=grbrush_get_text_width(iw->brush, notstr, strlen(notstr));
197
198         if(w>=maxw)
199             break;
200         
201         label=grbrush_make_label(iw->brush, nm, maxw-w);
202         if(label!=NULL){
203             nstr=(nadded>0
204                   ? scat3(notstr, ", ", label)
205                   : scat(notstr, label));
206             
207             if(nstr!=NULL){
208                 free(notstr);
209                 notstr=nstr;
210                 nadded++;
211             }
212             free(label);
213         }
214     }
215     
216     if(nfound > nadded){
217         char *nstr=NULL;
218         
219         libtu_asprintf(&nstr, "%s  +%d", notstr, nfound-nadded);
220         
221         if(nstr!=NULL){
222             free(notstr);
223             notstr=nstr;
224         }
225     }
226     
227     ptrlist_clear(&found);
228     
229     infowin_set_text(iw, notstr, 0);
230     
231     free(notstr);
232     
233     return;
234
235 unnotify:    
236     screen_unnotify(scr);
237 }
238
239
240 static void screen_do_update_notifywin(WScreen *scr)
241 {
242     if(ioncore_g.screen_notify)
243         screen_managed_activity(scr);
244     else
245         screen_unnotify(scr);
246 }
247
248
249 /*}}}*/
250
251
252 /*{{{ Infowin */
253
254
255 static WInfoWin *get_infowin(WScreen *scr)
256 {
257     WRegion *stdisp=NULL;
258     WMPlexSTDispInfo info;
259     uint pos=MPLEX_STDISP_TR;
260     
261     mplex_get_stdisp(&scr->mplex, &stdisp, &info);
262     if(stdisp!=NULL && info.pos==MPLEX_STDISP_TR)
263         pos=MPLEX_STDISP_BR;
264     
265     return do_get_notifywin(scr, &scr->infowin_watch, pos, "tab-info");
266 }
267
268
269 void screen_windowinfo(WScreen *scr, const char *str)
270 {
271     WInfoWin *iw=get_infowin(scr);
272     
273     if(iw!=NULL){
274         int maxw=REGION_GEOM(scr).w/3;
275         infowin_set_text(iw, str, maxw);
276     }
277 }
278
279
280 void screen_nowindowinfo(WScreen *scr)
281 {
282     do_unnotify(&scr->infowin_watch);
283 }
284
285
286 GR_DEFATTR(active);
287 GR_DEFATTR(inactive);
288 GR_DEFATTR(selected);
289 GR_DEFATTR(tagged);
290 GR_DEFATTR(not_tagged);
291 GR_DEFATTR(not_dragged);
292 GR_DEFATTR(activity);
293 GR_DEFATTR(no_activity);
294
295
296 static void init_attr()
297 {
298     GR_ALLOCATTR_BEGIN;
299     GR_ALLOCATTR(active);
300     GR_ALLOCATTR(inactive);
301     GR_ALLOCATTR(selected);
302     GR_ALLOCATTR(tagged);
303     GR_ALLOCATTR(not_tagged);
304     GR_ALLOCATTR(not_dragged);
305     GR_ALLOCATTR(no_activity);
306     GR_ALLOCATTR(activity);
307     GR_ALLOCATTR_END;
308 }
309
310
311 static void screen_do_update_infowin(WScreen *scr)
312 {
313     WRegion *reg=mplex_mx_current(&(scr->mplex));
314     bool tag=(reg!=NULL && region_is_tagged(reg));
315     bool act=(reg!=NULL && region_is_activity_r(reg) && !REGION_IS_ACTIVE(scr));
316     bool sac=REGION_IS_ACTIVE(scr);
317     
318     if(tag || act){
319         const char *n=region_displayname(reg);
320         WInfoWin *iw;
321                 
322         screen_windowinfo(scr, n);
323         
324         iw=(WInfoWin*)scr->infowin_watch.obj;
325         
326         if(iw!=NULL){
327             GrStyleSpec *spec=infowin_stylespec(iw);
328             
329             init_attr();
330             
331             gr_stylespec_unalloc(spec);
332             
333             gr_stylespec_set(spec, GR_ATTR(selected));
334             gr_stylespec_set(spec, GR_ATTR(not_dragged));
335             gr_stylespec_set(spec, sac ? GR_ATTR(active) : GR_ATTR(inactive));
336             gr_stylespec_set(spec, tag ? GR_ATTR(tagged) : GR_ATTR(not_tagged));
337             gr_stylespec_set(spec, act ? GR_ATTR(activity) : GR_ATTR(no_activity));
338         }
339             
340     }else{
341         screen_nowindowinfo(scr);
342     }
343 }
344
345
346
347 /*}}}*/
348
349
350 /*{{{ Notification callbacks and deferred updates*/
351
352
353 void screen_update_infowin(WScreen *scr)
354 {
355     mainloop_defer_action((Obj*)scr, 
356                           (WDeferredAction*)screen_do_update_infowin);
357 }
358
359
360 void screen_update_notifywin(WScreen *scr)
361 {
362     mainloop_defer_action((Obj*)scr, 
363                           (WDeferredAction*)screen_do_update_notifywin);
364 }
365
366
367 void screen_managed_notify(WScreen *scr, WRegion *reg, WRegionNotify how)
368 {
369     if(how==ioncore_g.notifies.tag)
370         screen_update_infowin(scr);
371 }
372
373
374 void ioncore_screen_activity_notify(WRegion *reg, WRegionNotify how)
375 {
376     if(how==ioncore_g.notifies.activity){
377         screen_update_notifywin(region_screen_of(reg));
378     }else if(how==ioncore_g.notifies.name){
379         if(region_is_activity(reg))
380             screen_update_notifywin(region_screen_of(reg));
381     }
382 }
383
384
385 /*}}}*/
386