调整壁纸绘制方案
This commit is contained in:
@@ -82,6 +82,8 @@ typedef struct rect_size_t {
|
|||||||
uint32_t height;
|
uint32_t height;
|
||||||
} rect_size_t;
|
} rect_size_t;
|
||||||
rect_size_t *get_screen_size(void);
|
rect_size_t *get_screen_size(void);
|
||||||
|
bar_cairo_params_t *prepare_wallpaper_surface_params(void);
|
||||||
|
void refresh_root_window(void);
|
||||||
void set_wallpaper(uint32_t *wallpaper_data);
|
void set_wallpaper(uint32_t *wallpaper_data);
|
||||||
|
|
||||||
typedef struct window_list_t {
|
typedef struct window_list_t {
|
||||||
@@ -105,6 +107,8 @@ typedef enum atom_t {
|
|||||||
atom_wm_delete,
|
atom_wm_delete,
|
||||||
atom_wm_take_focus,
|
atom_wm_take_focus,
|
||||||
atom_net_wm_name,
|
atom_net_wm_name,
|
||||||
|
atom__xrootpmap_id,
|
||||||
|
atom_esetroot_pmap_id,
|
||||||
} atom_t;
|
} atom_t;
|
||||||
xcb_atom_t get_xcb_atom(atom_t atom);
|
xcb_atom_t get_xcb_atom(atom_t atom);
|
||||||
bool send_event(xcb_window_t window, atom_t atom);
|
bool send_event(xcb_window_t window, atom_t atom);
|
||||||
|
|||||||
67
src/main.c
67
src/main.c
@@ -25,7 +25,8 @@ static void init_monitors(void);
|
|||||||
static char **get_monitor_tags(uint32_t monitor_count, uint32_t monitor_index);
|
static char **get_monitor_tags(uint32_t monitor_count, uint32_t monitor_index);
|
||||||
static void init_wallpaper(void);
|
static void init_wallpaper(void);
|
||||||
static gboolean update_wallpaper(gpointer user_data);
|
static gboolean update_wallpaper(gpointer user_data);
|
||||||
static void set_wallpaper_by_index(uint32_t index, wallpaper_config_t *config);
|
static void set_wallpaper_by_index(uint32_t index, wallpaper_config_t *config,
|
||||||
|
cairo_t *cr);
|
||||||
static wallpaper_config_t *parse_wallpaper_config(void);
|
static wallpaper_config_t *parse_wallpaper_config(void);
|
||||||
static void free_wallpaper_config(wallpaper_config_t *wallpaper_config);
|
static void free_wallpaper_config(wallpaper_config_t *wallpaper_config);
|
||||||
static void init_color_set(void);
|
static void init_color_set(void);
|
||||||
@@ -70,6 +71,7 @@ static void cleanup(void);
|
|||||||
|
|
||||||
static monitor_t *monitors = NULL;
|
static monitor_t *monitors = NULL;
|
||||||
static monitor_t *current_monitor = NULL;
|
static monitor_t *current_monitor = NULL;
|
||||||
|
static cairo_t *wallpaper_cr = NULL;
|
||||||
static wallpaper_config_t *wallpaper_config = NULL;
|
static wallpaper_config_t *wallpaper_config = NULL;
|
||||||
static color_set_t *color_set = NULL;
|
static color_set_t *color_set = NULL;
|
||||||
static GMainLoop *loop = NULL;
|
static GMainLoop *loop = NULL;
|
||||||
@@ -253,6 +255,28 @@ void init_wallpaper(void) {
|
|||||||
wallpaper_config = parse_wallpaper_config();
|
wallpaper_config = parse_wallpaper_config();
|
||||||
if (!wallpaper_config) return;
|
if (!wallpaper_config) return;
|
||||||
|
|
||||||
|
bar_cairo_params_t *p = prepare_wallpaper_surface_params();
|
||||||
|
rect_size_t *screen_size = get_screen_size();
|
||||||
|
if (wallpaper_cr) cairo_destroy(wallpaper_cr);
|
||||||
|
|
||||||
|
cairo_surface_t *surface = cairo_xcb_surface_create(
|
||||||
|
p->conn, p->window, p->visual, screen_size->width, screen_size->height);
|
||||||
|
free(p);
|
||||||
|
free(screen_size);
|
||||||
|
|
||||||
|
if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
|
||||||
|
cairo_surface_destroy(surface);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_t *cr = cairo_create(surface);
|
||||||
|
if (cairo_status(cr) != CAIRO_STATUS_SUCCESS) {
|
||||||
|
cairo_destroy(cr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wallpaper_cr = cr;
|
||||||
|
cairo_surface_destroy(surface);
|
||||||
|
|
||||||
update_wallpaper(wallpaper_config);
|
update_wallpaper(wallpaper_config);
|
||||||
if (!wallpaper_interval) return;
|
if (!wallpaper_interval) return;
|
||||||
g_timeout_add_seconds(wallpaper_interval, update_wallpaper, wallpaper_config);
|
g_timeout_add_seconds(wallpaper_interval, update_wallpaper, wallpaper_config);
|
||||||
@@ -260,10 +284,10 @@ void init_wallpaper(void) {
|
|||||||
|
|
||||||
gboolean update_wallpaper(gpointer user_data) {
|
gboolean update_wallpaper(gpointer user_data) {
|
||||||
wallpaper_config_t *wc = user_data;
|
wallpaper_config_t *wc = user_data;
|
||||||
if (!wc) return false;
|
if (!wc || !wallpaper_cr) return false;
|
||||||
|
|
||||||
static uint32_t index = 0;
|
static uint32_t index = 0;
|
||||||
set_wallpaper_by_index(index, wc);
|
set_wallpaper_by_index(index, wc, wallpaper_cr);
|
||||||
uint32_t monitor_count = 0;
|
uint32_t monitor_count = 0;
|
||||||
for (monitor_t *m = monitors; m; m = m->next) monitor_count++;
|
for (monitor_t *m = monitors; m; m = m->next) monitor_count++;
|
||||||
|
|
||||||
@@ -278,22 +302,29 @@ gboolean update_wallpaper(gpointer user_data) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_wallpaper_by_index(uint32_t index, wallpaper_config_t *config) {
|
void set_wallpaper_by_index(uint32_t index, wallpaper_config_t *config,
|
||||||
if (!config) return;
|
cairo_t *cr) {
|
||||||
|
|
||||||
rect_size_t *screen_size = get_screen_size();
|
rect_size_t *screen_size = get_screen_size();
|
||||||
uint32_t *wallpaper = generate_wallpaper(
|
uint32_t width = screen_size->width;
|
||||||
config, monitors, index, screen_size->width, screen_size->height);
|
uint32_t height = screen_size->height;
|
||||||
|
|
||||||
if (wallpaper) {
|
|
||||||
double start = get_time();
|
|
||||||
set_wallpaper(wallpaper);
|
|
||||||
double end = get_time();
|
|
||||||
free(wallpaper);
|
|
||||||
logger("set wallpaper cost: %fs\n", end - start);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(screen_size);
|
free(screen_size);
|
||||||
|
|
||||||
|
uint32_t *wallpaper =
|
||||||
|
generate_wallpaper(config, monitors, index, width, height);
|
||||||
|
|
||||||
|
if (!wallpaper) return;
|
||||||
|
|
||||||
|
double start = get_time();
|
||||||
|
uint8_t *data = (uint8_t *)wallpaper;
|
||||||
|
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
|
||||||
|
cairo_surface_t *s = cairo_image_surface_create_for_data(
|
||||||
|
data, CAIRO_FORMAT_ARGB32, width, height, stride);
|
||||||
|
cairo_set_source_surface(cr, s, 0, 0);
|
||||||
|
cairo_paint(cr);
|
||||||
|
refresh_root_window();
|
||||||
|
free(wallpaper);
|
||||||
|
double end = get_time();
|
||||||
|
logger("set wallpaper cost: %fs\n", end - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
wallpaper_config_t *parse_wallpaper_config(void) {
|
wallpaper_config_t *parse_wallpaper_config(void) {
|
||||||
@@ -926,7 +957,9 @@ void cleanup(void) {
|
|||||||
clean_pango_context();
|
clean_pango_context();
|
||||||
|
|
||||||
free_wallpaper_config(wallpaper_config);
|
free_wallpaper_config(wallpaper_config);
|
||||||
|
cairo_destroy(wallpaper_cr);
|
||||||
wallpaper_config = NULL;
|
wallpaper_config = NULL;
|
||||||
|
wallpaper_cr = NULL;
|
||||||
|
|
||||||
free(color_set);
|
free(color_set);
|
||||||
color_set = NULL;
|
color_set = NULL;
|
||||||
|
|||||||
@@ -57,11 +57,6 @@ void get_window_class_instance(xcb_window_t window,
|
|||||||
xcb_icccm_get_wm_class_reply_wipe(&prop);
|
xcb_icccm_get_wm_class_reply_wipe(&prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct visual_t {
|
|
||||||
uint8_t depth;
|
|
||||||
xcb_visualtype_t *visual;
|
|
||||||
} visual_t;
|
|
||||||
|
|
||||||
static visual_t *find_alpha_visual() {
|
static visual_t *find_alpha_visual() {
|
||||||
xcb_depth_iterator_t depth_iter;
|
xcb_depth_iterator_t depth_iter;
|
||||||
depth_iter = xcb_screen_allowed_depths_iterator(screen);
|
depth_iter = xcb_screen_allowed_depths_iterator(screen);
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
void set_window_class_instance(xcb_window_t window, const char *class,
|
void set_window_class_instance(xcb_window_t window, const char *class,
|
||||||
const char *instance);
|
const char *instance);
|
||||||
|
|
||||||
|
typedef struct visual_t {
|
||||||
|
uint8_t depth;
|
||||||
|
xcb_visualtype_t *visual;
|
||||||
|
} visual_t;
|
||||||
|
visual_t *get_xcb_visual(bool prefer_alpha);
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ static atom_map_t atom_map[] = {
|
|||||||
{.atom = atom_wm_delete, .name = "WM_DELETE_WINDOW"},
|
{.atom = atom_wm_delete, .name = "WM_DELETE_WINDOW"},
|
||||||
{.atom = atom_wm_take_focus, .name = "WM_TAKE_FOCUS"},
|
{.atom = atom_wm_take_focus, .name = "WM_TAKE_FOCUS"},
|
||||||
{.atom = atom_net_wm_name, .name = "_NET_WM_NAME"},
|
{.atom = atom_net_wm_name, .name = "_NET_WM_NAME"},
|
||||||
|
{.atom = atom__xrootpmap_id, .name = "_XROOTPMAP_ID"},
|
||||||
|
{.atom = atom_esetroot_pmap_id, .name = "ESETROOT_PMAP_ID"},
|
||||||
};
|
};
|
||||||
|
|
||||||
void init_icccm_extension(void) {
|
void init_icccm_extension(void) {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "window.h"
|
||||||
#include "xcb-private.h"
|
#include "xcb-private.h"
|
||||||
|
|
||||||
xcb_connection_t *conn = NULL;
|
xcb_connection_t *conn = NULL;
|
||||||
@@ -150,6 +151,52 @@ rect_size_t *get_screen_size(void) {
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bar_cairo_params_t *prepare_wallpaper_surface_params(void) {
|
||||||
|
uint32_t width = screen->width_in_pixels;
|
||||||
|
uint32_t height = screen->height_in_pixels;
|
||||||
|
xcb_window_t root = screen->root;
|
||||||
|
|
||||||
|
visual_t *v = get_xcb_visual(false);
|
||||||
|
|
||||||
|
static xcb_pixmap_t pixmap = XCB_PIXMAP_NONE;
|
||||||
|
if (pixmap != XCB_PIXMAP_NONE) {
|
||||||
|
xcb_kill_client(conn, pixmap);
|
||||||
|
xcb_free_pixmap(conn, pixmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixmap = xcb_generate_id(conn);
|
||||||
|
xcb_create_pixmap(conn, v->depth, pixmap, root, width, height);
|
||||||
|
xcb_gcontext_t gc = xcb_generate_id(conn);
|
||||||
|
xcb_create_gc(conn, gc, pixmap, 0, NULL);
|
||||||
|
xcb_change_window_attributes_value_list_t value_list = {
|
||||||
|
.background_pixmap = pixmap,
|
||||||
|
};
|
||||||
|
xcb_change_window_attributes_aux(conn, root, XCB_CW_BACK_PIXMAP, &value_list);
|
||||||
|
|
||||||
|
/* 兼容合成器,不设置若开启合成器壁纸会不显示 */
|
||||||
|
uint8_t mode = XCB_PROP_MODE_REPLACE;
|
||||||
|
xcb_atom_t atom = get_xcb_atom(atom__xrootpmap_id);
|
||||||
|
xcb_change_property(conn, mode, root, atom, XCB_ATOM_PIXMAP, 32, 1, &pixmap);
|
||||||
|
atom = get_xcb_atom(atom_esetroot_pmap_id);
|
||||||
|
xcb_change_property(conn, mode, root, atom, XCB_ATOM_PIXMAP, 32, 1, &pixmap);
|
||||||
|
|
||||||
|
xcb_clear_area(conn, 0, root, 0, 0, width, height);
|
||||||
|
xcb_free_gc(conn, gc);
|
||||||
|
xcb_flush(conn);
|
||||||
|
|
||||||
|
bar_cairo_params_t *p = ecalloc(1, sizeof(bar_cairo_params_t));
|
||||||
|
p->conn = conn;
|
||||||
|
p->visual = v->visual;
|
||||||
|
p->window = pixmap;
|
||||||
|
free(v);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void refresh_root_window(void) {
|
||||||
|
xcb_clear_area(conn, 0, screen->root, 0, 0, 0, 0);
|
||||||
|
xcb_flush(conn);
|
||||||
|
}
|
||||||
|
|
||||||
void set_wallpaper(uint32_t *wallpaper_data) {
|
void set_wallpaper(uint32_t *wallpaper_data) {
|
||||||
uint32_t width = screen->width_in_pixels;
|
uint32_t width = screen->width_in_pixels;
|
||||||
uint32_t height = screen->height_in_pixels;
|
uint32_t height = screen->height_in_pixels;
|
||||||
|
|||||||
Reference in New Issue
Block a user