Добавление скелета wm
This commit is contained in:
parent
859f1a9f29
commit
5fa590ff66
BIN
wm/x11/cwmX11
Executable file
BIN
wm/x11/cwmX11
Executable file
Binary file not shown.
348
wm/x11/src/main.c
Normal file
348
wm/x11/src/main.c
Normal file
@ -0,0 +1,348 @@
|
||||
// main.c - чистая версия для FreeBSD
|
||||
#ifndef __linux__
|
||||
#define __linux__ 1 // для совместимости
|
||||
#endif
|
||||
#ifndef _LINUX
|
||||
#define _LINUX 1
|
||||
#endif
|
||||
|
||||
#ifndef _SAPI
|
||||
#define _SAPI SciterAPI
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// X11, OpenGL и FreeBSD специфичные заголовки
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/extensions/Xcomposite.h>
|
||||
#include <GL/glx.h>
|
||||
|
||||
#include <uchar.h>
|
||||
|
||||
// Sciter C API (не C++!)
|
||||
#include <sciter-x.h>
|
||||
|
||||
// Глобальные переменные X11/GLX
|
||||
Display *dpy = NULL;
|
||||
Window root_win = 0;
|
||||
Window comp_win = 0;
|
||||
int screen = 0;
|
||||
int screen_width = 0;
|
||||
int screen_height = 0;
|
||||
|
||||
GLXContext glx_ctx = NULL;
|
||||
GLXFBConfig fb_config = 0;
|
||||
|
||||
Atom wm_delete_window = 0;
|
||||
|
||||
// Окно Sciter (структура вместо класса)
|
||||
HWINDOW g_sciter_hwnd = NULL;
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Инициализация X11
|
||||
// -------------------------------------------------------------
|
||||
void init_x11(void) {
|
||||
dpy = XOpenDisplay(NULL);
|
||||
if (!dpy) {
|
||||
fprintf(stderr, "Ошибка: не могу открыть дисплей\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
screen = DefaultScreen(dpy);
|
||||
root_win = DefaultRootWindow(dpy);
|
||||
|
||||
screen_width = WidthOfScreen(DefaultScreenOfDisplay(dpy));
|
||||
screen_height = HeightOfScreen(DefaultScreenOfDisplay(dpy));
|
||||
|
||||
XSetWindowAttributes attrs;
|
||||
attrs.override_redirect = True;
|
||||
attrs.background_pixel = 0;
|
||||
attrs.border_pixel = 0;
|
||||
attrs.event_mask = ExposureMask | KeyPressMask | StructureNotifyMask | KeyReleaseMask;
|
||||
|
||||
comp_win = XCreateWindow(dpy, root_win,
|
||||
0, 0, screen_width, screen_height, 0,
|
||||
CopyFromParent, InputOutput, CopyFromParent,
|
||||
CWOverrideRedirect | CWBackPixel | CWBorderPixel | CWEventMask,
|
||||
&attrs);
|
||||
|
||||
// Установка состояния окна (поверх всех и полноэкранный режим)
|
||||
Atom net_wm_state = XInternAtom(dpy, "_NET_WM_STATE", False);
|
||||
Atom net_wm_state_above = XInternAtom(dpy, "_NET_WM_STATE_ABOVE", False);
|
||||
Atom net_wm_state_fullscreen = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
|
||||
|
||||
Atom states[] = { net_wm_state_above, net_wm_state_fullscreen };
|
||||
XChangeProperty(dpy, comp_win, net_wm_state, XA_ATOM, 32,
|
||||
PropModeReplace, (unsigned char *)states, 2);
|
||||
|
||||
// Обработка закрытия окна
|
||||
wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
|
||||
XSetWMProtocols(dpy, comp_win, &wm_delete_window, 1);
|
||||
|
||||
XMapWindow(dpy, comp_win);
|
||||
XRaiseWindow(dpy, comp_win);
|
||||
XFlush(dpy);
|
||||
|
||||
printf("Окно создано: 0x%lx (%dx%d)\n", comp_win, screen_width, screen_height);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Инициализация GLX для FreeBSD
|
||||
// -------------------------------------------------------------
|
||||
void init_glx(void) {
|
||||
XWindowAttributes win_attrs;
|
||||
XGetWindowAttributes(dpy, comp_win, &win_attrs);
|
||||
Visual *window_visual = win_attrs.visual;
|
||||
VisualID window_visual_id = XVisualIDFromVisual(window_visual);
|
||||
|
||||
// Атрибуты для GLX
|
||||
int fb_attribs[] = {
|
||||
GLX_RENDER_TYPE, GLX_RGBA_BIT,
|
||||
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
|
||||
GLX_RED_SIZE, 8,
|
||||
GLX_GREEN_SIZE, 8,
|
||||
GLX_BLUE_SIZE, 8,
|
||||
GLX_ALPHA_SIZE, 8,
|
||||
GLX_DEPTH_SIZE, 24,
|
||||
GLX_DOUBLEBUFFER, True,
|
||||
None
|
||||
};
|
||||
|
||||
int num_fb;
|
||||
GLXFBConfig *fb_configs = glXChooseFBConfig(dpy, screen, fb_attribs, &num_fb);
|
||||
if (!fb_configs) {
|
||||
fprintf(stderr, "Ошибка: не удалось получить FBConfig\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Поиск совместимого FBConfig
|
||||
GLXFBConfig compatible_config = 0;
|
||||
for (int i = 0; i < num_fb; i++) {
|
||||
int visual_id = 0;
|
||||
glXGetFBConfigAttrib(dpy, fb_configs[i], GLX_VISUAL_ID, &visual_id);
|
||||
if ((VisualID)visual_id == window_visual_id) {
|
||||
compatible_config = fb_configs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!compatible_config) {
|
||||
compatible_config = fb_configs[0];
|
||||
printf("Предупреждение: используется несовместимый FBConfig\n");
|
||||
}
|
||||
|
||||
fb_config = compatible_config;
|
||||
XFree(fb_configs);
|
||||
|
||||
// Создание контекста OpenGL
|
||||
glx_ctx = glXCreateNewContext(dpy, fb_config, GLX_RGBA_TYPE, NULL, True);
|
||||
if (!glx_ctx) {
|
||||
fprintf(stderr, "Ошибка: не удалось создать GLX контекст\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Делаем контекст текущим
|
||||
if (!glXMakeCurrent(dpy, comp_win, glx_ctx)) {
|
||||
fprintf(stderr, "Ошибка: glXMakeCurrent не удался\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("GLX инициализирован. OpenGL: %s\n", glGetString(GL_VERSION));
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Функции обратного вызова Sciter
|
||||
// -------------------------------------------------------------
|
||||
// Вызывается при необходимости перерисовки окна
|
||||
void sciter_on_paint(HWINDOW hwnd, UINT_PTR reserved) {
|
||||
// Sciter сам обрабатывает отрисовку через OpenGL
|
||||
// Просто вызываем обновление
|
||||
SciterUpdateWindow(hwnd);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Инициализация Sciter
|
||||
// -------------------------------------------------------------
|
||||
void init_sciter(void) {
|
||||
// Устанавливаем графический слой OpenGL (через Skia)
|
||||
SciterSetOption(NULL, SCITER_SET_GFX_LAYER, GFX_LAYER_SKIA_OPENGL);
|
||||
|
||||
// Включаем возможности для скриптов
|
||||
SciterSetOption(NULL, SCITER_SET_SCRIPT_RUNTIME_FEATURES,
|
||||
ALLOW_FILE_IO | ALLOW_SOCKET_IO | ALLOW_EVAL | ALLOW_SYSINFO);
|
||||
|
||||
// Создаем окно Sciter (без WinAPI, через X11)
|
||||
RECT frame_rect = {0, 0, screen_width, screen_height};
|
||||
|
||||
g_sciter_hwnd = SciterCreateWindow(
|
||||
SW_MAIN | SW_ENABLE_DEBUG,
|
||||
&frame_rect,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (!g_sciter_hwnd) {
|
||||
fprintf(stderr, "Ошибка: не удалось создать Sciter окно\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Устанавливаем обработчик отрисовки
|
||||
//sciter_callback(g_sciter_hwnd, SCITER_CB_PAINT, (void*)sciter_on_paint);
|
||||
|
||||
// HTML контент
|
||||
const char *html =
|
||||
"<!DOCTYPE html>"
|
||||
"<html><head><meta charset='UTF-8'><style>"
|
||||
"html { background: transparent; overflow: hidden; }"
|
||||
"body { background: rgba(26,26,26,0.9); color:#e0e0e0; "
|
||||
"display:flex; justify-content:center; align-items:center; "
|
||||
"height:100vh; margin:0; font-family:system-ui; }"
|
||||
".panel { background:#2b2b2b; border-radius:16px; padding:32px; "
|
||||
"text-align:center; box-shadow:0 8px 20px rgba(0,0,0,0.3); }"
|
||||
"h1 { color:#fff; margin-bottom:16px; }"
|
||||
"button { background:#0060df; color:#fff; border:none; border-radius:6px; "
|
||||
"padding:12px 24px; margin:8px; cursor:pointer; font-size:16px; "
|
||||
"transition:background 0.2s; }"
|
||||
"button:hover { background:#003eaa; }"
|
||||
"#status { margin-top:20px; color:#00ff9d; font-weight:bold; }"
|
||||
"</style></head>"
|
||||
"<body><div class='panel'><h1>Calista + Sciter</h1>"
|
||||
"<p>Sciter работает через OpenGL на FreeBSD!</p>"
|
||||
"<button onclick='document.getElementById(\"status\").innerText=\"✓ Готово!\"'>"
|
||||
"Нажми меня</button>"
|
||||
"<div id='status'>Система готова</div>"
|
||||
"</div></body></html>";
|
||||
|
||||
// Загружаем HTML
|
||||
SciterLoadHtml(g_sciter_hwnd, html, (UINT)strlen(html), "/");
|
||||
|
||||
printf("Sciter инициализирован и HTML загружен\n");
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Обновление позиции окна Sciter
|
||||
// -------------------------------------------------------------
|
||||
void update_sciter_window_size(int width, int height) {
|
||||
if (g_sciter_hwnd) {
|
||||
RECT rect = {0, 0, width, height};
|
||||
//SciterSetWindowRect(g_sciter_hwnd, &rect);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Главный цикл обработки событий
|
||||
// -------------------------------------------------------------
|
||||
void main_loop(void) {
|
||||
XEvent ev;
|
||||
bool running = true;
|
||||
|
||||
printf("Композитор запущен. Нажмите Q или Escape для выхода.\n");
|
||||
|
||||
while (running) {
|
||||
// Обработка событий X11
|
||||
while (XPending(dpy) > 0) {
|
||||
XNextEvent(dpy, &ev);
|
||||
|
||||
switch (ev.type) {
|
||||
case Expose:
|
||||
if (ev.xexpose.count == 0) {
|
||||
// Обновляем Sciter при необходимости
|
||||
SciterUpdateWindow(g_sciter_hwnd);
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyPress:
|
||||
{
|
||||
char key_str[32];
|
||||
KeySym keysym;
|
||||
XLookupString(&ev.xkey, key_str, sizeof(key_str), &keysym, NULL);
|
||||
|
||||
// Выход по Q или Escape
|
||||
if (keysym == XK_q || keysym == XK_Q || keysym == XK_Escape) {
|
||||
printf("Выход по запросу пользователя\n");
|
||||
running = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ConfigureNotify:
|
||||
screen_width = ev.xconfigure.width;
|
||||
screen_height = ev.xconfigure.height;
|
||||
update_sciter_window_size(screen_width, screen_height);
|
||||
break;
|
||||
|
||||
case ClientMessage:
|
||||
if ((Atom)ev.xclient.data.l[0] == wm_delete_window) {
|
||||
printf("Получен WM_DELETE_WINDOW\n");
|
||||
running = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case DestroyNotify:
|
||||
printf("Окно разрушено\n");
|
||||
running = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Обновляем Sciter
|
||||
SciterUpdateWindow(g_sciter_hwnd);
|
||||
|
||||
// Небольшая задержка для снижения нагрузки на CPU
|
||||
usleep(10000); // 10ms
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Очистка ресурсов
|
||||
// -------------------------------------------------------------
|
||||
void cleanup(void) {
|
||||
if (g_sciter_hwnd) {
|
||||
//SciterCloseWindow(g_sciter_hwnd);
|
||||
g_sciter_hwnd = NULL;
|
||||
}
|
||||
|
||||
if (glx_ctx) {
|
||||
glXMakeCurrent(dpy, None, NULL);
|
||||
glXDestroyContext(dpy, glx_ctx);
|
||||
glx_ctx = NULL;
|
||||
}
|
||||
|
||||
if (comp_win) {
|
||||
XDestroyWindow(dpy, comp_win);
|
||||
comp_win = 0;
|
||||
}
|
||||
|
||||
if (dpy) {
|
||||
XCloseDisplay(dpy);
|
||||
dpy = NULL;
|
||||
}
|
||||
|
||||
printf("Ресурсы освобождены\n");
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Точка входа
|
||||
// -------------------------------------------------------------
|
||||
int main(int argc, char **argv) {
|
||||
// Игнорируем аргументы
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
printf("Запуск Calista композитора для FreeBSD\n");
|
||||
|
||||
init_x11();
|
||||
init_glx();
|
||||
init_sciter();
|
||||
|
||||
main_loop();
|
||||
cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
36
wm/x11/src/makefile
Normal file
36
wm/x11/src/makefile
Normal file
@ -0,0 +1,36 @@
|
||||
# Makefile for Calista Compositor
|
||||
|
||||
CC = cc
|
||||
CFLAGS = -Wall -Wextra -O2 -g
|
||||
CFLAGS += -I/usr/local/include
|
||||
CFLAGS += -I/calista/engine/include
|
||||
|
||||
LDFLAGS = -L/usr/local/lib -lX11 -lXcomposite -lXdamage -lXrender -lGL -lEGL
|
||||
LDFLAGS += -L/calista/engine -lsciter
|
||||
|
||||
TARGET = cwmX11
|
||||
SRCS = main.c
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJS)
|
||||
$(CC) $(OBJS) -o $(TARGET) $(LDFLAGS)
|
||||
mv $(TARGET) ./../
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) $(TARGET)
|
||||
|
||||
run: $(TARGET)
|
||||
./$(TARGET)
|
||||
|
||||
install: $(TARGET)
|
||||
cp $(TARGET) /usr/local/bin/
|
||||
|
||||
uninstall:
|
||||
rm -f /usr/local/bin/$(TARGET)
|
||||
|
||||
.PHONY: all clean run install uninstall
|
||||
Loading…
x
Reference in New Issue
Block a user