Added mouse events to conky (#955)
* Add mouse events. Signed-off-by: Tin Svagelj <tin.svagelj@live.com> * Rename MOUSE_EVENTS flag to BUILD_MOUSE_EVENTS. Signed-off-by: Tin Svagelj <tin.svagelj@live.com> * Update NORM_ERR func argument from std::string to char* Because func was previously char* I forgot to update NORM_ERR function argument to `func.c_str()` not that it's std::string. Previously func was pointing to std::string memory that was freed at assignment. Signed-off-by: Tin Svagelj <tin.svagelj@live.com> Signed-off-by: Tin Svagelj <tin.svagelj@live.com>
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -20,6 +20,9 @@ lua/libimlib2.c
|
|||||||
*.a
|
*.a
|
||||||
/config.h
|
/config.h
|
||||||
|
|
||||||
|
# Compiler cache
|
||||||
|
.cache
|
||||||
|
|
||||||
# Ignore vscode stuff
|
# Ignore vscode stuff
|
||||||
.vscode
|
.vscode
|
||||||
*.code-workspace
|
*.code-workspace
|
||||||
|
@@ -169,6 +169,7 @@ if(BUILD_X11)
|
|||||||
option(BUILD_XFT "Build Xft (freetype fonts) support" true)
|
option(BUILD_XFT "Build Xft (freetype fonts) support" true)
|
||||||
option(BUILD_IMLIB2 "Enable Imlib2 support" true)
|
option(BUILD_IMLIB2 "Enable Imlib2 support" true)
|
||||||
option(BUILD_XSHAPE "Enable Xshape support" true)
|
option(BUILD_XSHAPE "Enable Xshape support" true)
|
||||||
|
option(BUILD_MOUSE_EVENTS "Enable mouse event support" true)
|
||||||
else(BUILD_X11)
|
else(BUILD_X11)
|
||||||
set(OWN_WINDOW false CACHE BOOL "Enable own_window support" FORCE)
|
set(OWN_WINDOW false CACHE BOOL "Enable own_window support" FORCE)
|
||||||
set(BUILD_XDAMAGE false CACHE BOOL "Build Xdamage support" FORCE)
|
set(BUILD_XDAMAGE false CACHE BOOL "Build Xdamage support" FORCE)
|
||||||
@@ -177,6 +178,7 @@ else(BUILD_X11)
|
|||||||
set(BUILD_XFT false CACHE BOOL "Build Xft (freetype fonts) support" FORCE)
|
set(BUILD_XFT false CACHE BOOL "Build Xft (freetype fonts) support" FORCE)
|
||||||
set(BUILD_IMLIB2 false CACHE BOOL "Enable Imlib2 support" FORCE)
|
set(BUILD_IMLIB2 false CACHE BOOL "Enable Imlib2 support" FORCE)
|
||||||
set(BUILD_XSHAPE false CACHE BOOL "Enable Xshape support" FORCE)
|
set(BUILD_XSHAPE false CACHE BOOL "Enable Xshape support" FORCE)
|
||||||
|
set(BUILD_MOUSE_EVENTS false CACHE BOOL "Enable mouse event support" FORCE)
|
||||||
set(BUILD_NVIDIA false)
|
set(BUILD_NVIDIA false)
|
||||||
endif(BUILD_X11)
|
endif(BUILD_X11)
|
||||||
|
|
||||||
|
@@ -48,6 +48,8 @@
|
|||||||
|
|
||||||
#cmakedefine OWN_WINDOW 1
|
#cmakedefine OWN_WINDOW 1
|
||||||
|
|
||||||
|
#cmakedefine MOUSE_EVENTS 1
|
||||||
|
|
||||||
#cmakedefine BUILD_XDAMAGE 1
|
#cmakedefine BUILD_XDAMAGE 1
|
||||||
|
|
||||||
#cmakedefine BUILD_XINERAMA 1
|
#cmakedefine BUILD_XINERAMA 1
|
||||||
|
@@ -218,6 +218,16 @@ values:
|
|||||||
Imlib2 image cache size, in bytes. Increase this value if you use $image
|
Imlib2 image cache size, in bytes. Increase this value if you use $image
|
||||||
lots. Set to 0 to disable the image cache.
|
lots. Set to 0 to disable the image cache.
|
||||||
default: 4194304
|
default: 4194304
|
||||||
|
- name: lua_mouse_hook
|
||||||
|
desc: |-
|
||||||
|
This function, if defined, will be called by Conky upon receiving mouse
|
||||||
|
events from X. Requires X support. A table containing event information
|
||||||
|
will be passed to this function as the first argument. Use this hook for
|
||||||
|
detecting mouse input and acting on it. Conky puts 'conky_' in front of
|
||||||
|
function_name to prevent accidental calls to the wrong function unless
|
||||||
|
you place 'conky_' in front of it yourself.
|
||||||
|
args:
|
||||||
|
- function_name
|
||||||
- name: lowercase
|
- name: lowercase
|
||||||
desc: Boolean value, if true, text is rendered in lower case.
|
desc: Boolean value, if true, text is rendered in lower case.
|
||||||
- name: lua_draw_hook_post
|
- name: lua_draw_hook_post
|
||||||
|
@@ -236,6 +236,11 @@ if(BUILD_X11)
|
|||||||
find_package(Xinerama REQUIRED)
|
find_package(Xinerama REQUIRED)
|
||||||
set(conky_libs ${conky_libs} ${Xinerama_LIBRARIES})
|
set(conky_libs ${conky_libs} ${Xinerama_LIBRARIES})
|
||||||
endif(BUILD_XINERAMA)
|
endif(BUILD_XINERAMA)
|
||||||
|
|
||||||
|
if(BUILD_MOUSE_EVENTS)
|
||||||
|
set(mouse_events mouse-events.cc mouse-events.h)
|
||||||
|
set(optional_sources ${optional_sources} ${mouse_events})
|
||||||
|
endif(BUILD_MOUSE_EVENTS)
|
||||||
endif(BUILD_X11)
|
endif(BUILD_X11)
|
||||||
|
|
||||||
if(BUILD_GUI)
|
if(BUILD_GUI)
|
||||||
|
@@ -38,9 +38,13 @@
|
|||||||
#ifdef BUILD_XDAMAGE
|
#ifdef BUILD_XDAMAGE
|
||||||
#include <X11/extensions/Xdamage.h>
|
#include <X11/extensions/Xdamage.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include "fonts.h"
|
||||||
#ifdef BUILD_IMLIB2
|
#ifdef BUILD_IMLIB2
|
||||||
#include "imlib2.h"
|
#include "imlib2.h"
|
||||||
#endif /* BUILD_IMLIB2 */
|
#endif /* BUILD_IMLIB2 */
|
||||||
|
#ifdef BUILD_MOUSE_EVENTS
|
||||||
|
#include "mouse-events.h"
|
||||||
|
#endif
|
||||||
#endif /* BUILD_X11 */
|
#endif /* BUILD_X11 */
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -52,9 +56,6 @@
|
|||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
#include "llua.h"
|
#include "llua.h"
|
||||||
#include "x11.h"
|
#include "x11.h"
|
||||||
#ifdef BUILD_X11
|
|
||||||
#include "fonts.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* TODO: cleanup global namespace */
|
/* TODO: cleanup global namespace */
|
||||||
#ifdef BUILD_X11
|
#ifdef BUILD_X11
|
||||||
@@ -62,7 +63,7 @@
|
|||||||
// TODO: cleanup externs (move to conky.h ?)
|
// TODO: cleanup externs (move to conky.h ?)
|
||||||
#ifdef OWN_WINDOW
|
#ifdef OWN_WINDOW
|
||||||
extern int fixed_size, fixed_pos;
|
extern int fixed_size, fixed_pos;
|
||||||
#endif
|
#endif /* OWN_WINDOW */
|
||||||
extern int text_start_x, text_start_y; /* text start position in window */
|
extern int text_start_x, text_start_y; /* text start position in window */
|
||||||
extern int text_offset_x, text_offset_y; /* offset for start position */
|
extern int text_offset_x, text_offset_y; /* offset for start position */
|
||||||
extern int text_width,
|
extern int text_width,
|
||||||
@@ -364,6 +365,8 @@ bool display_output_x11::main_loop_wait(double t) {
|
|||||||
/* handle X events */
|
/* handle X events */
|
||||||
while (XPending(display) != 0) {
|
while (XPending(display) != 0) {
|
||||||
XEvent ev;
|
XEvent ev;
|
||||||
|
/* indicates whether processed event was consumed */
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
XNextEvent(display, &ev);
|
XNextEvent(display, &ev);
|
||||||
switch (ev.type) {
|
switch (ev.type) {
|
||||||
@@ -449,6 +452,13 @@ bool display_output_x11::main_loop_wait(double t) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ButtonPress:
|
case ButtonPress:
|
||||||
|
#ifdef BUILD_MOUSE_EVENTS
|
||||||
|
if (ev.xbutton.button == 4 || ev.xbutton.button == 5) {
|
||||||
|
consumed = llua_mouse_hook(mouse_scroll_event(&ev.xbutton));
|
||||||
|
} else {
|
||||||
|
consumed = llua_mouse_hook(mouse_press_event(&ev.xbutton));
|
||||||
|
}
|
||||||
|
#endif /* BUILD_MOUSE_EVENTS */
|
||||||
if (own_window.get(*state)) {
|
if (own_window.get(*state)) {
|
||||||
/* if an ordinary window with decorations */
|
/* if an ordinary window with decorations */
|
||||||
if ((own_window_type.get(*state) == TYPE_NORMAL &&
|
if ((own_window_type.get(*state) == TYPE_NORMAL &&
|
||||||
@@ -457,18 +467,26 @@ bool display_output_x11::main_loop_wait(double t) {
|
|||||||
/* allow conky to hold input focus. */
|
/* allow conky to hold input focus. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* forward the click to the desktop window */
|
|
||||||
XUngrabPointer(display, ev.xbutton.time);
|
XUngrabPointer(display, ev.xbutton.time);
|
||||||
ev.xbutton.window = window.desktop;
|
if (!consumed) {
|
||||||
ev.xbutton.x = ev.xbutton.x_root;
|
/* forward the click to the desktop window */
|
||||||
ev.xbutton.y = ev.xbutton.y_root;
|
ev.xbutton.window = window.desktop;
|
||||||
XSendEvent(display, ev.xbutton.window, False, ButtonPressMask, &ev);
|
ev.xbutton.x = ev.xbutton.x_root;
|
||||||
XSetInputFocus(display, ev.xbutton.window, RevertToParent,
|
ev.xbutton.y = ev.xbutton.y_root;
|
||||||
ev.xbutton.time);
|
XSendEvent(display, ev.xbutton.window, False, ButtonPressMask, &ev);
|
||||||
|
XSetInputFocus(display, ev.xbutton.window, RevertToParent,
|
||||||
|
ev.xbutton.time);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ButtonRelease:
|
case ButtonRelease:
|
||||||
|
#ifdef BUILD_MOUSE_EVENTS
|
||||||
|
/* don't report scrollwheel release events */
|
||||||
|
if (ev.xbutton.button != Button4 && ev.xbutton.button != Button5) {
|
||||||
|
llua_mouse_hook(mouse_release_event(&ev.xbutton));
|
||||||
|
}
|
||||||
|
#endif /* BUILD_MOUSE_EVENTS */
|
||||||
if (own_window.get(*state)) {
|
if (own_window.get(*state)) {
|
||||||
/* if an ordinary window with decorations */
|
/* if an ordinary window with decorations */
|
||||||
if ((own_window_type.get(*state) == TYPE_NORMAL) &&
|
if ((own_window_type.get(*state) == TYPE_NORMAL) &&
|
||||||
@@ -483,7 +501,21 @@ bool display_output_x11::main_loop_wait(double t) {
|
|||||||
XSendEvent(display, ev.xbutton.window, False, ButtonReleaseMask, &ev);
|
XSendEvent(display, ev.xbutton.window, False, ButtonReleaseMask, &ev);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#ifdef BUILD_MOUSE_EVENTS
|
||||||
|
/*
|
||||||
|
windows below are notified for the following events as well;
|
||||||
|
can't forward the event without filtering XQueryTree output.
|
||||||
|
*/
|
||||||
|
case MotionNotify:
|
||||||
|
llua_mouse_hook(mouse_move_event(&ev.xmotion));
|
||||||
|
break;
|
||||||
|
case EnterNotify:
|
||||||
|
llua_mouse_hook(mouse_enter_event(&ev.xcrossing));
|
||||||
|
break;
|
||||||
|
case LeaveNotify:
|
||||||
|
llua_mouse_hook(mouse_leave_event(&ev.xcrossing));
|
||||||
|
break;
|
||||||
|
#endif /* BUILD_MOUSE_EVENTS */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
38
src/llua.cc
38
src/llua.cc
@@ -95,6 +95,7 @@ class lua_load_setting : public conky::simple_config_setting<std::string> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
lua_load_setting lua_load;
|
lua_load_setting lua_load;
|
||||||
|
|
||||||
conky::simple_config_setting<std::string> lua_startup_hook("lua_startup_hook",
|
conky::simple_config_setting<std::string> lua_startup_hook("lua_startup_hook",
|
||||||
std::string(), true);
|
std::string(), true);
|
||||||
conky::simple_config_setting<std::string> lua_shutdown_hook("lua_shutdown_hook",
|
conky::simple_config_setting<std::string> lua_shutdown_hook("lua_shutdown_hook",
|
||||||
@@ -106,6 +107,12 @@ conky::simple_config_setting<std::string> lua_draw_hook_pre("lua_draw_hook_pre",
|
|||||||
true);
|
true);
|
||||||
conky::simple_config_setting<std::string> lua_draw_hook_post(
|
conky::simple_config_setting<std::string> lua_draw_hook_post(
|
||||||
"lua_draw_hook_post", std::string(), true);
|
"lua_draw_hook_post", std::string(), true);
|
||||||
|
|
||||||
|
#ifdef BUILD_MOUSE_EVENTS
|
||||||
|
conky::simple_config_setting<std::string> lua_mouse_hook("lua_mouse_hook",
|
||||||
|
std::string(), true);
|
||||||
|
#endif /* BUILD_MOUSE_EVENTS */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
@@ -483,6 +490,37 @@ void llua_draw_post_hook() {
|
|||||||
llua_do_call(lua_draw_hook_post.get(*state).c_str(), 0);
|
llua_do_call(lua_draw_hook_post.get(*state).c_str(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef BUILD_MOUSE_EVENTS
|
||||||
|
template <typename EventT>
|
||||||
|
bool llua_mouse_hook(const EventT &ev) {
|
||||||
|
if ((lua_L == nullptr) || lua_mouse_hook.get(*state).empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const std::string func = "conky_" + lua_mouse_hook.get(*state);
|
||||||
|
lua_getglobal(lua_L, func.c_str());
|
||||||
|
|
||||||
|
ev.push_lua_table(lua_L);
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
|
if (lua_pcall(lua_L, 1, 1, 0) != 0) {
|
||||||
|
NORM_ERR("llua_mouse_hook: function %s execution failed: %s", func.c_str(),
|
||||||
|
lua_tostring(lua_L, -1));
|
||||||
|
lua_pop(lua_L, 1);
|
||||||
|
} else {
|
||||||
|
result = lua_toboolean(lua_L, -1);
|
||||||
|
lua_pop(lua_L, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template bool llua_mouse_hook<mouse_scroll_event>(const mouse_scroll_event &ev);
|
||||||
|
template bool llua_mouse_hook<mouse_button_event>(const mouse_button_event &ev);
|
||||||
|
template bool llua_mouse_hook<mouse_move_event>(const mouse_move_event &ev);
|
||||||
|
template bool llua_mouse_hook<mouse_crossing_event>(
|
||||||
|
const mouse_crossing_event &ev);
|
||||||
|
#endif /* BUILD_MOUSE_EVENTS */
|
||||||
|
|
||||||
void llua_set_userdata(const char *key, const char *type, void *value) {
|
void llua_set_userdata(const char *key, const char *type, void *value) {
|
||||||
tolua_pushusertype(lua_L, value, type);
|
tolua_pushusertype(lua_L, value, type);
|
||||||
lua_setfield(lua_L, -2, key);
|
lua_setfield(lua_L, -2, key);
|
||||||
|
16
src/llua.h
16
src/llua.h
@@ -32,6 +32,13 @@ extern "C" {
|
|||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
|
#ifdef BUILD_X11
|
||||||
|
#include "x11.h"
|
||||||
|
#ifdef BUILD_MOUSE_EVENTS
|
||||||
|
#include "mouse-events.h"
|
||||||
|
#endif /* BUILD_MOUSE_EVENTS */
|
||||||
|
#endif /* BUILD_X11 */
|
||||||
|
|
||||||
#define LUAPREFIX "conky_"
|
#define LUAPREFIX "conky_"
|
||||||
|
|
||||||
#ifdef HAVE_SYS_INOTIFY_H
|
#ifdef HAVE_SYS_INOTIFY_H
|
||||||
@@ -46,6 +53,15 @@ void llua_shutdown_hook(void);
|
|||||||
void llua_draw_pre_hook(void);
|
void llua_draw_pre_hook(void);
|
||||||
void llua_draw_post_hook(void);
|
void llua_draw_post_hook(void);
|
||||||
|
|
||||||
|
#ifdef BUILD_MOUSE_EVENTS
|
||||||
|
/**
|
||||||
|
Takes a mouse_event as argument.
|
||||||
|
Returns true if event was properly consumed, false otherwise.
|
||||||
|
*/
|
||||||
|
template <typename EventT>
|
||||||
|
bool llua_mouse_hook(const EventT &ev);
|
||||||
|
#endif /* BUILD_MOUSE_EVENTS */
|
||||||
|
|
||||||
void llua_setup_window_table(int text_start_x, int text_start_y, int text_width,
|
void llua_setup_window_table(int text_start_x, int text_start_y, int text_width,
|
||||||
int text_height);
|
int text_height);
|
||||||
void llua_update_window_table(int text_start_x, int text_start_y,
|
void llua_update_window_table(int text_start_x, int text_start_y,
|
||||||
|
@@ -178,6 +178,9 @@ static void print_version() {
|
|||||||
#ifdef OWN_WINDOW
|
#ifdef OWN_WINDOW
|
||||||
<< _(" * Own window\n")
|
<< _(" * Own window\n")
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef BUILD_MOUSE_EVENTS
|
||||||
|
<< _(" * Mouse evenets\n")
|
||||||
|
#endif
|
||||||
#endif /* BUILD_X11 */
|
#endif /* BUILD_X11 */
|
||||||
#if defined BUILD_AUDACIOUS || defined BUILD_CMUS || defined BUILD_MPD || \
|
#if defined BUILD_AUDACIOUS || defined BUILD_CMUS || defined BUILD_MPD || \
|
||||||
defined BUILD_MOC || defined BUILD_XMMS2
|
defined BUILD_MOC || defined BUILD_XMMS2
|
||||||
|
180
src/mouse-events.cc
Normal file
180
src/mouse-events.cc
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
/*
|
||||||
|
* mouse_events.cc: conky support for mouse events
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 Tin Svagelj tin.svagelj@live.com
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mouse-events.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <string>
|
||||||
|
#include "X11/Xlib.h"
|
||||||
|
|
||||||
|
std::string event_type_to_str(int type) {
|
||||||
|
switch (type) {
|
||||||
|
case MOUSE_DOWN:
|
||||||
|
return "button_down";
|
||||||
|
case MOUSE_UP:
|
||||||
|
return "button_up";
|
||||||
|
case MOUSE_SCROLL:
|
||||||
|
return "mouse_scroll";
|
||||||
|
case MOUSE_MOVE:
|
||||||
|
return "mouse_move";
|
||||||
|
case AREA_ENTER:
|
||||||
|
return "mouse_enter";
|
||||||
|
case AREA_LEAVE:
|
||||||
|
return "mouse_leave";
|
||||||
|
default:
|
||||||
|
return "err";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lua helper functions */
|
||||||
|
template <typename T>
|
||||||
|
void push_table_value(lua_State *L, std::string key, T value);
|
||||||
|
|
||||||
|
void push_table_value(lua_State *L, std::string key, std::string value) {
|
||||||
|
lua_pushstring(L, key.c_str());
|
||||||
|
lua_pushstring(L, value.c_str());
|
||||||
|
lua_settable(L, -3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_table_value(lua_State *L, std::string key, int value) {
|
||||||
|
lua_pushstring(L, key.c_str());
|
||||||
|
lua_pushinteger(L, value);
|
||||||
|
lua_settable(L, -3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_table_value(lua_State *L, std::string key, uint value) {
|
||||||
|
lua_pushstring(L, key.c_str());
|
||||||
|
lua_pushinteger(L, value);
|
||||||
|
lua_settable(L, -3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_table_value(lua_State *L, std::string key, uint64_t value) {
|
||||||
|
lua_pushstring(L, key.c_str());
|
||||||
|
lua_pushinteger(L, value);
|
||||||
|
lua_settable(L, -3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_table_value(lua_State *L, std::string key, bool value) {
|
||||||
|
lua_pushstring(L, key.c_str());
|
||||||
|
lua_pushboolean(L, value);
|
||||||
|
lua_settable(L, -3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_table_value(lua_State *L, std::string key, float value) {
|
||||||
|
lua_pushstring(L, key.c_str());
|
||||||
|
lua_pushnumber(L, value);
|
||||||
|
lua_settable(L, -3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_table_value(lua_State *L, std::string key, double value) {
|
||||||
|
lua_pushstring(L, key.c_str());
|
||||||
|
lua_pushnumber(L, value);
|
||||||
|
lua_settable(L, -3);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t N>
|
||||||
|
void push_bitset(lua_State *L, std::bitset<N> it,
|
||||||
|
std::array<std::string, N> labels) {
|
||||||
|
lua_newtable(L);
|
||||||
|
for (size_t i = 0; i < N; i++) push_table_value(L, labels[i], it.test(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::array<std::string, 13> mod_names = {
|
||||||
|
{"shift", "lock", "control", "mod1", "num_lock", "mod3", "mod4", "mod5",
|
||||||
|
"mouse_left", "mouse_right", "mouse_middle", "scroll_up", "scroll_down"}};
|
||||||
|
|
||||||
|
void push_mods(lua_State *L, std::bitset<13> mods) {
|
||||||
|
lua_pushstring(L, "mods");
|
||||||
|
push_bitset(L, mods, mod_names);
|
||||||
|
lua_settable(L, -3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Class methods */
|
||||||
|
|
||||||
|
void mouse_event::push_lua_table(lua_State *L) const {
|
||||||
|
lua_newtable(L);
|
||||||
|
push_table_value(L, "type", event_type_to_str(this->type));
|
||||||
|
push_lua_data(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouse_positioned_event::push_lua_data(lua_State *L) const {
|
||||||
|
push_table_value(L, "x", this->x);
|
||||||
|
push_table_value(L, "y", this->y);
|
||||||
|
push_table_value(L, "x_abs", this->x_abs);
|
||||||
|
push_table_value(L, "y_abs", this->y_abs);
|
||||||
|
push_table_value(L, "time", this->time);
|
||||||
|
}
|
||||||
|
|
||||||
|
mouse_move_event::mouse_move_event(XMotionEvent *ev) {
|
||||||
|
this->type = MOUSE_MOVE;
|
||||||
|
this->x = ev->x;
|
||||||
|
this->y = ev->y;
|
||||||
|
this->x_abs = ev->x_root;
|
||||||
|
this->y_abs = ev->y_root;
|
||||||
|
this->time = ev->time;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouse_move_event::push_lua_data(lua_State *L) const {
|
||||||
|
mouse_positioned_event::push_lua_data(L);
|
||||||
|
push_mods(L, this->mods);
|
||||||
|
}
|
||||||
|
|
||||||
|
mouse_scroll_event::mouse_scroll_event(XButtonEvent *ev) {
|
||||||
|
this->type = MOUSE_SCROLL;
|
||||||
|
this->x = ev->x;
|
||||||
|
this->y = ev->y;
|
||||||
|
this->x_abs = ev->x_root;
|
||||||
|
this->y_abs = ev->y_root;
|
||||||
|
this->time = ev->time;
|
||||||
|
this->mods = ev->state;
|
||||||
|
this->up = ev->button == 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouse_scroll_event::push_lua_data(lua_State *L) const {
|
||||||
|
mouse_positioned_event::push_lua_data(L);
|
||||||
|
push_table_value(L, "direction", std::string(this->up ? "up" : "down"));
|
||||||
|
push_mods(L, this->mods);
|
||||||
|
}
|
||||||
|
|
||||||
|
mouse_button_event::mouse_button_event(XButtonEvent *ev) {
|
||||||
|
this->type = ev->type == ButtonPress ? MOUSE_DOWN : MOUSE_UP;
|
||||||
|
this->x = ev->x;
|
||||||
|
this->y = ev->y;
|
||||||
|
this->x_abs = ev->x_root;
|
||||||
|
this->y_abs = ev->y_root;
|
||||||
|
this->time = ev->time;
|
||||||
|
this->mods = ev->state;
|
||||||
|
this->button = ev->button;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouse_button_event::push_lua_data(lua_State *L) const {
|
||||||
|
mouse_positioned_event::push_lua_data(L);
|
||||||
|
push_table_value(L, "button", this->button);
|
||||||
|
push_mods(L, this->mods);
|
||||||
|
}
|
||||||
|
|
||||||
|
mouse_crossing_event::mouse_crossing_event(XCrossingEvent *ev) {
|
||||||
|
this->type = ev->type == EnterNotify ? AREA_ENTER : AREA_LEAVE;
|
||||||
|
this->x = ev->x;
|
||||||
|
this->y = ev->y;
|
||||||
|
this->x_abs = ev->x_root;
|
||||||
|
this->y_abs = ev->y_root;
|
||||||
|
this->time = ev->time;
|
||||||
|
}
|
97
src/mouse-events.h
Normal file
97
src/mouse-events.h
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* mouse_events.h: conky support for mouse events
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 Tin Svagelj tin.svagelj@live.com
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MOUSE_EVENTS_H
|
||||||
|
#define MOUSE_EVENTS_H
|
||||||
|
|
||||||
|
#include <bitset>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wvariadic-macros"
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#include <lua.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
enum mouse_event_type {
|
||||||
|
MOUSE_DOWN = 0,
|
||||||
|
MOUSE_UP = 1,
|
||||||
|
MOUSE_SCROLL = 2,
|
||||||
|
MOUSE_MOVE = 3,
|
||||||
|
AREA_ENTER = 4,
|
||||||
|
AREA_LEAVE = 5,
|
||||||
|
MOUSE_EVENT_COUNT = 6,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mouse_event {
|
||||||
|
mouse_event_type type;
|
||||||
|
uint64_t time = 0L; // event time
|
||||||
|
|
||||||
|
void push_lua_table(lua_State *L) const;
|
||||||
|
|
||||||
|
virtual void push_lua_data(lua_State *L) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mouse_positioned_event : public mouse_event {
|
||||||
|
int x = 0, y = 0; // positions relative to window
|
||||||
|
int x_abs = 0, y_abs = 0; // positions relative to root
|
||||||
|
|
||||||
|
void push_lua_data(lua_State *L) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mouse_move_event : public mouse_positioned_event {
|
||||||
|
std::bitset<13> mods; // held buttons and modifiers (ctrl, shift, ...)
|
||||||
|
|
||||||
|
explicit mouse_move_event(XMotionEvent *ev);
|
||||||
|
|
||||||
|
void push_lua_data(lua_State *L) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mouse_scroll_event : public mouse_positioned_event {
|
||||||
|
std::bitset<13> mods; // held buttons and modifiers (ctrl, shift, ...)
|
||||||
|
bool up = false;
|
||||||
|
|
||||||
|
explicit mouse_scroll_event(XButtonEvent *ev);
|
||||||
|
|
||||||
|
void push_lua_data(lua_State *L) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mouse_button_event : public mouse_positioned_event {
|
||||||
|
std::bitset<13> mods; // held buttons and modifiers (ctrl, shift, ...)
|
||||||
|
uint button = 0;
|
||||||
|
|
||||||
|
explicit mouse_button_event(XButtonEvent *ev);
|
||||||
|
|
||||||
|
void push_lua_data(lua_State *L) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct mouse_button_event mouse_press_event;
|
||||||
|
typedef struct mouse_button_event mouse_release_event;
|
||||||
|
|
||||||
|
struct mouse_crossing_event : public mouse_positioned_event {
|
||||||
|
explicit mouse_crossing_event(XCrossingEvent *ev);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct mouse_crossing_event mouse_enter_event;
|
||||||
|
typedef struct mouse_crossing_event mouse_leave_event;
|
||||||
|
|
||||||
|
#endif /* MOUSE_EVENTS_H */
|
20
src/x11.cc
20
src/x11.cc
@@ -27,6 +27,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <X11/X.h>
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "conky.h"
|
#include "conky.h"
|
||||||
@@ -829,14 +830,19 @@ void x11_init_window(lua::state &l __attribute__((unused)), bool own) {
|
|||||||
|
|
||||||
XFlush(display);
|
XFlush(display);
|
||||||
|
|
||||||
XSelectInput(display, window.window,
|
long input_mask = ExposureMask | PropertyChangeMask;
|
||||||
ExposureMask | PropertyChangeMask
|
|
||||||
#ifdef OWN_WINDOW
|
#ifdef OWN_WINDOW
|
||||||
| (own_window.get(l) ? (StructureNotifyMask |
|
if (own_window.get(l)) {
|
||||||
ButtonPressMask | ButtonReleaseMask)
|
input_mask |= StructureNotifyMask | ButtonPressMask | ButtonReleaseMask;
|
||||||
: 0)
|
}
|
||||||
#endif
|
#endif /* OWN_WINDOW */
|
||||||
);
|
#ifdef BUILD_MOUSE_EVENTS
|
||||||
|
/* it's not recommended to add event masks to special windows in X; causes a crash */
|
||||||
|
if (own_window_type.get(l) != TYPE_DESKTOP) {
|
||||||
|
input_mask |= ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask;
|
||||||
|
}
|
||||||
|
#endif /* BUILD_MOUSE_EVENTS */
|
||||||
|
XSelectInput(display, window.window, input_mask);
|
||||||
|
|
||||||
window_created = 1;
|
window_created = 1;
|
||||||
DBGP("leave x11_init_window()");
|
DBGP("leave x11_init_window()");
|
||||||
|
Reference in New Issue
Block a user