Renamed package to ion1, and made it conflict with package 'ion'.
[ion1.git] / src / client.c
blobb430553e666ddeefa5f3aa11772141734b6c10c2
1 /*
2 * ion/client.c
4 * Copyright (c) Tuomo Valkonen 1999-2001.
5 * See the included file LICENSE for details.
6 */
8 #include <string.h>
9 #include <limits.h>
11 #include "common.h"
12 #include "client.h"
13 #include "sizehint.h"
14 #include "frame.h"
15 #include "clientwin.h"
16 #include "global.h"
17 #include "font.h"
18 #include "thingp.h"
19 #include "property.h"
20 #include "focus.h"
21 #include "draw.h"
22 #include "complete.h"
25 static void client_remove_child(WClient *client, WThing *thing);
27 static WThingFuntab client_funtab={
28 deinit_client,
29 client_remove_child
32 IMPLOBJ(WClient, WThing, &client_funtab)
35 /*{{{ Create/destroy */
38 static bool init_client(WClient *client)
40 LINK_ITEM(wglobal.client_list, client, g_client_next, g_client_prev);
41 client->label=NULL;
42 client->thing.flags|=WTHING_DESTREMPTY;
43 client->label_next=client;
44 client->label_prev=client;
45 client->label_inst=0;
46 return TRUE;
50 WClient *create_client(WScreen *scr)
52 CREATETHING_IMPL(WClient, client, scr, (p));
56 void deinit_client(WClient *client)
58 client_unuse_label(client);
59 UNLINK_ITEM(wglobal.client_list, client, g_client_next, g_client_prev);
60 if(client->label!=NULL)
61 free(client->label);
65 /*}}}*/
68 /*{{{ Add/remove clientwin */
71 void client_add_clientwin(WClient *client, WClientWin *cwin)
73 link_thing((WThing*)client, (WThing*)cwin);
75 if(FIRST_THING(client, WClientWin)==cwin)
76 client_use_label(client);
78 if(CLIENT_HAS_FRAME(client))
79 frame_add_clientwin(CLIENT_FRAME(client), client, cwin);
83 static void client_remove_child(WClient *client, WThing *thing)
85 WFrame *frame;
86 WClientWin *n;
88 if(!WTHING_IS(thing, WClientWin))
89 return;
91 frame=FIND_PARENT(client, WFrame);
93 if(frame==NULL || !IS_ACTIVE_FRAME(frame))
94 return;
96 if(frame->current_client!=client)
97 return;
99 unlink_thing(thing);
100 n=LAST_THING(client, WClientWin);
101 if(n!=NULL)
102 set_focus((WThing*)n);
106 /*}}}*/
109 /*{{{ Clientwin wrappers */
112 void hide_client(WClient *client)
114 WClientWin *cwin;
116 FOR_ALL_TYPED(client, cwin, WClientWin){
117 hide_clientwin(cwin);
122 void show_client(WClient *client)
124 WClientWin *cwin, *first;
126 FOR_ALL_TYPED(client, cwin, WClientWin){
127 show_clientwin(cwin);
132 void focus_client(WClient *client)
134 WClientWin *cwin=LAST_THING(client, WClientWin);
136 if(cwin!=NULL)
137 focus_clientwin(cwin);
141 void close_client(WClient *client)
143 WClientWin *cwin=LAST_THING(client, WClientWin);
145 if(cwin!=NULL)
146 close_clientwin(cwin);
150 void close_client_main(WClient *client)
152 WClientWin *cwin=FIRST_THING(client, WClientWin);
154 if(cwin!=NULL)
155 close_clientwin(cwin);
159 void kill_client(WClient *client)
161 WClientWin *cwin=FIRST_THING(client, WClientWin);
163 if(cwin!=NULL)
164 kill_clientwin(cwin);
168 /*}}}*/
171 /*{{{ Reparent/fit/reconf */
174 void reparent_client(WClient *client, Window win, int x, int y)
176 WClientWin *cwin;
178 FOR_ALL_TYPED(client, cwin, WClientWin){
179 reparent_clientwin(cwin, win, x, y);
184 void fit_client_frame(WClient *client, WFrame *frame)
186 WClientWin *cwin;
188 FOR_ALL_TYPED(client, cwin, WClientWin){
189 fit_clientwin_frame(cwin, frame);
194 void reparent_fit_client_frame(WClient *client, WFrame *frame)
196 WClientWin *cwin;
198 FOR_ALL_TYPED(client, cwin, WClientWin){
199 reparent_fit_clientwin_frame(cwin, frame);
204 void reconf_client_frame(WClient *client, WFrame *frame)
206 WClientWin *cwin;
208 FOR_ALL_TYPED(client, cwin, WClientWin){
209 reconf_clientwin_frame(cwin, frame);
214 /*}}}*/
217 /*{{{ Labels */
220 static char *untitled_label="<untitled>";
221 static char *empty_label="<empty>";
224 static const char *client_beg_label(WClient *client)
226 WClientWin *cwin=FIRST_THING(client, WClientWin);
228 if(cwin==NULL){
229 return empty_label;
230 }else{
231 if(cwin->name!=NULL)
232 return cwin->name;
233 /*else if(cwin->icon_name!=NULL)
234 return cwin->icon_name;*/
236 return untitled_label;
240 #define CLIENTNUM_TMPL "<%d>"
242 void client_make_label(WClient *client, int maxw)
244 const char *str=client_beg_label(client);
245 char tmp[16];
246 WGRData *grdata;
248 if(client->label_inst!=0)
249 sprintf(tmp, CLIENTNUM_TMPL, client->label_inst);
250 else
251 *tmp='\0';
253 if(client->label!=NULL)
254 free(client->label);
256 grdata=GRDATA_OF(client);
258 client->label=make_label(grdata->tab_font, str, tmp, maxw, NULL);
262 char *client_full_label(WClient *client)
264 const char *str=client_beg_label(client);
265 char tmp[16];
267 if(client->label_inst!=0){
268 sprintf(tmp, CLIENTNUM_TMPL, client->label_inst);
269 return scat(str, tmp);
270 }else{
271 return scopy(str);
276 static void use_label(WClient *client, const char *label)
278 WClient *p, *np, *minp=NULL;
279 int mininst=INT_MAX;
280 const char *str;
282 for(p=wglobal.client_list; p!=NULL; p=p->g_client_next){
283 if(p==client)
284 continue;
285 str=client_beg_label(p);
286 if(strcmp(str, label)==0)
287 break;
290 if(p==NULL)
291 return;
293 for(; ; p=np){
294 assert(p!=client);
295 np=p->label_next;
296 if(p->label_inst+1==np->label_inst){
297 continue;
298 }else if(p->label_inst>=np->label_inst && np->label_inst!=0){
299 mininst=0;
300 minp=p;
301 }else if(p->label_inst+1<mininst){
302 mininst=p->label_inst+1;
303 minp=p;
304 continue;
306 break;
309 assert(minp!=NULL);
311 np=minp->label_next;
312 client->label_next=np;
313 np->label_prev=client;
314 minp->label_next=client;
315 client->label_prev=minp;
316 client->label_inst=mininst;
320 void client_use_label(WClient *client)
322 WFrame *frame;
323 const char *p=client_beg_label(client);
325 use_label(client, p);
327 frame=FIND_PARENT(client, WFrame);
329 if(frame!=NULL)
330 frame_recalc_bar(frame);
334 void client_unuse_label(WClient *client)
336 client->label_next->label_prev=client->label_prev;
337 client->label_prev->label_next=client->label_next;
338 client->label_next=client;
339 client->label_prev=client;
340 client->label_inst=0;
344 /*}}}*/
347 /*{{{ Misc. */
350 void client_toggle_tagged(WClient *client)
352 /* ad hoc */
353 client->flags^=CLIENT_TAGGED;
355 if(CLIENT_HAS_FRAME(client))
356 draw_frame_bar(CLIENT_FRAME(client), FALSE);
360 void clear_tags()
362 WClient *client;
364 for(client=wglobal.client_list; client!=NULL; client=client->g_client_next){
365 if(!(client->flags&CLIENT_TAGGED))
366 continue;
367 client->flags&=~CLIENT_TAGGED;
368 if(CLIENT_HAS_FRAME(client))
369 draw_frame_bar(CLIENT_FRAME(client), FALSE);
374 void set_client_frame_id(WClient *client, int id)
376 WClientWin *cwin=FIRST_THING(client, WClientWin);
377 if(cwin!=NULL)
378 set_integer_property(cwin->win, wglobal.atom_frame_id, id);
382 bool goto_window(WWindow *wwin)
384 WWorkspace *ws;
386 if(wglobal.current_wswindow==wwin)
387 return FALSE;
389 ws=FIND_PARENT(wwin, WWorkspace);
391 if(ws==NULL)
392 return FALSE;
394 set_previous((WThing*)wwin);
395 protect_previous();
397 if(!active_workspace(ws))
398 switch_workspace(ws);
400 warp(wwin);
402 unprotect_previous();
404 return TRUE;
408 void goto_client(WClient *client)
410 WFrame *frame=FIND_PARENT(client, WFrame);
412 if(frame==NULL)
413 return;
415 set_previous((WThing*)client);
416 protect_previous();
418 goto_window((WWindow*)frame);
420 if(frame->current_client!=client)
421 frame_switch_client(frame, client);
423 unprotect_previous();
427 void goto_previous()
429 WThing *t=wglobal.previous;
431 if(t==NULL)
432 return;
434 if(WTHING_IS(t, WClient))
435 goto_client((WClient*)t);
436 else if(WTHING_IS(t, WWindow))
437 goto_window((WWindow*)t);
440 bool goto_client_name(const char *cname)
442 WClient *client=lookup_client(cname);
444 if(client==NULL)
445 return FALSE;
447 goto_client(client);
449 return TRUE;
452 /*}}}*/
455 /*{{{ Lookup */
458 WClient *lookup_client(const char *cname)
460 WClient *client;
461 char *name;
463 for(client=wglobal.client_list;
464 client!=NULL;
465 client=client->g_client_next){
467 name=client_full_label(client);
468 if(name==NULL)
469 continue;
471 if(strcmp(name, cname)){
472 free(name);
473 continue;
476 free(name);
478 return client;
481 return NULL;
485 int complete_client(char *nam, char ***cp_ret, char **beg)
487 WClient *client;
488 char *name;
489 char **cp;
490 int n=0, l=strlen(nam);
491 int lnum=0;
493 *cp_ret=NULL;
495 again:
497 for(client=wglobal.client_list;
498 client!=NULL;
499 client=client->g_client_next){
501 name=(char*)client_full_label(client);
502 if(name==NULL)
503 continue;
505 if((lnum==0 && l && strncmp(name, nam, l)) ||
506 (strstr(name, nam)==NULL)){
507 free(name);
508 continue;
511 if(!add_to_complist(cp_ret, &n, name))
512 free(name);
515 if(n==0 && lnum==0 && l>1){
516 lnum=1;
517 goto again;
520 return n;
524 /*}}}*/