mirror of
https://github.com/Raymo111/i3lock-color.git
synced 2025-02-17 15:55:52 -05:00
merge upstream
This commit is contained in:
commit
1d4cb5a398
4 changed files with 140 additions and 30 deletions
|
@ -21,9 +21,9 @@ addons:
|
||||||
- libxcb-xkb-dev
|
- libxcb-xkb-dev
|
||||||
before_install:
|
before_install:
|
||||||
- "echo 'APT::Default-Release \"trusty\";' | sudo tee /etc/apt/apt.conf.d/default-release"
|
- "echo 'APT::Default-Release \"trusty\";' | sudo tee /etc/apt/apt.conf.d/default-release"
|
||||||
- "echo 'deb http://archive.ubuntu.com/ubuntu/ wily main universe' | sudo tee /etc/apt/sources.list.d/wily.list"
|
- "echo 'deb http://archive.ubuntu.com/ubuntu/ xenial main universe' | sudo tee /etc/apt/sources.list.d/wily.list"
|
||||||
- sudo apt-get update
|
- sudo apt-get update
|
||||||
- sudo apt-get --force-yes -y install -t wily libxkbcommon-dev libxkbcommon-x11-dev
|
- sudo apt-get --force-yes -y install -t xenial libxkbcommon-dev libxkbcommon-x11-dev
|
||||||
script:
|
script:
|
||||||
- make -j
|
- make -j
|
||||||
- clang-format-3.5 -i *.[ch] && git diff --exit-code || (echo 'Code was not formatted using clang-format!'; false)
|
- clang-format-3.5 -i *.[ch] && git diff --exit-code || (echo 'Code was not formatted using clang-format!'; false)
|
||||||
|
|
51
i3lock.c
51
i3lock.c
|
@ -38,6 +38,7 @@
|
||||||
#ifdef __OpenBSD__
|
#ifdef __OpenBSD__
|
||||||
#include <strings.h> /* explicit_bzero(3) */
|
#include <strings.h> /* explicit_bzero(3) */
|
||||||
#endif
|
#endif
|
||||||
|
#include <xcb/xcb_aux.h>
|
||||||
|
|
||||||
#include "i3lock.h"
|
#include "i3lock.h"
|
||||||
#include "xcb.h"
|
#include "xcb.h"
|
||||||
|
@ -344,7 +345,8 @@ static void input_done(void) {
|
||||||
DEBUG("successfully authenticated\n");
|
DEBUG("successfully authenticated\n");
|
||||||
clear_password_memory();
|
clear_password_memory();
|
||||||
|
|
||||||
exit(0);
|
ev_break(EV_DEFAULT, EVBREAK_ALL);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (pam_authenticate(pam_handle, 0) == PAM_SUCCESS) {
|
if (pam_authenticate(pam_handle, 0) == PAM_SUCCESS) {
|
||||||
|
@ -358,7 +360,8 @@ static void input_done(void) {
|
||||||
pam_setcred(pam_handle, PAM_REFRESH_CRED);
|
pam_setcred(pam_handle, PAM_REFRESH_CRED);
|
||||||
pam_end(pam_handle, PAM_SUCCESS);
|
pam_end(pam_handle, PAM_SUCCESS);
|
||||||
|
|
||||||
exit(0);
|
ev_break(EV_DEFAULT, EVBREAK_ALL);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -517,14 +520,9 @@ static void handle_key_press(xcb_key_press_event_t *event) {
|
||||||
ksym == XKB_KEY_Escape) {
|
ksym == XKB_KEY_Escape) {
|
||||||
DEBUG("C-u pressed\n");
|
DEBUG("C-u pressed\n");
|
||||||
clear_input();
|
clear_input();
|
||||||
/* Hide the unlock indicator after a bit if the password buffer is
|
/* Also hide the unlock indicator */
|
||||||
* empty. */
|
if (unlock_indicator)
|
||||||
if (unlock_indicator) {
|
clear_indicator();
|
||||||
START_TIMER(clear_indicator_timeout, 1.0, clear_indicator_cb);
|
|
||||||
unlock_state = STATE_BACKSPACE_ACTIVE;
|
|
||||||
redraw_screen();
|
|
||||||
unlock_state = STATE_KEY_PRESSED;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1445,6 +1443,8 @@ int main(int argc, char *argv[]) {
|
||||||
/* Pixmap on which the image is rendered to (if any) */
|
/* Pixmap on which the image is rendered to (if any) */
|
||||||
xcb_pixmap_t bg_pixmap = draw_image(last_resolution);
|
xcb_pixmap_t bg_pixmap = draw_image(last_resolution);
|
||||||
|
|
||||||
|
xcb_window_t stolen_focus = find_focused_window(conn, screen->root);
|
||||||
|
|
||||||
/* Open the fullscreen window, already with the correct pixmap in place */
|
/* Open the fullscreen window, already with the correct pixmap in place */
|
||||||
win = open_fullscreen_window(conn, screen, color, bg_pixmap);
|
win = open_fullscreen_window(conn, screen, color, bg_pixmap);
|
||||||
xcb_free_pixmap(conn, bg_pixmap);
|
xcb_free_pixmap(conn, bg_pixmap);
|
||||||
|
@ -1459,7 +1459,23 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
/* Display the "locking…" message while trying to grab the pointer/keyboard. */
|
/* Display the "locking…" message while trying to grab the pointer/keyboard. */
|
||||||
auth_state = STATE_AUTH_LOCK;
|
auth_state = STATE_AUTH_LOCK;
|
||||||
grab_pointer_and_keyboard(conn, screen, cursor);
|
if (!grab_pointer_and_keyboard(conn, screen, cursor, 1000)) {
|
||||||
|
DEBUG("stole focus from X11 window 0x%08x\n", stolen_focus);
|
||||||
|
|
||||||
|
/* Set the focus to i3lock, possibly closing context menus which would
|
||||||
|
* otherwise prevent us from grabbing keyboard/pointer.
|
||||||
|
*
|
||||||
|
* We cannot use set_focused_window because _NET_ACTIVE_WINDOW only
|
||||||
|
* works for managed windows, but i3lock uses an unmanaged window
|
||||||
|
* (override_redirect=1). */
|
||||||
|
xcb_set_input_focus(conn, XCB_INPUT_FOCUS_PARENT /* revert_to */, win, XCB_CURRENT_TIME);
|
||||||
|
if (!grab_pointer_and_keyboard(conn, screen, cursor, 9000)) {
|
||||||
|
auth_state = STATE_I3LOCK_LOCK_FAILED;
|
||||||
|
redraw_screen();
|
||||||
|
sleep(1);
|
||||||
|
errx(EXIT_FAILURE, "Cannot grab pointer/keyboard");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pid_t pid = fork();
|
pid_t pid = fork();
|
||||||
/* The pid == -1 case is intentionally ignored here:
|
/* The pid == -1 case is intentionally ignored here:
|
||||||
|
@ -1509,4 +1525,17 @@ int main(int argc, char *argv[]) {
|
||||||
start_time_redraw_tick(main_loop);
|
start_time_redraw_tick(main_loop);
|
||||||
}
|
}
|
||||||
ev_loop(main_loop, 0);
|
ev_loop(main_loop, 0);
|
||||||
|
|
||||||
|
if (stolen_focus == XCB_NONE) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG("restoring focus to X11 window 0x%08x\n", stolen_focus);
|
||||||
|
xcb_ungrab_pointer(conn, XCB_CURRENT_TIME);
|
||||||
|
xcb_ungrab_keyboard(conn, XCB_CURRENT_TIME);
|
||||||
|
xcb_destroy_window(conn, win);
|
||||||
|
set_focused_window(conn, screen->root, stolen_focus);
|
||||||
|
xcb_aux_sync(conn);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
111
xcb.c
111
xcb.c
|
@ -20,6 +20,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include "cursors.h"
|
#include "cursors.h"
|
||||||
#include "unlock_indicator.h"
|
#include "unlock_indicator.h"
|
||||||
|
@ -189,21 +190,27 @@ xcb_window_t open_fullscreen_window(xcb_connection_t *conn, xcb_screen_t *scr, c
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Repeatedly tries to grab pointer and keyboard (up to 10000 times).
|
* Repeatedly tries to grab pointer and keyboard (up to the specified number of
|
||||||
|
* tries).
|
||||||
|
*
|
||||||
|
* Returns true if the grab succeeded, false if not.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, xcb_cursor_t cursor) {
|
bool grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, xcb_cursor_t cursor, int tries) {
|
||||||
xcb_grab_pointer_cookie_t pcookie;
|
xcb_grab_pointer_cookie_t pcookie;
|
||||||
xcb_grab_pointer_reply_t *preply;
|
xcb_grab_pointer_reply_t *preply;
|
||||||
|
|
||||||
xcb_grab_keyboard_cookie_t kcookie;
|
xcb_grab_keyboard_cookie_t kcookie;
|
||||||
xcb_grab_keyboard_reply_t *kreply;
|
xcb_grab_keyboard_reply_t *kreply;
|
||||||
|
|
||||||
int tries = 10000;
|
const suseconds_t screen_redraw_timeout = 100000; /* 100ms */
|
||||||
|
|
||||||
/* Using few variables to trigger a redraw_screen() if too many tries */
|
/* Using few variables to trigger a redraw_screen() if too many tries */
|
||||||
bool redrawn = false;
|
bool redrawn = false;
|
||||||
time_t start = clock();
|
struct timeval start;
|
||||||
|
if (gettimeofday(&start, NULL) == -1) {
|
||||||
|
err(EXIT_FAILURE, "gettimeofday");
|
||||||
|
}
|
||||||
|
|
||||||
while (tries-- > 0) {
|
while (tries-- > 0) {
|
||||||
pcookie = xcb_grab_pointer(
|
pcookie = xcb_grab_pointer(
|
||||||
|
@ -226,10 +233,17 @@ void grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, xcb
|
||||||
/* Make this quite a bit slower */
|
/* Make this quite a bit slower */
|
||||||
usleep(50);
|
usleep(50);
|
||||||
|
|
||||||
/* Measure elapsed time and trigger a screen redraw if elapsed > 250000 */
|
struct timeval now;
|
||||||
|
if (gettimeofday(&now, NULL) == -1) {
|
||||||
|
err(EXIT_FAILURE, "gettimeofday");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timeval elapsed;
|
||||||
|
timersub(&now, &start, &elapsed);
|
||||||
|
|
||||||
if (!redrawn &&
|
if (!redrawn &&
|
||||||
(tries % 100) == 0 &&
|
(tries % 100) == 0 &&
|
||||||
(clock() - start) > 250000) {
|
elapsed.tv_usec >= screen_redraw_timeout) {
|
||||||
redraw_screen();
|
redraw_screen();
|
||||||
redrawn = true;
|
redrawn = true;
|
||||||
}
|
}
|
||||||
|
@ -253,23 +267,24 @@ void grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, xcb
|
||||||
/* Make this quite a bit slower */
|
/* Make this quite a bit slower */
|
||||||
usleep(50);
|
usleep(50);
|
||||||
|
|
||||||
/* Measure elapsed time and trigger a screen redraw if elapsed > 250000 */
|
struct timeval now;
|
||||||
|
if (gettimeofday(&now, NULL) == -1) {
|
||||||
|
err(EXIT_FAILURE, "gettimeofday");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timeval elapsed;
|
||||||
|
timersub(&now, &start, &elapsed);
|
||||||
|
|
||||||
|
/* Trigger a screen redraw if 100ms elapsed */
|
||||||
if (!redrawn &&
|
if (!redrawn &&
|
||||||
(tries % 100) == 0 &&
|
(tries % 100) == 0 &&
|
||||||
(clock() - start) > 250000) {
|
elapsed.tv_usec >= screen_redraw_timeout) {
|
||||||
redraw_screen();
|
redraw_screen();
|
||||||
redrawn = true;
|
redrawn = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* After trying for 10000 times, i3lock will display an error message
|
return (tries > 0);
|
||||||
* for 2 sec prior to terminate. */
|
|
||||||
if (tries <= 0) {
|
|
||||||
auth_state = STATE_I3LOCK_LOCK_FAILED;
|
|
||||||
redraw_screen();
|
|
||||||
sleep(1);
|
|
||||||
errx(EXIT_FAILURE, "Cannot grab pointer/keyboard");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_cursor_t create_cursor(xcb_connection_t *conn, xcb_screen_t *screen, xcb_window_t win, int choice) {
|
xcb_cursor_t create_cursor(xcb_connection_t *conn, xcb_screen_t *screen, xcb_window_t win, int choice) {
|
||||||
|
@ -335,6 +350,70 @@ xcb_cursor_t create_cursor(xcb_connection_t *conn, xcb_screen_t *screen, xcb_win
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static xcb_atom_t _NET_ACTIVE_WINDOW = XCB_NONE;
|
||||||
|
void _init_net_active_window(xcb_connection_t *conn) {
|
||||||
|
if (_NET_ACTIVE_WINDOW != XCB_NONE) {
|
||||||
|
/* already initialized */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
xcb_generic_error_t *err;
|
||||||
|
xcb_intern_atom_reply_t *atom_reply = xcb_intern_atom_reply(
|
||||||
|
conn,
|
||||||
|
xcb_intern_atom(conn, 0, strlen("_NET_ACTIVE_WINDOW"), "_NET_ACTIVE_WINDOW"),
|
||||||
|
&err);
|
||||||
|
if (atom_reply == NULL) {
|
||||||
|
fprintf(stderr, "X11 Error %d\n", err->error_code);
|
||||||
|
free(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_NET_ACTIVE_WINDOW = atom_reply->atom;
|
||||||
|
free(atom_reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_window_t find_focused_window(xcb_connection_t *conn, const xcb_window_t root) {
|
||||||
|
xcb_window_t result = XCB_NONE;
|
||||||
|
|
||||||
|
_init_net_active_window(conn);
|
||||||
|
|
||||||
|
xcb_get_property_reply_t *prop_reply = xcb_get_property_reply(
|
||||||
|
conn,
|
||||||
|
xcb_get_property_unchecked(
|
||||||
|
conn, false, root, _NET_ACTIVE_WINDOW, XCB_GET_PROPERTY_TYPE_ANY, 0, 1 /* word */),
|
||||||
|
NULL);
|
||||||
|
if (prop_reply == NULL) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (xcb_get_property_value_length(prop_reply) == 0) {
|
||||||
|
goto out_prop;
|
||||||
|
}
|
||||||
|
if (prop_reply->type != XCB_ATOM_WINDOW) {
|
||||||
|
goto out_prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = *((xcb_window_t *)xcb_get_property_value(prop_reply));
|
||||||
|
|
||||||
|
out_prop:
|
||||||
|
free(prop_reply);
|
||||||
|
out:
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_focused_window(xcb_connection_t *conn, const xcb_window_t root, const xcb_window_t window) {
|
||||||
|
xcb_client_message_event_t ev;
|
||||||
|
memset(&ev, '\0', sizeof(xcb_client_message_event_t));
|
||||||
|
|
||||||
|
_init_net_active_window(conn);
|
||||||
|
|
||||||
|
ev.response_type = XCB_CLIENT_MESSAGE;
|
||||||
|
ev.window = window;
|
||||||
|
ev.type = _NET_ACTIVE_WINDOW;
|
||||||
|
ev.format = 32;
|
||||||
|
ev.data.data32[0] = 2; /* 2 = pager */
|
||||||
|
|
||||||
|
xcb_send_event(conn, false, root, XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (char *)&ev);
|
||||||
|
xcb_flush(conn);
|
||||||
|
}
|
||||||
|
|
||||||
xcb_pixmap_t capture_bg_pixmap(xcb_connection_t *conn, xcb_screen_t *scr, u_int32_t * resolution) {
|
xcb_pixmap_t capture_bg_pixmap(xcb_connection_t *conn, xcb_screen_t *scr, u_int32_t * resolution) {
|
||||||
xcb_pixmap_t bg_pixmap = xcb_generate_id(conn);
|
xcb_pixmap_t bg_pixmap = xcb_generate_id(conn);
|
||||||
xcb_create_pixmap(conn, scr->root_depth, bg_pixmap, scr->root, resolution[0], resolution[1]);
|
xcb_create_pixmap(conn, scr->root_depth, bg_pixmap, scr->root, resolution[0], resolution[1]);
|
||||||
|
|
4
xcb.h
4
xcb.h
|
@ -9,8 +9,10 @@ extern xcb_screen_t *screen;
|
||||||
xcb_visualtype_t *get_root_visual_type(xcb_screen_t *s);
|
xcb_visualtype_t *get_root_visual_type(xcb_screen_t *s);
|
||||||
xcb_pixmap_t create_bg_pixmap(xcb_connection_t *conn, xcb_screen_t *scr, u_int32_t *resolution, char *color);
|
xcb_pixmap_t create_bg_pixmap(xcb_connection_t *conn, xcb_screen_t *scr, u_int32_t *resolution, char *color);
|
||||||
xcb_window_t open_fullscreen_window(xcb_connection_t *conn, xcb_screen_t *scr, char *color, xcb_pixmap_t pixmap);
|
xcb_window_t open_fullscreen_window(xcb_connection_t *conn, xcb_screen_t *scr, char *color, xcb_pixmap_t pixmap);
|
||||||
void grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, xcb_cursor_t cursor);
|
bool grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, xcb_cursor_t cursor, int tries);
|
||||||
xcb_cursor_t create_cursor(xcb_connection_t *conn, xcb_screen_t *screen, xcb_window_t win, int choice);
|
xcb_cursor_t create_cursor(xcb_connection_t *conn, xcb_screen_t *screen, xcb_window_t win, int choice);
|
||||||
|
xcb_window_t find_focused_window(xcb_connection_t *conn, const xcb_window_t root);
|
||||||
|
void set_focused_window(xcb_connection_t *conn, const xcb_window_t root, const xcb_window_t window);
|
||||||
xcb_pixmap_t capture_bg_pixmap(xcb_connection_t *conn, xcb_screen_t *scr, u_int32_t* resolution);
|
xcb_pixmap_t capture_bg_pixmap(xcb_connection_t *conn, xcb_screen_t *scr, u_int32_t* resolution);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue