wibox: get rid of simple window

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2009-07-28 16:04:58 +02:00
parent 367b3e03d5
commit 13efd8a199
14 changed files with 554 additions and 707 deletions

View File

@ -65,7 +65,6 @@ set(AWE_SRCS
${SOURCE_DIR}/image.c
${SOURCE_DIR}/draw.c
${SOURCE_DIR}/color.c
${SOURCE_DIR}/swindow.c
${SOURCE_DIR}/common/buffer.c
${SOURCE_DIR}/common/atoms.c
${SOURCE_DIR}/common/util.c

View File

@ -338,10 +338,10 @@ client_stack_above(client_t *c, xcb_window_t previous)
if(c->titlebar)
{
xcb_configure_window(globalconf.connection,
c->titlebar->sw.window,
c->titlebar->window,
XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE,
config_win_vals);
previous = c->titlebar->sw.window;
previous = c->titlebar->window;
}
else
previous = c->win;
@ -433,10 +433,10 @@ client_stack_refresh()
if(!sb->ontop)
{
xcb_configure_window(globalconf.connection,
sb->sw.window,
sb->window,
XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE,
config_win_vals);
config_win_vals[0] = sb->sw.window;
config_win_vals[0] = sb->window;
}
}
@ -454,10 +454,10 @@ client_stack_refresh()
if(sb->ontop)
{
xcb_configure_window(globalconf.connection,
sb->sw.window,
sb->window,
XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE,
config_win_vals);
config_win_vals[0] = sb->sw.window;
config_win_vals[0] = sb->window;
}
}
}

26
event.c
View File

@ -173,19 +173,19 @@ event_handle_button(void *data, xcb_connection_t *connection, xcb_button_press_e
{
/* If the wibox is child, then x,y are
* relative to root window */
if(wibox->sw.window == ev->child)
if(wibox->window == ev->child)
{
ev->event_x -= wibox->sw.geometry.x;
ev->event_y -= wibox->sw.geometry.y;
ev->event_x -= wibox->geometry.x;
ev->event_y -= wibox->geometry.y;
}
wibox_push(globalconf.L, wibox);
event_button_callback(ev, wibox->buttons, -1, 1, NULL);
/* then try to match a widget binding */
widget_t *w = widget_getbycoords(wibox->sw.orientation, &wibox->widgets,
wibox->sw.geometry.width,
wibox->sw.geometry.height,
widget_t *w = widget_getbycoords(wibox->orientation, &wibox->widgets,
wibox->geometry.width,
wibox->geometry.height,
&ev->event_x, &ev->event_y);
if(w)
{
@ -409,9 +409,9 @@ event_handle_motionnotify(void *data __attribute__ ((unused)),
if((wibox = wibox_getbywin(ev->event)))
{
widget_t *w = widget_getbycoords(wibox->sw.orientation, &wibox->widgets,
wibox->sw.geometry.width,
wibox->sw.geometry.height,
widget_t *w = widget_getbycoords(wibox->orientation, &wibox->widgets,
wibox->geometry.width,
wibox->geometry.height,
&ev->event_x, &ev->event_y);
if(w)
event_handle_widget_motionnotify(wibox, &wibox->mouse_over, w);
@ -485,9 +485,9 @@ event_handle_enternotify(void *data __attribute__ ((unused)),
if((wibox = wibox_getbywin(ev->event)))
{
widget_t *w = widget_getbycoords(wibox->sw.orientation, &wibox->widgets,
wibox->sw.geometry.width,
wibox->sw.geometry.height,
widget_t *w = widget_getbycoords(wibox->orientation, &wibox->widgets,
wibox->geometry.width,
wibox->geometry.height,
&ev->event_x, &ev->event_y);
if(w)
event_handle_widget_motionnotify(wibox, &wibox->mouse_over, w);
@ -558,7 +558,7 @@ event_handle_expose(void *data __attribute__ ((unused)),
wibox_t *wibox;
if((wibox = wibox_getbywin(ev->window)))
simplewindow_refresh_pixmap_partial(&wibox->sw,
wibox_refresh_pixmap_partial(wibox,
ev->x, ev->y,
ev->width, ev->height);

10
mouse.c
View File

@ -256,12 +256,12 @@ luaA_mouse_object_under_pointer(lua_State *L)
{
wibox_push(L, wibox);
int16_t x = mouse_x - wibox->sw.geometry.x;
int16_t y = mouse_y - wibox->sw.geometry.y;
int16_t x = mouse_x - wibox->geometry.x;
int16_t y = mouse_y - wibox->geometry.y;
widget_t *widget = widget_getbycoords(wibox->sw.orientation, &wibox->widgets,
wibox->sw.geometry.width,
wibox->sw.geometry.height,
widget_t *widget = widget_getbycoords(wibox->orientation, &wibox->widgets,
wibox->geometry.width,
wibox->geometry.height,
&x, &y);
if(widget)

View File

@ -468,7 +468,7 @@ property_handle_opacity(void *data __attribute__ ((unused)),
wibox_t *wibox = wibox_getbywin(window);
if (wibox)
wibox->sw.opacity = window_opacity_get_from_reply(reply);
wibox->opacity = window_opacity_get_from_reply(reply);
return 0;
}

389
swindow.c
View File

@ -1,389 +0,0 @@
/*
* swindow.c - simple window handling functions
*
* Copyright © 2008 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 <math.h>
#include <xcb/xcb.h>
#include <xcb/shape.h>
#include "structs.h"
#include "swindow.h"
#include "draw.h"
#include "common/xutil.h"
static int
have_shape(void)
{
const xcb_query_extension_reply_t *reply;
reply = xcb_get_extension_data(globalconf.connection, &xcb_shape_id);
if (!reply || !reply->present)
return 0;
/* We don't need a specific version of SHAPE, no version check required */
return 1;
}
static void
do_update_shape(xcb_window_t win, xcb_shape_kind_t kind, image_t *image, int offset)
{
xcb_pixmap_t shape;
if(image)
shape = image_to_1bit_pixmap(image, win);
else
/* Reset the shape */
shape = XCB_NONE;
xcb_shape_mask(globalconf.connection, XCB_SHAPE_SO_SET, kind,
win, offset, offset, shape);
if (shape != XCB_NONE)
xcb_free_pixmap(globalconf.connection, shape);
}
/** Update the window's shape.
* \param sw The simplw window whose shape should be updated.
*/
void
simplewindow_update_shape(simple_window_t *sw)
{
if(sw->window == XCB_NONE)
return;
if(!have_shape())
{
static bool warned = false;
if (!warned)
warn("The X server doesn't have the SHAPE extension; "
"can't change window's shape");
warned = true;
return;
}
do_update_shape(sw->window, XCB_SHAPE_SK_CLIP, sw->shape.clip, 0);
do_update_shape(sw->window, XCB_SHAPE_SK_BOUNDING, sw->shape.bounding, -sw->border.width);
}
static void
simplewindow_draw_context_update(simple_window_t *sw, xcb_screen_t *s)
{
xcolor_t fg = sw->ctx.fg, bg = sw->ctx.bg;
int phys_screen = sw->ctx.phys_screen;
draw_context_wipe(&sw->ctx);
/* update draw context */
switch(sw->orientation)
{
case South:
case North:
/* we need a new pixmap this way [ ] to render */
sw->ctx.pixmap = xcb_generate_id(globalconf.connection);
xcb_create_pixmap(globalconf.connection,
s->root_depth,
sw->ctx.pixmap, s->root,
sw->geometries.internal.height, sw->geometries.internal.width);
draw_context_init(&sw->ctx, phys_screen,
sw->geometries.internal.height, sw->geometries.internal.width,
sw->ctx.pixmap, &fg, &bg);
break;
case East:
draw_context_init(&sw->ctx, phys_screen,
sw->geometries.internal.width, sw->geometries.internal.height,
sw->pixmap, &fg, &bg);
break;
}
}
/** Initialize a simple window.
* \param sw The simple window to initialize.
* \param phys_screen Physical screen number.
* \param geometry Window geometry.
* \param border_width Window border width.
* \param border_color Window border color.
* \param orientation The rendering orientation.
* \param fg Default foreground color.
* \param bg Default background color.
*/
void
simplewindow_init(simple_window_t *sw,
int phys_screen,
area_t geometry,
uint16_t border_width,
const xcolor_t *border_color,
orientation_t orientation,
const xcolor_t *fg, const xcolor_t *bg)
{
xcb_screen_t *s = xutil_screen_get(globalconf.connection, phys_screen);
uint32_t create_win_val[4];
const uint32_t gc_mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND;
const uint32_t gc_values[2] = { s->black_pixel, s->white_pixel };
sw->geometry.x = geometry.x;
sw->geometry.y = geometry.y;
sw->geometry.width = geometry.width;
sw->geometry.height = geometry.height;
sw->border.width = border_width;
/* The real protocol window. */
sw->geometries.internal.x = geometry.x;
sw->geometries.internal.y = geometry.y;
sw->geometries.internal.width = geometry.width;
sw->geometries.internal.height = geometry.height;
sw->orientation = orientation;
sw->ctx.fg = *fg;
sw->ctx.bg = *bg;
sw->border.color = *border_color;
create_win_val[0] = XCB_BACK_PIXMAP_PARENT_RELATIVE;
create_win_val[1] = border_color->pixel;
create_win_val[2] = 1;
create_win_val[3] = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT
| XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_ENTER_WINDOW
| XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_STRUCTURE_NOTIFY
| XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE
| XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_EXPOSURE
| XCB_EVENT_MASK_PROPERTY_CHANGE;
sw->window = xcb_generate_id(globalconf.connection);
xcb_create_window(globalconf.connection, s->root_depth, sw->window, s->root,
sw->geometries.internal.x, sw->geometries.internal.y, sw->geometries.internal.width, sw->geometries.internal.height,
border_width, XCB_COPY_FROM_PARENT, s->root_visual,
XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK,
create_win_val);
sw->pixmap = xcb_generate_id(globalconf.connection);
xcb_create_pixmap(globalconf.connection, s->root_depth, sw->pixmap, s->root,
sw->geometries.internal.width, sw->geometries.internal.height);
sw->ctx.phys_screen = phys_screen;
simplewindow_draw_context_update(sw, s);
/* The default GC is just a newly created associated to the root window */
sw->gc = xcb_generate_id(globalconf.connection);
xcb_create_gc(globalconf.connection, sw->gc, s->root, gc_mask, gc_values);
simplewindow_update_shape(sw);
}
/** Destroy all resources of a simple window.
* \param sw The simple_window_t to wipe.
*/
void
simplewindow_wipe(simple_window_t *sw)
{
if(sw->window)
{
xcb_destroy_window(globalconf.connection, sw->window);
sw->window = XCB_NONE;
}
if(sw->pixmap)
{
xcb_free_pixmap(globalconf.connection, sw->pixmap);
sw->pixmap = XCB_NONE;
}
if(sw->gc)
{
xcb_free_gc(globalconf.connection, sw->gc);
sw->gc = XCB_NONE;
}
draw_context_wipe(&sw->ctx);
}
/** Move a simple window.
* \param sw The simple window to move.
* \param x New x coordinate.
* \param y New y coordinate.
*/
void
simplewindow_move(simple_window_t *sw, int x, int y)
{
const uint32_t move_win_vals[] = { x, y };
if(x != sw->geometries.internal.x || y != sw->geometries.internal.y)
{
sw->geometry.x = sw->geometries.internal.x = x;
sw->geometry.y = sw->geometries.internal.y = y;
xcb_configure_window(globalconf.connection, sw->window,
XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y,
move_win_vals);
}
}
/** Resize a simple window.
* \param sw The simple_window_t to resize.
* \param w New width.
* \param h New height.
*/
void
simplewindow_resize(simple_window_t *sw, int w, int h)
{
int iw = w - 2 * sw->border.width;
int ih = h - 2 * sw->border.width;
if(iw > 0 && ih > 0 &&
(sw->geometries.internal.width != iw || sw->geometries.internal.height != ih))
{
xcb_screen_t *s = xutil_screen_get(globalconf.connection, sw->ctx.phys_screen);
uint32_t resize_win_vals[2];
sw->geometries.internal.width = resize_win_vals[0] = iw;
sw->geometries.internal.height = resize_win_vals[1] = ih;
sw->geometry.width = w;
sw->geometry.height = h;
xcb_free_pixmap(globalconf.connection, sw->pixmap);
/* orientation != East */
if(sw->pixmap != sw->ctx.pixmap)
xcb_free_pixmap(globalconf.connection, sw->ctx.pixmap);
sw->pixmap = xcb_generate_id(globalconf.connection);
xcb_create_pixmap(globalconf.connection, s->root_depth, sw->pixmap, s->root, iw, ih);
xcb_configure_window(globalconf.connection, sw->window,
XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
resize_win_vals);
simplewindow_draw_context_update(sw, s);
}
}
/** Move and resize a window in one call.
* \param sw The simple window to move and resize.
* \param geom The new geometry.
*/
void
simplewindow_moveresize(simple_window_t *sw, area_t geom)
{
uint32_t moveresize_win_vals[4], mask_vals = 0;
xcb_screen_t *s = xutil_screen_get(globalconf.connection, sw->ctx.phys_screen);
area_t geom_internal = geom;
geom_internal.width -= 2 * sw->border.width;
geom_internal.height -= 2* sw->border.width;
if(sw->geometries.internal.x != geom_internal.x || sw->geometries.internal.y != geom_internal.y)
{
sw->geometries.internal.x = moveresize_win_vals[0] = geom_internal.x;
sw->geometries.internal.y = moveresize_win_vals[1] = geom_internal.y;
mask_vals |= XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y;
}
if(sw->geometry.width != geom.width || sw->geometry.height != geom.height)
{
if(mask_vals)
{
sw->geometries.internal.width = moveresize_win_vals[2] = geom_internal.width;
sw->geometries.internal.height = moveresize_win_vals[3] = geom_internal.height;
}
else
{
sw->geometries.internal.width = moveresize_win_vals[0] = geom_internal.width;
sw->geometries.internal.height = moveresize_win_vals[1] = geom_internal.height;
}
mask_vals |= XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
xcb_free_pixmap(globalconf.connection, sw->pixmap);
/* orientation != East */
if(sw->pixmap != sw->ctx.pixmap)
xcb_free_pixmap(globalconf.connection, sw->ctx.pixmap);
sw->pixmap = xcb_generate_id(globalconf.connection);
xcb_create_pixmap(globalconf.connection, s->root_depth, sw->pixmap, s->root, geom_internal.width, geom_internal.height);
simplewindow_draw_context_update(sw, s);
}
/* Also save geometry including border. */
sw->geometry = geom;
xcb_configure_window(globalconf.connection, sw->window, mask_vals, moveresize_win_vals);
}
/** Refresh the window content by copying its pixmap data to its window.
* \param sw The simple window to refresh.
* \param x The copy starting point x component.
* \param y The copy starting point y component.
* \param w The copy width from the x component.
* \param h The copy height from the y component.
*/
void
simplewindow_refresh_pixmap_partial(simple_window_t *sw,
int16_t x, int16_t y,
uint16_t w, uint16_t h)
{
xcb_copy_area(globalconf.connection, sw->pixmap,
sw->window, sw->gc, x, y, x, y,
w, h);
}
/** Set a simple window border width.
* \param sw The simple window to change border width.
* \param border_width The border width in pixel.
*/
void
simplewindow_border_width_set(simple_window_t *sw, uint32_t border_width)
{
xcb_configure_window(globalconf.connection, sw->window, XCB_CONFIG_WINDOW_BORDER_WIDTH,
&border_width);
sw->border.width = border_width;
}
/** Set a simple window border color.
* \param sw The simple window to change border width.
* \param color The border color.
*/
void
simplewindow_border_color_set(simple_window_t *sw, const xcolor_t *color)
{
xcb_change_window_attributes(globalconf.connection, sw->window,
XCB_CW_BORDER_PIXEL, &color->pixel);
sw->border.color = *color;
}
/** Set simple window orientation.
* \param sw The simple window.
* \param o The new orientation
*/
void
simplewindow_orientation_set(simple_window_t *sw, orientation_t o)
{
if(o != sw->orientation)
{
xcb_screen_t *s = xutil_screen_get(globalconf.connection, sw->ctx.phys_screen);
sw->orientation = o;
/* orientation != East */
if(sw->pixmap != sw->ctx.pixmap)
xcb_free_pixmap(globalconf.connection, sw->ctx.pixmap);
simplewindow_draw_context_update(sw, s);
}
}
/** Set simple window cursor.
* \param sw The simple window.
* \param c The cursor.
*/
void
simplewindow_cursor_set(simple_window_t *sw, xcb_cursor_t c)
{
if(sw->window)
{
const uint32_t change_win_vals[] = { c };
xcb_change_window_attributes(globalconf.connection, sw->window, XCB_CW_CURSOR, change_win_vals);
}
}
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

115
swindow.h
View File

@ -1,115 +0,0 @@
/*
* swindow.h - simple window handling functions header
*
* Copyright © 2008 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_SWINDOW_H
#define AWESOME_SWINDOW_H
#include "draw.h"
#include "window.h"
/** A simple window. */
typedef struct simple_window_t
{
/** The window object. */
xcb_window_t window;
/** The pixmap copied to the window object. */
xcb_pixmap_t pixmap;
/** The graphic context. */
xcb_gcontext_t gc;
/** The window geometry. */
area_t geometry;
struct
{
/** Internal geometry (matching X11 protocol) */
area_t internal;
} geometries;
/** The window border */
struct
{
/** The window border width */
uint16_t width;
/** The window border color */
xcolor_t color;
} border;
/** Draw context */
draw_context_t ctx;
/** Orientation */
orientation_t orientation;
/** Opacity */
double opacity;
/** The window's shape */
struct
{
/** The window's content */
image_t *clip;
/** The window's content and border */
image_t *bounding;
} shape;
} simple_window_t;
void simplewindow_init(simple_window_t *s,
int, area_t, uint16_t, const xcolor_t *,
orientation_t, const xcolor_t *, const xcolor_t *);
void simplewindow_wipe(simple_window_t *);
void simplewindow_move(simple_window_t *, int, int);
void simplewindow_resize(simple_window_t *, int, int);
void simplewindow_moveresize(simple_window_t *, area_t);
void simplewindow_refresh_pixmap_partial(simple_window_t *, int16_t, int16_t, uint16_t, uint16_t);
void simplewindow_border_width_set(simple_window_t *, uint32_t);
void simplewindow_border_color_set(simple_window_t *, const xcolor_t *);
void simplewindow_orientation_set(simple_window_t *, orientation_t);
void simplewindow_cursor_set(simple_window_t *, xcb_cursor_t);
void simplewindow_update_shape(simple_window_t *);
/** Refresh the window content by copying its pixmap data to its window.
* \param sw The simple window to refresh.
*/
static inline void
simplewindow_refresh_pixmap(simple_window_t *sw)
{
simplewindow_refresh_pixmap_partial(sw, 0, 0, sw->geometry.width, sw->geometry.height);
}
/** Set a simplewindow's opacity.
* \param sw The window the adjust the opacity of.
* \param opacity A value between 0 and 1 which describes the opacity.
*/
static inline void
simplewindow_opacity_set(simple_window_t *sw, double opacity)
{
sw->opacity = opacity;
if(sw->window != XCB_NONE)
window_opacity_set(sw->window, opacity);
}
/** Get a simplewindow's opacity.
* \return The opacity as a value between 0 and 1, or -1 if unset.
*/
static inline double
simplewindow_opacity_get(simple_window_t *sw)
{
return sw->opacity;
}
#endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -49,7 +49,7 @@ client_t *
client_getbytitlebarwin(xcb_window_t win)
{
foreach(c, globalconf.clients)
if((*c)->titlebar && (*c)->titlebar->sw.window == win)
if((*c)->titlebar && (*c)->titlebar->window == win)
return *c;
return NULL;
@ -65,10 +65,9 @@ titlebar_ban(wibox_t *titlebar)
if(titlebar && !titlebar->isbanned)
{
client_t *c;
simple_window_t *sw = &titlebar->sw;
if(sw->window)
xcb_unmap_window(globalconf.connection, sw->window);
if(titlebar->window)
xcb_unmap_window(globalconf.connection, titlebar->window);
/* Remove titlebar geometry from client. */
if((c = client_getbytitlebar(titlebar)))
@ -90,10 +89,9 @@ titlebar_unban(wibox_t *titlebar)
if(titlebar && titlebar->isbanned)
{
client_t *c;
simple_window_t *sw = &titlebar->sw;
if(sw->window)
xcb_map_window(globalconf.connection, sw->window);
if(titlebar->window)
xcb_map_window(globalconf.connection, titlebar->window);
titlebar->isbanned = false;
@ -131,9 +129,9 @@ titlebar_geometry_compute(client_t *c, area_t geometry, area_t *res)
break;
}
res->x = geometry.x + x_offset;
res->y = geometry.y - c->titlebar->sw.geometry.height;
res->y = geometry.y - c->titlebar->geometry.height;
res->width = width;
res->height = c->titlebar->sw.geometry.height;
res->height = c->titlebar->geometry.height;
break;
case Bottom:
width = MAX(1, geometry.width);
@ -151,7 +149,7 @@ titlebar_geometry_compute(client_t *c, area_t geometry, area_t *res)
res->x = geometry.x + x_offset;
res->y = geometry.y + geometry.height;
res->width = width;
res->height = c->titlebar->sw.geometry.height;
res->height = c->titlebar->geometry.height;
break;
case Left:
height = MAX(1, geometry.height);
@ -166,9 +164,9 @@ titlebar_geometry_compute(client_t *c, area_t geometry, area_t *res)
y_offset = (geometry.height - height) / 2;
break;
}
res->x = geometry.x - c->titlebar->sw.geometry.width;
res->x = geometry.x - c->titlebar->geometry.width;
res->y = geometry.y + y_offset;
res->width = c->titlebar->sw.geometry.width;
res->width = c->titlebar->geometry.width;
res->height = height;
break;
case Right:
@ -186,7 +184,7 @@ titlebar_geometry_compute(client_t *c, area_t geometry, area_t *res)
}
res->x = geometry.x + geometry.width;
res->y = geometry.y + y_offset;
res->width = c->titlebar->sw.geometry.width;
res->width = c->titlebar->geometry.width;
res->height = height;
break;
}
@ -203,7 +201,7 @@ titlebar_client_detach(client_t *c)
{
/* Update client geometry to exclude the titlebar. */
c->geometry = titlebar_geometry_remove(c->titlebar, 0, c->geometry);
simplewindow_wipe(&c->titlebar->sw);
wibox_wipe(c->titlebar);
c->titlebar->type = WIBOX_TYPE_NORMAL;
c->titlebar->screen = NULL;
@ -242,13 +240,13 @@ titlebar_client_attach(client_t *c)
{
case Top:
case Bottom:
if(!t->sw.geometry.height)
t->sw.geometry.height = 1.5 * globalconf.font->height;
if(!t->geometry.height)
t->geometry.height = 1.5 * globalconf.font->height;
break;
case Left:
case Right:
if(!t->sw.geometry.width)
t->sw.geometry.width = 1.5 * globalconf.font->height;
if(!t->geometry.width)
t->geometry.width = 1.5 * globalconf.font->height;
break;
}
@ -256,12 +254,9 @@ titlebar_client_attach(client_t *c)
c->geometry = titlebar_geometry_add(c->titlebar, 0, c->geometry);
/* Client geometry without titlebar, but including borders, since that is always consistent. */
area_t wingeom;
titlebar_geometry_compute(c, titlebar_geometry_remove(c->titlebar, 0, c->geometry), &wingeom);
titlebar_geometry_compute(c, titlebar_geometry_remove(c->titlebar, 0, c->geometry), &t->geometry);
simplewindow_init(&t->sw, c->phys_screen,
wingeom, 0, &t->sw.border.color,
t->sw.orientation, &t->sw.ctx.fg, &t->sw.ctx.bg);
wibox_init(t, c->phys_screen);
t->need_update = true;
@ -270,7 +265,7 @@ titlebar_client_attach(client_t *c)
* titlebar if needed. */
titlebar_update_geometry(c);
xcb_map_window(globalconf.connection, t->sw.window);
xcb_map_window(globalconf.connection, t->window);
hook_property(client, c, "titlebar");
client_stack();
@ -321,14 +316,14 @@ luaA_titlebar_newindex(lua_State *L, wibox_t *titlebar, awesome_token_t tok)
break;
case A_TK_BORDER_WIDTH:
if((i = luaL_checknumber(L, 3)) >= 0)
simplewindow_border_width_set(&titlebar->sw, i);
wibox_border_width_set(titlebar, i);
else
return 0;
break;
case A_TK_BORDER_COLOR:
if((buf = luaL_checklstring(L, 3, &len)))
if(xcolor_init_reply(xcolor_init_unchecked(&titlebar->sw.border.color, buf, len)))
simplewindow_border_color_set(&titlebar->sw, &titlebar->sw.border.color);
if(xcolor_init_reply(xcolor_init_unchecked(&titlebar->border.color, buf, len)))
wibox_border_color_set(titlebar, &titlebar->border.color);
return 0;
case A_TK_POSITION:
buf = luaL_checklstring(L, 3, &len);
@ -346,12 +341,12 @@ luaA_titlebar_newindex(lua_State *L, wibox_t *titlebar, awesome_token_t tok)
break;
case Top:
case Bottom:
tmp = titlebar->sw.geometry.width;
titlebar->sw.geometry.width = titlebar->sw.geometry.height;
titlebar->sw.geometry.height = tmp;
tmp = titlebar->geometry.width;
titlebar->geometry.width = titlebar->geometry.height;
titlebar->geometry.height = tmp;
break;
}
simplewindow_orientation_set(&titlebar->sw, North);
wibox_orientation_set(titlebar, North);
break;
case Right:
switch(titlebar->position)
@ -362,12 +357,12 @@ luaA_titlebar_newindex(lua_State *L, wibox_t *titlebar, awesome_token_t tok)
break;
case Top:
case Bottom:
tmp = titlebar->sw.geometry.width;
titlebar->sw.geometry.width = titlebar->sw.geometry.height;
titlebar->sw.geometry.height = tmp;
tmp = titlebar->geometry.width;
titlebar->geometry.width = titlebar->geometry.height;
titlebar->geometry.height = tmp;
break;
}
simplewindow_orientation_set(&titlebar->sw, South);
wibox_orientation_set(titlebar, South);
break;
case Top:
case Bottom:
@ -376,15 +371,15 @@ luaA_titlebar_newindex(lua_State *L, wibox_t *titlebar, awesome_token_t tok)
int tmp;
case Left:
case Right:
tmp = titlebar->sw.geometry.width;
titlebar->sw.geometry.width = titlebar->sw.geometry.height;
titlebar->sw.geometry.height = tmp;
tmp = titlebar->geometry.width;
titlebar->geometry.width = titlebar->geometry.height;
titlebar->geometry.height = tmp;
break;
case Top:
case Bottom:
break;
}
simplewindow_orientation_set(&titlebar->sw, East);
wibox_orientation_set(titlebar, East);
break;
}
titlebar->position = position;

View File

@ -69,18 +69,18 @@ titlebar_geometry_add(wibox_t *t, int border, area_t geometry)
switch(t->position)
{
case Top:
geometry.y -= t->sw.geometry.height;
geometry.height += t->sw.geometry.height;
geometry.y -= t->geometry.height;
geometry.height += t->geometry.height;
break;
case Bottom:
geometry.height += t->sw.geometry.height;
geometry.height += t->geometry.height;
break;
case Left:
geometry.x -= t->sw.geometry.width;
geometry.width += t->sw.geometry.width;
geometry.x -= t->geometry.width;
geometry.width += t->geometry.width;
break;
case Right:
geometry.width += t->sw.geometry.width;
geometry.width += t->geometry.width;
break;
default:
break;
@ -110,18 +110,18 @@ titlebar_geometry_remove(wibox_t *t, int border, area_t geometry)
switch(t->position)
{
case Top:
geometry.y += t->sw.geometry.height;
unsigned_subtract(geometry.height, t->sw.geometry.height);
geometry.y += t->geometry.height;
unsigned_subtract(geometry.height, t->geometry.height);
break;
case Bottom:
unsigned_subtract(geometry.height, t->sw.geometry.height);
unsigned_subtract(geometry.height, t->geometry.height);
break;
case Left:
geometry.x += t->sw.geometry.width;
unsigned_subtract(geometry.width, t->sw.geometry.width);
geometry.x += t->geometry.width;
unsigned_subtract(geometry.width, t->geometry.width);
break;
case Right:
unsigned_subtract(geometry.width, t->sw.geometry.width);
unsigned_subtract(geometry.width, t->geometry.width);
break;
default:
break;

503
wibox.c
View File

@ -1,7 +1,7 @@
/*
* wibox.c - wibox functions
*
* Copyright © 2008 Julien Danjou <julien@danjou.info>
* Copyright © 2008-2009 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
@ -19,6 +19,8 @@
*
*/
#include <xcb/shape.h>
#include "screen.h"
#include "wibox.h"
#include "titlebar.h"
@ -39,7 +41,7 @@ luaA_wibox_gc(lua_State *L)
{
wibox_t *wibox = luaL_checkudata(L, 1, "wibox");
p_delete(&wibox->cursor);
simplewindow_wipe(&wibox->sw);
wibox_wipe(wibox);
widget_node_array_wipe(&wibox->widgets);
return luaA_object_gc(L);
}
@ -50,6 +52,289 @@ wibox_unref_simplified(wibox_t **item)
wibox_unref(globalconf.L, *item);
}
static int
have_shape(void)
{
const xcb_query_extension_reply_t *reply;
reply = xcb_get_extension_data(globalconf.connection, &xcb_shape_id);
if (!reply || !reply->present)
return 0;
/* We don't need a specific version of SHAPE, no version check required */
return 1;
}
static void
shape_update(xcb_window_t win, xcb_shape_kind_t kind, image_t *image, int offset)
{
xcb_pixmap_t shape;
if(image)
shape = image_to_1bit_pixmap(image, win);
else
/* Reset the shape */
shape = XCB_NONE;
xcb_shape_mask(globalconf.connection, XCB_SHAPE_SO_SET, kind,
win, offset, offset, shape);
if (shape != XCB_NONE)
xcb_free_pixmap(globalconf.connection, shape);
}
/** Update the window's shape.
* \param wibox The simplw window whose shape should be updated.
*/
static void
wibox_shape_update(wibox_t *wibox)
{
if(wibox->window == XCB_NONE)
return;
if(!have_shape())
{
static bool warned = false;
if(!warned)
warn("The X server doesn't have the SHAPE extension; "
"can't change window's shape");
warned = true;
return;
}
shape_update(wibox->window, XCB_SHAPE_SK_CLIP, wibox->shape.clip, 0);
shape_update(wibox->window, XCB_SHAPE_SK_BOUNDING, wibox->shape.bounding, - wibox->border.width);
wibox->need_shape_update = false;
}
static void
wibox_draw_context_update(wibox_t *w, xcb_screen_t *s)
{
xcolor_t fg = w->ctx.fg, bg = w->ctx.bg;
int phys_screen = w->ctx.phys_screen;
draw_context_wipe(&w->ctx);
/* update draw context */
switch(w->orientation)
{
case South:
case North:
/* we need a new pixmap this way [ ] to render */
w->ctx.pixmap = xcb_generate_id(globalconf.connection);
xcb_create_pixmap(globalconf.connection,
s->root_depth,
w->ctx.pixmap, s->root,
w->geometries.internal.height, w->geometries.internal.width);
draw_context_init(&w->ctx, phys_screen,
w->geometries.internal.height, w->geometries.internal.width,
w->ctx.pixmap, &fg, &bg);
break;
case East:
draw_context_init(&w->ctx, phys_screen,
w->geometries.internal.width, w->geometries.internal.height,
w->pixmap, &fg, &bg);
break;
}
}
/** Initialize a wibox.
* \param w The wibox to initialize.
* \param phys_screen Physical screen number.
*/
void
wibox_init(wibox_t *w, int phys_screen)
{
xcb_screen_t *s = xutil_screen_get(globalconf.connection, phys_screen);
/* Copy the real protocol window geometry. */
w->geometries.internal.x = w->geometry.x;
w->geometries.internal.y = w->geometry.y;
w->geometries.internal.width = w->geometry.width;
w->geometries.internal.height = w->geometry.height;
w->window = xcb_generate_id(globalconf.connection);
xcb_create_window(globalconf.connection, s->root_depth, w->window, s->root,
w->geometries.internal.x, w->geometries.internal.y,
w->geometries.internal.width, w->geometries.internal.height,
w->border.width, XCB_COPY_FROM_PARENT, s->root_visual,
XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL
| XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK,
(const uint32_t [])
{
XCB_BACK_PIXMAP_PARENT_RELATIVE,
w->border.color.pixel,
1,
XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT
| XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_ENTER_WINDOW
| XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_STRUCTURE_NOTIFY
| XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE
| XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_EXPOSURE
| XCB_EVENT_MASK_PROPERTY_CHANGE
});
/* Create a pixmap. */
w->pixmap = xcb_generate_id(globalconf.connection);
xcb_create_pixmap(globalconf.connection, s->root_depth, w->pixmap, s->root,
w->geometries.internal.width, w->geometries.internal.height);
/* Update draw context physical screen, important for Zaphod. */
w->ctx.phys_screen = phys_screen;
wibox_draw_context_update(w, s);
/* The default GC is just a newly created associated to the root window */
w->gc = xcb_generate_id(globalconf.connection);
xcb_create_gc(globalconf.connection, w->gc, s->root, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND,
(const uint32_t[]) { s->black_pixel, s->white_pixel });
wibox_shape_update(w);
}
/** Refresh the window content by copying its pixmap data to its window.
* \param w The wibox to refresh.
*/
static inline void
wibox_refresh_pixmap(wibox_t *w)
{
wibox_refresh_pixmap_partial(w, 0, 0, w->geometry.width, w->geometry.height);
}
/** Set a wibox opacity.
* \param w The wibox the adjust the opacity of.
* \param opacity A value between 0 and 1 which describes the opacity.
*/
static inline void
wibox_opacity_set(wibox_t *w, double opacity)
{
w->opacity = opacity;
if(w->window != XCB_NONE)
window_opacity_set(w->window, opacity);
}
void
wibox_moveresize(wibox_t *w, area_t geometry)
{
if(w->window)
{
uint32_t moveresize_win_vals[4], mask_vals = 0;
xcb_screen_t *s = xutil_screen_get(globalconf.connection, w->ctx.phys_screen);
area_t geom_internal = geometry;
geom_internal.width -= 2 * w->border.width;
geom_internal.height -= 2* w->border.width;
if(w->geometries.internal.x != geom_internal.x || w->geometries.internal.y != geom_internal.y)
{
w->geometries.internal.x = moveresize_win_vals[0] = geom_internal.x;
w->geometries.internal.y = moveresize_win_vals[1] = geom_internal.y;
mask_vals |= XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y;
}
if(w->geometry.width != geometry.width || w->geometry.height != geometry.height)
{
if(mask_vals)
{
w->geometries.internal.width = moveresize_win_vals[2] = geom_internal.width;
w->geometries.internal.height = moveresize_win_vals[3] = geom_internal.height;
}
else
{
w->geometries.internal.width = moveresize_win_vals[0] = geom_internal.width;
w->geometries.internal.height = moveresize_win_vals[1] = geom_internal.height;
}
mask_vals |= XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
xcb_free_pixmap(globalconf.connection, w->pixmap);
/* orientation != East */
if(w->pixmap != w->ctx.pixmap)
xcb_free_pixmap(globalconf.connection, w->ctx.pixmap);
w->pixmap = xcb_generate_id(globalconf.connection);
xcb_create_pixmap(globalconf.connection, s->root_depth, w->pixmap, s->root, geom_internal.width, geom_internal.height);
wibox_draw_context_update(w, s);
}
/* Also save geometry including border. */
w->geometry = geometry;
xcb_configure_window(globalconf.connection, w->window, mask_vals, moveresize_win_vals);
}
else
w->geometry = geometry;
w->need_update = true;
}
/** Refresh the window content by copying its pixmap data to its window.
* \param wibox The wibox to refresh.
* \param x The copy starting point x component.
* \param y The copy starting point y component.
* \param w The copy width from the x component.
* \param h The copy height from the y component.
*/
void
wibox_refresh_pixmap_partial(wibox_t *wibox,
int16_t x, int16_t y,
uint16_t w, uint16_t h)
{
xcb_copy_area(globalconf.connection, wibox->pixmap,
wibox->window, wibox->gc, x, y, x, y,
w, h);
}
/** Set a wibox border width.
* \param w The wibox to change border width.
* \param border_width The border width in pixel.
*/
void
wibox_border_width_set(wibox_t *w, uint32_t border_width)
{
xcb_configure_window(globalconf.connection, w->window, XCB_CONFIG_WINDOW_BORDER_WIDTH,
&border_width);
w->border.width = border_width;
}
/** Set a wibox border color.
* \param w The wibox to change border width.
* \param color The border color.
*/
void
wibox_border_color_set(wibox_t *w, const xcolor_t *color)
{
xcb_change_window_attributes(globalconf.connection, w->window,
XCB_CW_BORDER_PIXEL, &color->pixel);
w->border.color = *color;
}
/** Set wibox orientation.
* \param w The wibox.
* \param o The new orientation.
*/
void
wibox_orientation_set(wibox_t *w, orientation_t o)
{
if(o != w->orientation)
{
xcb_screen_t *s = xutil_screen_get(globalconf.connection, w->ctx.phys_screen);
w->orientation = o;
/* orientation != East */
if(w->pixmap != w->ctx.pixmap)
xcb_free_pixmap(globalconf.connection, w->ctx.pixmap);
wibox_draw_context_update(w, s);
}
}
/** Set wibox cursor.
* \param w The wibox.
* \param c The cursor.
*/
static void
wibox_cursor_set(wibox_t *w, xcb_cursor_t c)
{
if(w->window)
xcb_change_window_attributes(globalconf.connection, w->window, XCB_CW_CURSOR,
(const uint32_t[]) { c });
}
static void
wibox_need_update(wibox_t *wibox)
{
@ -60,7 +345,7 @@ wibox_need_update(wibox_t *wibox)
static void
wibox_map(wibox_t *wibox)
{
xcb_map_window(globalconf.connection, wibox->sw.window);
xcb_map_window(globalconf.connection, wibox->window);
/* We must make sure the wibox does not display garbage */
wibox_need_update(wibox);
/* Stack this wibox correctly */
@ -70,32 +355,61 @@ wibox_map(wibox_t *wibox)
static void
wibox_move(wibox_t *wibox, int16_t x, int16_t y)
{
if(wibox->sw.window)
wibox->geometry.x = x;
wibox->geometry.y = y;
if(wibox->window
&& (x != wibox->geometries.internal.x || y != wibox->geometries.internal.y))
{
simplewindow_move(&wibox->sw, x, y);
wibox->geometry.x = wibox->geometries.internal.x = x;
wibox->geometry.y = wibox->geometries.internal.y = y;
xcb_configure_window(globalconf.connection, wibox->window,
XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y,
(const uint32_t[]) { x, y });
wibox->screen = screen_getbycoord(wibox->screen, x, y);
}
else
{
wibox->sw.geometry.x = x;
wibox->sw.geometry.y = y;
}
}
static void
wibox_resize(wibox_t *wibox, uint16_t width, uint16_t height)
wibox_resize(wibox_t *w, uint16_t width, uint16_t height)
{
if(wibox->sw.window)
simplewindow_resize(&wibox->sw, width, height);
if(w->window)
{
int iw = width - 2 * w->border.width;
int ih = height - 2 * w->border.width;
if(iw > 0 && ih > 0 &&
(w->geometries.internal.width != iw || w->geometries.internal.height != ih))
{
xcb_screen_t *s = xutil_screen_get(globalconf.connection, w->ctx.phys_screen);
uint32_t resize_win_vals[2];
w->geometries.internal.width = resize_win_vals[0] = iw;
w->geometries.internal.height = resize_win_vals[1] = ih;
w->geometry.width = width;
w->geometry.height = height;
xcb_free_pixmap(globalconf.connection, w->pixmap);
/* orientation != East */
if(w->pixmap != w->ctx.pixmap)
xcb_free_pixmap(globalconf.connection, w->ctx.pixmap);
w->pixmap = xcb_generate_id(globalconf.connection);
xcb_create_pixmap(globalconf.connection, s->root_depth, w->pixmap, s->root, iw, ih);
xcb_configure_window(globalconf.connection, w->window,
XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
resize_win_vals);
wibox_draw_context_update(w, s);
}
}
else
{
wibox->sw.geometry.width = width;
wibox->sw.geometry.height = height;
w->geometry.width = width;
w->geometry.height = height;
}
wibox_need_update(wibox);
wibox_need_update(w);
}
/** Kick out systray windows.
* \param phys_screen Physical screen number.
*/
@ -128,11 +442,11 @@ wibox_systray_refresh(wibox_t *wibox)
widget_node_t *systray = &wibox->widgets.tab[i];
if(systray->widget->type == widget_systray)
{
uint32_t config_back[] = { wibox->sw.ctx.bg.pixel };
uint32_t config_back[] = { wibox->ctx.bg.pixel };
uint32_t config_win_vals[4];
uint32_t config_win_vals_off[2] = { -512, -512 };
xembed_window_t *em;
int phys_screen = wibox->sw.ctx.phys_screen;
int phys_screen = wibox->ctx.phys_screen;
if(wibox->isvisible
&& systray->widget->isvisible
@ -145,11 +459,11 @@ wibox_systray_refresh(wibox_t *wibox)
/* Map it. */
xcb_map_window(globalconf.connection, globalconf.screens.tab[phys_screen].systray.window);
/* Move it. */
switch(wibox->sw.orientation)
switch(wibox->orientation)
{
case North:
config_win_vals[0] = systray->geometry.y;
config_win_vals[1] = wibox->sw.geometry.height - systray->geometry.x - systray->geometry.width;
config_win_vals[1] = wibox->geometry.height - systray->geometry.x - systray->geometry.width;
config_win_vals[2] = systray->geometry.height;
config_win_vals[3] = systray->geometry.width;
break;
@ -167,13 +481,13 @@ wibox_systray_refresh(wibox_t *wibox)
break;
}
/* reparent */
if(globalconf.screens.tab[phys_screen].systray.parent != wibox->sw.window)
if(globalconf.screens.tab[phys_screen].systray.parent != wibox->window)
{
xcb_reparent_window(globalconf.connection,
globalconf.screens.tab[phys_screen].systray.window,
wibox->sw.window,
wibox->window,
config_win_vals[0], config_win_vals[1]);
globalconf.screens.tab[phys_screen].systray.parent = wibox->sw.window;
globalconf.screens.tab[phys_screen].systray.parent = wibox->window;
}
xcb_configure_window(globalconf.connection,
globalconf.screens.tab[phys_screen].systray.window,
@ -189,7 +503,7 @@ wibox_systray_refresh(wibox_t *wibox)
else
return wibox_systray_kickout(phys_screen);
switch(wibox->sw.orientation)
switch(wibox->orientation)
{
case North:
config_win_vals[1] = systray->geometry.width - config_win_vals[3];
@ -198,7 +512,7 @@ wibox_systray_refresh(wibox_t *wibox)
em = &globalconf.embedded.tab[j];
if(em->phys_screen == phys_screen)
{
if(config_win_vals[1] - config_win_vals[2] >= (uint32_t) wibox->sw.geometry.y)
if(config_win_vals[1] - config_win_vals[2] >= (uint32_t) wibox->geometry.y)
{
xcb_map_window(globalconf.connection, em->win);
xcb_configure_window(globalconf.connection, em->win,
@ -225,7 +539,7 @@ wibox_systray_refresh(wibox_t *wibox)
if(em->phys_screen == phys_screen)
{
/* if(y + width <= wibox.y + systray.right) */
if(config_win_vals[1] + config_win_vals[3] <= (uint32_t) wibox->sw.geometry.y + AREA_RIGHT(systray->geometry))
if(config_win_vals[1] + config_win_vals[3] <= (uint32_t) wibox->geometry.y + AREA_RIGHT(systray->geometry))
{
xcb_map_window(globalconf.connection, em->win);
xcb_configure_window(globalconf.connection, em->win,
@ -252,7 +566,7 @@ wibox_systray_refresh(wibox_t *wibox)
if(em->phys_screen == phys_screen)
{
/* if(x + width < systray.x + systray.width) */
if(config_win_vals[0] + config_win_vals[2] <= (uint32_t) AREA_RIGHT(systray->geometry) + wibox->sw.geometry.x)
if(config_win_vals[0] + config_win_vals[2] <= (uint32_t) AREA_RIGHT(systray->geometry) + wibox->geometry.x)
{
xcb_map_window(globalconf.connection, em->win);
xcb_configure_window(globalconf.connection, em->win,
@ -285,13 +599,13 @@ wibox_t *
wibox_getbywin(xcb_window_t win)
{
foreach(w, globalconf.wiboxes)
if((*w)->sw.window == win)
if((*w)->window == win)
return *w;
foreach(_c, globalconf.clients)
{
client_t *c = *_c;
if(c->titlebar && c->titlebar->sw.window == win)
if(c->titlebar && c->titlebar->window == win)
return c->titlebar;
}
@ -307,7 +621,7 @@ wibox_draw(wibox_t *wibox)
if(wibox->isvisible)
{
widget_render(wibox);
simplewindow_refresh_pixmap(&wibox->sw);
wibox_refresh_pixmap(wibox);
wibox->need_update = false;
}
@ -323,10 +637,7 @@ wibox_refresh(void)
foreach(w, globalconf.wiboxes)
{
if((*w)->need_shape_update)
{
simplewindow_update_shape(&(*w)->sw);
(*w)->need_shape_update = false;
}
wibox_shape_update(*w);
if((*w)->need_update)
wibox_draw(*w);
}
@ -356,7 +667,7 @@ wibox_setvisible(wibox_t *wibox, bool v)
if(wibox->isvisible)
wibox_map(wibox);
else
xcb_unmap_window(globalconf.connection, wibox->sw.window);
xcb_unmap_window(globalconf.connection, wibox->window);
/* kick out systray if needed */
wibox_systray_refresh(wibox);
@ -366,6 +677,30 @@ wibox_setvisible(wibox_t *wibox, bool v)
}
}
/** Destroy all X resources of a wibox.
* \param w The wibox to wipe.
*/
void
wibox_wipe(wibox_t *w)
{
if(w->window)
{
xcb_destroy_window(globalconf.connection, w->window);
w->window = XCB_NONE;
}
if(w->pixmap)
{
xcb_free_pixmap(globalconf.connection, w->pixmap);
w->pixmap = XCB_NONE;
}
if(w->gc)
{
xcb_free_gc(globalconf.connection, w->gc);
w->gc = XCB_NONE;
}
draw_context_wipe(&w->ctx);
}
/** Remove a wibox from a screen.
* \param wibox Wibox to detach from screen.
*/
@ -385,7 +720,7 @@ wibox_detach(wibox_t *wibox)
wibox->mouse_over = NULL;
simplewindow_wipe(&wibox->sw);
wibox_wipe(wibox);
foreach(item, globalconf.wiboxes)
if(*item == wibox)
@ -419,7 +754,7 @@ wibox_attach(screen_t *s)
/* Check that the wibox coordinates matches the screen. */
screen_t *cscreen =
screen_getbycoord(wibox->screen, wibox->sw.geometry.x, wibox->sw.geometry.y);
screen_getbycoord(wibox->screen, wibox->geometry.x, wibox->geometry.y);
/* If it does not match, move it to the screen coordinates */
if(cscreen != wibox->screen)
@ -427,17 +762,12 @@ wibox_attach(screen_t *s)
wibox_array_append(&globalconf.wiboxes, wibox);
simplewindow_init(&wibox->sw, phys_screen,
wibox->sw.geometry,
wibox->sw.border.width,
&wibox->sw.border.color,
wibox->sw.orientation,
&wibox->sw.ctx.fg, &wibox->sw.ctx.bg);
wibox_init(wibox, phys_screen);
simplewindow_cursor_set(&wibox->sw,
wibox_cursor_set(wibox,
xcursor_new(globalconf.connection, xcursor_font_fromstr(wibox->cursor)));
simplewindow_opacity_set(&wibox->sw, wibox->sw.opacity);
wibox_opacity_set(wibox, wibox->opacity);
if(wibox->isvisible)
wibox_map(wibox);
@ -468,26 +798,26 @@ luaA_wibox_new(lua_State *L)
w = wibox_new(L);
w->sw.ctx.fg = globalconf.colors.fg;
w->ctx.fg = globalconf.colors.fg;
if((buf = luaA_getopt_lstring(L, 2, "fg", NULL, &len)))
reqs[++reqs_nbr] = xcolor_init_unchecked(&w->sw.ctx.fg, buf, len);
reqs[++reqs_nbr] = xcolor_init_unchecked(&w->ctx.fg, buf, len);
w->sw.ctx.bg = globalconf.colors.bg;
w->ctx.bg = globalconf.colors.bg;
if((buf = luaA_getopt_lstring(L, 2, "bg", NULL, &len)))
reqs[++reqs_nbr] = xcolor_init_unchecked(&w->sw.ctx.bg, buf, len);
reqs[++reqs_nbr] = xcolor_init_unchecked(&w->ctx.bg, buf, len);
w->sw.border.color = globalconf.colors.bg;
w->border.color = globalconf.colors.bg;
if((buf = luaA_getopt_lstring(L, 2, "border_color", NULL, &len)))
reqs[++reqs_nbr] = xcolor_init_unchecked(&w->sw.border.color, buf, len);
reqs[++reqs_nbr] = xcolor_init_unchecked(&w->border.color, buf, len);
w->ontop = luaA_getopt_boolean(L, 2, "ontop", false);
w->sw.opacity = -1;
w->sw.border.width = luaA_getopt_number(L, 2, "border_width", 0);
w->sw.geometry.x = luaA_getopt_number(L, 2, "x", 0);
w->sw.geometry.y = luaA_getopt_number(L, 2, "y", 0);
w->sw.geometry.width = luaA_getopt_number(L, 2, "width", 100);
w->sw.geometry.height = luaA_getopt_number(L, 2, "height", globalconf.font->height * 1.5);
w->opacity = -1;
w->border.width = luaA_getopt_number(L, 2, "border_width", 0);
w->geometry.x = luaA_getopt_number(L, 2, "x", 0);
w->geometry.y = luaA_getopt_number(L, 2, "y", 0);
w->geometry.width = luaA_getopt_number(L, 2, "width", 100);
w->geometry.height = luaA_getopt_number(L, 2, "height", globalconf.font->height * 1.5);
w->isvisible = true;
w->cursor = a_strdup("left_ptr");
@ -595,10 +925,10 @@ luaA_wibox_index(lua_State *L)
lua_pushnumber(L, screen_array_indexof(&globalconf.screens, wibox->screen) + 1);
break;
case A_TK_BORDER_WIDTH:
lua_pushnumber(L, wibox->sw.border.width);
lua_pushnumber(L, wibox->border.width);
break;
case A_TK_BORDER_COLOR:
luaA_pushxcolor(L, &wibox->sw.border.color);
luaA_pushxcolor(L, &wibox->border.color);
break;
case A_TK_ALIGN:
if(wibox->type == WIBOX_TYPE_NORMAL)
@ -606,10 +936,10 @@ luaA_wibox_index(lua_State *L)
lua_pushstring(L, draw_align_tostr(wibox->align));
break;
case A_TK_FG:
luaA_pushxcolor(L, &wibox->sw.ctx.fg);
luaA_pushxcolor(L, &wibox->ctx.fg);
break;
case A_TK_BG:
luaA_pushxcolor(L, &wibox->sw.ctx.bg);
luaA_pushxcolor(L, &wibox->ctx.bg);
break;
case A_TK_BG_IMAGE:
luaA_object_push_item(L, 1, wibox->bg_image);
@ -623,7 +953,7 @@ luaA_wibox_index(lua_State *L)
lua_pushboolean(L, wibox->ontop);
break;
case A_TK_ORIENTATION:
lua_pushstring(L, orientation_tostr(wibox->sw.orientation));
lua_pushstring(L, orientation_tostr(wibox->orientation));
break;
case A_TK_WIDGETS:
return luaA_object_push_item(L, 1, wibox->widgets_table);
@ -631,22 +961,19 @@ luaA_wibox_index(lua_State *L)
lua_pushstring(L, wibox->cursor);
break;
case A_TK_OPACITY:
{
double d = simplewindow_opacity_get(&wibox->sw);
if (d >= 0)
lua_pushnumber(L, d);
if (wibox->opacity >= 0)
lua_pushnumber(L, wibox->opacity);
else
return 0;
}
break;
case A_TK_MOUSE_ENTER:
return luaA_object_push_item(L, 1, wibox->mouse_enter);
case A_TK_MOUSE_LEAVE:
return luaA_object_push_item(L, 1, wibox->mouse_leave);
case A_TK_SHAPE_BOUNDING:
return luaA_object_push_item(L, 1, wibox->sw.shape.bounding);
return luaA_object_push_item(L, 1, wibox->shape.bounding);
case A_TK_SHAPE_CLIP:
return luaA_object_push_item(L, 1, wibox->sw.shape.clip);
return luaA_object_push_item(L, 1, wibox->shape.clip);
case A_TK_BUTTONS:
return luaA_object_push_item(L, 1, wibox->buttons);
default:
@ -673,10 +1000,10 @@ luaA_wibox_geometry(lua_State *L)
area_t wingeom;
luaA_checktable(L, 2);
wingeom.x = luaA_getopt_number(L, 2, "x", wibox->sw.geometry.x);
wingeom.y = luaA_getopt_number(L, 2, "y", wibox->sw.geometry.y);
wingeom.width = luaA_getopt_number(L, 2, "width", wibox->sw.geometry.width);
wingeom.height = luaA_getopt_number(L, 2, "height", wibox->sw.geometry.height);
wingeom.x = luaA_getopt_number(L, 2, "x", wibox->geometry.x);
wingeom.y = luaA_getopt_number(L, 2, "y", wibox->geometry.y);
wingeom.width = luaA_getopt_number(L, 2, "width", wibox->geometry.width);
wingeom.height = luaA_getopt_number(L, 2, "height", wibox->geometry.height);
switch(wibox->type)
{
@ -689,7 +1016,7 @@ luaA_wibox_geometry(lua_State *L)
}
}
return luaA_pusharea(L, wibox->sw.geometry);
return luaA_pusharea(L, wibox->geometry);
}
/** Wibox newindex.
@ -710,12 +1037,12 @@ luaA_wibox_newindex(lua_State *L)
case A_TK_FG:
if((buf = luaL_checklstring(L, 3, &len)))
if(xcolor_init_reply(xcolor_init_unchecked(&wibox->sw.ctx.fg, buf, len)))
if(xcolor_init_reply(xcolor_init_unchecked(&wibox->ctx.fg, buf, len)))
wibox->need_update = true;
break;
case A_TK_BG:
if((buf = luaL_checklstring(L, 3, &len)))
if(xcolor_init_reply(xcolor_init_unchecked(&wibox->sw.ctx.bg, buf, len)))
if(xcolor_init_reply(xcolor_init_unchecked(&wibox->ctx.bg, buf, len)))
wibox->need_update = true;
break;
case A_TK_BG_IMAGE:
@ -770,7 +1097,7 @@ luaA_wibox_newindex(lua_State *L)
xcb_cursor_t cursor = xcursor_new(globalconf.connection, cursor_font);
p_delete(&wibox->cursor);
wibox->cursor = a_strdup(buf);
simplewindow_cursor_set(&wibox->sw, cursor);
wibox_cursor_set(wibox, cursor);
}
}
break;
@ -803,15 +1130,15 @@ luaA_wibox_newindex(lua_State *L)
case A_TK_ORIENTATION:
if((buf = luaL_checklstring(L, 3, &len)))
{
simplewindow_orientation_set(&wibox->sw, orientation_fromstr(buf, len));
wibox_orientation_set(wibox, orientation_fromstr(buf, len));
wibox_need_update(wibox);
}
break;
case A_TK_BORDER_COLOR:
if((buf = luaL_checklstring(L, 3, &len)))
if(xcolor_init_reply(xcolor_init_unchecked(&wibox->sw.border.color, buf, len)))
if(wibox->sw.window)
simplewindow_border_color_set(&wibox->sw, &wibox->sw.border.color);
if(xcolor_init_reply(xcolor_init_unchecked(&wibox->border.color, buf, len)))
if(wibox->window)
wibox_border_color_set(wibox, &wibox->border.color);
break;
case A_TK_VISIBLE:
b = luaA_checkboolean(L, 3);
@ -841,12 +1168,12 @@ luaA_wibox_newindex(lua_State *L)
break;
case A_TK_OPACITY:
if(lua_isnil(L, 3))
simplewindow_opacity_set(&wibox->sw, -1);
wibox_opacity_set(wibox, -1);
else
{
double d = luaL_checknumber(L, 3);
if(d >= 0 && d <= 1)
simplewindow_opacity_set(&wibox->sw, d);
wibox_opacity_set(wibox, d);
}
break;
case A_TK_MOUSE_ENTER:
@ -860,13 +1187,13 @@ luaA_wibox_newindex(lua_State *L)
wibox->mouse_leave = luaA_object_ref_item(L, 1, 3);
return 0;
case A_TK_SHAPE_BOUNDING:
luaA_object_unref_item(L, 1, wibox->sw.shape.bounding);
wibox->sw.shape.bounding = luaA_object_ref_item(L, 1, 3);
luaA_object_unref_item(L, 1, wibox->shape.bounding);
wibox->shape.bounding = luaA_object_ref_item(L, 1, 3);
wibox->need_shape_update = true;
break;
case A_TK_SHAPE_CLIP:
luaA_object_unref_item(L, 1, wibox->sw.shape.clip);
wibox->sw.shape.clip = luaA_object_ref_item(L, 1, 3);
luaA_object_unref_item(L, 1, wibox->shape.clip);
wibox->shape.clip = luaA_object_ref_item(L, 1, 3);
wibox->need_shape_update = true;
case A_TK_BUTTONS:
luaA_object_unref_item(L, 1, wibox->buttons);

60
wibox.h
View File

@ -1,7 +1,7 @@
/*
* wibox.h - wibox functions header
*
* Copyright © 2007-2008 Julien Danjou <julien@danjou.info>
* Copyright © 2007-2009 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
@ -19,11 +19,10 @@
*
*/
#ifndef AWESOME_STATUSBAR_H
#define AWESOME_STATUSBAR_H
#ifndef AWESOME_WIBOX_H
#define AWESOME_WIBOX_H
#include "widget.h"
#include "swindow.h"
/** Wibox types */
typedef enum
@ -44,8 +43,6 @@ struct wibox_t
position_t position;
/** Wibox type */
wibox_type_t type;
/** Window */
simple_window_t sw;
/** Alignment */
alignment_t align;
/** Screen */
@ -69,6 +66,41 @@ struct wibox_t
bool isbanned;
/** Button bindings */
void *buttons;
/** The window object. */
xcb_window_t window;
/** The pixmap copied to the window object. */
xcb_pixmap_t pixmap;
/** The graphic context. */
xcb_gcontext_t gc;
/** The window geometry. */
area_t geometry;
struct
{
/** Internal geometry (matching X11 protocol) */
area_t internal;
} geometries;
/** The window border */
struct
{
/** The window border width */
uint16_t width;
/** The window border color */
xcolor_t color;
} border;
/** Draw context */
draw_context_t ctx;
/** Orientation */
orientation_t orientation;
/** Opacity */
double opacity;
/** The window's shape */
struct
{
/** The window's content */
image_t *clip;
/** The window's content and border */
image_t *bounding;
} shape;
};
void wibox_unref_simplified(wibox_t **);
@ -81,15 +113,13 @@ void luaA_wibox_invalidate_byitem(lua_State *, const void *);
wibox_t * wibox_getbywin(xcb_window_t);
static inline void
wibox_moveresize(wibox_t *wibox, area_t geometry)
{
if(wibox->sw.window)
simplewindow_moveresize(&wibox->sw, geometry);
else
wibox->sw.geometry = geometry;
wibox->need_update = true;
}
void wibox_moveresize(wibox_t *, area_t);
void wibox_refresh_pixmap_partial(wibox_t *, int16_t, int16_t, uint16_t, uint16_t);
void wibox_init(wibox_t *, int);
void wibox_wipe(wibox_t *);
void wibox_border_width_set(wibox_t *, uint32_t);
void wibox_border_color_set(wibox_t *, const xcolor_t *);
void wibox_orientation_set(wibox_t *, orientation_t);
LUA_OBJECT_FUNCS(wibox_t, wibox, "wibox")

View File

@ -153,20 +153,20 @@ widget_geometries(wibox_t *wibox)
if(lua_isfunction(globalconf.L, -1))
{
/* Push 1st argument: wibox geometry */
area_t geometry = wibox->sw.geometry;
area_t geometry = wibox->geometry;
geometry.x = 0;
geometry.y = 0;
/* we need to exchange the width and height of the wibox window if it
* it is rotated, so the layout function doesn't need to care about that
*/
if(wibox->sw.orientation != East)
if(wibox->orientation != East)
{
int i = geometry.height;
geometry.height = geometry.width;
geometry.width = i;
}
geometry.height -= 2 * wibox->sw.border.width;
geometry.width -= 2 * wibox->sw.border.width;
geometry.height -= 2 * wibox->border.width;
geometry.width -= 2 * wibox->border.width;
luaA_pusharea(globalconf.L, geometry);
/* Re-push 2nd argument: widget table */
lua_pushvalue(globalconf.L, -3);
@ -212,8 +212,8 @@ widget_geometries(wibox_t *wibox)
area_t geometry = widget->extents(globalconf.L, widget);
lua_pop(globalconf.L, 1);
geometry.x = geometry.y = 0;
geometry.width = MIN(wibox->sw.geometry.width, geometry.width);
geometry.height = MIN(wibox->sw.geometry.height, geometry.height);
geometry.width = MIN(wibox->geometry.width, geometry.width);
geometry.height = MIN(wibox->geometry.height, geometry.height);
luaA_pusharea(globalconf.L, geometry);
@ -231,7 +231,7 @@ void
widget_render(wibox_t *wibox)
{
lua_State *L = globalconf.L;
draw_context_t *ctx = &wibox->sw.ctx;
draw_context_t *ctx = &wibox->ctx;
area_t rectangle = { 0, 0, 0, 0 };
color_t col;
@ -243,7 +243,7 @@ widget_render(wibox_t *wibox)
if(ctx->bg.alpha != 0xffff)
{
int x = wibox->sw.geometry.x, y = wibox->sw.geometry.y;
int x = wibox->geometry.x, y = wibox->geometry.y;
xcb_get_property_reply_t *prop_r;
char *data;
xcb_pixmap_t rootpix;
@ -256,7 +256,7 @@ widget_render(wibox_t *wibox)
if(prop_r->value_len
&& (data = xcb_get_property_value(prop_r))
&& (rootpix = *(xcb_pixmap_t *) data))
switch(wibox->sw.orientation)
switch(wibox->orientation)
{
case North:
draw_rotate(ctx,
@ -278,7 +278,7 @@ widget_render(wibox_t *wibox)
break;
case East:
xcb_copy_area(globalconf.connection, rootpix,
wibox->sw.pixmap, wibox->sw.gc,
wibox->pixmap, wibox->gc,
x, y,
0, 0,
ctx->width, ctx->height);
@ -306,8 +306,8 @@ widget_render(wibox_t *wibox)
lua_pushnumber(L, i + 1);
lua_gettable(L, -2);
widgets->tab[i].geometry.x = luaA_getopt_number(L, -1, "x", wibox->sw.geometry.x);
widgets->tab[i].geometry.y = luaA_getopt_number(L, -1, "y", wibox->sw.geometry.y);
widgets->tab[i].geometry.x = luaA_getopt_number(L, -1, "x", wibox->geometry.x);
widgets->tab[i].geometry.y = luaA_getopt_number(L, -1, "y", wibox->geometry.y);
widgets->tab[i].geometry.width = luaA_getopt_number(L, -1, "width", 1);
widgets->tab[i].geometry.height = luaA_getopt_number(L, -1, "height", 1);
@ -329,16 +329,16 @@ widget_render(wibox_t *wibox)
widgets->tab[i].widget->draw(widgets->tab[i].widget,
ctx, widgets->tab[i].geometry, wibox);
switch(wibox->sw.orientation)
switch(wibox->orientation)
{
case South:
draw_rotate(ctx, ctx->pixmap, wibox->sw.pixmap,
draw_rotate(ctx, ctx->pixmap, wibox->pixmap,
ctx->width, ctx->height,
ctx->height, ctx->width,
M_PI_2, ctx->height, 0);
break;
case North:
draw_rotate(ctx, ctx->pixmap, wibox->sw.pixmap,
draw_rotate(ctx, ctx->pixmap, wibox->pixmap,
ctx->width, ctx->height,
ctx->height, ctx->width,
- M_PI_2, 0, ctx->width);

View File

@ -83,12 +83,12 @@ systray_draw(widget_t *widget, draw_context_t *ctx,
}
systray_data_t *d = widget->data;
d->height = p->sw.geometry.height;
d->height = p->geometry.height;
/* set wibox orientation */
/** \todo stop setting that property on each redraw */
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE,
globalconf.screens.tab[p->sw.ctx.phys_screen].systray.window,
globalconf.screens.tab[p->ctx.phys_screen].systray.window,
_NET_SYSTEM_TRAY_ORIENTATION, CARDINAL, 32, 1, &orient);
}

View File

@ -127,7 +127,7 @@ textbox_draw(widget_t *widget, draw_context_t *ctx, area_t geometry, wibox_t *p)
}
}
geometry.y += (geometry.height - textbox_geometry(widget, ctx->phys_screen).height - p->sw.border.width + 1) / 2;
geometry.y += (geometry.height - textbox_geometry(widget, ctx->phys_screen).height - p->border.width + 1) / 2;
draw_text(ctx, &d->data, d->ellip, d->wrap, d->align, &d->margin, geometry, &d->extents);
}