First titlebar support

This commit is contained in:
Julien Danjou 2008-03-14 14:27:56 +01:00
parent 46ebf25fbb
commit ea88e324a0
10 changed files with 201 additions and 71 deletions

View File

@ -44,6 +44,8 @@ general
^^^^^^^
General is a section containing some general options for this screen.
titlebar::
This option defines the position of window titlebar.
border::
This defines the window borders size in pixel.
font::

202
client.c
View File

@ -132,6 +132,39 @@ client_get_byname(Client *list, char *name)
return NULL;
}
static void
client_updatetitlebar(Client *c)
{
DrawCtx *ctx;
int phys_screen;
style_t style;
area_t geometry;
if(!c->titlebar)
return;
phys_screen = get_phys_screen(c->screen);
ctx = draw_context_new(globalconf.display, phys_screen,
c->titlebar->geometry.width,
c->titlebar->geometry.height,
c->titlebar->drawable);
style = globalconf.focus->client == c ?
globalconf.screens[c->screen].styles.focus :
globalconf.screens[c->screen].styles.normal;
geometry = c->titlebar->geometry;
geometry.x = geometry.y = 0;
draw_text(ctx, geometry, AlignCenter, 0,
c->name, style);
simplewindow_refresh_drawable(c->titlebar, phys_screen);
draw_context_delete(ctx);
}
/** Update client name attribute with its title
* \param c the client
*/
@ -143,6 +176,8 @@ client_updatetitle(Client *c)
xgettextprop(globalconf.display, c->win,
XInternAtom(globalconf.display, "WM_NAME", False), c->name, sizeof(c->name));
client_updatetitlebar(c);
widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
}
@ -151,10 +186,11 @@ client_unfocus(Client *c)
{
if(globalconf.screens[c->screen].opacity_unfocused != -1)
window_settrans(c->win, globalconf.screens[c->screen].opacity_unfocused);
focus_add_client(NULL);
XSetWindowBorder(globalconf.display, c->win,
globalconf.screens[c->screen].styles.normal.border.pixel);
widget_invalidate_cache(c->screen, WIDGET_CACHE_CLIENTS);
focus_add_client(NULL);
client_updatetitlebar(c);
}
/** Ban client and unmap it
@ -167,6 +203,8 @@ client_ban(Client *c)
client_unfocus(c);
XUnmapWindow(globalconf.display, c->win);
window_setstate(c->win, IconicState);
if(c->titlebar)
XUnmapWindow(globalconf.display, c->titlebar->window);
}
/** Give focus to client, or to first client if c is NULL
@ -201,13 +239,18 @@ client_focus(Client *c, int screen, Bool raise)
window_settrans(c->win, -1);
XSetWindowBorder(globalconf.display, c->win,
globalconf.screens[screen].styles.focus.border.pixel);
client_updatetitlebar(c);
XSetInputFocus(globalconf.display, c->win, RevertToPointerRoot, CurrentTime);
if(raise)
{
XWindowChanges wc;
Layout *curlay = layout_get_current(screen);
if(c->isfloating || curlay->arrange == layout_floating)
{
XRaiseWindow(globalconf.display, c->win);
if(c->titlebar)
XRaiseWindow(globalconf.display, c->titlebar->window);
}
else
{
Client *client;
@ -216,14 +259,32 @@ client_focus(Client *c, int screen, Bool raise)
for(client = globalconf.clients; client; client = client->next)
if(client != c && client_isvisible(client, c->screen) && client->isfloating)
{
if(client->titlebar)
{
XConfigureWindow(globalconf.display, client->titlebar->window,
CWSibling | CWStackMode, &wc);
wc.sibling = client->titlebar->window;
}
XConfigureWindow(globalconf.display, client->win, CWSibling | CWStackMode, &wc);
wc.sibling = client->win;
}
if(c->titlebar)
{
XConfigureWindow(globalconf.display, c->titlebar->window,
CWSibling | CWStackMode, &wc);
wc.sibling = c->titlebar->window;
}
XConfigureWindow(globalconf.display, c->win, CWSibling | CWStackMode, &wc);
wc.sibling = c->win;
for(client = globalconf.clients; client; client = client->next)
if(client != c && IS_TILED(client, c->screen))
{
if(client->titlebar)
{
XConfigureWindow(globalconf.display, client->titlebar->window,
CWSibling | CWStackMode, &wc);
wc.sibling = client->titlebar->window;
}
XConfigureWindow(globalconf.display, client->win, CWSibling | CWStackMode, &wc);
wc.sibling = client->win;
}
@ -257,7 +318,7 @@ client_manage(Window w, XWindowAttributes *wa, int screen)
Tag *tag;
Rule *rule;
area_t screen_geom;
int phys_screen = get_phys_screen(screen);
int phys_screen = get_phys_screen(screen), titlebar_height;
long flags;
c = p_new(Client, 1);
@ -286,6 +347,23 @@ client_manage(Window w, XWindowAttributes *wa, int screen)
/* propagates border_width, if size doesn't change */
window_configure(c->win, c->geometry, c->border);
switch(globalconf.screens[c->screen].titlebar)
{
case Top:
titlebar_height = 1.5 * MAX(globalconf.screens[c->screen].styles.normal.font->height,
MAX(globalconf.screens[c->screen].styles.focus.font->height,
globalconf.screens[c->screen].styles.urgent.font->height)),
c->titlebar = simplewindow_new(globalconf.display,
phys_screen,
c->geometry.x,
c->geometry.y - titlebar_height,
c->geometry.width,
titlebar_height,
0);
break;
default:
break;
}
/* update window title */
client_updatetitle(c);
@ -387,6 +465,53 @@ client_manage(Window w, XWindowAttributes *wa, int screen)
ewmh_update_net_client_list(phys_screen);
}
static area_t
client_geometry_sizehint(Client *c, area_t geometry)
{
double dx, dy, max, min, ratio;
if(c->minay > 0 && c->maxay > 0 && (geometry.height - c->baseh) > 0
&& (geometry.width - c->basew) > 0)
{
dx = (double) (geometry.width - c->basew);
dy = (double) (geometry.height - c->baseh);
min = (double) (c->minax) / (double) (c->minay);
max = (double) (c->maxax) / (double) (c->maxay);
ratio = dx / dy;
if(max > 0 && min > 0 && ratio > 0)
{
if(ratio < min)
{
dy = (dx * min + dy) / (min * min + 1);
dx = dy * min;
geometry.width = (int) dx + c->basew;
geometry.height = (int) dy + c->baseh;
}
else if(ratio > max)
{
dy = (dx * min + dy) / (max * max + 1);
dx = dy * min;
geometry.width = (int) dx + c->basew;
geometry.height = (int) dy + c->baseh;
}
}
}
if(c->minw && geometry.width < c->minw)
geometry.width = c->minw;
if(c->minh && geometry.height < c->minh)
geometry.height = c->minh;
if(c->maxw && geometry.width > c->maxw)
geometry.width = c->maxw;
if(c->maxh && geometry.height > c->maxh)
geometry.height = c->maxh;
if(c->incw)
geometry.width -= (geometry.width - c->basew) % c->incw;
if(c->inch)
geometry.height -= (geometry.height - c->baseh) % c->inch;
return geometry;
}
/** Resize client window
* \param c client to resize
* \param geometry new window geometry
@ -397,53 +522,21 @@ Bool
client_resize(Client *c, area_t geometry, Bool sizehints)
{
int new_screen;
double dx, dy, max, min, ratio;
area_t area;
XWindowChanges wc;
if(sizehints)
if(c->titlebar)
{
if(c->minay > 0 && c->maxay > 0 && (geometry.height - c->baseh) > 0
&& (geometry.width - c->basew) > 0)
{
dx = (double) (geometry.width - c->basew);
dy = (double) (geometry.height - c->baseh);
min = (double) (c->minax) / (double) (c->minay);
max = (double) (c->maxax) / (double) (c->maxay);
ratio = dx / dy;
if(max > 0 && min > 0 && ratio > 0)
{
if(ratio < min)
{
dy = (dx * min + dy) / (min * min + 1);
dx = dy * min;
geometry.width = (int) dx + c->basew;
geometry.height = (int) dy + c->baseh;
}
else if(ratio > max)
{
dy = (dx * min + dy) / (max * max + 1);
dx = dy * min;
geometry.width = (int) dx + c->basew;
geometry.height = (int) dy + c->baseh;
}
}
}
if(c->minw && geometry.width < c->minw)
geometry.width = c->minw;
if(c->minh && geometry.height < c->minh)
geometry.height = c->minh;
if(c->maxw && geometry.width > c->maxw)
geometry.width = c->maxw;
if(c->maxh && geometry.height > c->maxh)
geometry.height = c->maxh;
if(c->incw)
geometry.width -= (geometry.width - c->basew) % c->incw;
if(c->inch)
geometry.height -= (geometry.height - c->baseh) % c->inch;
geometry.y += c->titlebar->geometry.height;
geometry.height -= c->titlebar->geometry.height;
}
if(sizehints)
geometry = client_geometry_sizehint(c, geometry);
if(geometry.width <= 0 || geometry.height <= 0)
return False;
/* offscreen appearance fixes */
area = get_display_area(get_phys_screen(c->screen),
NULL,
@ -463,10 +556,22 @@ client_resize(Client *c, area_t geometry, Bool sizehints)
new_screen = screen_get_bycoord(globalconf.screens_info, c->screen, geometry.x, geometry.y);
c->geometry.x = wc.x = geometry.x;
c->geometry.y = wc.y = geometry.y;
c->geometry.width = wc.width = geometry.width;
c->geometry.y = wc.y = geometry.y;
c->geometry.height = wc.height = geometry.height;
wc.border_width = c->border;
if(c->titlebar)
{
simplewindow_move_resize(c->titlebar,
geometry.x,
geometry.y - c->titlebar->geometry.height,
geometry.width,
c->titlebar->geometry.height);
client_updatetitlebar(c);
c->geometry.y -= c->titlebar->geometry.height;
c->geometry.height += c->titlebar->geometry.height;
}
/* save the floating geometry if the window is floating but not
* maximized */
@ -474,8 +579,10 @@ client_resize(Client *c, area_t geometry, Bool sizehints)
layout_get_current(new_screen)->arrange == layout_floating) && !c->ismax)
c->f_geometry = geometry;
printf("moving client %s to %d\n", c->name, c->geometry.y);
XConfigureWindow(globalconf.display, c->win,
CWX | CWY | CWWidth | CWHeight | CWBorderWidth, &wc);
CWX | CWY | CWWidth | CWHeight, &wc);
window_configure(c->win, geometry, c->border);
if(c->screen != new_screen)
@ -547,6 +654,8 @@ client_unban(Client *c)
{
XMapWindow(globalconf.display, c->win);
window_setstate(c->win, NormalState);
if(c->titlebar)
XMapWindow(globalconf.display, c->titlebar->window);
}
void
@ -579,6 +688,9 @@ client_unmanage(Client *c)
XSync(globalconf.display, False);
XUngrabServer(globalconf.display);
if(c->titlebar)
simplewindow_delete(c->titlebar);
p_delete(&c);
}

View File

@ -70,6 +70,7 @@ cfg_awesome_include(cfg_t *cfg, cfg_opt_t *opt,
cfg_opt_t general_opts[] =
{
CFG_INT((char *) "border", 1, CFGF_NONE),
CFG_STR((char *) "titlebar", (char *) "off", CFGF_NONE),
CFG_INT((char *) "snap", 8, CFGF_NONE),
CFG_BOOL((char *) "resize_hints", cfg_true, CFGF_NONE),
CFG_BOOL((char *) "sloppy_focus", cfg_true, CFGF_NONE),

View File

@ -96,6 +96,20 @@ name_func_lookup(const char *funcname, const name_func_link_t *list)
return NULL;
}
Position
position_get_from_str(const char *pos)
{
if(!a_strncmp(pos, "top", 3))
return Top;
else if(!a_strncmp(pos, "bottom", 6))
return Bottom;
else if(!a_strncmp(pos, "right", 5))
return Right;
else if(!a_strncmp(pos, "left", 4))
return Left;
return Off;
}
/** \brief safe limited strcpy.
*
* Copies at most min(<tt>n-1</tt>, \c l) characters from \c src into \c dst,

View File

@ -26,6 +26,16 @@
#include <string.h>
#include <stdlib.h>
/** A list of possible position, not sex related */
typedef enum
{
Off = 0,
Top,
Bottom,
Right,
Left
} Position;
/** Link a name to a function */
typedef struct
{
@ -228,6 +238,7 @@ void _eprint(int, const char *, const char *, ...)
void _warn(int, const char *, const char *, ...)
__attribute__ ((format(printf, 3, 4)));
Position position_get_from_str(const char *);
double compute_new_value_from_arg(const char *, double);
void *name_func_lookup(const char *, const name_func_link_t *);

View File

@ -319,6 +319,7 @@ config_parse_screen(cfg_t *cfg, int screen)
virtscreen->floating_placement =
name_func_lookup(cfg_getstr(cfg_general, "floating_placement"),
FloatingPlacementList);
virtscreen->titlebar = position_get_from_str(cfg_getstr(cfg_general, "titlebar"));
virtscreen->mwfact_lower_limit = cfg_getfloat(cfg_general, "mwfact_lower_limit");
virtscreen->mwfact_upper_limit = cfg_getfloat(cfg_general, "mwfact_upper_limit");
@ -378,7 +379,7 @@ config_parse_screen(cfg_t *cfg, int screen)
statusbar = p_new(Statusbar, 1);
cfgsectmp = cfg_getnsec(cfg_screen, "statusbar", i);
statusbar->position = statusbar->dposition =
statusbar_get_position_from_str(cfg_getstr(cfgsectmp, "position"));
position_get_from_str(cfg_getstr(cfgsectmp, "position"));
statusbar->height = cfg_getint(cfgsectmp, "height");
statusbar->width = cfg_getint(cfgsectmp, "width");
statusbar->name = a_strdup(cfg_title(cfgsectmp));

10
event.c
View File

@ -289,8 +289,10 @@ event_handle_expose(XEvent *e)
XExposeEvent *ev = &e->xexpose;
int screen;
Statusbar *statusbar;
Client *c;
if(!ev->count)
{
for(screen = 0; screen < globalconf.screens_info->nscreen; screen++)
for(statusbar = globalconf.screens[screen].statusbar; statusbar; statusbar = statusbar->next)
if(statusbar->sw->window == ev->window)
@ -298,6 +300,14 @@ event_handle_expose(XEvent *e)
statusbar_display(statusbar);
return;
}
for(c = globalconf.clients; c; c = c->next)
if(c->titlebar && c->titlebar->window == ev->window)
{
simplewindow_refresh_drawable(c->titlebar, get_phys_screen(c->screen));
return;
}
}
}
/** Handle XKey events

View File

@ -244,20 +244,6 @@ statusbar_refresh()
}
}
Position
statusbar_get_position_from_str(const char *pos)
{
if(!a_strncmp(pos, "off", 3))
return Off;
else if(!a_strncmp(pos, "bottom", 6))
return Bottom;
else if(!a_strncmp(pos, "right", 5))
return Right;
else if(!a_strncmp(pos, "left", 4))
return Left;
return Top;
}
static Statusbar *
get_statusbar_byname(int screen, const char *name)
{

View File

@ -28,7 +28,6 @@ void statusbar_refresh(void);
void statusbar_preinit(Statusbar *);
void statusbar_init(Statusbar *);
void statusbar_display(Statusbar *);
Position statusbar_get_position_from_str(const char *);
Uicb uicb_statusbar_toggle;

View File

@ -28,16 +28,6 @@
#include "common/swindow.h"
#include "common/xscreen.h"
/** Bar possible position */
typedef enum
{
Top,
Bottom,
Left,
Right,
Off
} Position;
/** Rules for floating rule */
typedef enum
{
@ -200,6 +190,8 @@ struct Client
int screen;
/** True if the client is a new one */
Bool newcomer;
/** Titlebar */
SimpleWindow *titlebar;
};
typedef struct client_node_t client_node_t;
@ -260,6 +252,8 @@ typedef struct
typedef area_t (FloatingPlacement)(area_t, int, int);
typedef struct
{
/** Titlebar position */
Position titlebar;
/** Number of pixels to snap windows */
int snap;
/** Border size */