🎉 Let's go
A minimalistic but working X XM POC.
This commit is contained in:
commit
cb31369947
15
CMakeLists.txt
Normal file
15
CMakeLists.txt
Normal 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
3
include/configure.h
Normal file
@ -0,0 +1,3 @@
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
void OnConfigureRequest(const XConfigureRequestEvent*);
|
3
include/create.h
Normal file
3
include/create.h
Normal file
@ -0,0 +1,3 @@
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
void OnCreateNotify(const XCreateWindowEvent*);
|
3
include/destroy.h
Normal file
3
include/destroy.h
Normal file
@ -0,0 +1,3 @@
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
void OnDestroyNotify(const XDestroyWindowEvent* e);
|
3
include/map.h
Normal file
3
include/map.h
Normal file
@ -0,0 +1,3 @@
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
void OnMapRequest(Window root, const XMapRequestEvent* e);
|
3
include/reparent.h
Normal file
3
include/reparent.h
Normal file
@ -0,0 +1,3 @@
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
void OnReparentNotify(const XReparentEvent*);
|
3
include/unmap.h
Normal file
3
include/unmap.h
Normal file
@ -0,0 +1,3 @@
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
void OnUnmapRequest(Window root, const XMapRequestEvent* e);
|
21
src/configure.c
Normal file
21
src/configure.c
Normal 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
10
src/create.c
Normal 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
7
src/destroy.c
Normal 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
46
src/main.c
Normal 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
75
src/map.c
Normal 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
6
src/reparent.c
Normal 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
29
src/unmap.c
Normal 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 << "]";
|
||||
* }
|
||||
*/
|
Loading…
Reference in New Issue
Block a user