add mouseover focus, seperate border for focused window,
keyboard directional focus, start working on config ipc with sockets
This commit is contained in:
parent
452d103a08
commit
02dfb31656
237
wm.c
237
wm.c
@ -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
28
wm.h
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user