检测显示器信息
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.24)
|
||||
|
||||
set(APP_NAME "zswm")
|
||||
set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
# generate compile_commands.json for clangd
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
@@ -14,7 +15,26 @@ project(${APP_NAME}
|
||||
LANGUAGES C
|
||||
)
|
||||
|
||||
add_executable(${APP_NAME} main.c)
|
||||
add_executable(${APP_NAME} main.c utils.c)
|
||||
|
||||
# use C17
|
||||
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