🎉 Let's go

A minimalistic but working X XM POC.
This commit is contained in:
Paul Breugnot 2024-12-07 10:13:17 +01:00
commit cb31369947
14 changed files with 227 additions and 0 deletions

15
CMakeLists.txt Normal file
View File

@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.20)
project(aswm)
find_package(X11 REQUIRED)
add_executable(aswm
src/main.c
src/create.c
src/configure.c
src/reparent.c
src/destroy.c
src/map.c)
target_include_directories(aswm PUBLIC ${X11_INCLUDE_DIR} include)
target_link_libraries(aswm ${X11_LIBRARIES})

3
include/configure.h Normal file
View File

@ -0,0 +1,3 @@
#include <X11/Xlib.h>
void OnConfigureRequest(const XConfigureRequestEvent*);

3
include/create.h Normal file
View File

@ -0,0 +1,3 @@
#include <X11/Xlib.h>
void OnCreateNotify(const XCreateWindowEvent*);

3
include/destroy.h Normal file
View File

@ -0,0 +1,3 @@
#include <X11/Xlib.h>
void OnDestroyNotify(const XDestroyWindowEvent* e);

3
include/map.h Normal file
View File

@ -0,0 +1,3 @@
#include <X11/Xlib.h>
void OnMapRequest(Window root, const XMapRequestEvent* e);

3
include/reparent.h Normal file
View File

@ -0,0 +1,3 @@
#include <X11/Xlib.h>
void OnReparentNotify(const XReparentEvent*);

3
include/unmap.h Normal file
View File

@ -0,0 +1,3 @@
#include <X11/Xlib.h>
void OnUnmapRequest(Window root, const XMapRequestEvent* e);

21
src/configure.c Normal file
View File

@ -0,0 +1,21 @@
#ifndef ASWM_CONFIGURE
#define ASWM_CONFIGURE
#include "configure.h"
#include <stdio.h>
void OnConfigureRequest(const XConfigureRequestEvent* e) {
XWindowChanges changes;
printf("XConfigureRequestEvent %lu\n", e->window);
// Copy fields from e to changes.
changes.x = e->x;
changes.y = e->y;
changes.width = e->width;
changes.height = e->height;
changes.border_width = e->border_width;
changes.sibling = e->above;
changes.stack_mode = e->detail;
// Grant request by calling XConfigureWindow().
XConfigureWindow(e->display, e->window, e->value_mask, &changes);
}
#endif

10
src/create.c Normal file
View File

@ -0,0 +1,10 @@
#ifndef ASWM_CREATE
#define ASWM_CREATE
#include "create.h"
#include <stdio.h>
void OnCreateNotify(const XCreateWindowEvent* e) {
printf("XCreateWindowEvent %lu\n", e->window);
}
#endif

7
src/destroy.c Normal file
View File

@ -0,0 +1,7 @@
#include "destroy.h"
#include <stdio.h>
void OnDestroyNotify(const XDestroyWindowEvent* e) {
printf("XDestroyWindowEvent %lu\n", e->window);
// TODO: destroy frame
}

46
src/main.c Normal file
View File

@ -0,0 +1,46 @@
#include <X11/Xlib.h>
#include "create.h"
#include "configure.h"
#include "map.h"
#include "reparent.h"
#include "destroy.h"
Display *display;
Window root;
int main(int argc, char** argv) {
display = XOpenDisplay(NULL);
root = DefaultRootWindow(display);
XSelectInput(display, root, SubstructureRedirectMask | SubstructureNotifyMask);
XSync(display, 0);
for (;;) {
XEvent e;
XNextEvent(display, &e);
switch(e.type) {
case CreateNotify:
OnCreateNotify(&e.xcreatewindow);
break;
case ConfigureRequest:
OnConfigureRequest(&e.xconfigurerequest);
break;
case MapRequest:
OnMapRequest(root, &e.xmaprequest);
break;
case DestroyNotify:
OnDestroyNotify(&e.xdestroywindow);
break;
case ReparentNotify:
OnReparentNotify(&e.xreparent);
break;
default:
break;
/* LOG(WARNING) << "Ignored event"; */
}
}
XCloseDisplay(display);
}

75
src/map.c Normal file
View File

@ -0,0 +1,75 @@
#ifndef ASWM_MAP
#define ASWM_MAP
#include "map.h"
#include <stdio.h>
void map_fullscreen_window(Window root, Display* display, Window w);
void OnMapRequest(Window root, const XMapRequestEvent* e) {
printf("XMapRequestEvent %lu\n", e->window);
map_fullscreen_window(root, e->display, e->window);
XMapWindow(e->display, e->window);
}
void map_fullscreen_window(Window root, Display* display, Window w) {
// Visual properties of the frame to create.
const unsigned int BORDER_WIDTH = 0;
const unsigned long BORDER_COLOR = 0xff0000;
const unsigned long BG_COLOR = 0x0000ff;
// 1. Retrieve attributes of window to frame.
XWindowAttributes x_window_attrs;
XGetWindowAttributes(display, w, &x_window_attrs);
// 2. TODO - see Framing Existing Top-Level Windows section below.
printf("\tXCreateSimpleWindow:\n");
printf("\t\tx: %i\n", x_window_attrs.x);
printf("\t\ty: %i\n", x_window_attrs.y);
printf("\t\tw: %i\n", x_window_attrs.width);
printf("\t\th: %i\n", x_window_attrs.height);
// 3. Create frame.
const Window frame = XCreateSimpleWindow(
display,
root,
x_window_attrs.x,
x_window_attrs.y,
x_window_attrs.width,
x_window_attrs.height,
BORDER_WIDTH,
BORDER_COLOR,
BG_COLOR);
// 3. Select events on frame.
XSelectInput(
display,
frame,
SubstructureRedirectMask | SubstructureNotifyMask);
// 4. Add client to save set, so that it will be restored and kept alive if we
// crash.
XAddToSaveSet(display, w);
// 5. Reparent client window.
XReparentWindow(
display,
w,
frame,
0, 0); // Offset of client window within frame.
// 6. Map frame.
XMapWindow(display, frame);
// 7. Save frame handle.
/* clients_[w] = frame; */
// 8. Grab events for window management actions on client window.
// a. Move windows with alt + left button.
/* XGrabButton(...); */
// b. Resize windows with alt + right button.
/* XGrabButton(...); */
// c. Kill windows with alt + f4.
/* XGrabKey(...); */
// d. Switch windows with alt + tab.
/* XGrabKey(...); */
printf("\tFramed window %lu [%lu]\n", w, frame);
}
#endif

6
src/reparent.c Normal file
View File

@ -0,0 +1,6 @@
#include "reparent.h"
#include <stdio.h>
void OnReparentNotify(const XReparentEvent* e) {
printf("XReparentEvent %lu\n", e->window);
}

29
src/unmap.c Normal file
View File

@ -0,0 +1,29 @@
#include "unmap.h"
#include <stdio.h>
void OnUnmapRequest(Window root, const XMapRequestEvent* e) {
printf("XUnmapWindow %lu", e->window);
}
/*
* void unframe(Window root, Display* display, Window w) {
* // We reverse the steps taken in Frame().
* const Window frame = clients_[w];
* // 1. Unmap frame.
* XUnmapWindow(display, frame);
* // 2. Reparent client window back to root window.
* XReparentWindow(
* display,
* w,
* root,
* 0, 0); // Offset of client window within root.
* // 3. Remove client window from save set, as it is now unrelated to us.
* XRemoveFromSaveSet(display, w);
* // 4. Destroy frame.
* XDestroyWindow(display, frame);
* // 5. Drop reference to frame handle.
* clients_.erase(w);
*
* LOG(INFO) << "Unframed window " << w << " [" << frame << "]";
* }
*/