Fixes #7–#11: launcher Other tab, ICCCM size hints, icon loading, multi-desktop
Fix #7: Add "Other" catch-all category to the launcher. map_category() now returns "Other" instead of "" for unrecognized .desktop Categories, and an "Other" tab is added to the CATS list so those apps are discoverable instead of silently hidden. Fix #8: Respect ICCCM WM_NORMAL_HINTS. client_add() reads PMinSize, PResizeInc, and PBaseSize from the window's size hints. The resize drag handler in events.c clamps to min_w/min_h and snaps to the width_inc/height_inc grid, fixing jank in character-cell terminal emulators (xterm, Alacritty). Fix #10: Optional freedesktop icon loading via imlib2. The launcher now parses the Icon= field from .desktop files and attempts to render a PNG icon from Papirus-Dark (or hicolor fallback). When imlib2 is not present the existing letter-square is shown unchanged. launcher/Makefile auto-detects imlib2 via pkg-config and sets -DHAVE_IMLIB2. Fix #11: True 4-desktop support in the WM. Each Client carries a desktop field (assigned at map time from wm->cur_desktop). Clicking a workspace button in the deskbar sends _NET_CURRENT_DESKTOP; the WM now handles it via wm_switch_desktop() which unmaps frames on the leaving desktop, maps frames on the arriving desktop, and re-focuses. _NET_WM_DESKTOP is set per window so the deskbar can filter db_update_apps() to show only current-desktop windows (sticky windows with desktop 0xFFFFFFFF are always shown).
This commit is contained in:
7 files changed
+165
-8
No files matched your search
@@ -111,8 +111,14 @@ void db_update_apps(Deskbar *db) {
|
|||||||
|
|
||||||
Atom net_wm_state = XInternAtom(db->dpy, "_NET_WM_STATE", False);
|
Atom net_wm_state = XInternAtom(db->dpy, "_NET_WM_STATE", False);
|
||||||
Atom net_wm_state_hidden = XInternAtom(db->dpy, "_NET_WM_STATE_HIDDEN", False);
|
Atom net_wm_state_hidden = XInternAtom(db->dpy, "_NET_WM_STATE_HIDDEN", False);
|
||||||
|
Atom net_wm_desktop = XInternAtom(db->dpy, "_NET_WM_DESKTOP", False);
|
||||||
|
|
||||||
for (unsigned long i = 0; i < n && db->napps < DB_MAX_APPS; i++) {
|
for (unsigned long i = 0; i < n && db->napps < DB_MAX_APPS; i++) {
|
||||||
|
/* only show windows on the current desktop (or sticky: desktop == 0xFFFFFFFF) */
|
||||||
|
long win_desk = ewmh_get_long(db, wins[i], net_wm_desktop);
|
||||||
|
if (win_desk >= 0 && win_desk != (long)db->cur_ws && win_desk != (long)0xFFFFFFFF)
|
||||||
|
continue;
|
||||||
|
|
||||||
db->apps[db->napps].win = wins[i];
|
db->apps[db->napps].win = wins[i];
|
||||||
db->apps[db->napps].focused = (wins[i] == (Window)active_win);
|
db->apps[db->napps].focused = (wins[i] == (Window)active_win);
|
||||||
db->apps[db->napps].minimized = 0;
|
db->apps[db->napps].minimized = 0;
|
||||||
@@ -1285,6 +1291,8 @@ void db_run(Deskbar *db) {
|
|||||||
db_draw(db);
|
db_draw(db);
|
||||||
} else if (e.xproperty.atom == db->net_current_desktop) {
|
} else if (e.xproperty.atom == db->net_current_desktop) {
|
||||||
db_update_workspace(db);
|
db_update_workspace(db);
|
||||||
|
db_update_apps(db); /* re-filter by new desktop */
|
||||||
|
db_resize(db);
|
||||||
db_draw(db);
|
db_draw(db);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -7,6 +7,14 @@ ifeq ($(PKG_XFT_C),)
|
|||||||
PKG_XFT_L := -L/opt/homebrew/lib -lXft -lfontconfig
|
PKG_XFT_L := -L/opt/homebrew/lib -lXft -lfontconfig
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Optional: imlib2 for freedesktop icon loading
|
||||||
|
PKG_IL_C := $(shell pkg-config --cflags imlib2 2>/dev/null)
|
||||||
|
PKG_IL_L := $(shell pkg-config --libs imlib2 2>/dev/null)
|
||||||
|
ifneq ($(PKG_IL_C),)
|
||||||
|
PKG_XFT_C += $(PKG_IL_C) -DHAVE_IMLIB2
|
||||||
|
PKG_XFT_L += $(PKG_IL_L)
|
||||||
|
endif
|
||||||
|
|
||||||
CFLAGS = -Wall -Wextra -O2 $(PKG_XFT_C)
|
CFLAGS = -Wall -Wextra -O2 $(PKG_XFT_C)
|
||||||
LDFLAGS = $(PKG_XFT_L)
|
LDFLAGS = $(PKG_XFT_L)
|
||||||
|
|
||||||
|
|||||||
+46
-5
@@ -58,13 +58,13 @@ static const unsigned long ICON_BG[] = {
|
|||||||
#define FONT_ICON "Sans:size=13:weight=bold"
|
#define FONT_ICON "Sans:size=13:weight=bold"
|
||||||
#define MAX_FLT 64
|
#define MAX_FLT 64
|
||||||
|
|
||||||
typedef struct { char name[64]; char cmd[256]; char cat[32]; } App;
|
typedef struct { char name[64]; char cmd[256]; char cat[32]; char icon[64]; } App;
|
||||||
|
|
||||||
static App APPS[MAX_APPS];
|
static App APPS[MAX_APPS];
|
||||||
static int NAPP = 0;
|
static int NAPP = 0;
|
||||||
|
|
||||||
static const char *CATS[] = {
|
static const char *CATS[] = {
|
||||||
"All", "Internet", "Media", "Office", "System", "Settings"
|
"All", "Internet", "Media", "Office", "System", "Settings", "Other"
|
||||||
};
|
};
|
||||||
#define NCAT ((int)(sizeof(CATS)/sizeof(CATS[0])))
|
#define NCAT ((int)(sizeof(CATS)/sizeof(CATS[0])))
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ static const char *map_category(const char *cats) {
|
|||||||
strstr(cats, "FileManager") || strstr(cats, "Utility") ||
|
strstr(cats, "FileManager") || strstr(cats, "Utility") ||
|
||||||
strstr(cats, "Monitor") || strstr(cats, "Security"))
|
strstr(cats, "Monitor") || strstr(cats, "Security"))
|
||||||
return "System";
|
return "System";
|
||||||
return "";
|
return "Other";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clean_exec(char *dst, const char *src, size_t dstsz) {
|
static void clean_exec(char *dst, const char *src, size_t dstsz) {
|
||||||
@@ -108,7 +108,7 @@ static void load_desktop_file(const char *path) {
|
|||||||
FILE *f = fopen(path, "r");
|
FILE *f = fopen(path, "r");
|
||||||
if (!f) return;
|
if (!f) return;
|
||||||
|
|
||||||
char name[64] = {0}, exec[256] = {0}, cats[128] = {0};
|
char name[64] = {0}, exec[256] = {0}, cats[128] = {0}, icon[64] = {0};
|
||||||
int in_entry = 0, nodisplay = 0, is_app = 0;
|
int in_entry = 0, nodisplay = 0, is_app = 0;
|
||||||
char line[512];
|
char line[512];
|
||||||
|
|
||||||
@@ -126,6 +126,8 @@ static void load_desktop_file(const char *path) {
|
|||||||
snprintf(exec, sizeof(exec), "%s", line + 5);
|
snprintf(exec, sizeof(exec), "%s", line + 5);
|
||||||
else if (!cats[0] && strncmp(line, "Categories=", 11) == 0)
|
else if (!cats[0] && strncmp(line, "Categories=", 11) == 0)
|
||||||
snprintf(cats, sizeof(cats), "%s", line + 11);
|
snprintf(cats, sizeof(cats), "%s", line + 11);
|
||||||
|
else if (!icon[0] && strncmp(line, "Icon=", 5) == 0)
|
||||||
|
snprintf(icon, sizeof(icon), "%s", line + 5);
|
||||||
else if (strncmp(line, "NoDisplay=true", 14) == 0)
|
else if (strncmp(line, "NoDisplay=true", 14) == 0)
|
||||||
nodisplay = 1;
|
nodisplay = 1;
|
||||||
else if (strncmp(line, "Type=Application", 16) == 0)
|
else if (strncmp(line, "Type=Application", 16) == 0)
|
||||||
@@ -137,6 +139,7 @@ static void load_desktop_file(const char *path) {
|
|||||||
snprintf(APPS[NAPP].name, 64, "%s", name);
|
snprintf(APPS[NAPP].name, 64, "%s", name);
|
||||||
clean_exec(APPS[NAPP].cmd, exec, 256);
|
clean_exec(APPS[NAPP].cmd, exec, 256);
|
||||||
snprintf(APPS[NAPP].cat, 32, "%s", map_category(cats));
|
snprintf(APPS[NAPP].cat, 32, "%s", map_category(cats));
|
||||||
|
snprintf(APPS[NAPP].icon, 64, "%s", icon);
|
||||||
NAPP++;
|
NAPP++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,6 +295,39 @@ static int card_at_vis(int x, int y) {
|
|||||||
return row * COLS + col;
|
return row * COLS + col;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ── icon loading (imlib2, optional) ─────────────────────────────────── */
|
||||||
|
#ifdef HAVE_IMLIB2
|
||||||
|
#include <Imlib2.h>
|
||||||
|
static const char *ICON_DIRS[] = {
|
||||||
|
"/usr/share/icons/Papirus-Dark/48x48/apps",
|
||||||
|
"/usr/share/icons/Papirus/48x48/apps",
|
||||||
|
"/usr/share/icons/hicolor/48x48/apps",
|
||||||
|
"/usr/share/pixmaps",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
static int render_icon(L *l, const char *icon_name, int ix, int iy, int sz) {
|
||||||
|
if (!icon_name || !icon_name[0]) return 0;
|
||||||
|
char path[512];
|
||||||
|
for (int i = 0; ICON_DIRS[i]; i++) {
|
||||||
|
snprintf(path, sizeof(path), "%s/%s.png", ICON_DIRS[i], icon_name);
|
||||||
|
if (access(path, R_OK) == 0) goto found;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
found:;
|
||||||
|
imlib_context_set_display(l->dpy);
|
||||||
|
imlib_context_set_visual(l->visual);
|
||||||
|
imlib_context_set_colormap(l->cmap);
|
||||||
|
imlib_context_set_drawable(l->win);
|
||||||
|
imlib_context_set_blend(1);
|
||||||
|
Imlib_Image img = imlib_load_image_immediately(path);
|
||||||
|
if (!img) return 0;
|
||||||
|
imlib_context_set_image(img);
|
||||||
|
imlib_render_image_on_drawable_at_size(ix, iy, sz, sz);
|
||||||
|
imlib_free_image();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ── draw ────────────────────────────────────────────────────────────── */
|
/* ── draw ────────────────────────────────────────────────────────────── */
|
||||||
static void draw(L *l) {
|
static void draw(L *l) {
|
||||||
XftDraw *xd = XftDrawCreate(l->dpy, l->win, l->visual, l->cmap);
|
XftDraw *xd = XftDrawCreate(l->dpy, l->win, l->visual, l->cmap);
|
||||||
@@ -382,12 +418,17 @@ static void draw(L *l) {
|
|||||||
for (const char *p = APPS[app_i].name; *p; p++) h = h * 31 + (unsigned char)*p;
|
for (const char *p = APPS[app_i].name; *p; p++) h = h * 31 + (unsigned char)*p;
|
||||||
int ix = cx + (CARD_W - ICON_SZ) / 2;
|
int ix = cx + (CARD_W - ICON_SZ) / 2;
|
||||||
int iy = cy + 10;
|
int iy = cy + 10;
|
||||||
|
int icon_rendered = 0;
|
||||||
|
#ifdef HAVE_IMLIB2
|
||||||
|
icon_rendered = render_icon(l, APPS[app_i].icon, ix, iy, ICON_SZ);
|
||||||
|
#endif
|
||||||
|
if (!icon_rendered) {
|
||||||
XSetForeground(l->dpy, l->gc, mkc(l, ICON_BG[h % NICON]));
|
XSetForeground(l->dpy, l->gc, mkc(l, ICON_BG[h % NICON]));
|
||||||
XFillRectangle(l->dpy, l->win, l->gc, ix, iy, ICON_SZ, ICON_SZ);
|
XFillRectangle(l->dpy, l->win, l->gc, ix, iy, ICON_SZ, ICON_SZ);
|
||||||
|
|
||||||
char letter[2] = { APPS[app_i].name[0], '\0' };
|
char letter[2] = { APPS[app_i].name[0], '\0' };
|
||||||
if (letter[0] >= 'a' && letter[0] <= 'z') letter[0] -= 32;
|
if (letter[0] >= 'a' && letter[0] <= 'z') letter[0] -= 32;
|
||||||
ds_ctr(l, xd, l->font_icon, 0xEAF0FF, ix, iy, ICON_SZ, ICON_SZ, letter);
|
ds_ctr(l, xd, l->font_icon, 0xEAF0FF, ix, iy, ICON_SZ, ICON_SZ, letter);
|
||||||
|
}
|
||||||
|
|
||||||
char lbl[14];
|
char lbl[14];
|
||||||
snprintf(lbl, sizeof(lbl), "%.12s", APPS[app_i].name);
|
snprintf(lbl, sizeof(lbl), "%.12s", APPS[app_i].name);
|
||||||
|
|||||||
@@ -73,10 +73,15 @@ typedef struct Client {
|
|||||||
int focused;
|
int focused;
|
||||||
int minimized;
|
int minimized;
|
||||||
int maximized;
|
int maximized;
|
||||||
|
int desktop; /* virtual desktop this window lives on */
|
||||||
int saved_x, saved_y; /* pre-maximize position */
|
int saved_x, saved_y; /* pre-maximize position */
|
||||||
unsigned saved_w, saved_h; /* pre-maximize size */
|
unsigned saved_w, saved_h; /* pre-maximize size */
|
||||||
Time last_click_time; /* for double-click detection */
|
Time last_click_time; /* for double-click detection */
|
||||||
char title[256];
|
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 */
|
||||||
struct Client *next;
|
struct Client *next;
|
||||||
} Client;
|
} Client;
|
||||||
|
|
||||||
@@ -104,6 +109,8 @@ typedef struct WM {
|
|||||||
Client *clients;
|
Client *clients;
|
||||||
Client *focused;
|
Client *focused;
|
||||||
|
|
||||||
|
int cur_desktop; /* active virtual desktop (0-based) */
|
||||||
|
|
||||||
Atom wm_delete_window;
|
Atom wm_delete_window;
|
||||||
Atom wm_protocols;
|
Atom wm_protocols;
|
||||||
Atom wm_state;
|
Atom wm_state;
|
||||||
@@ -112,6 +119,8 @@ typedef struct WM {
|
|||||||
Atom net_wm_state_hidden;
|
Atom net_wm_state_hidden;
|
||||||
Atom net_wm_state_maximized_vert;
|
Atom net_wm_state_maximized_vert;
|
||||||
Atom net_wm_state_maximized_horz;
|
Atom net_wm_state_maximized_horz;
|
||||||
|
Atom net_wm_desktop;
|
||||||
|
Atom net_current_desktop;
|
||||||
|
|
||||||
DragMode drag_mode;
|
DragMode drag_mode;
|
||||||
int drag_start_x, drag_start_y;
|
int drag_start_x, drag_start_y;
|
||||||
|
|||||||
@@ -57,6 +57,9 @@ Client *client_add(WM *wm, Window win) {
|
|||||||
c->win = win;
|
c->win = win;
|
||||||
c->w = wa.width;
|
c->w = wa.width;
|
||||||
c->h = wa.height;
|
c->h = wa.height;
|
||||||
|
c->desktop = wm->cur_desktop;
|
||||||
|
c->min_w = MIN_WIN_W;
|
||||||
|
c->min_h = MIN_WIN_H;
|
||||||
|
|
||||||
/* use application-requested position if non-zero, otherwise smart place */
|
/* use application-requested position if non-zero, otherwise smart place */
|
||||||
if (wa.x == 0 && wa.y == 0) {
|
if (wa.x == 0 && wa.y == 0) {
|
||||||
@@ -93,6 +96,36 @@ Client *client_add(WM *wm, Window win) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ICCCM WM_NORMAL_HINTS — size constraints and resize increments */
|
||||||
|
{
|
||||||
|
XSizeHints hints;
|
||||||
|
long supplied = 0;
|
||||||
|
if (XGetWMNormalHints(wm->dpy, win, &hints, &supplied)) {
|
||||||
|
if (hints.flags & PMinSize) {
|
||||||
|
if (hints.min_width > c->min_w) c->min_w = hints.min_width;
|
||||||
|
if (hints.min_height > c->min_h) c->min_h = hints.min_height;
|
||||||
|
}
|
||||||
|
if (hints.flags & PResizeInc) {
|
||||||
|
c->inc_w = hints.width_inc;
|
||||||
|
c->inc_h = hints.height_inc;
|
||||||
|
}
|
||||||
|
if (hints.flags & PBaseSize) {
|
||||||
|
c->base_w = hints.base_width;
|
||||||
|
c->base_h = hints.base_height;
|
||||||
|
} else if (hints.flags & PMinSize) {
|
||||||
|
c->base_w = hints.min_width;
|
||||||
|
c->base_h = hints.min_height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* advertise which desktop this window lives on */
|
||||||
|
{
|
||||||
|
long desk = wm->cur_desktop;
|
||||||
|
XChangeProperty(wm->dpy, win, wm->net_wm_desktop, XA_CARDINAL, 32,
|
||||||
|
PropModeReplace, (unsigned char *)&desk, 1);
|
||||||
|
}
|
||||||
|
|
||||||
int fw = (int)c->w + BORDER_W * 2;
|
int fw = (int)c->w + BORDER_W * 2;
|
||||||
int fh = (int)c->h + TITLE_HEIGHT + BORDER_W;
|
int fh = (int)c->h + TITLE_HEIGHT + BORDER_W;
|
||||||
|
|
||||||
|
|||||||
+56
-2
@@ -94,11 +94,55 @@ void on_enter_notify(WM *wm, XCrossingEvent *e) {
|
|||||||
if (c && !c->minimized) set_cursor(wm, c, e->x, e->y);
|
if (c && !c->minimized) set_cursor(wm, c, e->x, e->y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void wm_switch_desktop(WM *wm, int new_desk) {
|
||||||
|
if (new_desk < 0 || new_desk >= 4 || new_desk == wm->cur_desktop) return;
|
||||||
|
|
||||||
|
/* hide windows on old desktop */
|
||||||
|
for (Client *c = wm->clients; c; c = c->next) {
|
||||||
|
if (!c->minimized && c->desktop == wm->cur_desktop)
|
||||||
|
XUnmapWindow(wm->dpy, c->frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
wm->cur_desktop = new_desk;
|
||||||
|
|
||||||
|
/* show windows on new desktop */
|
||||||
|
for (Client *c = wm->clients; c; c = c->next) {
|
||||||
|
if (!c->minimized && c->desktop == new_desk)
|
||||||
|
XMapWindow(wm->dpy, c->frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update focus */
|
||||||
|
if (wm->focused && wm->focused->desktop != new_desk) {
|
||||||
|
wm->focused->focused = 0;
|
||||||
|
frame_draw(wm, wm->focused);
|
||||||
|
wm->focused = NULL;
|
||||||
|
}
|
||||||
|
if (!wm->focused) {
|
||||||
|
for (Client *c = wm->clients; c; c = c->next) {
|
||||||
|
if (!c->minimized && c->desktop == new_desk) {
|
||||||
|
client_focus(wm, c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* advertise new desktop */
|
||||||
|
long nd = new_desk;
|
||||||
|
XChangeProperty(wm->dpy, wm->root, wm->net_current_desktop, XA_CARDINAL, 32,
|
||||||
|
PropModeReplace, (unsigned char *)&nd, 1);
|
||||||
|
}
|
||||||
|
|
||||||
void on_client_message(WM *wm, XClientMessageEvent *e) {
|
void on_client_message(WM *wm, XClientMessageEvent *e) {
|
||||||
Atom net_active = XInternAtom(wm->dpy, "_NET_ACTIVE_WINDOW", False);
|
Atom net_active = XInternAtom(wm->dpy, "_NET_ACTIVE_WINDOW", False);
|
||||||
Atom net_close = XInternAtom(wm->dpy, "_NET_CLOSE_WINDOW", False);
|
Atom net_close = XInternAtom(wm->dpy, "_NET_CLOSE_WINDOW", False);
|
||||||
Atom wm_change_state = XInternAtom(wm->dpy, "WM_CHANGE_STATE", False);
|
Atom wm_change_state = XInternAtom(wm->dpy, "WM_CHANGE_STATE", False);
|
||||||
|
|
||||||
|
/* _NET_CURRENT_DESKTOP → switch virtual desktop */
|
||||||
|
if (e->message_type == wm->net_current_desktop && e->window == wm->root) {
|
||||||
|
wm_switch_desktop(wm, (int)e->data.l[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (e->message_type == net_active) {
|
if (e->message_type == net_active) {
|
||||||
Client *c = client_find_by_win(wm, e->window);
|
Client *c = client_find_by_win(wm, e->window);
|
||||||
if (c) client_restore(wm, c);
|
if (c) client_restore(wm, c);
|
||||||
@@ -271,8 +315,18 @@ void on_motion_notify(WM *wm, XMotionEvent *e) {
|
|||||||
} else {
|
} else {
|
||||||
int nw = (int)wm->drag_win_w + dx;
|
int nw = (int)wm->drag_win_w + dx;
|
||||||
int nh = (int)wm->drag_win_h + dy;
|
int nh = (int)wm->drag_win_h + dy;
|
||||||
if (nw < MIN_WIN_W) nw = MIN_WIN_W;
|
/* clamp to minimum */
|
||||||
if (nh < MIN_WIN_H) nh = MIN_WIN_H;
|
if (nw < c->min_w) nw = c->min_w;
|
||||||
|
if (nh < c->min_h) nh = c->min_h;
|
||||||
|
/* snap to resize-increment grid (e.g. terminal character cells) */
|
||||||
|
if (c->inc_w > 1) {
|
||||||
|
nw = c->base_w + ((nw - c->base_w) / c->inc_w) * c->inc_w;
|
||||||
|
if (nw < c->min_w) nw += c->inc_w;
|
||||||
|
}
|
||||||
|
if (c->inc_h > 1) {
|
||||||
|
nh = c->base_h + ((nh - c->base_h) / c->inc_h) * c->inc_h;
|
||||||
|
if (nh < c->min_h) nh += c->inc_h;
|
||||||
|
}
|
||||||
c->w = (unsigned)nw; c->h = (unsigned)nh;
|
c->w = (unsigned)nw; c->h = (unsigned)nh;
|
||||||
XResizeWindow(wm->dpy, c->frame, c->w+BORDER_W*2, c->h+TITLE_HEIGHT+BORDER_W);
|
XResizeWindow(wm->dpy, c->frame, c->w+BORDER_W*2, c->h+TITLE_HEIGHT+BORDER_W);
|
||||||
XResizeWindow(wm->dpy, c->win, c->w, c->h);
|
XResizeWindow(wm->dpy, c->win, c->w, c->h);
|
||||||
|
|||||||
+5
-1
@@ -48,6 +48,8 @@ void wm_init(WM *wm) {
|
|||||||
wm->net_wm_state_hidden = XInternAtom(wm->dpy, "_NET_WM_STATE_HIDDEN", False);
|
wm->net_wm_state_hidden = XInternAtom(wm->dpy, "_NET_WM_STATE_HIDDEN", False);
|
||||||
wm->net_wm_state_maximized_vert = XInternAtom(wm->dpy, "_NET_WM_STATE_MAXIMIZED_VERT", False);
|
wm->net_wm_state_maximized_vert = XInternAtom(wm->dpy, "_NET_WM_STATE_MAXIMIZED_VERT", False);
|
||||||
wm->net_wm_state_maximized_horz = XInternAtom(wm->dpy, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
|
wm->net_wm_state_maximized_horz = XInternAtom(wm->dpy, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
|
||||||
|
wm->net_wm_desktop = XInternAtom(wm->dpy, "_NET_WM_DESKTOP", False);
|
||||||
|
wm->net_current_desktop = XInternAtom(wm->dpy, "_NET_CURRENT_DESKTOP", False);
|
||||||
|
|
||||||
/* advertise basic EWMH support */
|
/* advertise basic EWMH support */
|
||||||
Atom net_supported = XInternAtom(wm->dpy, "_NET_SUPPORTED", False);
|
Atom net_supported = XInternAtom(wm->dpy, "_NET_SUPPORTED", False);
|
||||||
@@ -55,10 +57,12 @@ void wm_init(WM *wm) {
|
|||||||
wm->net_wm_state, wm->net_wm_state_hidden,
|
wm->net_wm_state, wm->net_wm_state_hidden,
|
||||||
wm->net_wm_state_maximized_vert,
|
wm->net_wm_state_maximized_vert,
|
||||||
wm->net_wm_state_maximized_horz,
|
wm->net_wm_state_maximized_horz,
|
||||||
|
wm->net_wm_desktop,
|
||||||
|
wm->net_current_desktop,
|
||||||
XInternAtom(wm->dpy, "_NET_ACTIVE_WINDOW", False),
|
XInternAtom(wm->dpy, "_NET_ACTIVE_WINDOW", False),
|
||||||
XInternAtom(wm->dpy, "_NET_CLIENT_LIST", False),
|
XInternAtom(wm->dpy, "_NET_CLIENT_LIST", False),
|
||||||
|
XInternAtom(wm->dpy, "_NET_CLOSE_WINDOW", False),
|
||||||
XInternAtom(wm->dpy, "_NET_NUMBER_OF_DESKTOPS", False),
|
XInternAtom(wm->dpy, "_NET_NUMBER_OF_DESKTOPS", False),
|
||||||
XInternAtom(wm->dpy, "_NET_CURRENT_DESKTOP", False),
|
|
||||||
XInternAtom(wm->dpy, "_NET_WM_NAME", False),
|
XInternAtom(wm->dpy, "_NET_WM_NAME", False),
|
||||||
};
|
};
|
||||||
XChangeProperty(wm->dpy, wm->root, net_supported, XA_ATOM, 32,
|
XChangeProperty(wm->dpy, wm->root, net_supported, XA_ATOM, 32,
|
||||||
|
|||||||
Reference in new issue
Block a user