add a focus history

This commit is contained in:
Julien Danjou 2007-12-14 21:51:54 +01:00
parent c7c1da5693
commit df2a8e1b1d
12 changed files with 205 additions and 56 deletions

View File

@ -3,7 +3,7 @@
include config.mk
SRC = client.c draw.c event.c layout.c awesome.c tag.c util.c xutil.c config.c screen.c statusbar.c uicb.c window.c rules.c mouse.c awesome-client-common.c
SRC = focus.c client.c draw.c event.c layout.c awesome.c tag.c util.c xutil.c config.c screen.c statusbar.c uicb.c window.c rules.c mouse.c awesome-client-common.c
OBJ = ${SRC:.c=.o} ${LAYOUTS:.c=.o}
DOCS = awesome.1.txt awesome-client.1.txt

View File

@ -46,6 +46,7 @@
#include "uicb.h"
#include "window.h"
#include "client.h"
#include "focus.h"
#include "awesome-client.h"
static int (*xerrorxlib) (Display *, XErrorEvent *);
@ -339,6 +340,7 @@ main(int argc, char *argv[])
/* allocate stuff */
awesomeconf = p_new(awesome_config, 1);
awesomeconf->screens = p_new(VirtScreen, get_screen_count(dpy));
focus_add_client(&awesomeconf->focus, NULL);
/* store display */
awesomeconf->display = dpy;
parse_config(confpath, awesomeconf);

View File

@ -32,6 +32,7 @@
#include "xutil.h"
#include "statusbar.h"
#include "window.h"
#include "focus.h"
#include "layouts/floating.h"
/** Load windows properties, restoring client's tag
@ -195,24 +196,22 @@ client_detach(Client **head, Client *c)
void
focus(Client *c, Bool selscreen, awesome_config *awesomeconf, int screen)
{
Tag *tag, *curtag = get_current_tag(awesomeconf->screens[screen]);
/* unfocus current selected client */
if(awesomeconf->focus->client)
{
window_grabbuttons(awesomeconf->focus->client->display, awesomeconf->focus->client->phys_screen,
awesomeconf->focus->client->win, False, True, awesomeconf->buttons.root,
awesomeconf->buttons.client, awesomeconf->numlockmask);
XSetWindowBorder(awesomeconf->focus->client->display, awesomeconf->focus->client->win,
awesomeconf->screens[screen].colors_normal[ColBorder].pixel);
window_settrans(awesomeconf->focus->client->display, awesomeconf->focus->client->win,
awesomeconf->screens[screen].opacity_unfocused);
}
/* if c is NULL or invisible, take next client in the stack */
if((!c && selscreen) || (c && !client_isvisible(c, &awesomeconf->screens[screen], screen)))
for(c = awesomeconf->clients; c && !client_isvisible(c, &awesomeconf->screens[screen], screen); c = c->next);
/* XXX unfocus other tags clients, this is a bit too much */
for(tag = awesomeconf->screens[screen].tags; tag; tag = tag->next)
if(tag->client_sel)
{
window_grabbuttons(tag->client_sel->display, tag->client_sel->phys_screen,
tag->client_sel->win, False, True, awesomeconf->buttons.root,
awesomeconf->buttons.client, awesomeconf->numlockmask);
XSetWindowBorder(tag->client_sel->display, tag->client_sel->win,
awesomeconf->screens[screen].colors_normal[ColBorder].pixel);
window_settrans(tag->client_sel->display, tag->client_sel->win,
awesomeconf->screens[screen].opacity_unfocused);
}
if(c)
{
XSetWindowBorder(awesomeconf->display, c->win, awesomeconf->screens[screen].colors_selected[ColBorder].pixel);
@ -220,20 +219,29 @@ focus(Client *c, Bool selscreen, awesome_config *awesomeconf, int screen)
True, True, awesomeconf->buttons.root,
awesomeconf->buttons.client, awesomeconf->numlockmask);
}
if(!selscreen)
return;
curtag->client_sel = c;
/* save old sel in focus history */
focus_add_client(&awesomeconf->focus, c);
statusbar_draw(awesomeconf, screen);
if(curtag->client_sel)
if(awesomeconf->focus->client)
{
XSetInputFocus(curtag->client_sel->display, curtag->client_sel->win, RevertToPointerRoot, CurrentTime);
XSetInputFocus(awesomeconf->focus->client->display,
awesomeconf->focus->client->win, RevertToPointerRoot, CurrentTime);
for(c = awesomeconf->clients; c; c = c->next)
if(c != curtag->client_sel)
window_settrans(awesomeconf->display, curtag->client_sel->win, awesomeconf->screens[screen].opacity_unfocused);
window_settrans(awesomeconf->display, curtag->client_sel->win, -1);
if(c != awesomeconf->focus->client)
window_settrans(awesomeconf->display, awesomeconf->focus->client->win,
awesomeconf->screens[screen].opacity_unfocused);
window_settrans(awesomeconf->display, awesomeconf->focus->client->win, -1);
}
else
XSetInputFocus(awesomeconf->display, RootWindow(awesomeconf->display, get_phys_screen(awesomeconf->display, screen)), RevertToPointerRoot, CurrentTime);
XSetInputFocus(awesomeconf->display,
RootWindow(awesomeconf->display, get_phys_screen(awesomeconf->display, screen)),
RevertToPointerRoot, CurrentTime);
}
/** Manage a new client
@ -486,8 +494,9 @@ client_unmanage(Client *c, long state, awesome_config *awesomeconf)
XGrabServer(c->display);
XConfigureWindow(c->display, c->win, CWBorderWidth, &wc); /* restore border */
client_detach(&awesomeconf->clients, c);
if(get_current_tag(awesomeconf->screens[c->screen])->client_sel == c)
if(awesomeconf->focus->client == c)
focus(NULL, True, awesomeconf, c->screen);
focus_delete_client(&awesomeconf->focus, c);
for(tag = awesomeconf->screens[c->screen].tags; tag; tag = tag->next)
untag_client(&awesomeconf->screens[c->screen].tclink, c, tag);
XUngrabButton(c->display, AnyButton, AnyModifier, c->win);
@ -589,7 +598,7 @@ client_isvisible(Client *c, VirtScreen *scr, int screen)
*/
void
uicb_client_settrans(awesome_config *awesomeconf,
int screen,
int screen __attribute__ ((unused)),
const char *arg)
{
double delta = 100.0, current_opacity = 100.0;
@ -599,7 +608,7 @@ uicb_client_settrans(awesome_config *awesomeconf,
unsigned long n, left;
unsigned int current_opacity_raw = 0;
int set_prop = 0;
Client *sel = get_current_tag(awesomeconf->screens[screen])->client_sel;
Client *sel = awesomeconf->focus->client;
if(!sel)
return;
@ -656,7 +665,7 @@ uicb_client_swapnext(awesome_config *awesomeconf,
int screen,
const char *arg __attribute__ ((unused)))
{
Client *next, *sel = get_current_tag(awesomeconf->screens[screen])->client_sel;
Client *next, *sel = awesomeconf->focus->client;
if(!sel)
return;
@ -676,7 +685,7 @@ uicb_client_swapprev(awesome_config *awesomeconf,
int screen,
const char *arg __attribute__ ((unused)))
{
Client *prev, *sel = get_current_tag(awesomeconf->screens[screen])->client_sel;
Client *prev, *sel = awesomeconf->focus->client;
if(!sel)
return;
@ -701,7 +710,7 @@ uicb_client_moveresize(awesome_config *awesomeconf,
int mx, my, dx, dy, nmx, nmy;
unsigned int dui;
Window dummy;
Client *sel = get_current_tag(awesomeconf->screens[screen])->client_sel;
Client *sel = awesomeconf->focus->client;
if(get_current_layout(awesomeconf->screens[screen])->arrange != layout_floating)
if(!sel || !sel->isfloating || sel->isfixed || !arg)
@ -735,11 +744,11 @@ uicb_client_moveresize(awesome_config *awesomeconf,
*/
void
uicb_client_kill(awesome_config *awesomeconf,
int screen,
int screen __attribute__ ((unused)),
const char *arg __attribute__ ((unused)))
{
XEvent ev;
Client *sel = get_current_tag(awesomeconf->screens[screen])->client_sel;
Client *sel = awesomeconf->focus->client;
if(!sel)
return;

View File

@ -132,6 +132,13 @@ struct Client
int phys_screen;
};
typedef struct FocusList FocusList;
struct FocusList
{
Client *client;
FocusList *prev;
};
/** Tag type */
typedef struct Tag Tag;
struct Tag
@ -144,8 +151,6 @@ struct Tag
Bool was_selected;
/** Current tag layout */
Layout *layout;
/** Selected client on this tag */
Client *client_sel;
/** Master width factor */
double mwfact;
/** Number of master windows */
@ -243,6 +248,8 @@ struct awesome_config
Client *clients;
/** Path to config file */
char *configpath;
/** Selected clients on this tag */
FocusList *focus;
};
void parse_config(const char *, awesome_config *);

View File

@ -365,7 +365,7 @@ handle_event_propertynotify(XEvent * e, awesome_config *awesomeconf)
if(ev->atom == XA_WM_NAME || ev->atom == XInternAtom(c->display, "_NET_WM_NAME", False))
{
client_updatetitle(c);
if(c == get_current_tag(awesomeconf->screens[c->screen])->client_sel)
if(c == awesomeconf->focus->client)
statusbar_draw(awesomeconf, c->screen);
}
}

102
focus.c Normal file
View File

@ -0,0 +1,102 @@
/*
* focus.c - focus management
*
* Copyright © 2007 Julien Danjou <julien@danjou.info>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include "util.h"
#include "tag.h"
#include "focus.h"
static FocusList *
focus_get_node_by_client(FocusList *head, Client *c)
{
FocusList *fh;
for(fh = head; fh; fh = fh->prev)
if(fh->client == c)
return fh;
return NULL;
}
static FocusList *
focus_detach_node(FocusList **head, FocusList *fl)
{
FocusList *tmp;
if(*head == fl)
*head = fl->prev;
else
{
for(tmp = *head; tmp && tmp->prev != fl; tmp = tmp->prev);
tmp->prev = fl->prev;
}
return fl;
}
static FocusList *
focus_attach_node(FocusList **head, FocusList *fl)
{
FocusList *old_head;
old_head = *head;
*head = fl;
fl->prev = old_head;
return fl;
}
void
focus_add_client(FocusList **head, Client *c)
{
FocusList *new_fh;
/* if we don't find this node, create a new one */
if(!(new_fh = focus_get_node_by_client(*head, c)))
{
new_fh = p_new(FocusList, 1);
new_fh->client = c;
}
else /* if we've got a node, detach it */
focus_detach_node(head, new_fh);
focus_attach_node(head, new_fh);
}
void
focus_delete_client(FocusList **head, Client *c)
{
FocusList *target = focus_detach_node(head, focus_get_node_by_client(*head, c));
p_delete(&target);
}
Client *
focus_get_latest_client_for_tag(FocusList *head, TagClientLink *tc, Tag *t)
{
FocusList *fl;
for(fl = head; fl; fl = fl->prev)
if(is_client_tagged(tc, fl->client, t))
return fl->client;
return NULL;
}
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99

32
focus.h Normal file
View File

@ -0,0 +1,32 @@
/*
* focus.h - focus management header
*
* Copyright © 2007 Julien Danjou <julien@danjou.info>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#ifndef AWESOME_FOCUS_H
#define AWESOME_FOCUS_H
#include "config.h"
void focus_add_client(FocusList **, Client *);
void focus_delete_client(FocusList **, Client *);
Client * focus_get_latest_client_for_tag(FocusList *, TagClientLink *, Tag *);
#endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99

View File

@ -27,6 +27,7 @@
#include "tag.h"
#include "util.h"
#include "xutil.h"
#include "focus.h"
#include "statusbar.h"
#include "layouts/floating.h"
@ -66,7 +67,8 @@ arrange(awesome_config *awesomeconf, int screen)
}
curtag->layout->arrange(awesomeconf, screen);
focus(curtag->client_sel, True, awesomeconf, screen);
focus(focus_get_latest_client_for_tag(awesomeconf->focus, awesomeconf->screens[screen].tclink, curtag),
True, awesomeconf, screen);
restack(awesomeconf, screen);
}
@ -86,7 +88,7 @@ uicb_client_focusnext(awesome_config * awesomeconf,
int screen,
const char *arg __attribute__ ((unused)))
{
Client *c, *sel = get_current_tag(awesomeconf->screens[screen])->client_sel;
Client *c, *sel = awesomeconf->focus->client;
if(!sel)
return;
@ -105,7 +107,7 @@ uicb_client_focusprev(awesome_config *awesomeconf,
int screen,
const char *arg __attribute__ ((unused)))
{
Client *c, *sel = get_current_tag(awesomeconf->screens[screen])->client_sel;
Client *c, *sel = awesomeconf->focus->client;
if(!sel)
return;
@ -149,7 +151,7 @@ loadawesomeprops(awesome_config *awesomeconf, int screen)
void
restack(awesome_config *awesomeconf, int screen)
{
Client *c, *sel = get_current_tag(awesomeconf->screens[screen])->client_sel;
Client *c, *sel = awesomeconf->focus->client;
XEvent ev;
XWindowChanges wc;
@ -235,7 +237,7 @@ uicb_tag_setlayout(awesome_config * awesomeconf,
if(tag->selected)
tag->layout = l;
if(get_current_tag(awesomeconf->screens[screen])->client_sel)
if(awesomeconf->focus->client)
arrange(awesomeconf, screen);
else
statusbar_draw(awesomeconf, screen);
@ -246,7 +248,7 @@ uicb_tag_setlayout(awesome_config * awesomeconf,
static void
maximize(int x, int y, int w, int h, awesome_config *awesomeconf, int screen)
{
Client *sel = get_current_tag(awesomeconf->screens[screen])->client_sel;
Client *sel = awesomeconf->focus->client;
if(!sel)
return;
@ -284,7 +286,7 @@ uicb_client_toggleverticalmax(awesome_config *awesomeconf,
int screen,
const char *arg __attribute__ ((unused)))
{
Client *sel = get_current_tag(awesomeconf->screens[screen])->client_sel;
Client *sel = awesomeconf->focus->client;
ScreenInfo *si = get_screen_info(awesomeconf->display, screen, &awesomeconf->screens[screen].statusbar, &awesomeconf->screens[screen].padding);
if(sel)
@ -302,7 +304,7 @@ uicb_client_togglehorizontalmax(awesome_config *awesomeconf,
int screen,
const char *arg __attribute__ ((unused)))
{
Client *sel = get_current_tag(awesomeconf->screens[screen])->client_sel;
Client *sel = awesomeconf->focus->client;
ScreenInfo *si = get_screen_info(awesomeconf->display, screen, &awesomeconf->screens[screen].statusbar, &awesomeconf->screens[screen].padding);
if(sel)
@ -319,7 +321,7 @@ uicb_client_zoom(awesome_config *awesomeconf,
int screen,
const char *arg __attribute__ ((unused)))
{
Client *sel = get_current_tag(awesomeconf->screens[screen])->client_sel;
Client *sel = awesomeconf->focus->client;
if(awesomeconf->clients == sel)
for(sel = sel->next; sel && !client_isvisible(sel, &awesomeconf->screens[screen], screen); sel = sel->next);

View File

@ -36,7 +36,7 @@ uicb_client_movemouse(awesome_config *awesomeconf, int screen, const char *arg _
Window dummy;
XEvent ev;
ScreenInfo *si;
Client *c = get_current_tag(awesomeconf->screens[screen])->client_sel;
Client *c = awesomeconf->focus->client;
if(!c)
return;
@ -96,7 +96,7 @@ uicb_client_resizemouse(awesome_config *awesomeconf, int screen, const char *arg
{
int ocx, ocy, nw, nh;
XEvent ev;
Client *c = get_current_tag(awesomeconf->screens[screen])->client_sel;
Client *c = awesomeconf->focus->client;
if(!c)
return;

View File

@ -261,8 +261,7 @@ uicb_screen_focus(awesome_config *awesomeconf, int screen, const char *arg)
if (new_screen > (numscreens - 1))
new_screen = 0;
focus(get_current_tag(awesomeconf->screens[new_screen])->client_sel,
True, awesomeconf, new_screen);
focus(awesomeconf->focus->client, True, awesomeconf, new_screen);
move_mouse_pointer_to_screen(awesomeconf->display, new_screen);
}
@ -274,11 +273,11 @@ uicb_screen_focus(awesome_config *awesomeconf, int screen, const char *arg)
*/
void
uicb_client_movetoscreen(awesome_config * awesomeconf,
int screen,
int screen __attribute__ ((unused)),
const char *arg)
{
int new_screen, prev_screen;
Client *sel = get_current_tag(awesomeconf->screens[screen])->client_sel;
Client *sel = awesomeconf->focus->client;
if(!sel || !XineramaIsActive(awesomeconf->display))
return;

View File

@ -51,7 +51,7 @@ void
statusbar_draw(awesome_config *awesomeconf, int screen)
{
int z, x = 0, y = 0, w;
Client *sel = get_current_tag(awesomeconf->screens[screen])->client_sel;
Client *sel = awesomeconf->focus->client;
Drawable drawable;
int phys_screen = get_phys_screen(awesomeconf->display, screen);
Tag *tag;

10
tag.c
View File

@ -75,11 +75,7 @@ untag_client(TagClientLink **head, Client *c, Tag *t)
for(tc = *head; tc; tc = tc->next)
if(tc->client == c && tc->tag == t)
{
detach_tagclientlink(head, tc);
if(t->client_sel == c)
t->client_sel = NULL;
}
}
Bool
@ -144,7 +140,7 @@ uicb_client_tag(awesome_config *awesomeconf,
{
int tag_id = -1;
Tag *tag, *target_tag;
Client *sel = get_current_tag(awesomeconf->screens[screen])->client_sel;
Client *sel = awesomeconf->focus->client;
if(!sel)
return;
@ -181,7 +177,7 @@ uicb_client_togglefloating(awesome_config * awesomeconf,
int screen,
const char *arg __attribute__ ((unused)))
{
Client *sel = get_current_tag(awesomeconf->screens[screen])->client_sel;
Client *sel = awesomeconf->focus->client;
if(!sel)
return;
@ -206,7 +202,7 @@ uicb_client_toggletag(awesome_config *awesomeconf,
int screen,
const char *arg)
{
Client *sel = get_current_tag(awesomeconf->screens[screen])->client_sel;
Client *sel = awesomeconf->focus->client;
int i;
Tag *tag, *target_tag;