检测显示器信息
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
cmake_minimum_required(VERSION 3.24)
|
cmake_minimum_required(VERSION 3.24)
|
||||||
|
|
||||||
set(APP_NAME "zswm")
|
set(APP_NAME "zswm")
|
||||||
|
set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
# generate compile_commands.json for clangd
|
# generate compile_commands.json for clangd
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
@@ -14,7 +15,26 @@ project(${APP_NAME}
|
|||||||
LANGUAGES C
|
LANGUAGES C
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(${APP_NAME} main.c)
|
add_executable(${APP_NAME} main.c utils.c)
|
||||||
|
|
||||||
# use C17
|
# use C17
|
||||||
set_property(TARGET ${APP_NAME} PROPERTY C_STANDARD 17)
|
set_property(TARGET ${APP_NAME} PROPERTY C_STANDARD 17)
|
||||||
|
|
||||||
|
target_include_directories(${APP_NAME} PRIVATE "${SOURCE_DIR}/include")
|
||||||
|
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
|
||||||
|
pkg_check_modules(XCB REQUIRED
|
||||||
|
xcb
|
||||||
|
xcb-cursor
|
||||||
|
xcb-icccm
|
||||||
|
xcb-keysyms
|
||||||
|
xcb-util
|
||||||
|
xcb-xfixes
|
||||||
|
xcb-xinerama
|
||||||
|
xcb-xrm
|
||||||
|
)
|
||||||
|
target_include_directories(${APP_NAME} SYSTEM PUBLIC ${XCB_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
add_subdirectory(xcb)
|
||||||
|
target_link_libraries(${APP_NAME} ${LIB_XCB_NAME})
|
||||||
|
|||||||
8
src/include/utils.h
Normal file
8
src/include/utils.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#define LENGTH(X) (sizeof(X) / sizeof(X)[0])
|
||||||
|
|
||||||
|
void die(const char *format, ...);
|
||||||
|
void *ecalloc(size_t number_of_member, size_t member_size);
|
||||||
16
src/include/xcb.h
Normal file
16
src/include/xcb.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct monitor_rect_t monitor_rect_t;
|
||||||
|
struct monitor_rect_t {
|
||||||
|
int32_t x;
|
||||||
|
int32_t y;
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
monitor_rect_t *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool has_other_wm_running(void);
|
||||||
|
monitor_rect_t *detect_monitor_rect(void);
|
||||||
26
src/main.c
26
src/main.c
@@ -1 +1,25 @@
|
|||||||
int main(int argc, char *argv[]) { return 0; }
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
#include "xcb.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if (has_other_wm_running()) {
|
||||||
|
die("another window manager is already running");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
monitor_rect_t *mr = detect_monitor_rect();
|
||||||
|
uint32_t i = 0;
|
||||||
|
while (mr) {
|
||||||
|
printf("mon[%u]: x: %d, y: %d, w: %u, h: %u\n", i, mr->x, mr->y,
|
||||||
|
mr->width, mr->height);
|
||||||
|
mr = mr->next;
|
||||||
|
free(mr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
32
src/utils.c
Normal file
32
src/utils.c
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void die(const char *fmt, ...) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vfprintf(stderr, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
if (fmt[0] && fmt[strlen(fmt) - 1] == ':') {
|
||||||
|
fputc(' ', stderr);
|
||||||
|
perror(NULL);
|
||||||
|
} else {
|
||||||
|
fputc('\n', stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ecalloc(size_t number_of_member, size_t member_size) {
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
if (!(p = calloc(number_of_member, member_size))) {
|
||||||
|
die("calloc:");
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
9
src/xcb/CMakeLists.txt
Normal file
9
src/xcb/CMakeLists.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
set(LIB_XCB "zswm-xcb")
|
||||||
|
set(LIB_XCB_NAME ${LIB_XCB} PARENT_SCOPE)
|
||||||
|
|
||||||
|
add_library(${LIB_XCB} STATIC xcb.c)
|
||||||
|
|
||||||
|
target_include_directories(${LIB_XCB} SYSTEM PUBLIC ${XCB_INCLUDE_DIRS})
|
||||||
|
target_include_directories(${LIB_XCB} PUBLIC "${CMAKE_SOURCE_DIR}/include")
|
||||||
|
|
||||||
|
target_link_libraries(${LIB_XCB} ${XCB_LIBRARIES})
|
||||||
5
src/xcb/xcb-private.h
Normal file
5
src/xcb/xcb-private.h
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
|
||||||
|
extern xcb_connection_t *conn;
|
||||||
70
src/xcb/xcb.c
Normal file
70
src/xcb/xcb.c
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#include "xcb.h"
|
||||||
|
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
#include <xcb/xcb_aux.h>
|
||||||
|
#include <xcb/xinerama.h>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
#include "xcb-private.h"
|
||||||
|
|
||||||
|
xcb_connection_t *conn = NULL;
|
||||||
|
|
||||||
|
bool has_other_wm_running(void) {
|
||||||
|
conn = xcb_connect(NULL, NULL);
|
||||||
|
if (!conn || xcb_connection_has_error(conn)) {
|
||||||
|
die("connection:");
|
||||||
|
}
|
||||||
|
|
||||||
|
const xcb_setup_t *setup = xcb_get_setup(conn);
|
||||||
|
xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);
|
||||||
|
xcb_screen_t *screen = iter.data;
|
||||||
|
uint32_t mask = XCB_CW_EVENT_MASK;
|
||||||
|
xcb_params_cw_t params = {
|
||||||
|
.event_mask = XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_ENTER_WINDOW |
|
||||||
|
XCB_EVENT_MASK_POINTER_MOTION |
|
||||||
|
XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT |
|
||||||
|
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY,
|
||||||
|
};
|
||||||
|
xcb_void_cookie_t cookie =
|
||||||
|
xcb_aux_change_window_attributes(conn, screen->root, mask, ¶ms);
|
||||||
|
xcb_generic_error_t *error = xcb_request_check(conn, cookie);
|
||||||
|
if (error) {
|
||||||
|
xcb_disconnect(conn);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor_rect_t *detect_monitor_rect(void) {
|
||||||
|
monitor_rect_t *list, *prev;
|
||||||
|
xcb_xinerama_query_screens_cookie_t cookie = xcb_xinerama_query_screens(conn);
|
||||||
|
xcb_xinerama_query_screens_reply_t *reply =
|
||||||
|
xcb_xinerama_query_screens_reply(conn, cookie, NULL);
|
||||||
|
xcb_xinerama_screen_info_t *screen_info =
|
||||||
|
xcb_xinerama_query_screens_screen_info(reply);
|
||||||
|
|
||||||
|
if (screen_info == NULL) {
|
||||||
|
die("no monitor finded");
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = xcb_xinerama_query_screens_screen_info_length(reply);
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
monitor_rect_t *m = ecalloc(1, sizeof(monitor_rect_t));
|
||||||
|
xcb_xinerama_screen_info_t info = screen_info[i];
|
||||||
|
m->x = info.x_org;
|
||||||
|
m->y = info.y_org;
|
||||||
|
m->width = info.width;
|
||||||
|
m->height = info.height;
|
||||||
|
m->next = NULL;
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
list = m;
|
||||||
|
} else {
|
||||||
|
prev->next = m;
|
||||||
|
}
|
||||||
|
prev = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user