From 13efd8a199e8a1c753f116bd7963216c2c8659a6 Mon Sep 17 00:00:00 2001 From: Julien Danjou Date: Tue, 28 Jul 2009 16:04:58 +0200 Subject: [PATCH] wibox: get rid of simple window Signed-off-by: Julien Danjou --- CMakeLists.txt | 1 - client.c | 12 +- event.c | 30 +-- mouse.c | 10 +- property.c | 2 +- swindow.c | 389 ----------------------------------- swindow.h | 115 ----------- titlebar.c | 73 ++++--- titlebar.h | 24 +-- wibox.c | 509 +++++++++++++++++++++++++++++++++++++--------- wibox.h | 60 ++++-- widget.c | 30 +-- widgets/systray.c | 4 +- widgets/textbox.c | 2 +- 14 files changed, 554 insertions(+), 707 deletions(-) delete mode 100644 swindow.c delete mode 100644 swindow.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f905a7f9d..2c21b137a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/client.c b/client.c index f78666832..a16a89358 100644 --- a/client.c +++ b/client.c @@ -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; } } } diff --git a/event.c b/event.c index 521c5d4ad..db837faa4 100644 --- a/event.c +++ b/event.c @@ -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,9 +558,9 @@ event_handle_expose(void *data __attribute__ ((unused)), wibox_t *wibox; if((wibox = wibox_getbywin(ev->window))) - simplewindow_refresh_pixmap_partial(&wibox->sw, - ev->x, ev->y, - ev->width, ev->height); + wibox_refresh_pixmap_partial(wibox, + ev->x, ev->y, + ev->width, ev->height); return 0; } diff --git a/mouse.c b/mouse.c index 59b8a91cc..c9edd17b7 100644 --- a/mouse.c +++ b/mouse.c @@ -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) diff --git a/property.c b/property.c index a59faa462..0645df9f4 100644 --- a/property.c +++ b/property.c @@ -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; } diff --git a/swindow.c b/swindow.c deleted file mode 100644 index 21a4eb333..000000000 --- a/swindow.c +++ /dev/null @@ -1,389 +0,0 @@ -/* - * swindow.c - simple window handling functions - * - * Copyright © 2008 Julien Danjou - * - * 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 - -#include -#include - -#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 diff --git a/swindow.h b/swindow.h deleted file mode 100644 index d199aeae2..000000000 --- a/swindow.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * swindow.h - simple window handling functions header - * - * Copyright © 2008 Julien Danjou - * - * 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 diff --git a/titlebar.c b/titlebar.c index 56ef7185f..a5847d74d 100644 --- a/titlebar.c +++ b/titlebar.c @@ -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; diff --git a/titlebar.h b/titlebar.h index 485f717fc..a4886986a 100644 --- a/titlebar.h +++ b/titlebar.h @@ -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; diff --git a/wibox.c b/wibox.c index a70c5fe0e..f79e65ca1 100644 --- a/wibox.c +++ b/wibox.c @@ -1,7 +1,7 @@ /* * wibox.c - wibox functions * - * Copyright © 2008 Julien Danjou + * Copyright © 2008-2009 Julien Danjou * * 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 + #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, - xcursor_new(globalconf.connection, xcursor_font_fromstr(wibox->cursor))); + 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); - else - return 0; - } + 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); diff --git a/wibox.h b/wibox.h index 1351e5e71..ad17e7947 100644 --- a/wibox.h +++ b/wibox.h @@ -1,7 +1,7 @@ /* * wibox.h - wibox functions header * - * Copyright © 2007-2008 Julien Danjou + * Copyright © 2007-2009 Julien Danjou * * 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") diff --git a/widget.c b/widget.c index b95de8d99..abd7f669d 100644 --- a/widget.c +++ b/widget.c @@ -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); diff --git a/widgets/systray.c b/widgets/systray.c index bd53ef6e9..cd98ceec1 100644 --- a/widgets/systray.c +++ b/widgets/systray.c @@ -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); } diff --git a/widgets/textbox.c b/widgets/textbox.c index 535bd2da4..69884e3d7 100644 --- a/widgets/textbox.c +++ b/widgets/textbox.c @@ -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); }