Browse Source

handle screen resolution images and redraw the lock window

master
Stefan Breunig 13 years ago
committed by Michael Stapelberg
parent
commit
c8eecefe83
  1. 101
      i3lock.c
  2. 11
      xcb.c
  3. 2
      xcb.h

101
i3lock.c

@ -51,6 +51,43 @@ static cairo_surface_t *img = NULL;
static bool tile = false; static bool tile = false;
#endif #endif
/*
* Draws global image with fill color onto a pixmap with the given
* resolution and returns it.
*
*/
xcb_pixmap_t draw_image(xcb_visualtype_t *vistype, u_int32_t* resolution, char* color) {
xcb_pixmap_t bg_pixmap = XCB_NONE;
#ifndef NOLIBCAIRO
if (!img)
return bg_pixmap;
bg_pixmap = create_bg_pixmap(conn, scr, resolution, color);
/* Initialize cairo */
cairo_surface_t *output;
output = cairo_xcb_surface_create(conn, bg_pixmap, vistype,
resolution[0], resolution[1]);
cairo_t *ctx = cairo_create(output);
if (!tile) {
cairo_set_source_surface(ctx, img, 0, 0);
cairo_paint(ctx);
} else {
/* create a pattern and fill a rectangle as big as the screen */
cairo_pattern_t *pattern;
pattern = cairo_pattern_create_for_surface(img);
cairo_set_source(ctx, pattern);
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
cairo_rectangle(ctx, 0, 0, resolution[0], resolution[1]);
cairo_fill(ctx);
cairo_pattern_destroy(pattern);
}
cairo_surface_destroy(output);
cairo_destroy(ctx);
#endif
return bg_pixmap;
}
static void input_done() { static void input_done() {
if (input_position == 0) if (input_position == 0)
return; return;
@ -211,6 +248,36 @@ static void handle_mapping_notify(xcb_mapping_notify_event_t *event) {
xcb_flush(conn); xcb_flush(conn);
} }
/*
* Called when the properties on the root window change, e.g. when the screen
* resolution changes. If so we update the window to cover the whole screen
* and also redraw the image, if any.
*
*/
void handle_screen_resize(xcb_visualtype_t *vistype, xcb_window_t win, uint32_t* last_resolution, char* color) {
xcb_get_geometry_cookie_t geomc;
xcb_get_geometry_reply_t *geom;
geomc = xcb_get_geometry(conn, scr->root);
if ((geom = xcb_get_geometry_reply(conn, geomc, 0)) == NULL) {
return;
}
if (last_resolution[0] == geom->width && last_resolution[1] == geom->height)
return;
last_resolution[0] = geom->width;
last_resolution[1] = geom->height;
if (img) {
xcb_pixmap_t bg_pixmap = draw_image(vistype, last_resolution, color);
xcb_change_window_attributes(conn, win, XCB_CW_BACK_PIXMAP, (uint32_t[1]){ bg_pixmap });
}
uint32_t mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
xcb_configure_window(conn, win, mask, last_resolution);
xcb_flush(conn);
}
/* /*
* Callback function for PAM. We only react on password request callbacks. * Callback function for PAM. We only react on password request callbacks.
* *
@ -362,37 +429,20 @@ int main(int argc, char *argv[]) {
scr = xcb_setup_roots_iterator(xcb_get_setup(conn)).data; scr = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
vistype = get_root_visual_type(scr); vistype = get_root_visual_type(scr);
/* Pixmap on which the image is rendered to (if any) */ uint32_t last_resolution[2] = {scr->width_in_pixels, scr->height_in_pixels};
xcb_pixmap_t bg_pixmap = XCB_NONE;
#ifndef NOLIBCAIRO #ifndef NOLIBCAIRO
if (image_path) { if (image_path) {
bg_pixmap = create_bg_pixmap(conn, scr, color);
/* Create a pixmap to render on, fill it with the background color */ /* Create a pixmap to render on, fill it with the background color */
img = cairo_image_surface_create_from_png(image_path); img = cairo_image_surface_create_from_png(image_path);
} }
if (img) {
/* Initialize cairo */
cairo_surface_t *output;
output = cairo_xcb_surface_create(conn, bg_pixmap, vistype,
scr->width_in_pixels, scr->height_in_pixels);
cairo_t *ctx = cairo_create(output);
if (!tile) {
cairo_set_source_surface(ctx, img, 0, 0);
cairo_paint(ctx);
} else {
/* create a pattern and fill a rectangle as big as the screen */
cairo_pattern_t *pattern;
pattern = cairo_pattern_create_for_surface(img);
cairo_set_source(ctx, pattern);
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
cairo_rectangle(ctx, 0, 0, scr->width_in_pixels, scr->height_in_pixels);
cairo_fill(ctx);
}
}
#endif #endif
/* Pixmap on which the image is rendered to (if any) */
xcb_pixmap_t bg_pixmap = draw_image(vistype, last_resolution, color);
/* open the fullscreen window, already with the correct pixmap in place */ /* open the fullscreen window, already with the correct pixmap in place */
win = open_fullscreen_window(conn, scr, color, bg_pixmap); win = open_fullscreen_window(conn, scr, color, bg_pixmap);
@ -440,6 +490,11 @@ int main(int argc, char *argv[]) {
continue; continue;
} }
if (type == XCB_CONFIGURE_NOTIFY) {
handle_screen_resize(vistype, win, last_resolution, color);
continue;
}
printf("WARNING: unhandled event of type %d\n", type); printf("WARNING: unhandled event of type %d\n", type);
} }

11
xcb.c

@ -53,7 +53,7 @@ static uint32_t get_colorpixel(char *hex) {
(strtol(strgroups[2], NULL, 16))}; (strtol(strgroups[2], NULL, 16))};
return (rgb16[0] << 16) + (rgb16[1] << 8) + rgb16[2]; return (rgb16[0] << 16) + (rgb16[1] << 8) + rgb16[2];
} }
xcb_visualtype_t *get_root_visual_type(xcb_screen_t *screen) { xcb_visualtype_t *get_root_visual_type(xcb_screen_t *screen) {
xcb_visualtype_t *visual_type = NULL; xcb_visualtype_t *visual_type = NULL;
@ -78,17 +78,17 @@ xcb_visualtype_t *get_root_visual_type(xcb_screen_t *screen) {
return NULL; return NULL;
} }
xcb_pixmap_t create_bg_pixmap(xcb_connection_t *conn, xcb_screen_t *scr, char *color) { xcb_pixmap_t create_bg_pixmap(xcb_connection_t *conn, xcb_screen_t *scr, u_int32_t* resolution, char *color) {
xcb_pixmap_t bg_pixmap = xcb_generate_id(conn); xcb_pixmap_t bg_pixmap = xcb_generate_id(conn);
xcb_create_pixmap(conn, scr->root_depth, bg_pixmap, scr->root, xcb_create_pixmap(conn, scr->root_depth, bg_pixmap, scr->root,
scr->width_in_pixels, scr->height_in_pixels); resolution[0], resolution[1]);
/* Generate a Graphics Context and fill the pixmap with background color /* Generate a Graphics Context and fill the pixmap with background color
* (for images that are smaller than your screen) */ * (for images that are smaller than your screen) */
xcb_gcontext_t gc = xcb_generate_id(conn); xcb_gcontext_t gc = xcb_generate_id(conn);
uint32_t values[] = { get_colorpixel(color) }; uint32_t values[] = { get_colorpixel(color) };
xcb_create_gc(conn, gc, bg_pixmap, XCB_GC_FOREGROUND, values); xcb_create_gc(conn, gc, bg_pixmap, XCB_GC_FOREGROUND, values);
xcb_rectangle_t rect = { 0, 0, scr->width_in_pixels, scr->height_in_pixels }; xcb_rectangle_t rect = { 0, 0, resolution[0], resolution[1] };
xcb_poly_fill_rectangle(conn, bg_pixmap, gc, 1, &rect); xcb_poly_fill_rectangle(conn, bg_pixmap, gc, 1, &rect);
return bg_pixmap; return bg_pixmap;
@ -114,7 +114,8 @@ xcb_window_t open_fullscreen_window(xcb_connection_t *conn, xcb_screen_t *scr, c
values[2] = XCB_EVENT_MASK_EXPOSURE | values[2] = XCB_EVENT_MASK_EXPOSURE |
XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_PRESS |
XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_KEY_RELEASE |
XCB_EVENT_MASK_VISIBILITY_CHANGE; XCB_EVENT_MASK_VISIBILITY_CHANGE |
XCB_EVENT_MASK_STRUCTURE_NOTIFY;
xcb_create_window(conn, xcb_create_window(conn,
24, 24,

2
xcb.h

@ -4,7 +4,7 @@
#include <xcb/xcb.h> #include <xcb/xcb.h>
xcb_visualtype_t *get_root_visual_type(xcb_screen_t *s); xcb_visualtype_t *get_root_visual_type(xcb_screen_t *s);
xcb_pixmap_t create_bg_pixmap(xcb_connection_t *conn, xcb_screen_t *scr, char *color); xcb_pixmap_t create_bg_pixmap(xcb_connection_t *conn, xcb_screen_t *scr, u_int32_t *resolution, char *color);
xcb_window_t open_fullscreen_window(xcb_connection_t *conn, xcb_screen_t *scr, char *color, xcb_pixmap_t pixmap); xcb_window_t open_fullscreen_window(xcb_connection_t *conn, xcb_screen_t *scr, char *color, xcb_pixmap_t pixmap);
void grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, xcb_cursor_t cursor); void grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, xcb_cursor_t cursor);
uint32_t get_mod_mask(xcb_connection_t *conn, xcb_key_symbols_t *symbols, uint32_t keycode); uint32_t get_mod_mask(xcb_connection_t *conn, xcb_key_symbols_t *symbols, uint32_t keycode);

Loading…
Cancel
Save