Fork ElemetryOS with macOS-style window decorations
- Move traffic-light buttons to the LEFT side of titlebars (close/minimize/maximize) in macOS order, using fixed left-pad positions instead of right-edge offsets - Adopt macOS dark-mode color palette: #3C3C3C active titlebar, #2C2C2C inactive, traffic-light colors #FF5F57/#FEBC2E/#28C840, near-black #1C1C1C desktop - Center window title text in the titlebar (macOS style), clamped to avoid overlapping the left button cluster - Thin 1px window borders replacing the original 3px beveled border - macOS blue (#4A90D9) selection highlight in the context menu - Neutral dark context menu (#2C2C2C) with subtle separators and text indent - Update README to document the ElemetryOS macOS fork identity and design changes
This commit is contained in:
4 files changed
+92
-87
No files matched your search
@@ -1,12 +1,22 @@
|
||||
# OrionOS
|
||||
# OrionOS — ElemetryOS macOS Fork
|
||||
|
||||
A BeOS-inspired Linux desktop built from scratch in C. Custom window manager, panel, app launcher, settings panel, package manager, and graphical installer — all running on Arch Linux, shipped as a bootable ISO.
|
||||
A macOS-inspired Linux desktop forked from ElemetryOS, built from scratch in C. Custom window manager, panel, app launcher, settings panel, package manager, and graphical installer — all running on Arch Linux, shipped as a bootable ISO.
|
||||
|
||||
---
|
||||
|
||||
## What it is
|
||||
|
||||
OrionOS is a complete desktop environment built on X11/Xlib with a dark navy aesthetic. It ships as a bootable ISO you can try live or install to disk. Every shell component is written in native C with no toolkit dependency — just Xlib and Xft.
|
||||
OrionOS is a complete desktop environment built on X11/Xlib with a macOS dark-mode aesthetic. It ships as a bootable ISO you can try live or install to disk. Every shell component is written in native C with no toolkit dependency — just Xlib and Xft.
|
||||
|
||||
### macOS design language
|
||||
|
||||
This fork re-skins the window manager with macOS design conventions:
|
||||
|
||||
- **Traffic-light buttons on the left** — close (red), minimize (yellow), maximize (green), just like macOS
|
||||
- **macOS dark-mode palette** — near-black desktop, `#3C3C3C` active titlebars, `#2C2C2C` inactive
|
||||
- **Centered window titles** — title text centered in the titlebar, macOS-style
|
||||
- **Thin 1 px borders** — minimal window chrome, no thick bevels
|
||||
- **macOS blue selection** (`#4A90D9`) in context menus and snap overlays
|
||||
|
||||
### Components
|
||||
|
||||
|
||||
+27
-26
@@ -12,28 +12,29 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* ── palette (modern dark) ───────────────────────────────────────────── */
|
||||
#define COLOR_TITLE_ACTIVE 0x1E4D78 /* deep blue active title bar */
|
||||
#define COLOR_TITLE_INACTIVE 0x252830 /* dark grey inactive */
|
||||
#define COLOR_TITLE_TEXT_ACT 0xE8EEF8 /* near-white active text */
|
||||
#define COLOR_TITLE_TEXT_INACT 0x5C6070 /* dimmed inactive text */
|
||||
#define COLOR_BORDER_LIGHT 0x3A6898 /* blue-grey highlight */
|
||||
#define COLOR_BORDER_DARK 0x0C1018 /* near-black shadow */
|
||||
#define COLOR_CLOSE_BTN 0xCC3333 /* red close */
|
||||
#define COLOR_MAXIMIZE_BTN 0x2E8B44 /* green maximize */
|
||||
#define COLOR_MINIMIZE_BTN 0xBB8820 /* amber minimize */
|
||||
#define COLOR_CLOSE_BTN_HOV 0xFF5050
|
||||
#define COLOR_MAXIMIZE_BTN_HOV 0x44CC66
|
||||
#define COLOR_MINIMIZE_BTN_HOV 0xFFBB30
|
||||
#define COLOR_BG 0x1A2840 /* desktop background */
|
||||
#define COLOR_SNAP_OVERLAY 0x3A6898 /* snap highlight (unused, placeholder) */
|
||||
/* ── palette (macOS dark mode) ───────────────────────────────────────── */
|
||||
#define COLOR_TITLE_ACTIVE 0x3C3C3C /* macOS dark titlebar */
|
||||
#define COLOR_TITLE_INACTIVE 0x2C2C2C /* inactive, slightly darker */
|
||||
#define COLOR_TITLE_TEXT_ACT 0xFFFFFF /* white active text */
|
||||
#define COLOR_TITLE_TEXT_INACT 0x686868 /* dimmed inactive text */
|
||||
#define COLOR_BORDER_LIGHT 0x505050 /* subtle border highlight */
|
||||
#define COLOR_BORDER_DARK 0x1C1C1C /* near-black shadow */
|
||||
#define COLOR_CLOSE_BTN 0xFF5F57 /* macOS traffic-light red */
|
||||
#define COLOR_MAXIMIZE_BTN 0x28C840 /* macOS traffic-light green */
|
||||
#define COLOR_MINIMIZE_BTN 0xFEBC2E /* macOS traffic-light yellow */
|
||||
#define COLOR_CLOSE_BTN_HOV 0xFF3B30
|
||||
#define COLOR_MAXIMIZE_BTN_HOV 0x34C759
|
||||
#define COLOR_MINIMIZE_BTN_HOV 0xFFCC00
|
||||
#define COLOR_BG 0x1C1C1C /* near-black desktop */
|
||||
#define COLOR_SNAP_OVERLAY 0x4A90D9 /* macOS blue snap highlight */
|
||||
|
||||
/* ── geometry ────────────────────────────────────────────────────────── */
|
||||
#define TITLE_HEIGHT 28 /* taller for modern look */
|
||||
#define TITLE_HEIGHT 28 /* macOS-style height */
|
||||
#define TITLE_TAB_W 200
|
||||
#define BORDER_W 3
|
||||
#define BTN_SIZE 14
|
||||
#define BTN_MARGIN 5
|
||||
#define BORDER_W 1 /* thin 1px macOS-style border */
|
||||
#define BTN_SIZE 12 /* macOS traffic-light diameter */
|
||||
#define BTN_MARGIN 8 /* spacing between traffic lights */
|
||||
#define BTN_LEFT_PAD 10 /* left edge → first button */
|
||||
#define RESIZE_GRIP 12
|
||||
#define MIN_WIN_W 120
|
||||
#define MIN_WIN_H 60
|
||||
@@ -41,14 +42,14 @@
|
||||
#define DBL_CLICK_MS 400 /* double-click threshold */
|
||||
|
||||
/*
|
||||
* Three buttons on right side (left to right): minimize, maximize, close
|
||||
* close = fw - BTN_SIZE - BTN_MARGIN - BORDER_W
|
||||
* max = close - BTN_SIZE - BTN_MARGIN - 2
|
||||
* min = max - BTN_SIZE - BTN_MARGIN - 2
|
||||
* macOS-style: three traffic-light buttons on LEFT side
|
||||
* close = BTN_LEFT_PAD
|
||||
* minimize = BTN_LEFT_PAD + BTN_SIZE + BTN_MARGIN
|
||||
* maximize = BTN_LEFT_PAD + (BTN_SIZE + BTN_MARGIN) * 2
|
||||
*/
|
||||
#define BTN_CLOSE_X(fw) ((fw) - BTN_SIZE - BTN_MARGIN - BORDER_W)
|
||||
#define BTN_MAX_X(fw) ((fw) - BTN_SIZE*2 - BTN_MARGIN*2 - BORDER_W - 2)
|
||||
#define BTN_MIN_X(fw) ((fw) - BTN_SIZE*3 - BTN_MARGIN*3 - BORDER_W - 4)
|
||||
#define BTN_CLOSE_X (BTN_LEFT_PAD)
|
||||
#define BTN_MIN_X (BTN_LEFT_PAD + BTN_SIZE + BTN_MARGIN)
|
||||
#define BTN_MAX_X (BTN_LEFT_PAD + (BTN_SIZE + BTN_MARGIN) * 2)
|
||||
#define BTN_Y (((TITLE_HEIGHT) - BTN_SIZE) / 2)
|
||||
|
||||
/* ── fonts ───────────────────────────────────────────────────────────── */
|
||||
|
||||
+37
-43
@@ -1,33 +1,30 @@
|
||||
#include "wm.h"
|
||||
|
||||
/*
|
||||
* Frame layout (3 buttons on right):
|
||||
* Frame layout — macOS style, traffic-light buttons on LEFT:
|
||||
*
|
||||
* ┌─[Title______________]──────[_][□][X]─┐ <- TITLE_HEIGHT
|
||||
* ┌─[●][●][●]──── Title (centered) ────────┐ <- TITLE_HEIGHT
|
||||
* │ content │
|
||||
* │ [grip]────┘
|
||||
* │ [grip]──────┘
|
||||
*/
|
||||
|
||||
/* ── hit tests ───────────────────────────────────────────────────────── */
|
||||
|
||||
int frame_hit_close(Client *c, int x, int y) {
|
||||
int fw = (int)c->w + BORDER_W * 2;
|
||||
int bx = BTN_CLOSE_X(fw);
|
||||
return (x >= bx && x <= bx + BTN_SIZE &&
|
||||
(void)c;
|
||||
return (x >= BTN_CLOSE_X && x <= BTN_CLOSE_X + BTN_SIZE &&
|
||||
y >= BTN_Y && y <= BTN_Y + BTN_SIZE);
|
||||
}
|
||||
|
||||
int frame_hit_maximize(Client *c, int x, int y) {
|
||||
int fw = (int)c->w + BORDER_W * 2;
|
||||
int bx = BTN_MAX_X(fw);
|
||||
return (x >= bx && x <= bx + BTN_SIZE &&
|
||||
(void)c;
|
||||
return (x >= BTN_MAX_X && x <= BTN_MAX_X + BTN_SIZE &&
|
||||
y >= BTN_Y && y <= BTN_Y + BTN_SIZE);
|
||||
}
|
||||
|
||||
int frame_hit_minimize(Client *c, int x, int y) {
|
||||
int fw = (int)c->w + BORDER_W * 2;
|
||||
int bx = BTN_MIN_X(fw);
|
||||
return (x >= bx && x <= bx + BTN_SIZE &&
|
||||
(void)c;
|
||||
return (x >= BTN_MIN_X && x <= BTN_MIN_X + BTN_SIZE &&
|
||||
y >= BTN_Y && y <= BTN_Y + BTN_SIZE);
|
||||
}
|
||||
|
||||
@@ -70,13 +67,14 @@ static void draw_circle_btn(WM *wm, Drawable d, int bx, int by,
|
||||
}
|
||||
|
||||
void frame_draw_buttons(WM *wm, Client *c) {
|
||||
int fw = (int)c->w + BORDER_W * 2;
|
||||
draw_circle_btn(wm, c->frame, BTN_CLOSE_X(fw), BTN_Y,
|
||||
/* macOS order left-to-right: close, minimize, maximize */
|
||||
draw_circle_btn(wm, c->frame, BTN_CLOSE_X, BTN_Y,
|
||||
color_alloc(wm, COLOR_CLOSE_BTN), 'X');
|
||||
draw_circle_btn(wm, c->frame, BTN_MAX_X(fw), BTN_Y,
|
||||
color_alloc(wm, COLOR_MAXIMIZE_BTN), 'O');
|
||||
draw_circle_btn(wm, c->frame, BTN_MIN_X(fw), BTN_Y,
|
||||
draw_circle_btn(wm, c->frame, BTN_MIN_X, BTN_Y,
|
||||
color_alloc(wm, COLOR_MINIMIZE_BTN), '_');
|
||||
draw_circle_btn(wm, c->frame, BTN_MAX_X, BTN_Y,
|
||||
color_alloc(wm, COLOR_MAXIMIZE_BTN), 'O');
|
||||
(void)c;
|
||||
}
|
||||
|
||||
/* ── resize grip ─────────────────────────────────────────────────────── */
|
||||
@@ -101,7 +99,6 @@ void frame_draw(WM *wm, Client *c) {
|
||||
int fw = (int)c->w + BORDER_W * 2;
|
||||
int fh = (int)c->h + TITLE_HEIGHT + BORDER_W;
|
||||
|
||||
unsigned long col_light = color_alloc(wm, COLOR_BORDER_LIGHT);
|
||||
unsigned long col_dark = color_alloc(wm, COLOR_BORDER_DARK);
|
||||
|
||||
/* title bar background */
|
||||
@@ -110,45 +107,42 @@ void frame_draw(WM *wm, Client *c) {
|
||||
XSetForeground(wm->dpy, wm->gc, col_title);
|
||||
XFillRectangle(wm->dpy, c->frame, wm->gc, 0, 0, fw, TITLE_HEIGHT);
|
||||
|
||||
/* subtle gradient effect: lighter top strip (2px) */
|
||||
if (c->focused) {
|
||||
unsigned long lighter = color_alloc(wm, 0x2A6098);
|
||||
XSetForeground(wm->dpy, wm->gc, lighter);
|
||||
XFillRectangle(wm->dpy, c->frame, wm->gc, 0, 0, fw, 2);
|
||||
}
|
||||
|
||||
/* client area background strip (below title) */
|
||||
/* thin borders (1px, macOS style) */
|
||||
XSetForeground(wm->dpy, wm->gc, col_dark);
|
||||
XFillRectangle(wm->dpy, c->frame, wm->gc, 0, TITLE_HEIGHT, BORDER_W, fh - TITLE_HEIGHT);
|
||||
XFillRectangle(wm->dpy, c->frame, wm->gc, fw - BORDER_W, TITLE_HEIGHT, BORDER_W, fh - TITLE_HEIGHT);
|
||||
XFillRectangle(wm->dpy, c->frame, wm->gc, 0, fh - BORDER_W, fw, BORDER_W);
|
||||
|
||||
/* outer bevel */
|
||||
XSetForeground(wm->dpy, wm->gc, col_light);
|
||||
XDrawLine(wm->dpy, c->frame, wm->gc, 0, 0, fw - 1, 0);
|
||||
XDrawLine(wm->dpy, c->frame, wm->gc, 0, 0, 0, fh - 1);
|
||||
XSetForeground(wm->dpy, wm->gc, col_dark);
|
||||
XDrawLine(wm->dpy, c->frame, wm->gc, fw-1, 0, fw-1, fh-1);
|
||||
XDrawLine(wm->dpy, c->frame, wm->gc, 0, fh-1, fw-1, fh-1);
|
||||
|
||||
/* thin separator line under title */
|
||||
XSetForeground(wm->dpy, wm->gc, col_dark);
|
||||
/* subtle 1px separator under titlebar */
|
||||
unsigned long col_sep = color_alloc(wm, 0x1A1A1A);
|
||||
XSetForeground(wm->dpy, wm->gc, col_sep);
|
||||
XDrawLine(wm->dpy, c->frame, wm->gc, 0, TITLE_HEIGHT - 1, fw - 1, TITLE_HEIGHT - 1);
|
||||
|
||||
/* title text */
|
||||
int btn_area = BTN_SIZE * 3 + BTN_MARGIN * 3 + BORDER_W + 8;
|
||||
int text_max_w = fw - BORDER_W * 2 - btn_area - 8;
|
||||
if (text_max_w < 10) text_max_w = 10;
|
||||
|
||||
/* centered title text (macOS style) */
|
||||
XftDraw *xd = XftDrawCreate(wm->dpy, c->frame, wm->visual, wm->cmap);
|
||||
if (xd) {
|
||||
XftColor col_text;
|
||||
xft_color(wm, c->focused ? COLOR_TITLE_TEXT_ACT : COLOR_TITLE_TEXT_INACT, &col_text);
|
||||
XRectangle clip = { BORDER_W + 4, 1, (unsigned short)text_max_w, TITLE_HEIGHT - 2 };
|
||||
|
||||
XGlyphInfo ext;
|
||||
XftTextExtentsUtf8(wm->dpy, wm->font_title,
|
||||
(const FcChar8 *)c->title, strlen(c->title), &ext);
|
||||
|
||||
/* center in the full title bar */
|
||||
int tx = (fw - ext.width) / 2;
|
||||
/* clamp so text doesn't overlap the left buttons */
|
||||
int left_btn_end = BTN_MAX_X + BTN_SIZE + 6;
|
||||
if (tx < left_btn_end) tx = left_btn_end;
|
||||
|
||||
int text_max_w = fw - tx - 8;
|
||||
if (text_max_w < 10) text_max_w = 10;
|
||||
|
||||
XRectangle clip = { (short)tx, 1, (unsigned short)text_max_w, TITLE_HEIGHT - 2 };
|
||||
XftDrawSetClipRectangles(xd, 0, 0, &clip, 1);
|
||||
|
||||
int ty = (TITLE_HEIGHT + wm->font_title->ascent - wm->font_title->descent) / 2;
|
||||
XftDrawStringUtf8(xd, &col_text, wm->font_title,
|
||||
BORDER_W + 6, ty,
|
||||
tx, ty,
|
||||
(const FcChar8 *)c->title, strlen(c->title));
|
||||
XftColorFree(wm->dpy, wm->visual, wm->cmap, &col_text);
|
||||
XftDrawDestroy(xd);
|
||||
|
||||
+15
-15
@@ -1,7 +1,7 @@
|
||||
#include "wm.h"
|
||||
|
||||
#define MENU_ITEM_H 24
|
||||
#define MENU_W 220
|
||||
#define MENU_ITEM_H 26
|
||||
#define MENU_W 230
|
||||
#define MENU_PADDING 5
|
||||
|
||||
static const MenuItem MENU_ITEMS[] = {
|
||||
@@ -51,7 +51,7 @@ void menu_show(WM *wm, int x, int y) {
|
||||
|
||||
XSetWindowAttributes swa;
|
||||
swa.override_redirect = True;
|
||||
swa.background_pixel = color_alloc(wm, 0x1C2030); /* dark menu bg */
|
||||
swa.background_pixel = color_alloc(wm, 0x2C2C2C); /* macOS dark menu bg */
|
||||
swa.event_mask = ExposureMask | ButtonPressMask
|
||||
| ButtonReleaseMask | PointerMotionMask
|
||||
| LeaveWindowMask;
|
||||
@@ -65,8 +65,8 @@ void menu_show(WM *wm, int x, int y) {
|
||||
&swa
|
||||
);
|
||||
|
||||
/* 1px accent border */
|
||||
XSetWindowBorder(wm->dpy, wm->menu_win, color_alloc(wm, COLOR_BORDER_LIGHT));
|
||||
/* subtle 1px border (macOS-like) */
|
||||
XSetWindowBorder(wm->dpy, wm->menu_win, color_alloc(wm, 0x505050));
|
||||
|
||||
XMapRaised(wm->dpy, wm->menu_win);
|
||||
wm->menu_visible = 1;
|
||||
@@ -110,29 +110,29 @@ void menu_draw(WM *wm) {
|
||||
if (!xd) return;
|
||||
|
||||
XftColor col_normal, col_hover_bg, col_hover_text, col_sep;
|
||||
xft_color(wm, 0xC8D4E8, &col_normal); /* light text on dark bg */
|
||||
xft_color(wm, 0x2060A0, &col_hover_bg); /* blue highlight */
|
||||
xft_color(wm, 0xF0F4FF, &col_hover_text);
|
||||
xft_color(wm, 0x303848, &col_sep);
|
||||
xft_color(wm, 0xE8E8E8, &col_normal); /* macOS light menu text */
|
||||
xft_color(wm, 0x4A90D9, &col_hover_bg); /* macOS blue selection */
|
||||
xft_color(wm, 0xFFFFFF, &col_hover_text);
|
||||
xft_color(wm, 0x444444, &col_sep);
|
||||
|
||||
/* clear background */
|
||||
XSetForeground(wm->dpy, wm->gc, color_alloc(wm, 0x1C2030));
|
||||
XSetForeground(wm->dpy, wm->gc, color_alloc(wm, 0x2C2C2C));
|
||||
XFillRectangle(wm->dpy, wm->menu_win, wm->gc, 0, 0, MENU_W, menu_height());
|
||||
|
||||
for (int i = 0; i < MENU_COUNT; i++) {
|
||||
int iy = item_y(i);
|
||||
|
||||
if (is_separator(i)) {
|
||||
XSetForeground(wm->dpy, wm->gc, color_alloc(wm, 0x2A3040));
|
||||
XSetForeground(wm->dpy, wm->gc, color_alloc(wm, 0x3C3C3C));
|
||||
XDrawLine(wm->dpy, wm->menu_win, wm->gc, 8, iy + 4, MENU_W - 8, iy + 4);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* hover highlight */
|
||||
/* hover highlight — macOS blue selection pill */
|
||||
if (i == wm->menu_hovered && wm->menu_hovered >= 0) {
|
||||
XSetForeground(wm->dpy, wm->gc, color_alloc(wm, 0x4A6888));
|
||||
XSetForeground(wm->dpy, wm->gc, color_alloc(wm, 0x4A90D9));
|
||||
XFillRectangle(wm->dpy, wm->menu_win, wm->gc,
|
||||
2, iy, MENU_W - 4, MENU_ITEM_H);
|
||||
4, iy + 1, MENU_W - 8, MENU_ITEM_H - 2);
|
||||
}
|
||||
|
||||
XftColor *tc = (i == wm->menu_hovered) ? &col_hover_text : &col_normal;
|
||||
@@ -142,7 +142,7 @@ void menu_draw(WM *wm) {
|
||||
strlen(MENU_ITEMS[i].label), &ext);
|
||||
int ty = iy + (MENU_ITEM_H - ext.height) / 2 + ext.height - ext.y;
|
||||
XftDrawStringUtf8(xd, tc, wm->font_menu,
|
||||
MENU_PADDING + 4, ty,
|
||||
MENU_PADDING + 10, ty,
|
||||
(const FcChar8 *)MENU_ITEMS[i].label,
|
||||
strlen(MENU_ITEMS[i].label));
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user