Initial commit - New improvments :
· Configuration with ~/.wmfsrc with libconfig
· Bugfixes
· Layouts and tile
· "virtuals desktops"
· Bugs added :D
Signed-off-by: Marc Lagrange <markocpc@gmail.com>
This commit is contained in:
commit
9e98027673
12
.gitignore
vendored
Normal file
12
.gitignore
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
CMakeCache.txt
|
||||
CMakeFiles/
|
||||
cmake_install.cmake
|
||||
Makefile
|
||||
*.o
|
||||
.*.sw?
|
||||
wmfs
|
||||
config.h
|
||||
CHANGELOG
|
||||
config.h
|
||||
#*
|
||||
\#*
|
||||
80
CMakeLists.txt
Normal file
80
CMakeLists.txt
Normal file
@ -0,0 +1,80 @@
|
||||
#CMakeLists.txt
|
||||
|
||||
# Minimum version of CMake
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
if(COMMAND cmake_policy)
|
||||
cmake_policy(VERSION 2.6)
|
||||
endif()
|
||||
# Source dir
|
||||
set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
# Project name - wmfs
|
||||
project(wmfs C)
|
||||
# Definition of the wmfs source
|
||||
set(wmfs_src
|
||||
wmfs.c
|
||||
config.c)
|
||||
|
||||
# Set the executable from the wmfs_src
|
||||
add_executable(wmfs ${wmfs_src})
|
||||
# Set the version - NOT USED AT THE MOMENT
|
||||
set(VERSION wmfs-devel)
|
||||
# CFLAGS
|
||||
set(CFLAGS "-g -Wall")
|
||||
set(CMAKE_C_FLAGS ${CFLAGS})
|
||||
# Link Libraries
|
||||
set(LIBRARIES_TO_LINK
|
||||
X11
|
||||
confuse)
|
||||
target_link_libraries(wmfs ${LIBRARIES_TO_LINK})
|
||||
|
||||
# Messages
|
||||
message("Project version : ${VERSION}")
|
||||
message("Using these CFLAGS : ${CFLAGS}")
|
||||
message("Linking with theses libraries : ${LIBRARIES_TO_LINK}")
|
||||
|
||||
# Include pkg-config
|
||||
include(FindPkgConfig)
|
||||
# Use pkgconfig to get required libraries
|
||||
pkg_check_modules(wmfs_required
|
||||
x11
|
||||
xcb
|
||||
libconfuse)
|
||||
# Find exterbal programs
|
||||
find_program(GIT_EXECUTABLE git)
|
||||
# Remplace strings in configs
|
||||
set(WMFS_VERSION ${VERSION})
|
||||
set(WMFS_COMPILE_MACHINE ${CMAKE_SYSTEM_PROCESSOR})
|
||||
set(WMFS_COMPILE_BY $ENV{USER})
|
||||
set(WMFS_COMPILE_FLAGS ${CFLAGS})
|
||||
set(WMFS_LINKED_LIBS ${LIBRARIES_TO_LINK})
|
||||
# Configure files
|
||||
set(wmfs_configure_files
|
||||
config.h.in)
|
||||
|
||||
macro(a_configure_file file)
|
||||
string(REGEX REPLACE ".in\$" "" outfile ${file})
|
||||
message(STATUS "Configuring ${outfile}")
|
||||
configure_file(${SOURCE_DIR}/${file}
|
||||
${BUILD_DIR}/${outfile}
|
||||
ESCAPE_QUOTE
|
||||
@ONLY)
|
||||
endmacro()
|
||||
|
||||
foreach(file ${wmfs_configure_files})
|
||||
a_configure_file(${file})
|
||||
endforeach()
|
||||
|
||||
# Generating CHANGELOG
|
||||
|
||||
if(EXISTS ${SOURCE_DIR}/.git/HEAD AND GIT_EXECUTABLE)
|
||||
# generate
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} log
|
||||
WORKING_DIRECTORY ${SOURCE_DIR}
|
||||
#COMMENT "Generating CHANGELOG"
|
||||
OUTPUT_VARIABLE WMFS_CHANGELOG
|
||||
)
|
||||
set(CHANGELOG_FILE ${SOURCE_DIR}/CHANGELOG)
|
||||
file(WRITE ${CHANGELOG_FILE} ${WMFS_CHANGELOG})
|
||||
endif()
|
||||
28
COPYING
Executable file
28
COPYING
Executable file
@ -0,0 +1,28 @@
|
||||
|
||||
Copyright (c) 1983 The Regents of the University of California.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
10
README
Executable file
10
README
Executable file
@ -0,0 +1,10 @@
|
||||
WMFS for GNU/Linux
|
||||
* Window Manager From Scratch
|
||||
|
||||
Un WM tout bete, crée a partir de 0.
|
||||
|
||||
Auteurs:
|
||||
* Code : Martin Duquesnoy <xorg62@gmail.com>
|
||||
* Build System & other : Marc Lagrange <markocpc@gmail.com>
|
||||
|
||||
License: BSD
|
||||
14
config.h.in
Normal file
14
config.h.in
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#include "local.h"
|
||||
|
||||
#define WMFS_VERSION "@WMFS_VERSION@"
|
||||
#define WMFS_COMPILE_MACHINE "@WMFS_COMPILE_MACHINE@"
|
||||
#define WMFS_COMPILE_BY "@WMFS_COMPILE_BY@"
|
||||
#define WMFS_COMPILE_FLAGS "@WMFS_COMPILE_FLAGS@"
|
||||
#define WMFS_LINKED_LIBS "@WMFS_LINKED_LIBS@"
|
||||
|
||||
void init_conf(void);
|
||||
|
||||
#endif /* CONFIG_H */
|
||||
163
local.h
Normal file
163
local.h
Normal file
@ -0,0 +1,163 @@
|
||||
#ifndef LOCAL_H
|
||||
#define LOCAL_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <getopt.h>
|
||||
#include <confuse.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xproto.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/cursorfont.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/* DEFINE TYPES */
|
||||
#define FALSE 0
|
||||
#define TRUE (!FALSE)
|
||||
#define ButtonMask (ButtonPressMask | ButtonReleaseMask)
|
||||
#define MouseMask (ButtonMask | PointerMotionMask)
|
||||
#define KeyMask (KeyPressMask | KeyReleaseMask)
|
||||
#define CONTROL ControlMask
|
||||
#define ALT Mod1Mask
|
||||
#define SHIFT ShiftMask
|
||||
#define LEN(x) (sizeof x / sizeof x[0])
|
||||
#define Move 0
|
||||
#define Resize 1
|
||||
#define Free 0
|
||||
#define Tile 1
|
||||
#define Max 2
|
||||
#define MAXTAG 36
|
||||
|
||||
typedef struct Client Client;
|
||||
struct Client {
|
||||
char *title; /* client title */
|
||||
int tag; /* tag num */
|
||||
int x, y, w, h; /* window attribute */
|
||||
int ox, oy, ow, oh; /* old window attribute */
|
||||
int border; /* border height */
|
||||
Window win; /* window */
|
||||
Window tbar; /* Titlebar? */
|
||||
Window button; /* Close Button */
|
||||
Bool max; /* client info */
|
||||
int layout;
|
||||
Client *next; /* next client */
|
||||
Client *prev; /* previous client */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
unsigned long mod;
|
||||
KeySym keysym;
|
||||
void (*func)(char *cmd);
|
||||
char *cmd;
|
||||
} Key;
|
||||
|
||||
typedef struct {
|
||||
|
||||
char *name;
|
||||
void *func;
|
||||
|
||||
} func_name_list_t;
|
||||
|
||||
typedef struct {
|
||||
/* bool and size */
|
||||
char *font;
|
||||
bool raisefocus;
|
||||
bool raiseswitch;
|
||||
int borderheight;
|
||||
int ttbarheight;
|
||||
/* color */
|
||||
int bordernormal;
|
||||
int borderfocus;
|
||||
int barcolor;
|
||||
int buttoncolor;
|
||||
int textcolor;
|
||||
int tagselfg;
|
||||
int tagselbg;
|
||||
/* layout */
|
||||
char *symlayout[3];
|
||||
/* tag */
|
||||
int ntag;
|
||||
char *taglist[MAXTAG];
|
||||
} Conf;
|
||||
|
||||
enum { CurNormal, CurResize, CurMove, CurInput, CurLast };
|
||||
enum { WMState, WMProtocols, WMName, WMDelete, WMLast };
|
||||
enum { NetSupported, NetWMName, NetLast };
|
||||
|
||||
/* wmfs.c */
|
||||
void attach(Client *c);
|
||||
int clientpertag(int tag);
|
||||
void detach(Client *c);
|
||||
void *emallocz(unsigned int size);
|
||||
int errorhandler(Display *d, XErrorEvent *event);
|
||||
void focus(Client *c);
|
||||
Client* getbutton(Window w);
|
||||
Client* getclient(Window w);
|
||||
Client* getnext(Client *c);
|
||||
Client* gettbar(Window w);
|
||||
void getevent(void);
|
||||
void grabbuttons(Client *c, Bool focused);
|
||||
void grabkeys(void);
|
||||
void hide(Client *c);
|
||||
void init(void);
|
||||
Bool ishide(Client *c);
|
||||
void keymovex(char *cmd);
|
||||
void keymovey(char *cmd);
|
||||
void keypress(XEvent *e);
|
||||
void keyresize(char *cmd);
|
||||
void killclient(char *cmd);
|
||||
void mapclient(Client *c);
|
||||
void manage(Window w, XWindowAttributes *wa);
|
||||
void mouseaction(Client *c, int x, int y, int type);
|
||||
void moveresize(Client *c, int x, int y, int w, int h);
|
||||
void raiseclient(Client *c);
|
||||
void scan(void);
|
||||
void setborder(Window win, int color);
|
||||
void spawn(char *cmd);
|
||||
void tag(char *cmd);
|
||||
void tagn(int tag);
|
||||
void tagswitch(char *cmd);
|
||||
void tile(char *cmd);
|
||||
void togglemax(char *cmd);
|
||||
void unhide(Client *c);
|
||||
void unmanage(Client *c);
|
||||
void updatebar(void);
|
||||
void unmapclient(Client *c);
|
||||
void updateall(void);
|
||||
void updatetitle(Client *c);
|
||||
void wswitch(char *cmd);
|
||||
|
||||
#define BUTY(y) (y - conf.ttbarheight + 3)
|
||||
#define BUTH (conf.ttbarheight - 6)
|
||||
|
||||
GC gc;
|
||||
Key keys[1024];
|
||||
XEvent event;
|
||||
Display *dpy;
|
||||
XFontStruct* font;
|
||||
Conf conf;
|
||||
int screen;
|
||||
Window root;
|
||||
Window bar;
|
||||
fd_set fd;
|
||||
Atom wm_atom[WMLast];
|
||||
Atom net_atom[NetLast];
|
||||
Cursor cursor[CurLast];
|
||||
int mw, mh;
|
||||
int fonth;
|
||||
int barheight;
|
||||
Client *clients; /* Fisrt Client */
|
||||
Client *sel; /* selected client */
|
||||
int seltag; /* selected tag */
|
||||
#endif /* LOCAL_H */
|
||||
947
wmfs.c
Normal file
947
wmfs.c
Normal file
@ -0,0 +1,947 @@
|
||||
/* Copyright (c) 1998, Regents of the University of California
|
||||
* All rights reserved.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the University of California, Berkeley nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "local.h"
|
||||
|
||||
unsigned int numlockmask = 0;
|
||||
|
||||
int taglen[MAXTAG] = {3};
|
||||
|
||||
void
|
||||
attach(Client *c) {
|
||||
if(clients)
|
||||
clients->prev = c;
|
||||
c->next = clients;
|
||||
clients = c;
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
clientpertag(int tag) {
|
||||
Client *c;
|
||||
int i = 0;
|
||||
for(c = clients; c; c = c->next) {
|
||||
if(c->tag == tag)
|
||||
++i;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void
|
||||
detach(Client *c) {
|
||||
if(c->prev) c->prev->next = c->next;
|
||||
if(c->next) c->next->prev = c->prev;
|
||||
if(c == clients) clients = c->next;
|
||||
c->next = c->prev = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
void *
|
||||
emallocz(unsigned int size) {
|
||||
void *res = calloc(1, size);
|
||||
if(!res)
|
||||
fprintf(stderr,"fatal: could not malloc() %u bytes\n", size);
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
errorhandler(Display *d, XErrorEvent *event) {
|
||||
char mess[512];
|
||||
XGetErrorText(d, event->error_code, mess, 128);
|
||||
fprintf(stderr, "WMFS error: %s(%d) opcodes %d/%d\n resource 0x%lx\n", mess,
|
||||
event->error_code,
|
||||
event->request_code,
|
||||
event->minor_code,
|
||||
event->resourceid);
|
||||
return(1);
|
||||
}
|
||||
|
||||
void
|
||||
focus(Client *c) {
|
||||
if(sel && sel != c) {
|
||||
grabbuttons(sel, False);
|
||||
setborder(sel->win, conf.bordernormal);
|
||||
setborder(sel->tbar, conf.bordernormal);
|
||||
}
|
||||
|
||||
if(c) grabbuttons(c, True);
|
||||
|
||||
sel = c;
|
||||
|
||||
if(c) {
|
||||
setborder(c->win, conf.borderfocus);
|
||||
setborder(sel->tbar, conf.borderfocus);
|
||||
if(conf.raisefocus)
|
||||
raiseclient(c);
|
||||
XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
|
||||
updatetitle(c);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Client*
|
||||
getbutton(Window w) {
|
||||
Client *c;
|
||||
for(c = clients; c && c->button != w; c = c->next);
|
||||
return c;
|
||||
}
|
||||
|
||||
Client*
|
||||
getclient(Window w) {
|
||||
Client *c;
|
||||
for(c = clients; c && c->win != w; c = c->next);
|
||||
return c;
|
||||
}
|
||||
|
||||
Client*
|
||||
getnext(Client *c) {
|
||||
for(; c; c = c->prev);
|
||||
return c;
|
||||
}
|
||||
|
||||
Client*
|
||||
gettbar(Window w) {
|
||||
Client *c;
|
||||
for(c = clients; c && c->tbar != w; c = c->next);
|
||||
return c;
|
||||
}
|
||||
|
||||
void
|
||||
getevent(void) {
|
||||
XEvent event;
|
||||
XWindowAttributes at;
|
||||
Client *c;
|
||||
int i;
|
||||
struct timeval tv;
|
||||
if(QLength(dpy) > 0) {
|
||||
XNextEvent(dpy, &event);
|
||||
} else {
|
||||
XFlush(dpy);
|
||||
FD_ZERO(&fd);
|
||||
FD_SET(ConnectionNumber(dpy), &fd);
|
||||
event.type = LASTEvent;
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
if(select(FD_SETSIZE, &fd, NULL, NULL, &tv) > 0) {
|
||||
XNextEvent(dpy, &event);
|
||||
}
|
||||
}
|
||||
|
||||
switch (event.type) {
|
||||
case EnterNotify:
|
||||
if(event.xcrossing.mode != NotifyNormal
|
||||
|| event.xcrossing.detail == NotifyInferior) return;
|
||||
if((c = getclient(event.xcrossing.window))
|
||||
|| (c = gettbar(event.xcrossing.window)))
|
||||
focus(c);
|
||||
break;
|
||||
|
||||
case MapRequest:
|
||||
if(!XGetWindowAttributes(dpy, event.xmaprequest.window, &at)) return;
|
||||
if(at.override_redirect) return;
|
||||
if(!getclient(event.xmaprequest.window))
|
||||
manage(event.xmaprequest.window, &at);
|
||||
break;
|
||||
|
||||
case MappingNotify:
|
||||
if(event.xmapping.request == MappingKeyboard)
|
||||
grabkeys();
|
||||
break;
|
||||
|
||||
case PropertyNotify:
|
||||
if(event.xproperty.state == PropertyDelete)
|
||||
return;
|
||||
if(event.xproperty.atom == XA_WM_NAME &&
|
||||
event.xproperty.state == PropertyNewValue) {
|
||||
if((c = getclient(event.xproperty.window))) {
|
||||
if(c->title) {
|
||||
XFree(c->title);
|
||||
c->title = NULL;
|
||||
updatetitle(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case UnmapNotify:
|
||||
if((c = getclient(event.xunmap.window))) {
|
||||
unmanage(c);
|
||||
}
|
||||
break;
|
||||
|
||||
case DestroyNotify:
|
||||
if((c = getclient(event.xdestroywindow.window))) {
|
||||
unmanage(c);
|
||||
}
|
||||
break;
|
||||
|
||||
case FocusIn:
|
||||
if(sel && event.xfocus.window != sel->win)
|
||||
XSetInputFocus(dpy, sel->win, RevertToPointerRoot, CurrentTime);
|
||||
break;
|
||||
|
||||
case KeyPress: keypress(&event); break;
|
||||
|
||||
case ButtonPress:
|
||||
/* Window and Tbar */
|
||||
if((c = gettbar(event.xbutton.window))
|
||||
|| (c = getclient(event.xbutton.window))) {
|
||||
raiseclient(c);
|
||||
if(event.xbutton.button == Button1)
|
||||
mouseaction(c, event.xbutton.x_root, event.xbutton.y_root, Move); /* type 0 for move */
|
||||
else if(event.xbutton.button == Button2)
|
||||
tile(NULL);
|
||||
else if(event.xbutton.button == Button3)
|
||||
mouseaction(c, event.xbutton.x_root, event.xbutton.y_root, Resize); /* type 1 for resize */
|
||||
/* Button */
|
||||
} else if((c = getbutton(event.xbutton.window))) {
|
||||
if(event.xbutton.button == Button1) {
|
||||
unmanage(c);
|
||||
XKillClient(dpy, c->win);
|
||||
} else if(event.xbutton.button == Button3)
|
||||
togglemax(NULL);
|
||||
/* Bar */
|
||||
}
|
||||
else if(event.xbutton.window == bar) {
|
||||
for(i = 0; i < conf.ntag + 1; ++i) {
|
||||
if(event.xbutton.x > taglen[i-1]
|
||||
&& event.xbutton.x < taglen[i]) {
|
||||
if(event.xbutton.button == Button1) {
|
||||
tagn(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(event.xbutton.window == root) {
|
||||
if(event.xbutton.button == Button4)
|
||||
tagswitch("+1");
|
||||
else if(event.xbutton.button == Button5)
|
||||
tagswitch("-1");
|
||||
}
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
grabbuttons(Client *c, Bool focused) {
|
||||
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
|
||||
XUngrabButton(dpy, AnyButton, AnyModifier, c->tbar);
|
||||
XUngrabButton(dpy, AnyButton, AnyModifier, c->button);
|
||||
|
||||
if(focused) {
|
||||
/* Window */
|
||||
XGrabButton(dpy, Button1, ALT, c->win, 0, ButtonMask,GrabModeAsync,GrabModeSync, None, None);
|
||||
XGrabButton(dpy, Button1, ALT|LockMask, c->win, 0, ButtonMask,GrabModeAsync, GrabModeSync, None, None);
|
||||
XGrabButton(dpy, Button2, ALT, c->win, 0, ButtonMask,GrabModeAsync,GrabModeSync, None, None);
|
||||
XGrabButton(dpy, Button2, ALT|LockMask, c->win, 0, ButtonMask,GrabModeAsync, GrabModeSync, None, None);
|
||||
XGrabButton(dpy, Button3, ALT, c->win, 0, ButtonMask,GrabModeAsync,GrabModeSync, None, None);
|
||||
XGrabButton(dpy, Button3, ALT|LockMask, c->win, False, ButtonMask,GrabModeAsync, GrabModeSync, None, None);
|
||||
/* Titlebar */
|
||||
XGrabButton(dpy, Button1, AnyModifier, c->tbar, 0, ButtonMask,GrabModeAsync, GrabModeSync, None, None);
|
||||
XGrabButton(dpy, Button2, AnyModifier, c->tbar, 0, ButtonMask,GrabModeAsync, GrabModeSync, None, None);
|
||||
XGrabButton(dpy, Button3, AnyModifier, c->tbar, 0, ButtonMask,GrabModeAsync, GrabModeSync, None, None);
|
||||
/* Button */
|
||||
XGrabButton(dpy, Button1, AnyModifier, c->button, 0, ButtonMask,GrabModeAsync, GrabModeSync, None, None);
|
||||
XGrabButton(dpy, Button3, AnyModifier, c->button, 0, ButtonMask,GrabModeAsync, GrabModeSync, None, None);
|
||||
} else {
|
||||
XGrabButton(dpy, AnyButton, AnyModifier, c->win, 0, ButtonMask, GrabModeAsync, GrabModeSync, None, None);
|
||||
XGrabButton(dpy, AnyButton, AnyModifier, c->tbar, 0, ButtonMask, GrabModeAsync, GrabModeSync, None, None);
|
||||
|
||||
|
||||
XGrabButton(dpy, AnyButton, AnyModifier, c->button, 0, ButtonMask, GrabModeAsync, GrabModeSync, None, None);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
grabkeys(void) {
|
||||
unsigned int i;
|
||||
KeyCode code;
|
||||
XUngrabKey(dpy, AnyKey, AnyModifier, root);
|
||||
for(i = 0; i < LEN(keys); i++) {
|
||||
code = XKeysymToKeycode(dpy, keys[i].keysym);
|
||||
XGrabKey(dpy, code, keys[i].mod, root, True, GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(dpy, code, keys[i].mod|numlockmask, root, True, GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(dpy, code, keys[i].mod|LockMask, root, True, GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(dpy, code, keys[i].mod|LockMask|numlockmask, root, True, GrabModeAsync, GrabModeAsync);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
hide(Client *c) {
|
||||
if(c) {
|
||||
XMoveWindow(dpy,c->win,c->x,c->y+mh*2);
|
||||
XMoveWindow(dpy,c->tbar,c->x,c->y+mh*2);
|
||||
XMoveWindow(dpy,c->button,c->x,c->y+mh*2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
init(void) {
|
||||
XSetWindowAttributes at;
|
||||
XModifierKeymap *modmap;
|
||||
int i, j;
|
||||
|
||||
/* FIRST INIT */
|
||||
gc = DefaultGC (dpy, screen);
|
||||
screen = DefaultScreen (dpy);
|
||||
root = RootWindow (dpy, screen);
|
||||
mw = DisplayWidth (dpy, screen);
|
||||
mh = DisplayHeight (dpy, screen);
|
||||
seltag = 1;
|
||||
init_conf();
|
||||
|
||||
/* INIT FONT */
|
||||
font = XLoadQueryFont(dpy, conf.font);
|
||||
if(!font){
|
||||
fprintf(stderr, "XLoadQueryFont: failed loading font '%s'\n", conf.font);
|
||||
exit(0);
|
||||
|
||||
}
|
||||
XSetFont(dpy, gc, font->fid);
|
||||
fonth = font->ascent + font->descent;
|
||||
barheight = fonth + 3;
|
||||
|
||||
/* INIT CURSOR */
|
||||
cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
|
||||
cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
|
||||
cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
|
||||
|
||||
/* INIT MODIFIER */
|
||||
modmap = XGetModifierMapping(dpy);
|
||||
for(i = 0; i < 8; i++)
|
||||
for(j = 0; j < modmap->max_keypermod; j++) {
|
||||
if(modmap->modifiermap[i * modmap->max_keypermod + j]
|
||||
== XKeysymToKeycode(dpy, XK_Num_Lock))
|
||||
numlockmask = (1 << i);
|
||||
}
|
||||
XFreeModifiermap(modmap);
|
||||
|
||||
/* INIT ATOM */
|
||||
wm_atom[WMState] = XInternAtom(dpy, "WM_STATE", False);
|
||||
wm_atom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
|
||||
wm_atom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
|
||||
net_atom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
|
||||
net_atom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
|
||||
XChangeProperty(dpy, root, net_atom[NetSupported], XA_ATOM, 32,
|
||||
PropModeReplace, (unsigned char *) net_atom, NetLast);
|
||||
|
||||
/* INIT ROOT */
|
||||
at.event_mask = KeyMask | ButtonPressMask | ButtonReleaseMask |
|
||||
SubstructureRedirectMask | SubstructureNotifyMask |
|
||||
EnterWindowMask | LeaveWindowMask | StructureNotifyMask ;
|
||||
at.cursor = cursor[CurNormal];
|
||||
XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &at);
|
||||
|
||||
/* INIT BAR */
|
||||
at.override_redirect = 1;
|
||||
at.background_pixmap = ParentRelative;
|
||||
at.event_mask = ButtonPressMask | ExposureMask;
|
||||
bar = XCreateWindow(dpy, root, 0, 0, mw, barheight, 0, DefaultDepth(dpy, screen),
|
||||
CopyFromParent, DefaultVisual(dpy, screen),
|
||||
CWOverrideRedirect | CWBackPixmap | CWEventMask, &at);
|
||||
XSetWindowBackground(dpy, bar, conf.barcolor);
|
||||
XMapWindow(dpy, bar);
|
||||
|
||||
/* INIT STUFF */
|
||||
XSetErrorHandler(errorhandler);
|
||||
grabkeys();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Bool
|
||||
ishide(Client *c) {
|
||||
int i;
|
||||
for(i = 0; i < conf.ntag+1; ++i)
|
||||
if(c->tag == i && seltag == i)
|
||||
return False;
|
||||
return True;
|
||||
}
|
||||
|
||||
void
|
||||
keymovex(char *cmd) {
|
||||
if(sel) {
|
||||
if(cmd && !ishide(sel)) {
|
||||
int tmp;
|
||||
tmp = sel->x + atoi(cmd);
|
||||
moveresize(sel,tmp, sel->y, sel->w, sel->h);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
keymovey(char *cmd) {
|
||||
if(sel && !ishide(sel)) {
|
||||
if(cmd) {
|
||||
int tmp;
|
||||
tmp = sel->y + atoi(cmd);
|
||||
moveresize(sel, sel->x, tmp, sel->w, sel->h);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
keypress(XEvent *e) {
|
||||
unsigned int i;
|
||||
KeySym keysym;
|
||||
XKeyEvent *ev;
|
||||
ev = &e->xkey;
|
||||
keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
|
||||
for(i = 0; i < LEN(keys); i++)
|
||||
if(keysym == keys[i].keysym
|
||||
&& (keys[i].mod & ~(numlockmask | LockMask)) ==
|
||||
(ev->state & ~(numlockmask | LockMask))
|
||||
&& keys[i].func)
|
||||
{
|
||||
keys[i].func(keys[i].cmd);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
keyresize(char *cmd) {
|
||||
if(sel && !ishide(sel)) {
|
||||
int temph=0, tempw=0, modh=0, modw=0,
|
||||
tmp=0;
|
||||
|
||||
switch(cmd[1]) {
|
||||
case 'h': tmp = (cmd[0] == '+') ? 5 : -5; modh = tmp; break;
|
||||
case 'w': tmp = (cmd[0] == '+') ? 5 : -5; modw = tmp; break;
|
||||
}
|
||||
|
||||
temph = sel->h + modh;
|
||||
tempw = sel->w + modw;
|
||||
temph = (temph < 10) ? 10 : temph;
|
||||
tempw = (tempw < 10) ? 10 : tempw;
|
||||
moveresize(sel, sel->x, sel->y, tempw, temph);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
killclient(char *cmd) {
|
||||
if(sel && !ishide(sel)) {
|
||||
XEvent ev;
|
||||
ev.type = ClientMessage;
|
||||
ev.xclient.window = sel->win;
|
||||
ev.xclient.message_type = wm_atom[WMProtocols];
|
||||
ev.xclient.format = 32;
|
||||
ev.xclient.data.l[0] = wm_atom[WMDelete];
|
||||
ev.xclient.data.l[1] = CurrentTime;
|
||||
XSendEvent(dpy, sel->win, False, NoEventMask, &ev);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
mapclient(Client *c) {
|
||||
if(c) {
|
||||
XMapWindow(dpy, c->win);
|
||||
XMapWindow(dpy, c->tbar);
|
||||
XMapWindow(dpy, c->button);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
manage(Window w, XWindowAttributes *wa) {
|
||||
Client *c, *t = NULL;
|
||||
Window trans;
|
||||
Status rettrans;
|
||||
|
||||
c = emallocz(sizeof(Client));
|
||||
c->win = w;
|
||||
c->x = wa->x;
|
||||
c->y = wa->y + conf.ttbarheight + barheight;
|
||||
c->w = wa->width;
|
||||
c->h = wa->height;
|
||||
c->border = wa->border_width;
|
||||
c->tag = seltag;
|
||||
c->layout = Free;
|
||||
|
||||
setborder(w, conf.bordernormal);
|
||||
|
||||
XSelectInput(dpy, w, EnterWindowMask | FocusChangeMask |
|
||||
PropertyChangeMask | StructureNotifyMask);
|
||||
if((rettrans = XGetTransientForHint(dpy, w, &trans) == Success))
|
||||
for(t = clients; t && t->win != trans; t = t->next);
|
||||
|
||||
c->tbar = XCreateSimpleWindow(dpy,root,
|
||||
c->x,
|
||||
c->y - conf.ttbarheight,
|
||||
c->w,
|
||||
conf.ttbarheight,
|
||||
conf.borderheight,
|
||||
conf.bordernormal,
|
||||
conf.barcolor);
|
||||
XSelectInput(dpy, c->tbar, ExposureMask | EnterWindowMask);
|
||||
|
||||
c->button = XCreateSimpleWindow(dpy,root,
|
||||
c->x + c->w - 10,
|
||||
BUTY(c->y),
|
||||
5,
|
||||
BUTH,
|
||||
1,
|
||||
conf.buttoncolor,
|
||||
conf.buttoncolor);
|
||||
XSelectInput(dpy, c->button, ExposureMask | EnterWindowMask);
|
||||
|
||||
grabbuttons(c, False);
|
||||
attach(c);
|
||||
XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
|
||||
mapclient(c);
|
||||
updatetitle(c);
|
||||
setborder(c->tbar, conf.bordernormal);
|
||||
focus(c);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the type is 0, this function will move, else,
|
||||
this will resize */
|
||||
|
||||
void
|
||||
mouseaction(Client *c, int x, int y, int type) {
|
||||
int ocx, ocy;
|
||||
XEvent ev;
|
||||
|
||||
ocx = c->x;
|
||||
ocy = c->y;
|
||||
|
||||
if(XGrabPointer(dpy, root, 0, MouseMask, GrabModeAsync, GrabModeAsync,
|
||||
None, cursor[((type) ?CurResize:CurMove)], CurrentTime) != GrabSuccess) return;
|
||||
c->max = False;
|
||||
|
||||
if(type)
|
||||
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w, c->h);
|
||||
|
||||
for(;;) {
|
||||
XMaskEvent(dpy, MouseMask | ExposureMask | SubstructureRedirectMask, &ev);
|
||||
if(ev.type == ButtonRelease) {
|
||||
if(type)
|
||||
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w, c->h);
|
||||
XUngrabPointer(dpy, CurrentTime);
|
||||
return;
|
||||
} else if(ev.type == MotionNotify) {
|
||||
|
||||
if(c->y <= barheight + conf.ttbarheight) updatebar();
|
||||
XSync(dpy, 0);
|
||||
|
||||
if(type) /* Resize */
|
||||
moveresize(c, c->x, c->y,
|
||||
((ev.xmotion.x - ocx <= 0) ? 1 : ev.xmotion.x - ocx),
|
||||
((ev.xmotion.y - ocy <= 0) ? 1 : ev.xmotion.y - ocy));
|
||||
else /* Move */
|
||||
moveresize(c,
|
||||
(ocx + (ev.xmotion.x - x)),
|
||||
(ocy + (ev.xmotion.y - y)),
|
||||
c->w, c->h);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
moveresize(Client *c, int x, int y, int w, int h) {
|
||||
if(c) {
|
||||
if(w <= 0 || h <= 0)
|
||||
return;
|
||||
c->layout = Free;
|
||||
c->max = False;
|
||||
if(c->x != x || c->y != y || c->w != w || c->h != h) {
|
||||
c->x = x;
|
||||
c->y = y;
|
||||
c->w = w;
|
||||
c->h = h;
|
||||
XMoveResizeWindow(dpy, c->win, x, y, w ,h);
|
||||
XMoveResizeWindow(dpy, c->tbar, x, y - conf.ttbarheight, w, conf.ttbarheight);
|
||||
XMoveResizeWindow(dpy, c->button,
|
||||
(x + w - 10),
|
||||
BUTY(y),
|
||||
5,
|
||||
BUTH);
|
||||
updateall();
|
||||
XSync(dpy, False);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
raiseclient(Client *c) {
|
||||
if(c) {
|
||||
XRaiseWindow(dpy,c->win);
|
||||
XRaiseWindow(dpy,c->tbar);
|
||||
XRaiseWindow(dpy,c->button);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
scan(void) {
|
||||
unsigned int i, num;
|
||||
Window *wins, d1, d2;
|
||||
XWindowAttributes wa;
|
||||
|
||||
wins = NULL;
|
||||
if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
|
||||
for(i = 0; i < num; i++) {
|
||||
if(!XGetWindowAttributes(dpy, wins[i], &wa))
|
||||
continue;
|
||||
if(wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
|
||||
continue;
|
||||
if(wa.map_state == IsViewable)
|
||||
manage(wins[i], &wa);
|
||||
}
|
||||
}
|
||||
if(wins)
|
||||
XFree(wins);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
setborder(Window win, int color) {
|
||||
XSetWindowBorder(dpy, win, color);
|
||||
XSetWindowBorderWidth(dpy, win, conf.borderheight);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
spawn(char *cmd) {
|
||||
if(strlen(cmd) > 0 && !fork()) {
|
||||
execl(getenv("SHELL"), "sh", "-c", cmd, NULL);
|
||||
exit(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
tag(char *cmd) {
|
||||
Client *c;
|
||||
int tmp = atoi(cmd);
|
||||
|
||||
if(tmp > conf.ntag || tmp < 1 || tmp == seltag)
|
||||
return;
|
||||
for(c = clients; c; c = c->next) {
|
||||
if(!ishide(c))
|
||||
hide(c);
|
||||
if(c->tag == tmp) {
|
||||
unhide(c);
|
||||
updateall();
|
||||
}
|
||||
}
|
||||
seltag = tmp;
|
||||
sel = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
tagn(int tag) {
|
||||
Client *c;
|
||||
if(tag > conf.ntag || tag < 1 || tag == seltag)
|
||||
return;
|
||||
for(c = clients; c; c = c->next) {
|
||||
if(!ishide(c))
|
||||
hide(c);
|
||||
if(c->tag == tag) {
|
||||
unhide(c);
|
||||
updateall();
|
||||
}
|
||||
}
|
||||
seltag = tag;
|
||||
sel = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
tagswitch(char *cmd) {
|
||||
Client *c;
|
||||
int tmp;
|
||||
|
||||
tmp = atoi(cmd);
|
||||
|
||||
if(seltag + tmp > conf.ntag || seltag + tmp < 1)
|
||||
return;
|
||||
|
||||
seltag += tmp;
|
||||
for(c = clients; c; c = c->next) {
|
||||
if(c->tag == seltag - tmp)
|
||||
hide(c);
|
||||
|
||||
if(c->tag == seltag) {
|
||||
unhide(c);
|
||||
updateall();
|
||||
}
|
||||
}
|
||||
sel = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
tile(char *cmd) {
|
||||
if(sel) {
|
||||
Client *c;
|
||||
int i;
|
||||
unsigned int x, y, w, h, bord;
|
||||
unsigned int barto;
|
||||
|
||||
barto = conf.ttbarheight + barheight;
|
||||
bord = conf.borderheight * 2;
|
||||
|
||||
x = mw / 2 + conf.borderheight;
|
||||
y = barto;
|
||||
w = ((mw - bord ) / 2 - bord);
|
||||
if(clientpertag(seltag)-1)
|
||||
h = ((mh-bord) - conf.ttbarheight - barheight) / (clientpertag(seltag) - 1) ;
|
||||
|
||||
/* Master client in first (always the sel window) */
|
||||
moveresize(sel, 0, barto,
|
||||
((clientpertag(seltag) > 1) ? (mw-bord) / 2 : (mw-bord)),
|
||||
((mh-bord) - conf.ttbarheight - barheight));
|
||||
sel->layout = Tile;
|
||||
|
||||
/* tiling */
|
||||
for(i=0, c = clients; c; c = c->next, ++i) {
|
||||
if(c != sel && !ishide(c)) {
|
||||
moveresize(c, x, y, w, h);
|
||||
if(i < i + 1)
|
||||
y = c->y + c->h + bord + conf.ttbarheight;
|
||||
c->layout = Tile;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
togglemax(char *cmd) {
|
||||
if(sel && !ishide(sel)) {
|
||||
if(!sel->max) {
|
||||
sel->ox = sel->x;
|
||||
sel->oy = sel->y;
|
||||
sel->ow = sel->w;
|
||||
sel->oh = sel->h;
|
||||
moveresize(sel, 0,
|
||||
conf.ttbarheight + barheight,
|
||||
(mw-(conf.borderheight * 2)),
|
||||
(mh-(conf.borderheight * 2)- conf.ttbarheight - barheight));
|
||||
sel->max = True;
|
||||
sel->layout = Max;
|
||||
} else if(sel->max) {
|
||||
moveresize(sel, sel->ox, sel->oy, sel->ow, sel->oh);
|
||||
sel->max = False;
|
||||
sel->layout = Free;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
unhide(Client *c) {
|
||||
if(c) {
|
||||
XMoveWindow(dpy,c->win,c->x,c->y);
|
||||
XMoveWindow(dpy,c->tbar,c->x,
|
||||
(c->y - conf.ttbarheight));
|
||||
XMoveWindow(dpy,c->button,
|
||||
(c->x + c->w -10),
|
||||
(c->y - 9));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
unmanage(Client *c) {
|
||||
XSetErrorHandler(errorhandler);
|
||||
if(sel == c)
|
||||
sel = c->next;
|
||||
else
|
||||
sel = NULL;
|
||||
XUnmapWindow(dpy, c->tbar);
|
||||
XDestroyWindow(dpy, c->tbar);
|
||||
XUnmapWindow(dpy, c->button);
|
||||
XDestroyWindow(dpy, c->button);
|
||||
detach(c);
|
||||
free(c);
|
||||
XSync(dpy, False);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
updateall(void) {
|
||||
Client *c;
|
||||
for(c = clients; c; c = c->next) {
|
||||
if(!ishide(c))
|
||||
updatetitle(c);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
updatebar(void) {
|
||||
struct tm *tm;
|
||||
time_t lt;
|
||||
int slen = 0, i;
|
||||
char buf[conf.ntag][100] ;
|
||||
|
||||
tm = localtime(<);
|
||||
lt = time(NULL);
|
||||
|
||||
XClearWindow(dpy, bar);
|
||||
XSetForeground(dpy, gc, conf.textcolor);
|
||||
|
||||
for(i=0;i< conf.ntag;++i) {
|
||||
/* Make the tag string */
|
||||
if(clientpertag(i+1))
|
||||
sprintf(buf[i], "%s(%d) ", conf.taglist[i], clientpertag(i+1));
|
||||
else
|
||||
sprintf(buf[i], "%s() ", conf.taglist[i]);
|
||||
taglen[i+1] = taglen[i] + 6*(strlen(conf.taglist[i]) + ((clientpertag(i+1) >= 10) ? 5 : 4));
|
||||
/* Rectangle for the tag background */
|
||||
if(i+1 == seltag) XSetForeground(dpy, gc, conf.tagselbg);
|
||||
else XSetForeground(dpy, gc, 0x090909);
|
||||
XFillRectangle(dpy, bar, gc, taglen[i]-4, 0, strlen(buf[i])*6, barheight);
|
||||
/* Draw tag */
|
||||
if(i+1 == seltag) XSetForeground(dpy, gc, conf.tagselfg);
|
||||
else XSetForeground(dpy, gc, conf.textcolor);
|
||||
XDrawString(dpy, bar, gc, taglen[i], fonth-1, buf[i], strlen(buf[i]));
|
||||
}
|
||||
|
||||
/* Draw layout symbol */
|
||||
XSetForeground(dpy, gc, conf.tagselfg);
|
||||
XDrawString(dpy, bar, gc, taglen[conf.ntag],
|
||||
fonth-1,
|
||||
(sel) ? conf.symlayout[sel->layout] : conf.symlayout[Free],
|
||||
(sel) ? strlen(conf.symlayout[sel->layout]) :strlen(conf.symlayout[Free]) );
|
||||
|
||||
XSetForeground(dpy, gc, conf.textcolor);
|
||||
XDrawLine(dpy, bar, gc, mw-slen*6-5, 0 , mw-slen*6-5 , barheight);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
unmapclient(Client *c) {
|
||||
if(c) {
|
||||
XUnmapWindow(dpy, c->win);
|
||||
XUnmapWindow(dpy, c->tbar);
|
||||
XUnmapWindow(dpy, c->button);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
updatetitle(Client *c) {
|
||||
XFetchName(dpy, c->win, &(c->title));
|
||||
if(!c->title)
|
||||
c->title = strdup("WMFS");
|
||||
XClearWindow(dpy, c->tbar);
|
||||
XSetForeground(dpy, gc, conf.textcolor);
|
||||
XDrawString(dpy, c->tbar, gc, 5, 10, c->title, strlen(c->title));
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
wswitch(char *cmd) {
|
||||
if(sel && !ishide(sel)) {
|
||||
Client *c;
|
||||
if(cmd[0] == '+') {
|
||||
for(c = sel->next; c && ishide(c); c = c->next);
|
||||
if(!c)
|
||||
for(c = clients; c && ishide(c); c = c->next);
|
||||
if(c) {
|
||||
focus(c);
|
||||
raiseclient(c);
|
||||
}
|
||||
} else if(cmd[0] == '-') {
|
||||
for(c = sel->prev; c && ishide(c); c = c->prev);
|
||||
if(!c) {
|
||||
for(c = clients; c && c->next; c = c->next);
|
||||
for(; c && ishide(c); c = c->prev);
|
||||
}
|
||||
if(c) {
|
||||
focus(c);
|
||||
raiseclient(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc,char **argv) {
|
||||
dpy = XOpenDisplay(NULL);
|
||||
int i;
|
||||
|
||||
static struct option long_options[] ={
|
||||
{"help", 0, NULL, 'h'},
|
||||
{"info", 0, NULL, 'i'},
|
||||
{"version", 0, NULL, 'v'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
while ((i = getopt_long (argc, argv, "hvi", long_options, NULL)) != -1) {
|
||||
switch (i) {
|
||||
case 'h':
|
||||
default:
|
||||
printf("Usage: wmfs [OPTION]\n"
|
||||
" -h, --help show this page\n"
|
||||
" -i, --info show informations\n"
|
||||
" -v, --version show WMFS version\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
case 'i':
|
||||
printf("WMFS - Window Manager From Scratch. By :\n"
|
||||
" - Martun Duquesnoy (code)\n"
|
||||
" - Marc Lagrange (build system)\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
case 'v':
|
||||
printf("WMFS version : "WMFS_VERSION".\n"
|
||||
" Compilation settings :\n"
|
||||
" - Flags : "WMFS_COMPILE_FLAGS"\n"
|
||||
" - Linked Libs : "WMFS_LINKED_LIBS"\n"
|
||||
" - On "WMFS_COMPILE_MACHINE" by "WMFS_COMPILE_BY".\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!dpy) {printf("wmfs: cannot open X server\n"); exit(0);}
|
||||
|
||||
init();
|
||||
scan();
|
||||
|
||||
for(;;) {
|
||||
getevent();
|
||||
updatebar();
|
||||
}
|
||||
|
||||
XCloseDisplay(dpy);
|
||||
return 0;
|
||||
}
|
||||
72
wmfsrc
Normal file
72
wmfsrc
Normal file
@ -0,0 +1,72 @@
|
||||
# WMFS config file
|
||||
|
||||
misc
|
||||
{
|
||||
font = "*-fixed-medium-*-12-*"
|
||||
raisefocus = false
|
||||
raiseswitch = true
|
||||
border_height = 1
|
||||
titlebar_height = 12
|
||||
}
|
||||
|
||||
colors
|
||||
{
|
||||
border_normal = 0x354B5C
|
||||
border_focus = 0x6286A1
|
||||
bar = 0x090909
|
||||
button = 0x354B5C
|
||||
text = 0x6289A1
|
||||
tag_sel_fg = 0xFFFFFF
|
||||
tag_sel_bg = 0x354B5C
|
||||
}
|
||||
|
||||
layout
|
||||
{
|
||||
layout_symbol = { "[Free]", "[Tile]", "[Max]" }
|
||||
}
|
||||
|
||||
tag
|
||||
{
|
||||
tag = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }
|
||||
}
|
||||
|
||||
keys
|
||||
{
|
||||
#general keybind
|
||||
|
||||
key { mod = {"Control"} key = "Return" func = "spawn" cmd = "urxvt" }
|
||||
key { mod = {"Alt"} key = "t" func = "spawn" cmd = "thunar" }
|
||||
key { mod = {"Alt"} key = "q" func = "killclient" cmd = NULL }
|
||||
key { mod = {"Control"} key = "t" func = "togglemax" cmd = NULL }
|
||||
key { mod = {"Control"} key = "o" func = "tile" cmd = NULL }
|
||||
key { mod = {"Alt"} key = "Tab" func = "wswitch" cmd = "+" }
|
||||
key { mod = {"Alt","Shift"} key = "Tab" func = "wswitch" cmd = "-" }
|
||||
key { mod = {"Control"} key = "Right" func = "tagswitch" cmd = "+1" }
|
||||
key { mod = {"Control"} key = "Left" func = "tagswitch" cmd = "-1" }
|
||||
|
||||
# moving client keybind
|
||||
|
||||
key { mod = {"Control","Alt"} key = "Left" func = "keymovex" cmd = "-10" }
|
||||
key { mod = {"Control","Alt"} key = "Right" func = "keymovex" cmd = "+10" }
|
||||
key { mod = {"Control","Alt"} key = "Up" func = "keymovey" cmd = "-10" }
|
||||
key { mod = {"Control","Alt"} key = "Down" func = "keymovey" cmd = "+10" }
|
||||
|
||||
# resize client keybind
|
||||
|
||||
key { mod = {"Shift","Alt"} key = "Down" func = "keyresize" cmd = "+h" }
|
||||
key { mod = {"Shift","Alt"} key = "Right" func = "keyresize" cmd = "+w" }
|
||||
key { mod = {"Shift","Alt"} key = "Up" func = "keyresize" cmd = "-h" }
|
||||
key { mod = {"Shift","Alt"} key = "Left" func = "keyresize" cmd = "-w" }
|
||||
|
||||
# tag switching keybind
|
||||
|
||||
key { mod = {"Alt"} key = "F1" func = "tag" cmd = "1" }
|
||||
key { mod = {"Alt"} key = "F2" func = "tag" cmd = "2" }
|
||||
key { mod = {"Alt"} key = "F3" func = "tag" cmd = "3" }
|
||||
key { mod = {"Alt"} key = "F4" func = "tag" cmd = "4" }
|
||||
key { mod = {"Alt"} key = "F5" func = "tag" cmd = "5" }
|
||||
key { mod = {"Alt"} key = "F6" func = "tag" cmd = "6" }
|
||||
key { mod = {"Alt"} key = "F7" func = "tag" cmd = "7" }
|
||||
key { mod = {"Alt"} key = "F8" func = "tag" cmd = "8" }
|
||||
key { mod = {"Alt"} key = "F9" func = "tag" cmd = "9" }
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user