First titlebar support
This commit is contained in:
parent
46ebf25fbb
commit
ea88e324a0
|
@ -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
202
client.c
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 *);
|
||||
|
||||
|
|
3
config.c
3
config.c
|
@ -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
10
event.c
|
@ -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
|
||||
|
|
14
statusbar.c
14
statusbar.c
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
14
structs.h
14
structs.h
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue