Repository: mcpcpc/xwm
Branch: main
Commit: 8f79d3d69709
Files: 12
Total size: 23.3 KB
Directory structure:
gitextract_sdyjtq5f/
├── .github/
│ ├── CONTRIBUTING
│ ├── FUNDING.yml
│ └── workflows/
│ └── codacy-analysis.yml
├── .gitignore
├── CHANGELOG
├── LICENSE
├── Makefile
├── README
├── config.h
├── xwm.1
├── xwm.c
└── xwm.h
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/CONTRIBUTING
================================================
CONTRIBUTING
============
Want to contribute? Great! First, read this page.
Code reviews:
* All submissions, including submissions by project members, require
review. We use Github pull requests for this purpose.
Some tips for good pull requests:
* Use our code. When in doubt, try to stay true to the existing code
of the project.
* Write a descriptive commit message. What problem are you solving
and what are the consequences? Where and what did you test? Some
good tips:
http://robots.thoughtbot.com/5-useful-tips-for-a-better-commit-message
https://www.kernel.org/doc/Documentation/SubmittingPatches
* If your PR consists of multiple commits which are successive
improvements / fixes to your first commit, consider squashing them
into a single commit (`git rebase -i`) such that your PR is a
single commit on top of the current HEAD. This make reviewing the
code so much easier, and our history more readable.
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: mcpcpc
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: https://www.paypal.me/mcpcpc/usd5
================================================
FILE: .github/workflows/codacy-analysis.yml
================================================
# This workflow checks out code, performs a Codacy security scan
# and integrates the results with the
# GitHub Advanced Security code scanning feature. For more information on
# the Codacy security scan action usage and parameters, see
# https://github.com/codacy/codacy-analysis-cli-action.
# For more information on Codacy Analysis CLI in general, see
# https://github.com/codacy/codacy-analysis-cli.
name: Codacy Security Scan
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
codacy-security-scan:
name: Codacy Security Scan
runs-on: ubuntu-latest
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout code
uses: actions/checkout@v2
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
- name: Run Codacy Analysis CLI
uses: codacy/codacy-analysis-cli-action@1.1.0
with:
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
# You can also omit the token and run the tools that support default configurations
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
verbose: true
output: results.sarif
format: sarif
# Adjust severity of non-security issues
gh-code-scanning-compat: true
# Force 0 exit code to allow SARIF file generation
# This will handover control about PR rejection to the GitHub side
max-allowed-issues: 2147483647
# Upload the SARIF file generated in the previous step
- name: Upload SARIF results file
uses: github/codeql-action/upload-sarif@v1
with:
sarif_file: results.sarif
================================================
FILE: .gitignore
================================================
xwm
*.a
*.o
================================================
FILE: CHANGELOG
================================================
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.1.9] - 2022-01-25
### Added
- New year to LICENSE file.
### Removed
- "PATCHES" section from the README.
###Fixed
- Typographic errors in the CHANGELOG.
## [0.1.8] - 2021-03-14
### Fixed
- free(ev), which is called erroneously when ev might equal NULL.
### Removed
- xcb_destroy_window call in the spawn(), which is unnecessary and, furthermore,
not recommended per the developer documentation.
## [0.1.7] - 2021-03-03
### Fixed
- Memory leak due to xcb_wait_for_event() not being freed.
- Order of the CHANGELOG (i.e. latest on top).
## [0.1.6] - 2020-12-28
### Added
- Window fullscreen command alias (default: Win+f).
## [0.1.5] - 2020-12-23
### Removed
- Unused root padding definitions.
- xcb_wait_for_event() not being freed.
## [0.1.4] - 2020-12-22
### Added
- Raise focus command keys to xwm.1 and README.
### Changed
- The "Features" section of the README to indicate audience.
### Removed
- Pointer warp on window resize/move as this appears to be default.
### Fixed
- Spelling and grammar in man page.
## [0.1.3] - 2020-11-30
### Added
- Instructions in README for Arch Linux AUR installation.
### Changed
- Default new window location from top-left to center.
### Removed
- Global root variable.
- Removed leave notify event.
## [0.1.2] - 2020-11-23
### Changed
- Default surf start page to startpage.com.
### Fixed
- Zombie reaping.
## [0.1.1] - 2020-11-21
### Added
- Makefile warnings (e.g. -Wall, Wextra, etc.).
## [0.1.0] - 2020-11-20
### Fixed
- MISRA 10.4 non-compliance.
- Fix operator dependence.
## [0.0.9] - 2020-11-17
### Fixed
- Window resize lag.
- Bug where window border moves outside of root window.
## [0.0.8] - 2020-11-16
### Fixed
- Window focus/unfocus on new window creation.
## [0.0.7] - 2020-11-13
### Fixed
- Border focus/unfocus when leaving a window.
## [0.0.6] - 2020-11-12
### Added
- Window borders and color definitions.
## [0.0.5] - 2020-11-11
### Added
- Default key bindings in man page.
- Disclaimer section in README.
## [0.0.4] - 2020-11-10
### Added
- Instructions for patches and the patching process.
- Minimum window height and width parameters.
### Removed
- Unused stdarg.h library dependency.
### Fixed
- Crash when pointer x/y cords less than window origin.
## [0.0.3] - 2020-11-08
### Added
- Examples in the config.h file.
- Window height and width parameters.
### Removed
- string.h library dependency.
## [0.0.2] - 2020-11-07
### Added
- Close window command (default: Win+q).
### Fixed
- Resize crash in root window.
## [0.0.1] - 2020-11-06
### Added
- Initial release.
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2021-2022 Michael Czigler
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: Makefile
================================================
.POSIX:
ALL_WARNING = -Wall -Wextra -pedantic
ALL_LDFLAGS = -lxcb -lxcb-keysyms $(LDFLAGS)
ALL_CFLAGS = $(CPPFLAGS) $(CFLAGS) -std=c99 $(ALL_WARNING)
PREFIX = /usr/local
LDLIBS = -lm
BINDIR = $(PREFIX)/bin
MANDIR = $(PREFIX)/share/man
all: xwm
install: all
mkdir -p $(DESTDIR)$(BINDIR)
mkdir -p $(DESTDIR)$(MANDIR)/man1
cp -f xwm $(DESTDIR)$(BINDIR)
cp -f xwm.1 $(DESTDIR)$(MANDIR)/man1
chmod 755 $(DESTDIR)$(BINDIR)/xwm
chmod 644 $(DESTDIR)$(MANDIR)/man1/xwm.1
xwm: xwm.o
$(CC) -o xwm xwm.o $(ALL_LDFLAGS) $(LDLIBS)
xwm.o: xwm.c xwm.h config.h
clean:
rm -f xwm *.o
uninstall:
rm -f $(DESTDIR)$(BINDIR)/xwm
rm -f $(DESTDIR)$(MANDIR)/man1/xwm.1
.PHONY: all install uninstall clean
================================================
FILE: README
================================================
xwm - a tiny XCB floating window manager
========================================
A minimal viable solution that was developed with single-monitor
workflows in mind. Despite the small footprint, xwm maintains
extensibility and can be customized to enhance the user experience.
REQUIREMENTS
------------
xcb-util-keysyms, along with any default or user defined utilities:
application launcher https://git.suckless.org/dmenu
terminal emulator https://git.suckless.org/st
internet browser https://git.suckless.org/surf
COMMANDS
--------
Default keys and behavior can be customized via the config.h file:
Win+Button1 raise focused window to top of stack
Win+Button3 raise focused window to top of stack
Win+Button1+[drag] interactive window move
Win+Button3+[drag] interactive window resize
Win+Space run launcher menu (default: dmenu_run)
Win+Enter create new terminal window (default: st)
Win+b create new browser window (default: surf)
Win+q kill focused window
Win+f full-screen focused window
Win+Shift+q quit window manager
INSTALL
-------
Building and installing from source:
$ git clone https://github.com/mcpcpc/xwm
$ cd xwm
$ make
$ sudo make install
EXAMPLES
--------
Checking the installed version of xwm:
$ xwm -v
Using startx to run xwm:
$ echo "exec xwm" > ~/.xinitrc
$ startx
Using imagemagick to set a wallpaper:
$ display -window root background.png
Patching xwm:
$ patch -p0 < mypatch.patch
DISCLAIMER
----------
xwm ("XCB Window Manager") is an homage to the original and
now-defunct "X Window Manager". Both projects are unaffiliated
and do not share any common source code.
CONTACT
-------
For questions or issues, please contact michaelczigler[at]mcpcpc[dot]com.
================================================
FILE: config.h
================================================
/* DEFAULT KEYS
* The following are the possible mask definitions. Note
* that these definitions may vary between X implementations
* and keyboard models.
* XCB_MOD_MASK_1 -> Alt_L Alt_R Meta_L
* XCB_MOD_MASK_2 -> Num_Lock
* XCB_MOD_MASK_3 -> ISO_Level3_Shift
* XCB_MOD_MASK_4 -> Super_L Super_R SuperL Hyper_L
* XCB_MOD_MASK_5 -> ISO_Level5_Shifta
* XCB_MOD_MASK_SHIFT
* XCB_MOD_MASK_CONTROL
* XCB_MOD_MASK_LOCK
* XCB_MOD_MASK_ANY
*/
#define MOD1 XCB_MOD_MASK_4
#define MOD2 XCB_MOD_MASK_SHIFT
/* DEFAULT WINDOW PROPERTIES
* The following parameters can be used to change existing and new
* window behavior.
*/
#define WINDOW_WIDTH 600 /* pixels */
#define WINDOW_HEIGHT 400 /* pixels */
#define WINDOW_MIN_WIDTH 60 /* pixels */
#define WINDOW_MIN_HEIGHT 40 /* pixels */
#define BORDER_WIDTH 1 /* 0 = no border effect */
#define BORDER_COLOR_UNFOCUSED 0x696969 /* 0xRRGGBB */
#define BORDER_COLOR_FOCUSED 0xFFFFFF /* 0xRRGGBB */
/* ALIASED COMMANDS
* Each space delimited argument should be passed as an additional
* value to the character pointer array. For example, to run
* "foo -a bar", the array would be "{ "foo", "-a", "bar", NULL }".
* Since execvp() is a variadic functions, each argument pointer must
* be terminated by a NULL pointer.
*/
static char *termcmd[] = { "st", NULL };
static char *menucmd[] = { "dmenu_run", NULL };
static char *browcmd[] = { "surf", "https://startpage.com", NULL };
/* KEY ALIASES
* In general, one shortcut key should exist per alias. For more key
* definitions, refer to the keysymdef.h and XF86keysym.h headers.
*/
static Key keys[] = {
{ MOD1, 0x0062, spawn, browcmd }, /* 0x0062 = XK_b */
{ MOD1, 0xff0d, spawn, termcmd }, /* 0xff0d = XK_Enter */
{ MOD1, 0x0020, spawn, menucmd }, /* 0x0020 = XK_space */
{ MOD1, 0x0066, fullclient, NULL }, /* 0x0066 = XK_f */
{ MOD1, 0x0071, killclient, NULL }, /* 0x0071 = XK_q */
{ MOD1|MOD2, 0x0071, closewm, NULL } /* 0x0071 = XK_q */
};
================================================
FILE: xwm.1
================================================
.\"Manpage for xwm.
.TH XWM 1 "NOVEMBER 2020" Linux "User Manuals"
.SH NAME
xwm \- a tiny XCB floating window manager
.SH SYNOPSIS
.B xwm [-v]
.SH DESCRIPTION
.B xwm
is a tiny floating window manager implemented using
the XCB protocol. Other than
.BR xcb-util-keysyms (1),
xwm relies on third-party tools, which can be
configured or expanded to meet the user's preference.
The default configuration provides support and
command aliases for the
.BR surf (1)
web browser,
.BR st (1)
terminal emulator and
.BR dmenu (1)
application launcher.
.SH OPTIONS
.IP -v
Prints the current xwm version.
.SH DEFAULT KEY BINDINGS
.B xwm
may be controlled from an attached client using a key
combination of a prefix key, the 'Super' (Win) key by
default, followed by a command key.
.PP
The default command key bindings are:
.TS
tab(;);
lb l l.
_
Super;MouseButton1;T{
Raise focused window to top of stack.
T}
_
Super;MouseButton3;T{
Raise focused window to top of stack.
T}
_
Super-MouseButton1;[drag];T{
Interactive window move.
T}
_
Super-MouseButton3;[drag];T{
Interactive window resize.
T}
_
Super;Space;T{
Run launcher menu (default: dmenu_run).
T}
_
Super;Enter;T{
Create new terminal window (default: st).
T}
_
Super;b;T{
Create new browser window (default: surf).
T}
_
Super;f;T{
Full-screen focused window.
T}
_
Super;q;T{
Kill focused window.
T}
_
Super-Shift;q;T{
Quite window manager.
T}
_
.TE
.SH BUGS
No known bugs.
.SH AUTHOR
Michael Czigler <michaelczigler[at]mcpcpc[dot]com>
.SH "SEE ALSO"
.BR libxcb (1),
.BR st (1),
.BR surf (1),
.BR dmenu (1)
================================================
FILE: xwm.c
================================================
/* See LICENSE file for license details. */
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <xcb/xcb.h>
#include <xcb/xcb_keysyms.h>
#include "xwm.h"
#include "config.h"
#define UNUSED(x) (void)(x)
static xcb_connection_t * dpy;
static xcb_screen_t * scre;
static xcb_drawable_t win;
static uint32_t values[3];
static void killclient(char **com) {
UNUSED(com);
xcb_kill_client(dpy, win);
}
static void closewm(char **com) {
UNUSED(com);
if (dpy != NULL) {
xcb_disconnect(dpy);
}
}
static void spawn(char **com) {
if (fork() == 0) {
setsid();
if (fork() != 0) {
_exit(0);
}
execvp((char*)com[0], (char**)com);
_exit(0);
}
wait(NULL);
}
static void fullclient(char **com) {
UNUSED(com);
uint32_t vals[4];
vals[0] = 0 - BORDER_WIDTH;
vals[1] = 0 - BORDER_WIDTH;
vals[2] = scre->width_in_pixels;
vals[3] = scre->height_in_pixels;
xcb_configure_window(dpy, win, XCB_CONFIG_WINDOW_X |
XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH |
XCB_CONFIG_WINDOW_HEIGHT, vals);
xcb_flush(dpy);
}
static void handleButtonPress(xcb_generic_event_t *ev) {
xcb_button_press_event_t *e = (xcb_button_press_event_t *) ev;
win = e->child;
values[0] = XCB_STACK_MODE_ABOVE;
xcb_configure_window(dpy, win, XCB_CONFIG_WINDOW_STACK_MODE, values);
values[2] = ((1 == e->detail) ? 1 : ((win != 0) ? 3 : 0 ));
xcb_grab_pointer(dpy, 0, scre->root, XCB_EVENT_MASK_BUTTON_RELEASE
| XCB_EVENT_MASK_BUTTON_MOTION | XCB_EVENT_MASK_POINTER_MOTION_HINT,
XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC,
scre->root, XCB_NONE, XCB_CURRENT_TIME);
}
static void handleMotionNotify(xcb_generic_event_t *ev) {
UNUSED(ev);
xcb_query_pointer_cookie_t coord = xcb_query_pointer(dpy, scre->root);
xcb_query_pointer_reply_t *poin = xcb_query_pointer_reply(dpy, coord, 0);
if ((values[2] == (uint32_t)(1)) && (win != 0)) {
xcb_get_geometry_cookie_t geom_now = xcb_get_geometry(dpy, win);
xcb_get_geometry_reply_t *geom = xcb_get_geometry_reply(dpy, geom_now, NULL);
uint16_t geom_x = geom->width + (2 * BORDER_WIDTH);
uint16_t geom_y = geom->height + (2 * BORDER_WIDTH);
values[0] = ((poin->root_x + geom_x) > scre->width_in_pixels) ?
(scre->width_in_pixels - geom_x) : poin->root_x;
values[1] = ((poin->root_y + geom_y) > scre->height_in_pixels) ?
(scre->height_in_pixels - geom_y) : poin->root_y;
xcb_configure_window(dpy, win, XCB_CONFIG_WINDOW_X
| XCB_CONFIG_WINDOW_Y, values);
} else if ((values[2] == (uint32_t)(3)) && (win != 0)) {
xcb_get_geometry_cookie_t geom_now = xcb_get_geometry(dpy, win);
xcb_get_geometry_reply_t* geom = xcb_get_geometry_reply(dpy, geom_now, NULL);
if (!((poin->root_x <= geom->x) || (poin->root_y <= geom->y))) {
values[0] = poin->root_x - geom->x - BORDER_WIDTH;
values[1] = poin->root_y - geom->y - BORDER_WIDTH;
if ((values[0] >= (uint32_t)(WINDOW_MIN_WIDTH)) &&
(values[1] >= (uint32_t)(WINDOW_MIN_HEIGHT))) {
xcb_configure_window(dpy, win, XCB_CONFIG_WINDOW_WIDTH
| XCB_CONFIG_WINDOW_HEIGHT, values);
}
}
} else {}
}
static xcb_keycode_t *xcb_get_keycodes(xcb_keysym_t keysym) {
xcb_key_symbols_t *keysyms = xcb_key_symbols_alloc(dpy);
xcb_keycode_t *keycode;
keycode = (!(keysyms) ? NULL : xcb_key_symbols_get_keycode(keysyms, keysym));
xcb_key_symbols_free(keysyms);
return keycode;
}
static xcb_keysym_t xcb_get_keysym(xcb_keycode_t keycode) {
xcb_key_symbols_t *keysyms = xcb_key_symbols_alloc(dpy);
xcb_keysym_t keysym;
keysym = (!(keysyms) ? 0 : xcb_key_symbols_get_keysym(keysyms, keycode, 0));
xcb_key_symbols_free(keysyms);
return keysym;
}
static void setFocus(xcb_drawable_t window) {
if ((window != 0) && (window != scre->root)) {
xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, window,
XCB_CURRENT_TIME);
}
}
static void setFocusColor(xcb_window_t window, int focus) {
if ((BORDER_WIDTH > 0) && (scre->root != window) && (0 != window)) {
uint32_t vals[1];
vals[0] = focus ? BORDER_COLOR_FOCUSED : BORDER_COLOR_UNFOCUSED;
xcb_change_window_attributes(dpy, window, XCB_CW_BORDER_PIXEL, vals);
xcb_flush(dpy);
}
}
static void handleKeyPress(xcb_generic_event_t *ev) {
xcb_key_press_event_t *e = ( xcb_key_press_event_t *) ev;
xcb_keysym_t keysym = xcb_get_keysym(e->detail);
win = e->child;
int key_table_size = sizeof(keys) / sizeof(*keys);
for (int i = 0; i < key_table_size; ++i) {
if ((keys[i].keysym == keysym) && (keys[i].mod == e->state)) {
keys[i].func(keys[i].com);
}
}
}
static void handleEnterNotify(xcb_generic_event_t *ev) {
xcb_enter_notify_event_t *e = ( xcb_enter_notify_event_t *) ev;
setFocus(e->event);
}
static void handleButtonRelease(xcb_generic_event_t *ev) {
UNUSED(ev);
xcb_ungrab_pointer(dpy, XCB_CURRENT_TIME);
}
static void handleDestroyNotify(xcb_generic_event_t *ev) {
xcb_destroy_notify_event_t *e = (xcb_destroy_notify_event_t *) ev;
xcb_kill_client(dpy, e->window);
}
static void handleFocusIn(xcb_generic_event_t *ev) {
xcb_focus_in_event_t *e = (xcb_focus_in_event_t *) ev;
setFocusColor(e->event, 1);
}
static void handleFocusOut(xcb_generic_event_t *ev) {
xcb_focus_out_event_t *e = (xcb_focus_out_event_t *) ev;
setFocusColor(e->event, 0);
}
static void handleMapRequest(xcb_generic_event_t *ev) {
xcb_map_request_event_t *e = (xcb_map_request_event_t *) ev;
xcb_map_window(dpy, e->window);
uint32_t vals[5];
vals[0] = (scre->width_in_pixels / 2) - (WINDOW_WIDTH / 2);
vals[1] = (scre->height_in_pixels / 2) - (WINDOW_HEIGHT / 2);
vals[2] = WINDOW_WIDTH;
vals[3] = WINDOW_HEIGHT;
vals[4] = BORDER_WIDTH;
xcb_configure_window(dpy, e->window, XCB_CONFIG_WINDOW_X |
XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH |
XCB_CONFIG_WINDOW_HEIGHT | XCB_CONFIG_WINDOW_BORDER_WIDTH, vals);
xcb_flush(dpy);
values[0] = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE;
xcb_change_window_attributes_checked(dpy, e->window,
XCB_CW_EVENT_MASK, values);
setFocus(e->window);
}
static int eventHandler(void) {
int ret = xcb_connection_has_error(dpy);
if (ret == 0) {
xcb_generic_event_t *ev = xcb_wait_for_event(dpy);
if (ev != NULL) {
handler_func_t *handler;
for (handler = handler_funs; handler->func != NULL; handler++) {
if ((ev->response_type & ~0x80) == handler->request) {
handler->func(ev);
}
}
free(ev);
}
}
xcb_flush(dpy);
return ret;
}
static void setup(void) {
values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT
| XCB_EVENT_MASK_STRUCTURE_NOTIFY
| XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY
| XCB_EVENT_MASK_PROPERTY_CHANGE;
xcb_change_window_attributes_checked(dpy, scre->root,
XCB_CW_EVENT_MASK, values);
xcb_ungrab_key(dpy, XCB_GRAB_ANY, scre->root, XCB_MOD_MASK_ANY);
int key_table_size = sizeof(keys) / sizeof(*keys);
for (int i = 0; i < key_table_size; ++i) {
xcb_keycode_t *keycode = xcb_get_keycodes(keys[i].keysym);
if (keycode != NULL) {
xcb_grab_key(dpy, 1, scre->root, keys[i].mod, *keycode,
XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC );
}
}
xcb_flush(dpy);
xcb_grab_button(dpy, 0, scre->root, XCB_EVENT_MASK_BUTTON_PRESS |
XCB_EVENT_MASK_BUTTON_RELEASE, XCB_GRAB_MODE_ASYNC,
XCB_GRAB_MODE_ASYNC, scre->root, XCB_NONE, 1, MOD1);
xcb_grab_button(dpy, 0, scre->root, XCB_EVENT_MASK_BUTTON_PRESS |
XCB_EVENT_MASK_BUTTON_RELEASE, XCB_GRAB_MODE_ASYNC,
XCB_GRAB_MODE_ASYNC, scre->root, XCB_NONE, 3, MOD1);
xcb_flush(dpy);
}
static int die(char *errstr) {
size_t n = 0;
char *p = errstr;
while ((* (p++)) != 0) {
++n;
}
ssize_t o = write(STDERR_FILENO, errstr, n);
int ret = 1;
if (o < 0) {
ret = -1;
}
return ret;
}
static int strcmp_c(char *str1, char *str2) {
char *c1 = str1;
char *c2 = str2;
while ((* c1) && ((* c1) == (* c2))) {
++c1;
++c2;
}
int n = (* c1) - (* c2);
return n;
}
int main(int argc, char *argv[]) {
int ret = 0;
if ((argc == 2) && (strcmp_c("-v", argv[1]) == 0)) {
ret = die("xwm-0.1.9, Copyright © 2021-2022 Michael Czigler, MIT License\n");
}
if ((ret == 0) && (argc != 1)) {
ret = die("usage: xwm [-v]\n");
}
if (ret == 0) {
dpy = xcb_connect(NULL, NULL);
ret = xcb_connection_has_error(dpy);
if (ret > 0) {
ret = die("xcb_connection_has_error\n");
}
}
if (ret == 0) {
scre = xcb_setup_roots_iterator(xcb_get_setup(dpy)).data;
setup();
}
while (ret == 0) {
ret = eventHandler();
}
return ret;
}
================================================
FILE: xwm.h
================================================
/* See LICENSE file for copyright and license details. */
/* typedefs */
typedef struct {
unsigned int mod;
xcb_keysym_t keysym;
void (*func)(char **com);
char **com;
} Key;
typedef struct {
uint32_t request;
void (*func)(xcb_generic_event_t *ev);
} handler_func_t;
/* convert keycode to keysym and back */
static xcb_keycode_t *xcb_get_keycodes(xcb_keysym_t keysym);
static xcb_keysym_t xcb_get_keysym(xcb_keycode_t keycode);
/* user defined command actions */
static void killclient(char **com);
static void spawn(char **com);
static void closewm(char **com);
static void fullclient(char **com);
/* window behavior */
static void setFocus(xcb_drawable_t window);
static void setFocusColor(xcb_drawable_t window, int focus);
/* event hander actions */
static int eventHandler(void);
static void handleMotionNotify(xcb_generic_event_t *ev);
static void handleEnterNotify(xcb_generic_event_t *ev);
static void handleDestroyNotify(xcb_generic_event_t *ev);
static void handleButtonPress(xcb_generic_event_t *ev);
static void handleButtonRelease(xcb_generic_event_t *ev);
static void handleKeyPress(xcb_generic_event_t *ev);
static void handleMapRequest(xcb_generic_event_t *ev);
static void handleFocusIn(xcb_generic_event_t *ev);
static void handleFocusOut(xcb_generic_event_t *ev);
static handler_func_t handler_funs[] = {
{ XCB_MOTION_NOTIFY, handleMotionNotify },
{ XCB_ENTER_NOTIFY, handleEnterNotify },
{ XCB_DESTROY_NOTIFY, handleDestroyNotify },
{ XCB_BUTTON_PRESS, handleButtonPress },
{ XCB_BUTTON_RELEASE, handleButtonRelease },
{ XCB_KEY_PRESS, handleKeyPress },
{ XCB_MAP_REQUEST, handleMapRequest },
{ XCB_FOCUS_IN, handleFocusIn },
{ XCB_FOCUS_OUT, handleFocusOut },
{ XCB_NONE, NULL }
};
/* intialize */
static void setup(void);
/* error handling & misc. */
static int die(char *errstr);
static int strcmp_c(char *str1, char *str2);
gitextract_sdyjtq5f/ ├── .github/ │ ├── CONTRIBUTING │ ├── FUNDING.yml │ └── workflows/ │ └── codacy-analysis.yml ├── .gitignore ├── CHANGELOG ├── LICENSE ├── Makefile ├── README ├── config.h ├── xwm.1 ├── xwm.c └── xwm.h
SYMBOL INDEX (24 symbols across 2 files)
FILE: xwm.c
function killclient (line 17) | static void killclient(char **com) {
function closewm (line 22) | static void closewm(char **com) {
function spawn (line 29) | static void spawn(char **com) {
function fullclient (line 41) | static void fullclient(char **com) {
function handleButtonPress (line 54) | static void handleButtonPress(xcb_generic_event_t *ev) {
function handleMotionNotify (line 66) | static void handleMotionNotify(xcb_generic_event_t *ev) {
function xcb_keycode_t (line 96) | static xcb_keycode_t *xcb_get_keycodes(xcb_keysym_t keysym) {
function xcb_keysym_t (line 104) | static xcb_keysym_t xcb_get_keysym(xcb_keycode_t keycode) {
function setFocus (line 112) | static void setFocus(xcb_drawable_t window) {
function setFocusColor (line 119) | static void setFocusColor(xcb_window_t window, int focus) {
function handleKeyPress (line 128) | static void handleKeyPress(xcb_generic_event_t *ev) {
function handleEnterNotify (line 140) | static void handleEnterNotify(xcb_generic_event_t *ev) {
function handleButtonRelease (line 145) | static void handleButtonRelease(xcb_generic_event_t *ev) {
function handleDestroyNotify (line 150) | static void handleDestroyNotify(xcb_generic_event_t *ev) {
function handleFocusIn (line 155) | static void handleFocusIn(xcb_generic_event_t *ev) {
function handleFocusOut (line 160) | static void handleFocusOut(xcb_generic_event_t *ev) {
function handleMapRequest (line 165) | static void handleMapRequest(xcb_generic_event_t *ev) {
function eventHandler (line 184) | static int eventHandler(void) {
function setup (line 202) | static void setup(void) {
function die (line 228) | static int die(char *errstr) {
function strcmp_c (line 242) | static int strcmp_c(char *str1, char *str2) {
function main (line 253) | int main(int argc, char *argv[]) {
FILE: xwm.h
type Key (line 4) | typedef struct {
type handler_func_t (line 11) | typedef struct {
Condensed preview — 12 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (26K chars).
[
{
"path": ".github/CONTRIBUTING",
"chars": 966,
"preview": "CONTRIBUTING\n============\n\nWant to contribute? Great! First, read this page.\n\nCode reviews:\n* All submissions, includi"
},
{
"path": ".github/FUNDING.yml",
"chars": 602,
"preview": "# These are supported funding model platforms\n\ngithub: mcpcpc\npatreon: # Replace with a single Patreon username\nopen_col"
},
{
"path": ".github/workflows/codacy-analysis.yml",
"chars": 1798,
"preview": "# This workflow checks out code, performs a Codacy security scan\n# and integrates the results with the\n# GitHub Advanced"
},
{
"path": ".gitignore",
"chars": 12,
"preview": "xwm\n*.a\n*.o\n"
},
{
"path": "CHANGELOG",
"chars": 2825,
"preview": "# Changelog\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changel"
},
{
"path": "LICENSE",
"chars": 1077,
"preview": "MIT License\n\nCopyright (c) 2021-2022 Michael Czigler\n\nPermission is hereby granted, free of charge, to any person obtain"
},
{
"path": "Makefile",
"chars": 692,
"preview": ".POSIX:\nALL_WARNING = -Wall -Wextra -pedantic\nALL_LDFLAGS = -lxcb -lxcb-keysyms $(LDFLAGS)\nALL_CFLAGS = $(CPPFLAGS) $(CF"
},
{
"path": "README",
"chars": 1919,
"preview": "xwm - a tiny XCB floating window manager\n========================================\n\nA minimal viable solution that was de"
},
{
"path": "config.h",
"chars": 2188,
"preview": "/* DEFAULT KEYS\n * The following are the possible mask definitions. Note\n * that these definitions may vary between X i"
},
{
"path": "xwm.1",
"chars": 1547,
"preview": ".\\\"Manpage for xwm.\n.TH XWM 1 \"NOVEMBER 2020\" Linux \"User Manuals\"\n.SH NAME\nxwm \\- a tiny XCB floating window manager\n.S"
},
{
"path": "xwm.c",
"chars": 8309,
"preview": "/* See LICENSE file for license details. */\n#include <stdlib.h>\n#include <sys/wait.h>\n#include <unistd.h>\n#include <xcb/"
},
{
"path": "xwm.h",
"chars": 1956,
"preview": "/* See LICENSE file for copyright and license details. */\n\n/* typedefs */\ntypedef struct {\n unsigned int mod;\n xcb"
}
]
About this extraction
This page contains the full source code of the mcpcpc/xwm GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 12 files (23.3 KB), approximately 7.2k tokens, and a symbol index with 24 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.