- Super+1-4: switch virtual desktop; Super+Shift+1-4: move focused window to desktop N - Super+Space: Exposé window overview (tiled grid), click to select, Escape to cancel - wm/src/expose.c: expose_show/expose_hide using ceil(sqrt) grid layout with saved/restored geometry - client_move_to_desktop(): moves window between desktops, fires _NET_WM_DESKTOP update - on_client_message: handles _NET_WM_DESKTOP to move windows from external requests - deskbar: optional imlib2 app icon rendering (Papirus-Dark → Papirus → hicolor → pixmaps fallback) - deskbar: XGetClassHint populates cls field for better icon lookup - deskbar: context menu extended with separator + "→ Desktop 1-4" items via _NET_WM_DESKTOP - orionnotify/: freedesktop.org notification daemon (libdbus-1), stacks up to 5 popups top-right - orionlock/: PAM-authenticated fullscreen screen lock with clock, date, password dots - Lock Screen menu item wired to orionlock - Root Makefile includes orionnotify and orionlock targets Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHiBQKPfUoaJgCKuA9op1H
222 lines
7.6 KiB
C
222 lines
7.6 KiB
C
#ifndef WM_H
|
|
#define WM_H
|
|
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xutil.h>
|
|
#include <X11/Xatom.h>
|
|
#include <X11/keysym.h>
|
|
#include <X11/Xft/Xft.h>
|
|
#include <X11/cursorfont.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
/* ── 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 DESKBAR_W 200 /* must match DB_W in deskbar/include/deskbar.h */
|
|
#define TITLE_HEIGHT 28 /* macOS-style height */
|
|
#define TITLE_TAB_W 200
|
|
#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
|
|
#define SNAP_DIST 24 /* px from edge to trigger snap */
|
|
#define DBL_CLICK_MS 400 /* double-click threshold */
|
|
|
|
/*
|
|
* 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 (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 ───────────────────────────────────────────────────────────── */
|
|
#define FONT_TITLE "Sans:size=9:weight=bold"
|
|
#define FONT_MENU "Sans:size=10"
|
|
|
|
/* ── drag mode ───────────────────────────────────────────────────────── */
|
|
typedef enum { DRAG_NONE, DRAG_MOVE, DRAG_RESIZE } DragMode;
|
|
|
|
/* WM_STATE values (ICCCM) */
|
|
#define WM_STATE_NORMAL 1
|
|
#define WM_STATE_ICONIC 3
|
|
#define WM_STATE_WITHDRAWN 0
|
|
|
|
typedef struct Client {
|
|
Window win;
|
|
Window frame;
|
|
int x, y;
|
|
unsigned int w, h;
|
|
int focused;
|
|
int minimized;
|
|
int maximized;
|
|
int desktop; /* virtual desktop this window lives on */
|
|
int saved_x, saved_y; /* pre-maximize position */
|
|
unsigned saved_w, saved_h; /* pre-maximize size */
|
|
Time last_click_time; /* for double-click detection */
|
|
char title[256];
|
|
/* ICCCM WM_NORMAL_HINTS */
|
|
int min_w, min_h; /* PMinSize */
|
|
int inc_w, inc_h; /* PResizeInc — 0 means no constraint */
|
|
int base_w, base_h; /* PBaseSize — baseline for increment calc */
|
|
/* Exposé saved geometry */
|
|
int exp_x, exp_y;
|
|
unsigned exp_w, exp_h;
|
|
struct Client *next;
|
|
} Client;
|
|
|
|
typedef struct MenuItem {
|
|
const char *label;
|
|
const char *cmd;
|
|
} MenuItem;
|
|
|
|
typedef struct WM {
|
|
Display *dpy;
|
|
int screen;
|
|
Window root;
|
|
GC gc;
|
|
Colormap cmap;
|
|
Visual *visual;
|
|
int depth;
|
|
|
|
XftFont *font_title;
|
|
XftFont *font_menu;
|
|
|
|
Cursor cur_normal;
|
|
Cursor cur_move;
|
|
Cursor cur_resize;
|
|
|
|
Client *clients;
|
|
Client *focused;
|
|
|
|
int cur_desktop; /* active virtual desktop (0-based) */
|
|
|
|
Atom wm_delete_window;
|
|
Atom wm_protocols;
|
|
Atom wm_state;
|
|
Atom net_wm_name;
|
|
Atom net_wm_state;
|
|
Atom net_wm_state_hidden;
|
|
Atom net_wm_state_maximized_vert;
|
|
Atom net_wm_state_maximized_horz;
|
|
Atom net_wm_desktop;
|
|
Atom net_current_desktop;
|
|
|
|
DragMode drag_mode;
|
|
int drag_start_x, drag_start_y;
|
|
int drag_win_x, drag_win_y;
|
|
unsigned drag_win_w, drag_win_h;
|
|
Window drag_frame;
|
|
|
|
Window menu_win;
|
|
int menu_visible;
|
|
int menu_x, menu_y;
|
|
int menu_hovered;
|
|
|
|
/* Alt+Tab visual switcher */
|
|
Window swl_win;
|
|
int swl_visible;
|
|
int swl_idx;
|
|
int swl_count;
|
|
Window swl_wins[64];
|
|
char swl_titles[64][128];
|
|
int swl_mini[64]; /* 1 if corresponding entry is minimized */
|
|
|
|
/* Exposé window overview */
|
|
int expose_active;
|
|
int expose_count;
|
|
Window expose_wins[64]; /* frames shown in overview */
|
|
} WM;
|
|
|
|
/* core */
|
|
void wm_init(WM *wm);
|
|
void wm_run(WM *wm);
|
|
void wm_cleanup(WM *wm);
|
|
|
|
/* client */
|
|
Client *client_add(WM *wm, Window win);
|
|
void client_remove(WM *wm, Window win);
|
|
Client *client_find_by_frame(WM *wm, Window frame);
|
|
Client *client_find_by_win(WM *wm, Window win);
|
|
void client_focus(WM *wm, Client *c);
|
|
void client_raise(WM *wm, Client *c);
|
|
void client_minimize(WM *wm, Client *c);
|
|
void client_restore(WM *wm, Client *c);
|
|
void client_maximize(WM *wm, Client *c);
|
|
void client_unmaximize(WM *wm, Client *c);
|
|
void client_toggle_maximize(WM *wm, Client *c);
|
|
void client_snap_left(WM *wm, Client *c);
|
|
void client_snap_right(WM *wm, Client *c);
|
|
void client_set_wm_state(WM *wm, Client *c, long state);
|
|
void client_move_to_desktop(WM *wm, Client *c, int new_desk);
|
|
|
|
/* drawing */
|
|
void frame_draw(WM *wm, Client *c);
|
|
void frame_draw_buttons(WM *wm, Client *c);
|
|
unsigned long color_alloc(WM *wm, unsigned long rgb);
|
|
void xft_color(WM *wm, unsigned long rgb, XftColor *out);
|
|
|
|
/* hit testing */
|
|
int frame_hit_resize(Client *c, int x, int y);
|
|
int frame_hit_close(Client *c, int x, int y);
|
|
int frame_hit_minimize(Client *c, int x, int y);
|
|
int frame_hit_maximize(Client *c, int x, int y);
|
|
|
|
/* menu */
|
|
void menu_show(WM *wm, int x, int y);
|
|
void menu_hide(WM *wm);
|
|
void menu_draw(WM *wm);
|
|
void menu_click(WM *wm, int px, int py);
|
|
int menu_item_at(int py);
|
|
|
|
/* switcher */
|
|
void switcher_show(WM *wm);
|
|
void switcher_next(WM *wm);
|
|
void switcher_prev(WM *wm);
|
|
void switcher_hide(WM *wm, int commit);
|
|
void switcher_draw(WM *wm);
|
|
|
|
/* exposé */
|
|
void expose_show(WM *wm);
|
|
void expose_hide(WM *wm, Window selected_frame);
|
|
|
|
/* events */
|
|
void on_map_request(WM *wm, XMapRequestEvent *e);
|
|
void on_unmap_notify(WM *wm, XUnmapEvent *e);
|
|
void on_destroy_notify(WM *wm, XDestroyWindowEvent *e);
|
|
void on_expose(WM *wm, XExposeEvent *e);
|
|
void on_button_press(WM *wm, XButtonEvent *e);
|
|
void on_button_release(WM *wm, XButtonEvent *e);
|
|
void on_motion_notify(WM *wm, XMotionEvent *e);
|
|
void on_configure_request(WM *wm, XConfigureRequestEvent *e);
|
|
void on_key_press(WM *wm, XKeyEvent *e);
|
|
void on_enter_notify(WM *wm, XCrossingEvent *e);
|
|
void on_client_message(WM *wm, XClientMessageEvent *e);
|
|
void on_property_notify(WM *wm, XPropertyEvent *e);
|
|
void on_key_release(WM *wm, XKeyEvent *e);
|
|
|
|
#endif
|