add mouseover focus, seperate border for focused window,

keyboard directional focus, start working on config ipc
with sockets
This commit is contained in:
Akos Horvath 2022-07-29 22:18:34 +02:00
parent 452d103a08
commit 02dfb31656
2 changed files with 246 additions and 19 deletions

237
wm.c
View File

@ -1,8 +1,13 @@
#include "wm.h"
#include <X11/X.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xinerama.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
Monitor wm_monitor_open(Display *d, XineramaScreenInfo info)
{
@ -101,8 +106,12 @@ void wm_create_handler(XCreateWindowEvent e)
nc->next = NULL;
}
XSelectInput(wm_display, nc->wn, FocusChangeMask);
XSelectInput(wm_display, nc->wn, FocusChangeMask | EnterWindowMask);
DEBUG_PRINTV("%d window created.\n", nc->wn);
wm_mstack(nc->m);
//wm_client_focus(c);
}
// TODO
@ -198,9 +207,13 @@ void wm_keypress_handler(XKeyPressedEvent e)
KeyCode ck = XKeysymToKeycode(wm_display, XK_C);
DEBUG_PRINTV("xk_c keycode: %d\n", ck);
// TODO: bad code below: need to implement key structure with keysyms,
// and functions to be ran for clarity and configurabilty
// TODO: fix focusing left from master!
switch (e.state) {
case (Mod4Mask):
DEBUG_PRINT("mod4\n")
// cant use switch
if (e.keycode == XKeysymToKeycode(wm_display, XK_C)) {
DEBUG_PRINT("Kill key combination\n")
@ -209,7 +222,7 @@ void wm_keypress_handler(XKeyPressedEvent e)
wm_client_kill(c);
}
}
if (e.keycode == XKeysymToKeycode(wm_display, XK_Return)) {
else if (e.keycode == XKeysymToKeycode(wm_display, XK_Return)) {
if (fork() == 0) {
if (wm_display)
close(ConnectionNumber(wm_display));
@ -218,6 +231,19 @@ void wm_keypress_handler(XKeyPressedEvent e)
exit(0);
}
}
else if (e.keycode == XKeysymToKeycode(wm_display, XK_H)) {
wm_client_focus_dir(wm_client_get_focused(), LEFT);
}
else if (e.keycode == XKeysymToKeycode(wm_display, XK_J)) {
wm_client_focus_dir(wm_client_get_focused(), DOWN);
}
else if (e.keycode == XKeysymToKeycode(wm_display, XK_K)) {
wm_client_focus_dir(wm_client_get_focused(), UP);
}
else if (e.keycode == XKeysymToKeycode(wm_display, XK_L)) {
wm_client_focus_dir(wm_client_get_focused(), RIGHT);
}
break;
}
}
@ -287,9 +313,33 @@ void wm_client_focus(Client *c)
wm_monitor_clients_border(c->m);
}
void wm_client_focus_dir(Client *c, int dir)
{
RETURN_IF_NULL(c);
switch (dir) {
case UP:
wm_client_focus(wm_client_get_dir_rel_c(c, dir));
break;
case DOWN:
wm_client_focus(wm_client_get_dir_rel_c(c, dir));
break;
case LEFT:
wm_client_focus(wm_client_get_dir_rel_c(c, dir));
break;
case RIGHT:
wm_client_focus(wm_client_get_dir_rel_c(c, dir));
break;
default:
fprintf(stderr, "wm: %s invalid direction: %d\n", __func__, dir);
return;
}
}
void wm_client_kill(Client *c)
{
RETURN_IF_NULL(c);
Monitor *m;
if (c == wm_smon->clients) {
if (c->next)
@ -305,8 +355,71 @@ void wm_client_kill(Client *c)
}
}
m = c->m;
XDestroyWindow(wm_display, c->wn);
free(c);
wm_mstack(m);
}
Client* wm_client_get_dir_rel_c(Client *c, int dir)
{
DEBUG_PRINTV("%s\n", __func__)
if (!c)
return NULL;
Client *r;
int x, y, dx, dy;
switch (dir) {
case UP:
x = c->x + c->w/2;
y = c->y;
dx = 0;
dy = -1;
break;
case DOWN:
x = c->x + c->w/2;
y = c->y + c->h;
dx = 0;
dy = 1;
break;
case LEFT:
x = c->x;
y = c->y + c->h/2;
dx = -1;
dy = 0;
break;
case RIGHT:
x = c->x + c->h/2;
y = c->y + c->w;
dx = 1;
dy = 0;
break;
default:
fprintf(stderr, "wm: %s invalid direction: %d\n", __func__, dir);
return NULL;
}
x+=dx*5;
y+=dy*5;
do {
x+=dx*2;
y+=dy*2;
for (r = c->m->clients; r; r = r->next) {
if ((x > r->x && x < r->x+r->w) && (y > r->y && y < r->y+r->h)) {
DEBUG_PRINTV("%s ", __func__)
DEBUG_PRINTV("found window %d in direction ", c->wn)
DEBUG_PRINTV("%d\n", dir)
return r;
}
}
// TODO: bar
} while((x > 0 && x < c->m->info.width) &&
(y > 0 && y < c->m->info.height));
return r;
}
Client* wm_client_get_focused()
@ -323,6 +436,7 @@ Client* wm_client_get_focused()
void wm_client_border(Client *c)
{
DEBUG_PRINTV("%s\n", __func__);
RETURN_IF_NULL(c);
// if (c->has_border)
// return;
@ -355,7 +469,7 @@ void wm_client_border(Client *c)
DEBUG_PRINTV("drawing border for: %d\n", c->wn);
if (wm_client_is_focused(c)) {
DEBUG_PRINT("wm_client_border focused true\n")
DEBUG_PRINTV("drawing focused border for: %d\n", c->wn);
XSetWindowBorder(wm_display, c->wn, fcolor.pixel);
}
else
@ -388,10 +502,12 @@ void wm_client_border_focused(Client *c)
void wm_monitor_clients_border(Monitor *m)
{
DEBUG_PRINTV("%s\n", __func__)
RETURN_IF_NULL(m);
Client *c;
for (c = m->clients; c; c = c->next) {
for (c = wm_smon->clients; c; c = c->next) {
DEBUG_PRINTV("monitor border c: 0x%x\n", c)
if (c->wn != wm_root.wn)
wm_client_border(c);
}
@ -402,15 +518,30 @@ bool wm_client_is_focused(Client *c)
if (c == NULL)
return false;
int prop;
// prop = XGetWindowProperty(wm_display, c->wn,
// XInternAtom(wm_display, "_NET_ACTIVE_WINDOW", False), 0, 1, False,
// XInternAtom(wm_display, "_NET_ACTIVE_WINDOW", False), XA_WINDOW,
// XA_WINDOW, unsigned long *, unsigned long *, unsigned char **)
// XChangeProperty(wm_display, wm_root.wn,
// XInternAtom(wm_display, "_NET_ACTIVE_WINDOW", False),
// 33, 32, PropModeReplace, (unsigned char *) &c->wn, 1);
Client *c1;
Window w;
int r;
XGetInputFocus(wm_display, &w, &r);
DEBUG_PRINTV("is_focused focused window: %d\n", w)
if (w == c->w)
if (w == c->wn) {
DEBUG_PRINTV("IS_FOCUSED returning true for client: 0x%x", c)
DEBUG_PRINTV("window: %d\n", c->wn)
return true;
}
DEBUG_PRINTV("IS_FOCUSED returning false for client: 0x%x", c)
DEBUG_PRINTV("window: %d\n", c->wn)
return false;
}
@ -476,7 +607,7 @@ void wm_mstack(Monitor *m)
XConfigureWindow(wm_display, c->wn, value_mask, &ch);
wm_client_show(c);
wm_client_focus(c);
//wm_client_focus(c);
}
else {
// TODO
@ -488,10 +619,10 @@ void wm_mstack(Monitor *m)
c->w = m->info.width*wm_ms_p-wm_border_width*2;
c->h = m->info.height-wm_border_width*2;
} else {
c->x = (m->info.width*wm_ms_p)+1;
c->x = (m->info.width*wm_ms_p);
c->y = (n-1)*m->info.height/(cc_sws-1);
c->w = m->info.width - m->info.width*wm_ms_p;
c->h = m->info.height/(cc_sws-1);
c->w = (m->info.width - m->info.width*wm_ms_p)-wm_border_width*2;
c->h = m->info.height/(cc_sws-1)-wm_border_width*2;
}
n++;
ch = wm_client_to_xwchanges(*c);
@ -509,11 +640,16 @@ void wm_mstack(Monitor *m)
XConfigureWindow(wm_display, c->wn, value_mask, &ch);
wm_client_show(c);
wm_client_focus(c);
if (c->next == NULL)
{
wm_client_focus(c);
}
}
}
}
wm_monitor_clients_border(m);
}
void wm_set_layout(void(*f)(Monitor*))
@ -574,11 +710,21 @@ void wm_mainloop()
wm_keypress_handler(e.xkey);
break;
case FocusIn:
// TODO: draw focus window elsewhere
DEBUG_PRINTV("%d window focus in\n", e.xfocus.window);
wm_client_border_focused(wm_client_find(e.xfocus.window));
// wm_monitor_clients_border(wm_client_find(e.xfocus.window)->m);
// wm_client_border_focused(wm_client_find(e.xfocus.window));
break;
case FocusOut:
DEBUG_PRINTV("%d window focus out\n", e.xfocus.window);
//wm_client_border(wm_client_find(e.xfocus.window));
break;
case EnterNotify:
DEBUG_PRINTV("pointer entered window: %d\n", e.xcrossing.window);
wm_client_focus(wm_client_find(e.xcrossing.window));
break;
case LeaveNotify:
DEBUG_PRINTV("pointer left window: %d\n", e.xcrossing.window);
break;
}
}
@ -586,6 +732,7 @@ void wm_mainloop()
void wm_init()
{
signal(SIGINT, wm_sigint_handler);
XSetWindowAttributes xa;
DEBUG_PRINT("wm_init\n")
@ -593,9 +740,11 @@ void wm_init()
Display *d = wm_connect_display();
wm_display = d;
wm_monitors_open_all(d);
// TODO: only testing
wm_socket_init();
wm_root.wn = XRootWindow(wm_display, DefaultScreen(wm_display));
wm_last_client = &wm_root;
XSync(d, false);
@ -608,7 +757,7 @@ void wm_init()
DEBUG_PRINTV("root window id: %d\n", (wm_root.wn))
// TODO: CONFIG KEYS
// TODO: CONFIG KEYS!
XUngrabKey(wm_display, AnyKey, AnyModifier, wm_root.wn);
unsigned int modifiers[] = {0, LockMask, 0 | LockMask};
@ -620,8 +769,18 @@ void wm_init()
GrabModeAsync, GrabModeAsync);
XGrabKey(wm_display, XKeysymToKeycode(wm_display, XK_Return), Mod4Mask,
wm_root.wn, True, GrabModeAsync, GrabModeAsync);
//XSetErrorHandler(&wm_other_wm_handler);
// focus keys
XGrabKey(wm_display, XKeysymToKeycode(wm_display, XK_H), Mod4Mask,
wm_root.wn, True, GrabModeAsync, GrabModeAsync);
XGrabKey(wm_display, XKeysymToKeycode(wm_display, XK_J), Mod4Mask,
wm_root.wn, True, GrabModeAsync, GrabModeAsync);
XGrabKey(wm_display, XKeysymToKeycode(wm_display, XK_K), Mod4Mask,
wm_root.wn, True, GrabModeAsync, GrabModeAsync);
XGrabKey(wm_display, XKeysymToKeycode(wm_display, XK_L), Mod4Mask,
wm_root.wn, True, GrabModeAsync, GrabModeAsync);
//XSetErrorHandler(&wm_other_wm_handler);
if (wm_other_wm) {
printf("wm: Detected other window manager. Exiting.\n");
@ -635,3 +794,51 @@ void wm_init()
wm_mainloop();
}
//TODO: avoid global vars
void wm_socket_init()
{
struct sockaddr_un sock_addr;
int ret;
ret = wm_socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (ret == -1) {
fprintf(stderr, "wm: could not create socket. Exiting.\n");
exit(EXIT_FAILURE);
}
sock_addr.sun_family = AF_UNIX;
snprintf(sock_addr.sun_path, sizeof(sock_addr.sun_path),
"/tmp/wm_socket_%c", DisplayString(wm_display)[1]);
ret = bind(wm_socket_fd, (struct sockaddr *) &sock_addr, sizeof(sock_addr));
if (ret == -1) {
fprintf(stderr, "wm: could not bind to socket. Exiting.\n");
exit(EXIT_FAILURE);
}
ret = listen(wm_socket_fd, 512);
if (ret == -1) {
fprintf(stderr, "wm: could not listen to socket. Exiting.\n");
exit(EXIT_FAILURE);
}
}
void wm_socket_cleanup()
{
struct sockaddr s;
socklen_t t = 108;
getsockname(wm_socket_fd, &s, &t);
DEBUG_PRINTV("socket cleanup path: %s\n", s.sa_data)
remove(s.sa_data);
}
void wm_sigint_handler(int signum)
{
wm_socket_cleanup();
exit(1);
}

28
wm.h
View File

@ -5,10 +5,15 @@
#include <X11/Xutil.h>
#include <X11/Xresource.h>
#include <X11/Xproto.h>
#include <unistd.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xinerama.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/un.h>
// TODO: bar, config command line utility(sockets), avoid global vars
#define RETURN_IF_NULL(c) \
if (c == NULL) \
{ \
@ -33,6 +38,13 @@ for (c = smon->clients; c; c = c->next) \
typedef struct Client Client;
typedef struct Monitor Monitor;
enum Direction {
UP,
DOWN,
LEFT,
RIGHT
};
struct Monitor {
Display *display;
XineramaScreenInfo info;
@ -42,7 +54,6 @@ struct Monitor {
int wscount;
};
struct Client {
int x;
int y;
@ -65,13 +76,14 @@ static Monitor *wm_smon;
static int wm_mc;
static bool wm_other_wm;
static Client wm_root;
static Client *wm_last_client;
static void (*wm_active_layout)(Monitor*);
static float wm_ms_p;
static unsigned int wm_border_col = 0x222222;
static unsigned int wm_focused_border_col = 0x444444;
static unsigned char wm_border_width = 2;
static int wm_socket_fd;
static int wm_xerror_handler(Display *display, XErrorEvent *e);
static int wm_other_wm_handler(Display *display, XErrorEvent *e);
void wm_create_handler(XCreateWindowEvent e);
@ -96,7 +108,9 @@ void wm_create_client(Window w);
void wm_client_hide(Client *c);
void wm_client_show(Client *c);
void wm_client_focus(Client *c);
void wm_client_focus_dir(Client *c, int dir);
void wm_client_kill(Client *c);
Client* wm_client_get_dir_rel_c(Client *c, int dir);
Client* wm_client_get_focused();
void wm_client_border(Client *c);
void wm_client_border_focused(Client *c);
@ -105,6 +119,12 @@ bool wm_client_is_focused(Client *c);
XWindowChanges wm_client_to_xwchanges(Client c);
Client* wm_client_find(Window w);
void wm_switch_ws(int ws);
void wm_mainloop();
void wm_init();
void wm_socket_init();
void wm_socket_cleanup();
void wm_sigint_handler(int signum);