Repository: kuravih/gllock
Branch: master
Commit: 8123a6566e4e
Files: 19
Total size: 46.4 KB
Directory structure:
gitextract_5a6o3nxd/
├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── common.c
├── common.h
├── config.mk
├── gllock.c
├── install
└── shaders/
├── ascii.fragment.glsl
├── blur.fragment.glsl
├── bokeh.fragment.glsl
├── circle.fragment.glsl
├── crt.fragment.glsl
├── glitch.fragment.glsl
├── passthrough.vertex.glsl
├── radialbokeh.fragment.glsl
├── rain.fragment.glsl
└── square.fragment.glsl
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
*.o
================================================
FILE: LICENSE
================================================
MIT/X Consortium License
Copyright for portions of gllock are held by Anselm R Garbe <anselm@garbe.us>, 2006-2012 as part of the project slock.
All other copyright for gllock are held by Kuravi Hewawasam <kuravih@gmail.com>, 2019.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
================================================
FILE: Makefile
================================================
# gllock - simple screen locker
# See LICENSE file for copyright and license details.
include config.mk
SRC = gllock.c common.c
OBJ = ${SRC:.c=.o}
all: options gllock
options:
@echo gllock build options:
@echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}"
.c.o:
@echo CC $<
@${CC} -c ${CFLAGS} $<
${OBJ}: config.mk
gllock: ${OBJ}
@echo CC -o $@
@${CC} -o $@ ${OBJ} ${LDFLAGS}
clean:
@echo cleaning
@rm -f gllock ${OBJ} gllock-${VERSION}.tar.gz
dist: clean
@echo creating dist tarball
@mkdir -p gllock-${VERSION}
@cp -R LICENSE Makefile README config.mk ${SRC} gllock-${VERSION}
@tar -cf gllock-${VERSION}.tar gllock-${VERSION}
@gzip gllock-${VERSION}.tar
@rm -rf gllock-${VERSION}
install: all
@echo installing executable file to ${DESTDIR}${PREFIX}/bin
@mkdir -p ${DESTDIR}${PREFIX}/bin
@cp -f gllock ${DESTDIR}${PREFIX}/bin
@chmod 755 ${DESTDIR}${PREFIX}/bin/gllock
@chmod u+s ${DESTDIR}${PREFIX}/bin/gllock
@ln -sr shaders ${SHADER_LOCATION}
uninstall:
@echo removing executable file from ${DESTDIR}${PREFIX}/bin
@rm -f ${DESTDIR}${PREFIX}/bin/gllock
@echo removing shader link from ${SHADER_LOCATION}
@rm -f ${SHADER_LOCATION}/shaders
.PHONY: all options clean dist install uninstall
================================================
FILE: README.md
================================================
# gllock
OpenGL extension to the simple screen locker [slock](http://github.com/anekos/slock)
Inspired by this [reddit post](https://www.reddit.com/r/unixporn/comments/3358vu/i3lock_unixpornworthy_lock_screen/) this lock screen was implemented using the simplest lock program I could find.
**gllock** will obscure the screen using an opengl texture shader.
## few examples
#### [circles](http://www.shadertoy.com/view/4dsXWs)
<p align="center">
<img width="460" height="300" src="images/circle_shader.gif"></img>
</p>
#### [squares](http://www.shadertoy.com/view/MtfXRN)
<p align="center">
<img width="460" height="300" src="images/square_shader.gif"></img>
</p>
#### [ascii](http://www.shadertoy.com/view/lssGDj)
<p align="center">
<img width="460" height="300" src="images/ascii_shader.gif"></img>
</p>
#### [crt](http://www.shadertoy.com/view/lt3yz7)
<p align="center">
<img width="460" height="300" src="images/crt_shader.gif"></img>
</p>
#### [glitch](http://www.shadertoy.com/view/MlVSD3)
<p align="center">
<img width="460" height="300" src="images/glitch_shader.gif"></img>
</p>
## Requirements
In order to build gllock you need the following packages:
- _x11proto-core-dev_ for `#include <X11/keysym.h>`
- _libx11-dev_ for `#include <X11/Xlib.h>`
- _libglew-dev_ for `#include <GL/glew.h>`
The other requirement will be fulfilled automatically when installing the above.
## Installation
Edit `config.mk` to match your local setup (**gllock** is installed into the `/usr/local` namespace by default).
- `SHADER_LOCATION` - location of the shader files (default `~/.gllock/` which is a symlink to the shader folder of the repository)
- `FRGMNT_SHADER` - the shader file to use (default circle.fragment.glsl)
The following command builds and installs **gllock**:
> sudo make clean install
## Running gllock
Simply invoke the 'gllock' command. To get out of it, enter your password.
However the typical setup involves using gllock with **xautolock**.
For example in order to run **gllock** after N minutes of inactivity the following command may be used.
> sudo xautolock -time N -locker "gllock" &
### Note
when using a particular fragment shader you may want to figure out the supported glsl version for your system using
> glxinfo | grep 'version'
as explained [here](https://askubuntu.com/questions/47062/what-is-terminal-command-that-can-show-opengl-version) and then make the necessary modifications to the shader files.
Most opengl texture shaders from [Shadertoy](www.shadertoy.com) may be adapted to gllock with minimal modifications.
You may use the following substitutions as a starting point.
* use `uniform vec2 screenSize` for `uniform vec3 iResolution` : viewport resolution *pixels*. (i.e. `iResolution.xy` -> `screenSize`).
* use `uniform float time` for `uniform float iTime` : shader playback time *seconds*. (i.e. `iTime` -> `time`);
* use `uniform sampler2D imageData` for `uniform samplerXX iChannel0..3` : input texture channel. (i.e. `iChannel0` -> `imageData`);
* use `void main(void)` for `void mainImage( out vec4 fragColor, in vec2 fragCoord )` for the main function (i.e. `void mainImage(out vec4 fragColor, in vec2 fragCoord)` -> `void main(void)`);
`fragCoord` -> `gl_FragCoord` implicit input
`fragColor` -> `gl_FragColor` implicit output
================================================
FILE: common.c
================================================
#include "common.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#include <GL/glew.h>
#include <GL/glx.h>
#define DEBUG 0
#define MAX_N_TOKENS 65536
#define DELIMITERS " \t\r\n\a"
float
elapsed_time_s(struct timespec start_time)
{
struct timespec tick;
clock_gettime(CLOCK_MONOTONIC_RAW, &tick);
if (tick.tv_nsec < start_time.tv_nsec)
return (tick.tv_sec - 1.0f - start_time.tv_sec) + (1000000000.0f + tick.tv_nsec - start_time.tv_nsec)/1000000000.0f;
else
return (tick.tv_sec - start_time.tv_sec) + (tick.tv_nsec - start_time.tv_nsec)/1000000000.0f;
}
static GLuint
load_shaders_str(const char* vertex_shader_source, const char* fragment_shader_source)
{
// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
GLint Result = GL_FALSE;
int InfoLogLength;
#if DEBUG
printf("Compiling vertex shader\n");
printf("------------------------- vertex shader -------------------------\n%s\n-----------------------------------------------------------------\n\n",vertex_shader_source);
#endif
glShaderSource(VertexShaderID, 1, &vertex_shader_source , NULL);
glCompileShader(VertexShaderID);
// Check Vertex Shader
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if(InfoLogLength>0)
{
char* VertexShaderErrorMessage;
VertexShaderErrorMessage = (char*) malloc(InfoLogLength+1);
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
printf("%s\n", &VertexShaderErrorMessage[0]);
free(VertexShaderErrorMessage);
}
#if DEBUG
printf("Compiling fragment shader\n");
printf("------------------------ fragment shader ------------------------\n%s\n-----------------------------------------------------------------\n\n",fragment_shader_source);
#endif
glShaderSource(FragmentShaderID, 1, &fragment_shader_source , NULL);
glCompileShader(FragmentShaderID);
// Check Fragment Shader
glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if(InfoLogLength>0)
{
char* FragmentShaderErrorMessage;
FragmentShaderErrorMessage = (char*) malloc(InfoLogLength+1);
glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
printf("%s\n", &FragmentShaderErrorMessage[0]);
free(FragmentShaderErrorMessage);
}
// Link the program
#if DEBUG
printf("Linking program\n");
#endif
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
// Check the program
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if(InfoLogLength>0)
{
char* ProgramErrorMessage;
ProgramErrorMessage = (char*) malloc(InfoLogLength+1);
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
printf("%s\n", &ProgramErrorMessage[0]);
free(ProgramErrorMessage);
}
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
return ProgramID;
}
static char*
read_file(const char* filename)
{
char* buffer;
long length = 0;
size_t result = 0;
FILE* fp = fopen(filename, "r");
if(fp)
{
fseek(fp, 0, SEEK_END);
length = ftell(fp);
rewind(fp);
buffer = (char*)malloc(length);
if(buffer)
{
result = fread(buffer, 1, length, fp);
}
fclose(fp);
}
else
{
#if DEBUG
printf("file %s not loading\n",filename);
#endif
exit(0);
}
if (result != length)
{
#if DEBUG
printf("Reading error %s\n",filename);
#endif
exit(3);
}
return buffer;
}
static int
split_line (char* line, char*** p_tokens)
{
char* temp_tokens[MAX_N_TOKENS];
int i = 0, j = 0;
char *token;
int n_tokens = 0;
token = strtok(line, DELIMITERS);
while (token != NULL)
{
temp_tokens[i] = token;
// printf("token : %s\n", temp_tokens[i]);
i++;
token = strtok(NULL, DELIMITERS);
}
n_tokens = i;
// printf("----------\n");
*p_tokens = (char**) malloc(n_tokens * sizeof(char*));
for(j=0; j < n_tokens; j++)
{
// printf("token : %s\n", temp_tokens[j]);
(*p_tokens)[j] = temp_tokens[j];
}
return n_tokens;
}
static void
shaders_defs(char* fragment_shader_source, struct shader_data* data)
{
data->rate = 0.0f;
char** tokens;
int n_tokens;
n_tokens = split_line (fragment_shader_source, &tokens);
size_t i;
for(i=0; i < n_tokens; i++)
{
if((strcmp(tokens[i],"#define")==0) && (strcmp(tokens[i+1],"RATE")==0))
{
data->rate = atof(tokens[i+2]);
}
}
#if DEBUG
printf("shader data: rate = %f", data->rate);
#endif
return;
}
static GLuint
load_shaders_file(const char* vertex_shader_file, const char* fragment_shader_file, struct shader_data* data)
{
char *vertex_shader_str, *fragment_shader_str;
GLuint ProgramID;
vertex_shader_str = read_file(vertex_shader_file);
#if DEBUG
printf("------------------------- vertex shader -------------------------\nfile: %s\n-----------------------------------------------------------------\n\n",vertex_shader_file);
#endif
fragment_shader_str = read_file(fragment_shader_file);
#if DEBUG
printf("------------------------ fragment shader ------------------------\nfile: %s\n-----------------------------------------------------------------\n\n",fragment_shader_file);
#endif
ProgramID = load_shaders_str(vertex_shader_str, fragment_shader_str);
shaders_defs(fragment_shader_str, data);
free(vertex_shader_str);
free(fragment_shader_str);
return ProgramID;
}
Window
fullscreen_win(Display* xdisplay, Window root)
{
GLint attrib[] =
{
GLX_RGBA,
GLX_DEPTH_SIZE, 24,
GLX_DOUBLEBUFFER,
None
};
XVisualInfo* xvisual_info;
xvisual_info = glXChooseVisual(xdisplay, 0, attrib);
if(xvisual_info == NULL)
{
printf("no appropriate visual found\n");
exit(0);
}
XWindowAttributes xwindow_attrib;
XGetWindowAttributes(xdisplay, root, &xwindow_attrib);
XSetWindowAttributes set_xwindow_attrib;
set_xwindow_attrib.colormap = XCreateColormap(xdisplay, root, xvisual_info->visual, AllocNone);
set_xwindow_attrib.event_mask = ExposureMask | KeyPressMask;
set_xwindow_attrib.override_redirect = 1;
return XCreateWindow(xdisplay, root, 0, 0, xwindow_attrib.width, xwindow_attrib.height, 0, xvisual_info->depth, InputOutput, xvisual_info->visual, CWBorderPixel|CWColormap|CWEventMask|CWOverrideRedirect, &set_xwindow_attrib );
}
static XImage*
screen_capture(Display* xdisplay, Window root)
{
XWindowAttributes xwindow_attrib;
XGetWindowAttributes(xdisplay, root, &xwindow_attrib);
return XGetImage(xdisplay, root, 0, 0, xwindow_attrib.width, xwindow_attrib.height, AllPlanes, ZPixmap);
}
#define MAJOR_VERSION 3
#define MINOR_VERSION 3
typedef GLXContext (*glXCreateContextAttribsARBProc) (Display*, GLXFBConfig, GLXContext, Bool, const int*);
void
create_gl_context(Display* xdisplay, Window win)
{
// Create_the_modern_OpenGL_context
// --------------------------------
static int xvisual_attribs[] =
{
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_DOUBLEBUFFER, 1,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
None
};
int num_fbc;
GLXFBConfig* xfbc;
xfbc = glXChooseFBConfig(xdisplay, DefaultScreen(xdisplay), xvisual_attribs, &num_fbc);
if (!xfbc)
{
printf("glXChooseFBConfig() failed\n");
exit(1);
}
XVisualInfo* xvisual_info;
// Create old OpenGL context to get correct function pointer for glXCreateContextAttribsARB()
xvisual_info = glXGetVisualFromFBConfig(xdisplay, xfbc[0]);
GLXContext xcontext_old;
xcontext_old = glXCreateContext(xdisplay, xvisual_info, 0, GL_TRUE);
glXCreateContextAttribsARBProc glXCreateContextAttribsARB;
glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB");
/* Destroy old context */
glXMakeCurrent(xdisplay, 0, 0);
glXDestroyContext(xdisplay, xcontext_old);
if (!glXCreateContextAttribsARB)
{
printf("glXCreateContextAttribsARB() not found\n");
exit(1);
}
// Set desired minimum OpenGL version
static int context_attribs[] =
{
GLX_CONTEXT_MAJOR_VERSION_ARB, MAJOR_VERSION,
GLX_CONTEXT_MINOR_VERSION_ARB, MINOR_VERSION,
None
};
// Create modern OpenGL context
GLXContext xcontext;
xcontext = glXCreateContextAttribsARB(xdisplay, xfbc[0], NULL, 1, context_attribs);
if (!xcontext)
{
printf("Failed to create OpenGL context. Exiting.\n");
exit(1);
}
XMapRaised(xdisplay, win);
glXMakeCurrent(xdisplay, win, xcontext);
int major, minor;
glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor);
printf("OpenGL context created.\nVersion %d.%d\nVendor %s\nRenderer %s\n", major, minor, glGetString(GL_VENDOR), glGetString(GL_RENDERER));
glewExperimental = GL_TRUE; // Needed for core profile
if (glewInit() != GLEW_OK)
{
fprintf(stderr, "Failed to initialize GLEW\n");
exit(0);
}
XWindowAttributes xwindow_attrib;
XGetWindowAttributes(xdisplay, win, &xwindow_attrib);
glViewport(0, 0, xwindow_attrib.width, xwindow_attrib.height);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}
GLuint
setup_shaders(Display* xdisplay, Window root, Window win, struct shader_data* data, const char* vertex_shader_file, const char* fragment_shader_file)
{
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
GLuint programID;
programID = load_shaders_file(vertex_shader_file, fragment_shader_file, data); // Create and compile our GLSL program from the shaders
glUseProgram(programID);
GLuint imageDataID = glGetUniformLocation(programID, "imageData");
glUniform1i(imageDataID, 0);
glActiveTexture(GL_TEXTURE0);
GLuint screenSizeID = glGetUniformLocation(programID, "screenSize");
XWindowAttributes xwindow_attrib;
XGetWindowAttributes(xdisplay, win, &xwindow_attrib);
glUniform2f(screenSizeID, xwindow_attrib.width, xwindow_attrib.height);
static const GLfloat g_vertex_buffer_data[] =
{
-1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
-1.0f, -1.0f, 0.0f
};
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
XImage* ximage;
ximage = screen_capture(xdisplay, root);
if(ximage == NULL)
{
printf("\n\tximage could not be created.\n\n");
exit(0);
}
GLuint texture_id;
glGenTextures(1, &texture_id);
glBindTexture(GL_TEXTURE_2D, texture_id);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, xwindow_attrib.width, xwindow_attrib.height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (void*)(&(ximage->data[0])));
XDestroyImage(ximage);
data->timeID = glGetUniformLocation(programID, "time");
data->endID = glGetUniformLocation(programID, "end");
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); // Clear the screen
return programID;
}
void
animate(Display* xdisplay, Window win, Bool* condition, long* attempts, struct shader_data* data)
{
float time_s=0, end_s=0;
struct timespec start_time;
clock_gettime(CLOCK_MONOTONIC_RAW, &start_time);
glUniform1f(data->endID, end_s);
while (1)
{
time_s=elapsed_time_s(start_time);
glUniform1f(data->timeID, time_s);
glXSwapBuffers(xdisplay, win);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableVertexAttribArray(0);
if ( (end_s>0) && ((time_s-end_s)*data->rate>=1.0) ) { // unlock fade out
break;
}
// if ( (end_s==0) && (!*condition) ) { // TODO: unlock attempt fade out and in
// glUniform1f(data->endID, end_s);
// continue;
// }
if ( (end_s==0) && (!*condition) ) { // lock fade in and hold
end_s = time_s;
glUniform1f(data->endID, end_s);
continue;
}
#if DEBUG
printf("time_s : %f\n", time_s);
#endif
}
printf("Attempts : %ld\n", *attempts);
}
================================================
FILE: common.h
================================================
#ifndef _COMMON_h
#define _COMMON_h
#include <GL/glew.h>
#include <GL/glx.h>
#include <GL/gl.h>
struct shader_data {
float rate;
GLuint timeID;
GLuint endID;
GLuint rateID;
};
Window fullscreen_win(Display*, Window);
void create_gl_context(Display*, Window);
GLuint setup_shaders(Display* xdisplay, Window root, Window win, struct shader_data* data, const char* vertex_shader_file, const char* fragment_shader_file);
void animate(Display* xdisplay, Window win, Bool* condition, long* attempts, struct shader_data* data);
#endif /* _COMMON_h */
================================================
FILE: config.mk
================================================
# gllock version
VERSION = 0.1-alpha
# Customize below to fit your system
# paths
SHADER_LOCATION = $(HOME)/.gllock
# shader
# FRGMNT_SHADER = ascii.fragment.glsl
# FRGMNT_SHADER = blur.fragment.glsl
# FRGMNT_SHADER = bokeh.fragment.glsl
FRGMNT_SHADER = circle.fragment.glsl
# FRGMNT_SHADER = crt.fragment.glsl
# FRGMNT_SHADER = glitch.fragment.glsl
# FRGMNT_SHADER = radialbokeh.fragment.glsl
# FRGMNT_SHADER = rain.fragment.glsl
# FRGMNT_SHADER = square.fragment.glsl
PREFIX = /usr/local
X11INC = /usr/X11R6/include
X11LIB = /usr/X11R6/lib
# includes and libs
INCS = -I. -I/usr/include -I${X11INC}
LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lGL -lGLEW -lpthread
# flags
CPPFLAGS = -DVERSION=\"${VERSION}\" -DHAVE_SHADOW_H -DSHADER_LOCATION=\"${SHADER_LOCATION}\" -DFRGMNT_SHADER=\"${FRGMNT_SHADER}\"
CFLAGS = -pedantic -Wall -Os ${INCS} ${CPPFLAGS}
LDFLAGS = -s ${LIBS}
# On *BSD remove -DHAVE_SHADOW_H from CPPFLAGS and add -DHAVE_BSD_AUTH
# On OpenBSD and Darwin remove -lcrypt from LIBS
# compiler and linker
CC = cc
# Install mode. On BSD systems MODE=2755 and GROUP=auth
# On others MODE=4755 and GROUP=root
#MODE=2755
#GROUP=auth
================================================
FILE: gllock.c
================================================
/* See LICENSE file for license details. */
#define _XOPEN_SOURCE 500
#if HAVE_SHADOW_H
#include <shadow.h>
#endif
#include <ctype.h>
#include <errno.h>
#include <pwd.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <X11/keysym.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include "common.h"
#include <time.h>
#include <pthread.h>
#include <string.h>
#include <stdbool.h>
#include <crypt.h>
#include <GL/glew.h>
#include <GL/glx.h>
#if HAVE_BSD_AUTH
#include <login_cap.h>
#include <bsd_auth.h>
#endif
Display* xdisplay;
typedef struct
{
int screen;
Window root, win;
pthread_t tid;
Bool hold;
long attempts;
} lock_t;
static lock_t* locks;
static int nscreens;
static Bool running = True;
static void
die(const char *errstr, ...)
{
va_list ap;
va_start(ap, errstr);
vfprintf(stderr, errstr, ap);
va_end(ap);
exit(EXIT_FAILURE);
}
#ifndef HAVE_BSD_AUTH
static const char*
getpw(void)
{ /* only run as root */
const char *rval;
struct passwd *pw;
pw = getpwuid(getuid());
if(!pw)
die("gllock: cannot retrieve password entry (make sure to suid or sgid gllock)");
endpwent();
rval = pw->pw_passwd;
#if HAVE_SHADOW_H
if (strlen(rval)>=1)
{ /* kludge, assumes pw placeholder entry has len >= 1 */
struct spwd *sp;
sp = getspnam(getenv("USER"));
if(!sp)
die("gllock: cannot retrieve shadow entry (make sure to suid or sgid gllock)\n");
endspent();
rval = sp->sp_pwdp;
}
#endif
/* drop privileges */
if((setgid(pw->pw_gid)<0)||(setuid(pw->pw_uid)<0))
die("gllock: cannot drop privileges");
return rval;
}
#endif
static void
#ifdef HAVE_BSD_AUTH
readpw(void)
#else
readpw(const char* pws)
#endif
{
char buf[32], passwd[256];
int num, screen;
unsigned int len, llen;
KeySym ksym;
XEvent ev;
len = llen = 0;
running = True;
/* As "gllock" stands for "Simple X display locker".
* The DPMS settings had been removed and you can set it with "xset" or some other utility.
* This way the user can easily set a customized DPMS timeout. */
while(running && !XNextEvent(xdisplay, &ev))
{
if(ev.type == KeyPress)
{
buf[0] = 0;
num = XLookupString(&ev.xkey, buf, sizeof buf, &ksym, 0);
if(IsKeypadKey(ksym))
{
if(ksym == XK_KP_Enter)
ksym = XK_Return;
else if(ksym >= XK_KP_0 && ksym <= XK_KP_9)
ksym = (ksym - XK_KP_0) + XK_0;
}
if(IsFunctionKey(ksym) || IsKeypadKey(ksym) || IsMiscFunctionKey(ksym) || IsPFKey(ksym) || IsPrivateKeypadKey(ksym))
continue;
switch(ksym)
{
case XK_Return:
passwd[len] = 0;
#ifdef HAVE_BSD_AUTH
running = !auth_userokay(getlogin(), NULL, "auth-xlock", passwd);
#else
running = strcmp(crypt(passwd, pws), pws);
#endif
if(running != False) // Wrong password
{
XBell(xdisplay, 100);
for(screen = 0; screen < nscreens; screen++)
{
locks[screen].attempts++;
}
}
len = 0;
break;
case XK_Escape:
len = 0;
break;
case XK_BackSpace:
if(len)
--len;
break;
default:
if(num && !iscntrl((int) buf[0]) && (len + num < sizeof passwd))
{
memcpy(passwd + len, buf, num);
len += num;
}
break;
}
if(llen == 0 && len != 0)
{
for(screen = 0; screen < nscreens; screen++)
{
// characters on the buffer
}
}
else if(llen != 0 && len == 0)
{
for(screen = 0; screen < nscreens; screen++)
{
// Wrong password
}
}
llen = len;
}
else
for(screen = 0; screen < nscreens; screen++)
XRaiseWindow(xdisplay, locks[screen].win);
}
}
static void
unlockscreen(lock_t* lock)
{
if(xdisplay == NULL || lock == NULL)
return;
lock->hold = False;
pthread_join(lock->tid, NULL);
XUngrabPointer(xdisplay, CurrentTime);
XDestroyWindow(xdisplay, lock->win);
}
void*
animation_runner(void* arg)
{
lock_t* lock = (lock_t*) arg;
XLockDisplay(xdisplay);
create_gl_context(xdisplay, lock->win);
struct shader_data data;
setup_shaders(xdisplay, lock->root, lock->win, &data, SHADER_LOCATION"/passthrough.vertex.glsl", SHADER_LOCATION"/"FRGMNT_SHADER);
XUnlockDisplay(xdisplay);
animate(xdisplay, lock->win, &(lock->hold), &(lock->attempts), &data);
return NULL;
}
int
lockscreen(lock_t* lock) {
unsigned int len;
Cursor invisible = 0;
lock->hold = True;
lock->attempts = 0;
XLockDisplay(xdisplay);
lock->win = fullscreen_win(xdisplay, lock->root);
XUnlockDisplay(xdisplay);
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&(lock->tid), NULL, animation_runner, lock);
for(len = 1000; len; len--)
{
if(XGrabPointer(xdisplay, lock->root, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, GrabModeAsync, GrabModeAsync, None, invisible, CurrentTime) == GrabSuccess)
break;
usleep(1000);
}
if(running && (len > 0))
{
for(len = 1000; len; len--)
{
if(XGrabKeyboard(xdisplay, lock->root, True, GrabModeAsync, GrabModeAsync, CurrentTime) == GrabSuccess)
break;
usleep(1000);
}
}
running &= (len > 0);
if(!running)
{
unlockscreen(lock);
lock = NULL;
}
else
{
XSelectInput(xdisplay, lock->root, SubstructureNotifyMask);
XSync(xdisplay, False);
}
return 1;
}
static void
usage(void)
{
fprintf(stderr, "usage: gllock [-v]\n");
exit(EXIT_FAILURE);
}
int
main(int argc, char **argv)
{
#ifndef HAVE_BSD_AUTH
const char* password;
#endif
int screen;
{
int result;
while((result = getopt(argc,argv,"vo:")) != -1)
{
switch(result)
{
case 'v':
die("gllock-%s, © 2019 Kuravi H\n", VERSION);
case '?':
usage();
break;
}
}
if((argc - optind) > 0)
usage();
}
if(!getpwuid(getuid()))
die("gllock: no passwd entry for you");
#ifndef HAVE_BSD_AUTH
password = getpw();
#endif
XInitThreads();
if(!(xdisplay = XOpenDisplay(0)))
die("gllock: cannot open display");
/* Get the number of screens in display "xdisplay" and blank them all. */
nscreens = ScreenCount(xdisplay);
locks = malloc(nscreens*sizeof(lock_t));
for(screen = 0; screen < nscreens; screen++)
{
locks[screen].screen = screen;
locks[screen].root = RootWindow(xdisplay, locks[screen].screen);
}
if(locks == NULL)
die("gllock: malloc: %s", strerror(errno));
/* lock */
int nlocks = 0;
for(screen = 0; screen < nscreens; screen++)
{
if( lockscreen(&(locks[screen])) )
nlocks++;
}
XSync(xdisplay, False);
/* Did we actually manage to lock something? */
if(nlocks == 0)
{ // nothing to protect
free(locks);
XCloseDisplay(xdisplay);
return 1;
}
/* Everything is now blank. Now wait for the correct password. */
#ifdef HAVE_BSD_AUTH
readpw();
#else
readpw(password);
#endif
/* Password ok, unlock everything and quit. */
for(screen = 0; screen < nscreens; screen++)
unlockscreen(&(locks[screen]));
free(locks);
XCloseDisplay(xdisplay);
return 0;
}
================================================
FILE: install
================================================
#!/bin/sh
DEST=~/bin/gllock
make
sudo chown root: gllock
sudo chmod u+s gllock
mv gllock $DEST
================================================
FILE: shaders/ascii.fragment.glsl
================================================
// http://www.shadertoy.com/view/lssGDj
#version 330 core
// ---- gllock required fields -----------------------------------------------------------------------------------------
#define RATE 1.0
uniform float time;
uniform float end;
uniform sampler2D imageData;
uniform vec2 screenSize;
// ---------------------------------------------------------------------------------------------------------------------
#define MIN_SIZE 0.0f
#define MAX_SIZE 16.0f
float character(int n, vec2 p)
{
p = floor(p*vec2(4.0, -4.0) + 2.5);
if (clamp(p.x, 0.0, 4.0) == p.x)
{
if (clamp(p.y, 0.0, 4.0) == p.y)
{
int a = int(round(p.x) + 5.0 * round(p.y));
if (((n >> a) & 1) == 1) return 1.0;
}
}
return 0.0;
}
void main(void) {
float shaderTime = smoothstep(0.0,1.0,(time-end)*RATE);
shaderTime = (end==0)?shaderTime:(1.0-shaderTime);
float radius = mix(MIN_SIZE, MAX_SIZE, shaderTime); //Returns the linear blend of MIN_SIZE and MAX_SIZE
vec2 pix = vec2(1,-1)*gl_FragCoord.xy;
vec3 col = texture(imageData, floor(pix/radius)*radius/screenSize.xy).rgb;
float gray = 0.3 * col.r + 0.59 * col.g + 0.11 * col.b;
int n = 4096; // .
if (gray > 0.2) n = 65600; // :
if (gray > 0.3) n = 332772; // *
if (gray > 0.4) n = 15255086; // o
if (gray > 0.5) n = 23385164; // &
if (gray > 0.6) n = 15252014; // 8
if (gray > 0.7) n = 13199452; // @
if (gray > 0.8) n = 11512810; // #
vec2 p = mod(2*pix/radius, 2.0) - vec2(1.0);
col = col*character(n, p);
gl_FragColor = vec4(col, 1.0);
}
//
================================================
FILE: shaders/blur.fragment.glsl
================================================
//https://www.shadertoy.com/view/XdfGDH
#version 330 core
// ---- gllock required fields -----------------------------------------------------------------------------------------
#define RATE 0.75
uniform float time;
uniform float end;
uniform sampler2D imageData;
uniform vec2 screenSize;
// ---------------------------------------------------------------------------------------------------------------------
#define MIN_SIZE 0.0f
#define MAX_SIZE 7.0f //odd value required
float normpdf(in float x, in float sigma) {
return 0.39894*exp(-0.5*x*x/(sigma*sigma))/sigma;
}
void main(void) {
vec3 c = texture(imageData, vec2(1,-1)*gl_FragCoord.xy/screenSize).rgb;
//declare stuff
const int mSize = int(MAX_SIZE+4);
const int kSize = (mSize-1)/2;
float kernel[mSize];
vec3 final_colour = vec3(0.0);
float shaderTime = smoothstep(0.0,1.0,(time-end)*RATE);
shaderTime = (end==0)?shaderTime:(1.0-shaderTime);
float radius = mix(MIN_SIZE, MAX_SIZE, shaderTime); //Returns the linear blend of MIN_SIZE and MAX_SIZE
//create the 1-D kernel
float Z = 0.0;
for (int j = 0; j <= kSize; ++j) {
kernel[kSize+j] = kernel[kSize-j] = normpdf(float(j), radius);
}
//get the normalization factor (as the gaussian has been clamped)
for (int j = 0; j < mSize; ++j) {
Z += kernel[j];
}
//read out the texels
for (int i=-kSize; i <= kSize; ++i) {
for (int j=-kSize; j <= kSize; ++j) {
final_colour += kernel[kSize+j]*kernel[kSize+i]*texture(imageData, vec2(1,-1)*(gl_FragCoord.xy+vec2(float(i),float(j))) / screenSize).rgb;
}
}
gl_FragColor = vec4(final_colour/(Z*Z), 1.0);
}
================================================
FILE: shaders/bokeh.fragment.glsl
================================================
// https://www.shadertoy.com/view/XsfSRr
#version 330 core
// ---- gllock required fields -----------------------------------------------------------------------------------------
#define RATE 0.75
uniform float time;
uniform float end;
uniform sampler2D imageData;
uniform vec2 screenSize;
// ---------------------------------------------------------------------------------------------------------------------
#define MIN_SIZE 0.0f
#define MAX_SIZE 2.0f
vec2 pixel;
float factor;
float radius;
vec4 tex(vec2 uv) {
return pow(texture(imageData, uv), vec4(2.2));
}
vec4 accumCol = vec4(0.0);
vec4 accumW = vec4(0.0);
const float mas = 3.0;
void add(vec2 uv, float i, float j) {
vec2 offset = pixel * vec2(i, j);
vec4 col = tex(uv + offset * radius);
vec4 bokeh = vec4(1.0) + pow(col, vec4(4.0)) * vec4(factor);
accumCol += col * bokeh;
accumW += bokeh;
}
vec4 blur(vec2 uv) {
for (float j = -7.0 + mas; j <= 7.0 - mas; j += 1.0)
for (float i = -7.0 + mas; i <=7.0 - mas; i += 1.0)
add(uv, i, j);
for (float i = -5.0 + mas; i <=5.0 - mas; i+=1.0) {
add(uv, i, -8.0 + mas);
add(uv, i, 8.0 - mas);
}
for (float j = -5.0 + mas; j <=5.0 - mas; j+=1.0) {
add(uv, -8.0 + mas, j);
add(uv, 8.0 - mas, j);
}
for (float i = -3.0 +mas; i <=3.0 - mas; i+=1.0) {
add(uv, i, -9.0 + mas);
add(uv, i, 9.0 - mas);
}
for (float j = -3.0 + mas; j <=3.0 - mas; j+=1.0) {
add(uv, -9.0 + mas, j);
add(uv, 9.0 - mas, j);
}
return accumCol/accumW;
}
void main(void) {
pixel = 1.0/screenSize;
float shaderTime = smoothstep(0.0,1.0,(time-end)*RATE);
shaderTime = (end==0)?shaderTime:(1.0-shaderTime);
radius = mix(MIN_SIZE, MAX_SIZE, shaderTime); //Returns the linear blend of MIN_SIZE and MAX_SIZE
factor = radius*16.0;
vec2 uv = gl_FragCoord.xy / screenSize;
gl_FragColor = pow(blur(vec2(0.0, 1.0) + uv * vec2(1.0, -1.0)),1.0/vec4(2.2));
}
================================================
FILE: shaders/circle.fragment.glsl
================================================
// http://www.shadertoy.com/view/4dsXWs
#version 330 core
// ---- gllock required fields -----------------------------------------------------------------------------------------
#define RATE 1.0
uniform float time;
uniform float end;
uniform sampler2D imageData;
uniform vec2 screenSize;
// ---------------------------------------------------------------------------------------------------------------------
#define MIN_SIZE 2.0f
#define MAX_SIZE 18.0f
// Compute the relative distance to the circle, where < 0.0 is outside the feathered border, and > 1.0 is inside the feathered border.
float ComputeCircle(vec2 pos, vec2 center, float radius, float feather) {
// Determine the distance to the center of the circle.
float dist = length(center - pos);
// Use the distance and the specified feather factor to determine where the distance lies relative to the circle border.
float start = radius - feather;
float end = radius + feather;
return smoothstep(start, end, dist);
}
// The main function, which is executed once per pixel.
void main(void) {
float shaderTime = smoothstep(0.0,1.0,(time-end)*RATE);
shaderTime = (end==0)?shaderTime:(1.0-shaderTime);
float diameter = mix(MIN_SIZE, MAX_SIZE, shaderTime); //Returns the linear blend of MIN_SIZE and MAX_SIZE
float radius = diameter / 2.0;
vec2 center = vec2(0.0);
// Compute the relative distance to the circle, using mod() to repeat the circle across the display.
// A feather value (in pixels) is used to reduce aliasing artifacts when the circles are small.
// The position is adjusted so that a circle is in the center of the display.
vec2 screenPos = gl_FragCoord.xy - (screenSize / 2.0) - vec2(radius);
vec2 pos = mod(screenPos, vec2(diameter)) - vec2(radius);
float d = ComputeCircle(pos, center, radius, 0.5);
// Compute "pixelated" (stepped) texture coordinates using the floor() function.
// The position is adjusted to match the circles, i.e. so a pixelated block is at the center of the display.
vec2 count = screenSize / diameter;
vec2 shift = vec2(0.5) - fract(count / 2.0);
vec2 uv = floor(count * gl_FragCoord.xy / screenSize + shift) / count;
// Sample the texture, using an offset to the center of the pixelated block.
// NOTE: Use a large negative bias to effectively disable mipmapping, which would otherwise lead to sampling artifacts where the UVs change abruptly at the pixelated block boundaries.
uv += vec2(0.5) / count;
uv = clamp(uv, 0.0, 1.0);
uv.y = 1.0 - uv.y;
vec3 texColor = texture(imageData, uv, -32.0).rgb;
// Calculate the color based on the circle shape, mixing between that color and a background color.
// NOTE: Set the mix factor to 0.0 to see the pixelating effect directly, without the circles.
vec3 bg = vec3(0.0, 0.0, 0.0);
vec3 col = mix(texColor, bg, d);
// Set the final fragment color.
gl_FragColor = vec4(col, 1.0);
}
//
================================================
FILE: shaders/crt.fragment.glsl
================================================
// http://www.shadertoy.com/view/lt3yz7
#version 330 core
// ---- gllock required fields -----------------------------------------------------------------------------------------
#define RATE 0.75
uniform float time;
uniform float end;
uniform sampler2D imageData;
uniform vec2 screenSize;
// ---------------------------------------------------------------------------------------------------------------------
float rand(float seed){
return fract(sin(dot(vec2(seed) ,vec2(12.9898,78.233))) * 43758.5453);
}
vec2 displace(vec2 co, float seed, float seed2) {
vec2 shift = vec2(0);
if (rand(seed) > 0.5) {
shift += 0.1 * vec2(2. * (0.5 - rand(seed2)));
}
if (rand(seed2) > 0.6) {
if (co.y > 0.5) {
shift.x *= rand(seed2 * seed);
}
}
return shift;
}
vec4 interlace(vec2 co, vec4 col) {
float shaderTime = time*RATE;
if (int(co.y) % 3 == 0) {
return col * ((sin(shaderTime * 4.) * 0.1) + 0.75) + (rand(shaderTime) * 0.05);
}
return col;
}
void main(void) {
float shaderTime = time*RATE;
// Normalized pixel coordinates (from 0 to 1)
vec2 uv = vec2(1,-1)*gl_FragCoord.xy / screenSize;
vec2 rDisplace = vec2(0);
vec2 gDisplace = vec2(0);
vec2 bDisplace = vec2(0);
if (rand(shaderTime) > 0.95) {
rDisplace = displace(uv, shaderTime * 2., 2. + shaderTime);
gDisplace = displace(uv, shaderTime * 3., 3. + shaderTime);
bDisplace = displace(uv, shaderTime * 5., 5. + shaderTime);
}
rDisplace.x += 0.005 * (0.5 - rand(shaderTime * 37. * uv.y));
gDisplace.x += 0.007 * (0.5 - rand(shaderTime * 41. * uv.y));
bDisplace.x += 0.0011 * (0.5 - rand(shaderTime * 53. * uv.y));
rDisplace.y += 0.001 * (0.5 - rand(shaderTime * 37. * uv.x));
gDisplace.y += 0.001 * (0.5 - rand(shaderTime * 41. * uv.x));
bDisplace.y += 0.001 * (0.5 - rand(shaderTime * 53. * uv.x));
// Output to screen
float rcolor = texture(imageData, uv.xy + rDisplace).r;
float gcolor = texture(imageData, uv.xy + gDisplace).g;
float bcolor = texture(imageData, uv.xy + bDisplace).b;
gl_FragColor = interlace(gl_FragCoord.xy, vec4(rcolor, gcolor, bcolor, 1));
}
//
================================================
FILE: shaders/glitch.fragment.glsl
================================================
// http://www.shadertoy.com/view/MlVSD3
#version 330 core
// ---- gllock required fields -----------------------------------------------------------------------------------------
#define RATE 0.75
uniform float time;
uniform float end;
uniform sampler2D imageData;
uniform vec2 screenSize;
// ---------------------------------------------------------------------------------------------------------------------
float rand(vec2 co){
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453) * 2.0 - 1.0;
}
float offset(float blocks, vec2 uv) {
float shaderTime = time*RATE;
return rand(vec2(shaderTime, floor(uv.y * blocks)));
}
void main(void) {
vec2 uv = vec2(1,-1)*gl_FragCoord.xy / screenSize;
gl_FragColor = texture(imageData, uv);
gl_FragColor.r = texture(imageData, uv + vec2(offset(64.0, uv) * 0.03, 0.0)).r;
gl_FragColor.g = texture(imageData, uv + vec2(offset(64.0, uv) * 0.03 * 0.16666666, 0.0)).g;
gl_FragColor.b = texture(imageData, uv + vec2(offset(64.0, uv) * 0.03, 0.0)).b;
}
//
================================================
FILE: shaders/passthrough.vertex.glsl
================================================
#version 330 core
// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;
void main(void){
gl_Position = vec4(vertexPosition_modelspace,1);
}
================================================
FILE: shaders/radialbokeh.fragment.glsl
================================================
//https://www.shadertoy.com/view/XtjGWm
// Bokeh disc.
// by David Hoskins.
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
#version 330 core
// ---- gllock required fields -----------------------------------------------------------------------------------------
#define RATE 0.75
uniform float time;
uniform float end;
uniform sampler2D imageData;
uniform vec2 screenSize;
// ---------------------------------------------------------------------------------------------------------------------
#define MIN_SIZE 0.0f
#define MAX_SIZE 0.5f
#define PI 3.141596
// This is (3.-sqrt(5.0))*PI radians, which doesn't precompiled for some reason.
// The compiler is a dunce I tells-ya!!
#define GOLDEN_ANGLE 2.39996323
#define NUMBER 150.0
#define ITERATIONS (GOLDEN_ANGLE * NUMBER)
//-------------------------------------------------------------------------------------------
// This creates the 2D offset for the next point.
// (r-1.0) is the equivalent to sqrt(0, 1, 2, 3...)
vec2 Sample(in float theta, inout float r) {
r += 1.0 / r;
return (r-1.0) * vec2(cos(theta), sin(theta));
}
//-------------------------------------------------------------------------------------------
vec3 Bokeh(sampler2D tex, vec2 uv, float radius, float amount) {
vec3 acc = vec3(0.0);
vec3 div = vec3(0.0);
vec2 pixel = vec2(screenSize.y/screenSize.x, 1.0) * radius * .006;
float r = 1.0;
for (float j = 0.0; j < ITERATIONS; j += GOLDEN_ANGLE) {
vec3 col = texture(tex, uv + pixel * Sample(j, r), radius*1.5).xyz;
vec3 bokeh = vec3(5.0) + pow(col, vec3(9.0)) * amount;
acc += col * bokeh;
div += bokeh;
}
return acc / div;
}
void main(void) {
float shaderTime = smoothstep(0.0,1.0,(time-end)*RATE);
shaderTime = (end==0)?shaderTime:(1.0-shaderTime);
float radius = mix(MIN_SIZE, MAX_SIZE, shaderTime); //Returns the linear blend of MIN_SIZE and MAX_SIZE
vec2 uv = gl_FragCoord.xy / screenSize;
float a = 10.0;
vec2 xy = vec2(uv.x,1.0-uv.y);
float dis = distance(gl_FragCoord.xy, screenSize/2.0);
gl_FragColor = vec4(Bokeh(imageData, xy, radius*dis*0.001, a), 1.0);
}
//
================================================
FILE: shaders/rain.fragment.glsl
================================================
// https://www.shadertoy.com/view/ltffzl
#version 330 core
// ---- gllock required fields -----------------------------------------------------------------------------------------
#define RATE 0.5
uniform float time;
uniform float end;
uniform sampler2D imageData;
uniform vec2 screenSize;
// ---------------------------------------------------------------------------------------------------------------------
#define MIN_AMOUNT 0.0f
#define MAX_AMOUNT 1.0f //odd value required
// #define CHEAP_NORMALS
// #define USE_POST_PROCESSING
vec3 N13(float p) {
// from DAVE HOSKINS
vec3 p3 = fract(vec3(p) * vec3(.1031,.11369,.13787));
p3 += dot(p3, p3.yzx + 19.19);
return fract(vec3((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y, (p3.y+p3.z)*p3.x));
}
vec4 N14(float t) {
return fract(sin(t*vec4(123., 1024., 1456., 264.))*vec4(6547., 345., 8799., 1564.));
}
float N(float t) {
return fract(sin(t*12345.564)*7658.76);
}
float Saw(float b, float t) {
return smoothstep(0., b, t)*smoothstep(1., b, t);
}
vec2 DropLayer2(vec2 uv, float t) {
vec2 UV = uv;
uv.y += t*0.75;
vec2 a = vec2(6., 1.);
vec2 grid = a*2.;
vec2 id = floor(uv*grid);
float colShift = N(id.x);
uv.y += colShift;
id = floor(uv*grid);
vec3 n = N13(id.x*35.2+id.y*2376.1);
vec2 st = fract(uv*grid)-vec2(.5, 0);
float x = n.x-.5;
float y = UV.y*20.;
float wiggle = sin(y+sin(y));
x += wiggle*(.5-abs(x))*(n.z-.5);
x *= .7;
float ti = fract(t+n.z);
y = (Saw(.85, ti)-.5)*.9+.5;
vec2 p = vec2(x, y);
float d = length((st-p)*a.yx);
float mainDrop = smoothstep(.4, .0, d);
float r = sqrt(smoothstep(1., y, st.y));
float cd = abs(st.x-x);
float trail = smoothstep(.23*r, .15*r*r, cd);
float trailFront = smoothstep(-.02, .02, st.y-y);
trail *= trailFront*r*r;
y = UV.y;
float trail2 = smoothstep(.2*r, .0, cd);
float droplets = max(0., (sin(y*(1.-y)*120.)-st.y))*trail2*trailFront*n.z;
y = fract(y*10.)+(st.y-.5);
float dd = length(st-vec2(x, y));
droplets = smoothstep(.3, 0., dd);
float m = mainDrop+droplets*r*trailFront;
//m += st.x>a.y*.45 || st.y>a.x*.165 ? 1.2 : 0.;
return vec2(m, trail);
}
float StaticDrops(vec2 uv, float t) {
uv *= 40.;
vec2 id = floor(uv);
uv = fract(uv)-.5;
vec3 n = N13(id.x*107.45+id.y*3543.654);
vec2 p = (n.xy-.5)*.7;
float d = length(uv-p);
float fade = Saw(.025, fract(t+n.z));
float c = smoothstep(.3, 0., d)*fract(n.z*10.)*fade;
return c;
}
vec2 Drops(vec2 uv, float t, float l0, float l1, float l2) {
float s = StaticDrops(uv, t)*l0;
vec2 m1 = DropLayer2(uv, t)*l1;
vec2 m2 = DropLayer2(uv*1.85, t)*l2;
float c = s+m1.x+m2.x;
c = smoothstep(.3, 1., c);
return vec2(c, max(m1.y*l0, m2.y*l1));
}
void main(void) {
float shaderTime = time*RATE;
vec2 uv = (gl_FragCoord.xy-.5*screenSize) / screenSize.y;
vec2 UV = vec2(1,-1)*gl_FragCoord.xy/screenSize;
float amountTime = smoothstep(0.0,1.0,(time-end)*RATE);
amountTime = (end==0)?amountTime:(1.0-amountTime);
float amount = mix(MIN_AMOUNT, MAX_AMOUNT, amountTime); //Returns the linear blend of MIN_SIZE and MAX_SIZE
float rainAmount = amount*(0.3*sin(shaderTime*0.05)+0.7);
float maxBlur = mix(3.0, 6.0, rainAmount);
float minBlur = 2.0;
UV = (UV-0.5)+0.5;
float staticDrops = smoothstep(-.5, 1., rainAmount)*2.;
float layer1 = smoothstep(.25, .75, rainAmount);
float layer2 = smoothstep(.0, .5, rainAmount);
vec2 c = Drops(uv, shaderTime, staticDrops, layer1, layer2);
vec2 e = vec2(.001, 0.);
float cx = Drops(uv+e, shaderTime, staticDrops, layer1, layer2).x;
float cy = Drops(uv+e.yx, shaderTime, staticDrops, layer1, layer2).x;
vec2 n = vec2(cx-c.x, cy-c.x); // expensive normals
float focus = mix(maxBlur, minBlur, smoothstep(.1, .2, c.x));
vec3 col = textureLod(imageData, UV+n, focus).rgb;
gl_FragColor = vec4(col, 1.);
}
//
================================================
FILE: shaders/square.fragment.glsl
================================================
// http://www.shadertoy.com/view/MtfXRN
#version 330 core
// ---- gllock required fields -----------------------------------------------------------------------------------------
#define RATE 1.0
uniform float time;
uniform float end;
uniform sampler2D imageData;
uniform vec2 screenSize;
// ---------------------------------------------------------------------------------------------------------------------
#define MIN_SIZE 2.0f
#define MAX_SIZE 18.0f
#define USE_TILE_BORDER
#define USE_ROUNDED_CORNERS
void main(void) {
const float textureSamplesCount = 10.0;
const float textureEdgeOffset = 0.005;
const float borderSize = 0.75;
float shaderTime = smoothstep(0.0,1.0,(time-end)*RATE);
shaderTime = (end==0)?shaderTime:(1.0-shaderTime);
float tileSize = mix(MIN_SIZE, MAX_SIZE, shaderTime);
tileSize += mod(tileSize, 2.0);
vec2 tileNumber = floor(gl_FragCoord.xy / tileSize);
vec4 accumulator = vec4(0.0);
for (float y = 0.0; y < textureSamplesCount; ++y) {
for (float x = 0.0; x < textureSamplesCount; ++x) {
vec2 textureCoordinates = (tileNumber + vec2((x + 0.5)/textureSamplesCount, (y + 0.5)/textureSamplesCount)) * tileSize / screenSize;
textureCoordinates.y = 1.0 - textureCoordinates.y;
textureCoordinates = clamp(textureCoordinates, 0.0 + textureEdgeOffset, 1.0 - textureEdgeOffset);
accumulator += texture(imageData, textureCoordinates);
}
}
gl_FragColor = accumulator / vec4(textureSamplesCount * textureSamplesCount);
#if defined(USE_TILE_BORDER) || defined(USE_ROUNDED_CORNERS)
vec2 pixelNumber = floor(gl_FragCoord.xy - (tileNumber * tileSize));
pixelNumber = mod(pixelNumber + borderSize, tileSize);
#if defined(USE_TILE_BORDER)
float pixelBorder = step(min(pixelNumber.x, pixelNumber.y), borderSize) * step(borderSize * 2.0 + 1.0, tileSize);
#else
float pixelBorder = step(pixelNumber.x, borderSize) * step(pixelNumber.y, borderSize) * step(borderSize * 2.0 + 1.0, tileSize);
#endif
gl_FragColor *= pow(gl_FragColor, vec4(pixelBorder));
#endif
}
//
gitextract_5a6o3nxd/
├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── common.c
├── common.h
├── config.mk
├── gllock.c
├── install
└── shaders/
├── ascii.fragment.glsl
├── blur.fragment.glsl
├── bokeh.fragment.glsl
├── circle.fragment.glsl
├── crt.fragment.glsl
├── glitch.fragment.glsl
├── passthrough.vertex.glsl
├── radialbokeh.fragment.glsl
├── rain.fragment.glsl
└── square.fragment.glsl
SYMBOL INDEX (24 symbols across 3 files)
FILE: common.c
function elapsed_time_s (line 25) | float
function GLuint (line 45) | static GLuint
function split_line (line 179) | static int
function shaders_defs (line 216) | static void
function GLuint (line 246) | static GLuint
function Window (line 277) | Window
function XImage (line 315) | static XImage*
type GLXContext (line 335) | typedef GLXContext (*glXCreateContextAttribsARBProc) (Display*, GLXFBCon...
function create_gl_context (line 337) | void
function GLuint (line 429) | GLuint
function animate (line 504) | void
FILE: common.h
type shader_data (line 8) | struct shader_data {
type shader_data (line 17) | struct shader_data
type shader_data (line 18) | struct shader_data
FILE: gllock.c
type lock_t (line 45) | typedef struct
function die (line 67) | static void
type passwd (line 92) | struct passwd
type spwd (line 103) | struct spwd
function readpw (line 130) | readpw(void)
function unlockscreen (line 240) | static void
type shader_data (line 272) | struct shader_data
function lockscreen (line 291) | int
function usage (line 349) | static void
function main (line 365) | int
Condensed preview — 19 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (51K chars).
[
{
"path": ".gitignore",
"chars": 5,
"preview": "\n*.o\n"
},
{
"path": "LICENSE",
"chars": 1257,
"preview": "MIT/X Consortium License\n\nCopyright for portions of gllock are held by Anselm R Garbe <anselm@garbe.us>, 2006-2012 as pa"
},
{
"path": "Makefile",
"chars": 1258,
"preview": "# gllock - simple screen locker\n# See LICENSE file for copyright and license details.\n\ninclude config.mk\n\nSRC = gllock.c"
},
{
"path": "README.md",
"chars": 3341,
"preview": "# gllock\nOpenGL extension to the simple screen locker [slock](http://github.com/anekos/slock)\n\nInspired by this [reddit "
},
{
"path": "common.c",
"chars": 12845,
"preview": "#include \"common.h\"\n#include <stdio.h>\n#include <stdlib.h>\n#include <time.h>\n#include <unistd.h>\n\n#include <string.h>\n\n#"
},
{
"path": "common.h",
"chars": 558,
"preview": "#ifndef _COMMON_h\n#define _COMMON_h\n\n#include <GL/glew.h>\n#include <GL/glx.h>\n#include <GL/gl.h>\n\nstruct shader_data {\n "
},
{
"path": "config.mk",
"chars": 1154,
"preview": "# gllock version\nVERSION = 0.1-alpha\n\n# Customize below to fit your system\n\n# paths\nSHADER_LOCATION = $(HOME)/.gllock\n\n#"
},
{
"path": "gllock.c",
"chars": 7444,
"preview": "\n/* See LICENSE file for license details. */\n#define _XOPEN_SOURCE 500\n\n#if HAVE_SHADOW_H\n#include <shadow.h>\n#endif\n\n#i"
},
{
"path": "install",
"chars": 99,
"preview": "#!/bin/sh\n\nDEST=~/bin/gllock\n\nmake\nsudo chown root: gllock\nsudo chmod u+s gllock\nmv gllock $DEST\n\n\n"
},
{
"path": "shaders/ascii.fragment.glsl",
"chars": 1589,
"preview": "// http://www.shadertoy.com/view/lssGDj\n#version 330 core\n\n// ---- gllock required fields ------------------------------"
},
{
"path": "shaders/blur.fragment.glsl",
"chars": 1636,
"preview": "//https://www.shadertoy.com/view/XdfGDH\n#version 330 core\n\n// ---- gllock required fields ------------------------------"
},
{
"path": "shaders/bokeh.fragment.glsl",
"chars": 1929,
"preview": "// https://www.shadertoy.com/view/XsfSRr\n#version 330 core\n\n// ---- gllock required fields -----------------------------"
},
{
"path": "shaders/circle.fragment.glsl",
"chars": 2926,
"preview": "// http://www.shadertoy.com/view/4dsXWs\n#version 330 core\n\n// ---- gllock required fields ------------------------------"
},
{
"path": "shaders/crt.fragment.glsl",
"chars": 2131,
"preview": "// http://www.shadertoy.com/view/lt3yz7\n#version 330 core\n\n// ---- gllock required fields ------------------------------"
},
{
"path": "shaders/glitch.fragment.glsl",
"chars": 1021,
"preview": "// http://www.shadertoy.com/view/MlVSD3\n#version 330 core\n\n// ---- gllock required fields ------------------------------"
},
{
"path": "shaders/passthrough.vertex.glsl",
"chars": 223,
"preview": "#version 330 core\r\n\r\n// Input vertex data, different for all executions of this shader.\r\nlayout(location = 0) in vec3 ve"
},
{
"path": "shaders/radialbokeh.fragment.glsl",
"chars": 2143,
"preview": "//https://www.shadertoy.com/view/XtjGWm\n// Bokeh disc.\n// by David Hoskins.\n// License Creative Commons Attribution-NonC"
},
{
"path": "shaders/rain.fragment.glsl",
"chars": 3901,
"preview": "// https://www.shadertoy.com/view/ltffzl\n#version 330 core\n\n// ---- gllock required fields -----------------------------"
},
{
"path": "shaders/square.fragment.glsl",
"chars": 2055,
"preview": "// http://www.shadertoy.com/view/MtfXRN\n#version 330 core\n\n// ---- gllock required fields ------------------------------"
}
]
About this extraction
This page contains the full source code of the kuravih/gllock GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 19 files (46.4 KB), approximately 14.5k tokens, and a symbol index with 24 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.