Compare commits
1 Commits
main
...
9e53010ff7
| Author | SHA1 | Date | |
|---|---|---|---|
|
9e53010ff7
|
@@ -53,6 +53,8 @@ struct monitor_t {
|
|||||||
tag_t *tag_list;
|
tag_t *tag_list;
|
||||||
tag_t *selected_tag;
|
tag_t *selected_tag;
|
||||||
|
|
||||||
|
char *name;
|
||||||
|
|
||||||
xcb_window_t bar_window;
|
xcb_window_t bar_window;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
17
src/utils.c
17
src/utils.c
@@ -19,7 +19,8 @@ const char *current_time_str(void) {
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Print error and exit with EXIT_FAILURE code.
|
/**
|
||||||
|
* Print error and exit with EXIT_FAILURE code.
|
||||||
*/
|
*/
|
||||||
void _fatal(int line, const char *fct, const char *file, const char *fmt, ...) {
|
void _fatal(int line, const char *fct, const char *file, const char *fmt, ...) {
|
||||||
va_list ap;
|
va_list ap;
|
||||||
@@ -32,3 +33,17 @@ void _fatal(int line, const char *fct, const char *file, const char *fmt, ...) {
|
|||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print error message on stderr
|
||||||
|
*/
|
||||||
|
void _warn(int line, const char *fct, const char *file, const char *fmt, ...) {
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
const char *format = "(WW) [%s] %s\n%s:%d:%s:\n";
|
||||||
|
fprintf(stderr, format, APP_NAME, current_time_str(), file, line, fct);
|
||||||
|
vfprintf(stderr, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
|||||||
32
src/utils.h
32
src/utils.h
@@ -7,8 +7,10 @@
|
|||||||
#define countof(foo) (ssizeof(foo) / ssizeof(foo[0]))
|
#define countof(foo) (ssizeof(foo) / ssizeof(foo[0]))
|
||||||
|
|
||||||
#define p_alloc_nr(x) (((x) + 16) * 3 / 2)
|
#define p_alloc_nr(x) (((x) + 16) * 3 / 2)
|
||||||
|
#define p_new(type, count) ((type *)xmalloc(sizeof(type) * (count)))
|
||||||
#define p_clear(p, count) ((void)memset((p), 0, sizeof(*(p)) * (count)))
|
#define p_clear(p, count) ((void)memset((p), 0, sizeof(*(p)) * (count)))
|
||||||
#define p_realloc(pp, count) xrealloc((void *)(pp), sizeof(**(pp)) * (count))
|
#define p_realloc(pp, count) xrealloc((void *)(pp), sizeof(**(pp)) * (count))
|
||||||
|
#define p_dup(p, count) xmemdup((p), sizeof(*(p)) * (count))
|
||||||
|
|
||||||
#define p_delete(mem_p) \
|
#define p_delete(mem_p) \
|
||||||
do { \
|
do { \
|
||||||
@@ -46,6 +48,16 @@ static inline void xrealloc(void **ptr, ssize_t newsize) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Duplicate a memory zone.
|
||||||
|
* @param src The source.
|
||||||
|
* @param size The source size.
|
||||||
|
* @return The memory address of the copy.
|
||||||
|
*/
|
||||||
|
static inline void *xmemdup(const void *src, ssize_t size) {
|
||||||
|
return memcpy(xmalloc(size), src, size);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief NULL resistant strlen.
|
* @brief NULL resistant strlen.
|
||||||
*
|
*
|
||||||
@@ -57,10 +69,30 @@ static inline void xrealloc(void **ptr, ssize_t newsize) {
|
|||||||
*/
|
*/
|
||||||
static inline ssize_t a_strlen(const char *s) { return s ? strlen(s) : 0; }
|
static inline ssize_t a_strlen(const char *s) { return s ? strlen(s) : 0; }
|
||||||
|
|
||||||
|
/** \brief \c NULL resistant strdup.
|
||||||
|
*
|
||||||
|
* The a_strdup() function returns a pointer to a new string, which is a
|
||||||
|
* duplicate of \c s. Memory should be freed using p_delete().
|
||||||
|
*
|
||||||
|
* \warning when s is \c "", it returns NULL !
|
||||||
|
*
|
||||||
|
* \param[in] s the string to duplicate.
|
||||||
|
* \return a pointer to the duplicated string.
|
||||||
|
*/
|
||||||
|
static inline char *a_strdup(const char *s) {
|
||||||
|
ssize_t len = a_strlen(s);
|
||||||
|
return len ? p_dup(s, len + 1) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#define fatal(format, ...) \
|
#define fatal(format, ...) \
|
||||||
_fatal(__LINE__, __FUNCTION__, __FILE__, format, ##__VA_ARGS__)
|
_fatal(__LINE__, __FUNCTION__, __FILE__, format, ##__VA_ARGS__)
|
||||||
void _fatal(int line, const char *function, const char *file,
|
void _fatal(int line, const char *function, const char *file,
|
||||||
const char *format, ...) __attribute__((noreturn))
|
const char *format, ...) __attribute__((noreturn))
|
||||||
__attribute__((format(printf, 4, 5)));
|
__attribute__((format(printf, 4, 5)));
|
||||||
|
|
||||||
|
#define warn(format, ...) \
|
||||||
|
_fatal(__LINE__, __FUNCTION__, __FILE__, format, ##__VA_ARGS__)
|
||||||
|
void _warn(int line, const char *function, const char *file, const char *format,
|
||||||
|
...) __attribute__((format(printf, 4, 5)));
|
||||||
|
|
||||||
const char *current_time_str(void);
|
const char *current_time_str(void);
|
||||||
|
|||||||
120
src/wm.c
120
src/wm.c
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "backtrace.h"
|
#include "backtrace.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "types.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
static void wm_setup_signal(void);
|
static void wm_setup_signal(void);
|
||||||
@@ -123,7 +124,113 @@ void wm_check_xcb_extensions(void) {
|
|||||||
wm.have_randr = query && query->present;
|
wm.have_randr = query && query->present;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wm_detect_monitor(void) {}
|
static bool wm_detect_monitor_by_randr(void) {
|
||||||
|
xcb_randr_get_monitors_cookie_t monitors_cookie =
|
||||||
|
xcb_randr_get_monitors(wm.xcb_conn, wm.screen->root, 1);
|
||||||
|
xcb_randr_get_monitors_reply_t *monitors_reply =
|
||||||
|
xcb_randr_get_monitors_reply(wm.xcb_conn, monitors_cookie, NULL);
|
||||||
|
if (monitors_reply == NULL) {
|
||||||
|
warn("RandR get monitor failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor_t *prev_monitor = NULL;
|
||||||
|
xcb_randr_monitor_info_iterator_t monitor_iter;
|
||||||
|
for (monitor_iter = xcb_randr_get_monitors_monitors_iterator(monitors_reply);
|
||||||
|
monitor_iter.rem; xcb_randr_monitor_info_next(&monitor_iter)) {
|
||||||
|
monitor_t *monitor = p_new(monitor_t, 1);
|
||||||
|
monitor->geometry.x = monitor_iter.data->x;
|
||||||
|
monitor->geometry.y = monitor_iter.data->y;
|
||||||
|
monitor->geometry.width = monitor_iter.data->width;
|
||||||
|
monitor->geometry.height = monitor_iter.data->height;
|
||||||
|
|
||||||
|
xcb_get_atom_name_cookie_t name_cookie =
|
||||||
|
xcb_get_atom_name_unchecked(wm.xcb_conn, monitor_iter.data->name);
|
||||||
|
xcb_get_atom_name_reply_t *name_reply =
|
||||||
|
xcb_get_atom_name_reply(wm.xcb_conn, name_cookie, NULL);
|
||||||
|
|
||||||
|
if (name_reply) {
|
||||||
|
char *name = xcb_get_atom_name_name(name_reply);
|
||||||
|
int length = xcb_get_atom_name_name_length(name_reply);
|
||||||
|
monitor->name = memcpy(p_new(char, length + 1), name, length);
|
||||||
|
monitor->name[length] = '\0';
|
||||||
|
p_delete(&name_reply);
|
||||||
|
} else {
|
||||||
|
monitor->name = a_strdup("unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prev_monitor) {
|
||||||
|
prev_monitor->next = monitor;
|
||||||
|
} else {
|
||||||
|
wm.monitor_list = monitor;
|
||||||
|
prev_monitor = monitor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool wm_detect_monitor_by_xinerama(void) {
|
||||||
|
xcb_xinerama_is_active_cookie_t active_cookie =
|
||||||
|
xcb_xinerama_is_active(wm.xcb_conn);
|
||||||
|
xcb_xinerama_is_active_reply_t *active_reply =
|
||||||
|
xcb_xinerama_is_active_reply(wm.xcb_conn, active_cookie, NULL);
|
||||||
|
if (!active_reply || !active_reply->state) {
|
||||||
|
p_delete(&active_reply);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_xinerama_query_screens_cookie_t screens_cookie =
|
||||||
|
xcb_xinerama_query_screens(wm.xcb_conn);
|
||||||
|
xcb_xinerama_query_screens_reply_t *screens_reply =
|
||||||
|
xcb_xinerama_query_screens_reply(wm.xcb_conn, screens_cookie, NULL);
|
||||||
|
|
||||||
|
if (screens_reply == NULL) return false;
|
||||||
|
|
||||||
|
int count = xcb_xinerama_query_screens_screen_info_length(screens_reply);
|
||||||
|
if (count <= 0) {
|
||||||
|
p_delete(&screens_reply);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_xinerama_screen_info_t *screen_info =
|
||||||
|
xcb_xinerama_query_screens_screen_info(screens_reply);
|
||||||
|
|
||||||
|
monitor_t *prev_monitor = NULL;
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
monitor_t *monitor = p_new(monitor_t, 1);
|
||||||
|
monitor->geometry.x = screen_info[i].x_org;
|
||||||
|
monitor->geometry.y = screen_info[i].y_org;
|
||||||
|
monitor->geometry.width = screen_info[i].width;
|
||||||
|
monitor->geometry.height = screen_info[i].height;
|
||||||
|
|
||||||
|
if (prev_monitor) {
|
||||||
|
prev_monitor->next = monitor;
|
||||||
|
} else {
|
||||||
|
wm.monitor_list = monitor;
|
||||||
|
prev_monitor = monitor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p_delete(&screens_reply);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wm_detect_monitor(void) {
|
||||||
|
if (wm.have_randr && wm_detect_monitor_by_randr()) return;
|
||||||
|
if (wm.have_xinerama && wm_detect_monitor_by_xinerama()) return;
|
||||||
|
|
||||||
|
if (wm.screen == NULL) fatal("cannot detect monitor info");
|
||||||
|
|
||||||
|
monitor_t *monitor = p_new(monitor_t, 1);
|
||||||
|
monitor->geometry.x = 0;
|
||||||
|
monitor->geometry.y = 0;
|
||||||
|
monitor->geometry.width = wm.screen->width_in_pixels;
|
||||||
|
monitor->geometry.height = wm.screen->height_in_pixels;
|
||||||
|
|
||||||
|
wm.monitor_list = monitor;
|
||||||
|
}
|
||||||
|
|
||||||
void wm_scan_clients(void) {}
|
void wm_scan_clients(void) {}
|
||||||
|
|
||||||
void wm_restart(void) {
|
void wm_restart(void) {
|
||||||
@@ -138,6 +245,15 @@ void wm_quit(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void debug_show_monitor_list(void) {
|
||||||
|
printf("\n========================== monitors ==========================\n");
|
||||||
|
for (monitor_t *m = wm.monitor_list; m; m = m->next) {
|
||||||
|
printf("x: %4d, y: %4d, width: %4u, height: %4u -> monitor[%s]\n",
|
||||||
|
m->geometry.x, m->geometry.y, m->geometry.width, m->geometry.height,
|
||||||
|
m->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
p_clear(&wm, 1);
|
p_clear(&wm, 1);
|
||||||
cmd_argv = argv;
|
cmd_argv = argv;
|
||||||
@@ -148,6 +264,8 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
wm_detect_monitor();
|
wm_detect_monitor();
|
||||||
|
|
||||||
|
debug_show_monitor_list();
|
||||||
|
|
||||||
if (wm.loop == NULL) {
|
if (wm.loop == NULL) {
|
||||||
wm.loop = g_main_loop_new(NULL, FALSE);
|
wm.loop = g_main_loop_new(NULL, FALSE);
|
||||||
g_main_loop_run(wm.loop);
|
g_main_loop_run(wm.loop);
|
||||||
|
|||||||
Reference in New Issue
Block a user