diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index de35e8c..eb63206 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- compiler: [gcc-12, gcc-13]
+ compiler: [gcc-12, gcc-13, clang-17, clang-18]
env:
PREFIX: /usr/local/bin
CC: ${{ matrix.compiler }}
@@ -27,6 +27,8 @@ jobs:
libxrandr-dev \
build-essential \
gettext \
+ clang-17 \
+ clang-18 \
gcc-12 \
gcc-13
- name: CC ver
diff --git a/AUTHORS b/AUTHORS
index 6258f38..041737f 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,6 +1,6 @@
#
# Copyright © 2011-2019 Andreas Rönnquist.
-# Copyright © 2019-2021 Darren Salt.
+# Copyright © 2019-2025 Darren Salt.
# This file is distributed under the same license
# as the devilspie2 package, see COPYING file.
#
diff --git a/Makefile b/Makefile
index b47afa8..b28dd00 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
#
# This file is part of devilspie2
# Copyright (C) 2011-2016 Andreas Rönnquist
-# Copyright (C) 2019-2021 Darren Salt
+# Copyright (C) 2019-2025 Darren Salt
#
# devilspie2 is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
diff --git a/README.md b/README.md
index 8523cbf..1eb5e17 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-Copyright © 2011-2024 devilspie2 developers
+Copyright © 2011-2025 devilspie2 developers
This file is distributed under the same licence as the devilspie2 package
(see [COPYING](COPYING)).
@@ -10,7 +10,7 @@ It will read Lua scripts from a folder and run them whenever a window is
opened, and the rules in them are applied on the window. (See the
[Configuration section](#configuration) for more details.)
-Unfortunately the rules of the original Devil's Pie are not supported.
+Unfortunately, the rules of the original Devil's Pie are not supported.
`devilspie2` will load all the Lua files in this folder in alphabetical order.
@@ -73,7 +73,7 @@ scripts_window_close = {
With this, both `file1.lua` and `file2.lua` will be called whenever a window
is closed.
-As of v0.46, each script has 5 seconds to do its job ane exit or it will be
+As of v0.46, each script has 5 seconds to do its job and exit or it will be
unceremoniously interrupted.
## Scripting
@@ -86,8 +86,8 @@ The scripting language used is [Lua](https://www.lua.org/).
Tips:
* If you're going to be testing certain window properties a lot, it's best to
- assign those property values to variables then to test the variables.
-* String comparison is case sensitive. Comparing `SomeProgram` with
+ assign those property values to variables and then test against these.
+* String comparison is case-sensitive. Comparing `SomeProgram` with
`someprogram` will not report equality.
@@ -138,6 +138,13 @@ information:
*(Available from version 0.44)*
+* `get_process_owner()`
+
+
+ Returns the username who owns the process owning the current window.
+ This is done by getting the owner (UID) of `/proc//comm` with `stat()`
+ and mapping it to a username with `getpwuid()`.
+
* `get_window_geometry()`
@@ -245,7 +252,7 @@ information:
Returns whether the named window property is UTF-8.
- (Always returns `true` for properties which are converted to string.)
+ (Always returns `true` for properties which are converted to string)
Returns `nil` if the property doesn't exist.
@@ -271,7 +278,7 @@ information:
* `get_window_xid()`
- Returns the X window id of the current window.
+ Returns the X window ID of the current window.
* `get_window_class()`
@@ -320,7 +327,7 @@ information:
### Setters
-And the rest of the commands are used to modify the properties of the windows:
+The rest of the commands are used to modify the properties of the windows:
* `set_adjust_for_decoration([bool])`
@@ -531,7 +538,7 @@ And the rest of the commands are used to modify the properties of the windows:
* `unstick_window()`
- Ask the window manager not to have window's position fixed on the screen
+ Ask the window manager not to have the window's position fixed on the screen
when the workspace or viewport scrolls.
* `set_skip_tasklist(bool skip)`
@@ -698,7 +705,7 @@ And the rest of the commands are used to modify the properties of the windows:
With parameters, set the position and size of a window.
- Without, returns the position and size of a window.
+ When no parameters are passed, returns the position and size of a window.
### Utilities
@@ -832,3 +839,4 @@ See [AUTHORS](AUTHORS).
* See also: https://github.com/dsalt/devilspie
* IRC: irc://irc.libera.chat/#devilspie2
+
diff --git a/devilspie2.1 b/devilspie2.1
index c43019d..8080c69 100644
--- a/devilspie2.1
+++ b/devilspie2.1
@@ -1,6 +1,6 @@
.\"
.\" Copyright © 2011-2017 Andreas Rönnquist.
-.\" Copyright © 2021-2024 Darren Salt.
+.\" Copyright © 2021-2025 Darren Salt.
.\" This file is distributed under the same license
.\" as the devilspie2 package, see COPYING file.
.\"
diff --git a/src/compat.h b/src/compat.h
index 25ade54..0ca29fe 100644
--- a/src/compat.h
+++ b/src/compat.h
@@ -1,6 +1,6 @@
/**
* This file is part of devilspie2
- * Copyright (C) 2021 Darren Salt
+ * Copyright (C) 2025 Darren Salt
*
* devilspie2 is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
diff --git a/src/error_strings.c b/src/error_strings.c
index a04b6af..83e3afa 100644
--- a/src/error_strings.c
+++ b/src/error_strings.c
@@ -1,7 +1,7 @@
/**
* This file is part of devilspie2
* Copyright (C) 2012-2017 Andreas Rönnquist
- * Copyright (C) 2019-2021 Darren Salt
+ * Copyright (C) 2019-2025 Darren Salt
*
* devilspie2 is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
diff --git a/src/intl.h b/src/intl.h
index 2e1a809..4716eff 100644
--- a/src/intl.h
+++ b/src/intl.h
@@ -1,7 +1,7 @@
/**
* This file is part of devilspie2
* Copyright (C) 2001 Havoc Pennington, 2011-2019 Andreas Rönnquist
- * Copyright (C) 2019-2021 Darren Salt
+ * Copyright (C) 2019-2025 Darren Salt
*
* devilspie2 is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
diff --git a/src/script.c b/src/script.c
index 399680b..0e9369d 100644
--- a/src/script.c
+++ b/src/script.c
@@ -1,7 +1,7 @@
/**
* This file is part of devilspie2
* Copyright (C) 2011-2019 Andreas Rönnquist
- * Copyright (C) 2019-2021 Darren Salt
+ * Copyright (C) 2019-2025 Darren Salt
*
* devilspie2 is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@@ -202,6 +202,8 @@ register_cfunctions(lua_State *lua)
DP2_REGISTER(lua, get_process_name);
+ DP2_REGISTER(lua, get_process_owner);
+
DP2_REGISTER(lua, millisleep);
}
diff --git a/src/script_functions.c b/src/script_functions.c
index 240d582..8cc913c 100644
--- a/src/script_functions.c
+++ b/src/script_functions.c
@@ -1,7 +1,7 @@
/**
* This file is part of devilspie2
* Copyright (C) 2011-2019 Andreas Rönnquist
- * Copyright (C) 2019-2021 Darren Salt
+ * Copyright (C) 2019-2025 Darren Salt
*
* devilspie2 is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@@ -22,6 +22,9 @@
#include
#include
#include
+#include
+#include
+#include
#define WNCK_I_KNOW_THIS_IS_UNSTABLE
#include
@@ -1746,7 +1749,9 @@ int c_set_window_property(lua_State *lua)
switch (type) {
case LUA_TSTRING:
+ {
gboolean use_utf8 = default_use_utf8;
+
if (top > 2) {
type = lua_type(lua, 3);
if (type != LUA_TBOOLEAN) {
@@ -1759,7 +1764,7 @@ int c_set_window_property(lua_State *lua)
my_wnck_set_string_property(wnck_window_get_xid(window), my_wnck_atom_get(property),
lua_tostring(lua, 2), use_utf8);
break;
-
+ }
case LUA_TNUMBER:
if (!devilspie2_emulate && window)
my_wnck_set_cardinal_property(wnck_window_get_xid(window), my_wnck_atom_get(property),
@@ -1929,6 +1934,7 @@ int c_set_viewport(lua_State *lua)
switch (top)
{
case 1:
+ {
WnckScreen *screen;
int x;
int type = lua_type(lua, 1);
@@ -1982,7 +1988,9 @@ int c_set_viewport(lua_State *lua)
lua_pushboolean(lua, TRUE);
return 1;
+ }
case 2:
+ {
int type1 = lua_type(lua, 1);
int type2 = lua_type(lua, 2);
@@ -2032,6 +2040,7 @@ int c_set_viewport(lua_State *lua)
lua_pushboolean(lua, TRUE);
return 1;
+ }
}
return 0;
}
@@ -2353,6 +2362,7 @@ int c_xy(lua_State *lua)
switch (top)
{
case 0:
+ {
// return the xy coordinates of the window
WnckWindow *window = get_current_window();
@@ -2368,7 +2378,9 @@ int c_xy(lua_State *lua)
return 2;
}
break;
+ }
case 2:
+ {
// set the coordinates of the window
int type1 = lua_type(lua, 1);
@@ -2397,6 +2409,7 @@ int c_xy(lua_State *lua)
}
}
break;
+ }
}
return 0;
}
@@ -2415,54 +2428,58 @@ int c_xywh(lua_State *lua)
switch (top)
{
- case 0:
- // Return the xywh settings of the window
+ case 0:
+ {
+ // Return the xywh settings of the window
- WnckWindow *window = get_current_window();
- if (window) {
+ WnckWindow *window = get_current_window();
+ if (window) {
- int x, y, width, height;
+ int x, y, width, height;
- wnck_window_get_geometry(window, &x, &y, &width, &height);
+ wnck_window_get_geometry(window, &x, &y, &width, &height);
- lua_pushinteger(lua, x);
- lua_pushinteger(lua, y);
- lua_pushinteger(lua, width);
- lua_pushinteger(lua, height);
+ lua_pushinteger(lua, x);
+ lua_pushinteger(lua, y);
+ lua_pushinteger(lua, width);
+ lua_pushinteger(lua, height);
- return 4;
- }
- break;
- case 4:
- // Set the xywh settings in the window
+ return 4;
+ }
+ break;
+ }
+ case 4:
+ {
+ // Set the xywh settings in the window
- int type1 = lua_type(lua, 1);
- int type2 = lua_type(lua, 2);
- int type3 = lua_type(lua, 3);
- int type4 = lua_type(lua, 4);
+ int type1 = lua_type(lua, 1);
+ int type2 = lua_type(lua, 2);
+ int type3 = lua_type(lua, 3);
+ int type4 = lua_type(lua, 4);
- if ((type1 != LUA_TNUMBER) ||
- (type2 != LUA_TNUMBER) ||
- (type3 != LUA_TNUMBER) ||
- (type4 != LUA_TNUMBER)) {
- luaL_error(lua, "xywh: %s", number_expected_as_indata_error);
- return 0;
- }
+ if ((type1 != LUA_TNUMBER) ||
+ (type2 != LUA_TNUMBER) ||
+ (type3 != LUA_TNUMBER) ||
+ (type4 != LUA_TNUMBER)) {
+ luaL_error(lua, "xywh: %s", number_expected_as_indata_error);
+ return 0;
+ }
- int x = lua_tonumber(lua, 1);
- int y = lua_tonumber(lua, 2);
- int xsize = lua_tonumber(lua, 3);
- int ysize = lua_tonumber(lua, 4);
+ int x = lua_tonumber(lua, 1);
+ int y = lua_tonumber(lua, 2);
+ int xsize = lua_tonumber(lua, 3);
+ int ysize = lua_tonumber(lua, 4);
- if (!devilspie2_emulate) {
- WnckWindow *window = get_current_window();
- if (window) {
- set_window_geometry(window, x, y, xsize, ysize, adjusting_for_decoration);
- }
- }
+ if (!devilspie2_emulate) {
+ WnckWindow *window = get_current_window();
+ if (window) {
+ set_window_geometry(window, x, y, xsize, ysize, adjusting_for_decoration);
+ }
+ }
- return 0;
+ return 0;
+ }
}
return 0;
}
@@ -2523,6 +2540,7 @@ int c_on_geometry_changed(lua_State *lua)
*/
static ATTR_MALLOC gchar *c_get_process_name_INT_proc(lua_State *, pid_t);
static ATTR_MALLOC gchar *c_get_process_name_INT_ps(lua_State *, pid_t);
+static ATTR_MALLOC gchar *c_get_process_owner_INT_proc(lua_State *, pid_t);
int c_get_process_name(lua_State *lua)
{
@@ -2608,6 +2626,47 @@ static gchar *c_get_process_name_INT_ps(lua_State *lua, pid_t pid)
return g_strdup(cmdname);
}
+int c_get_process_owner(lua_State *lua)
+{
+ if (!check_param_count(lua, "get_process_owner", 0)) {
+ return 0;
+ }
+
+
+ WnckWindow *window = get_current_window();
+
+ if (window) {
+ pid_t pid = wnck_window_get_pid(window);
+
+ if (pid != 0) {
+ gchar *ownername = c_get_process_owner_INT_proc(lua, pid);
+ lua_pushstring(lua, ownername ? ownername : "");
+ g_free(ownername);
+ return 1;
+ }
+ }
+
+ lua_pushstring(lua, "");
+ return 1;
+}
+
+static gchar *c_get_process_owner_INT_proc(lua_State *lua, pid_t pid)
+{
+ char proc_comm_file[1024];
+ snprintf(proc_comm_file, sizeof(proc_comm_file), "/proc/%lu/comm", (unsigned long)pid);
+ struct stat info;
+ if (stat(proc_comm_file, &info) < 0){
+ perror("stat");
+ return NULL;
+ }
+ struct passwd *pw = getpwuid(info.st_uid);
+ if (pw != NULL){
+ return g_strdup(pw->pw_name);
+ }
+ return NULL;
+}
+
+
/**
*
diff --git a/src/script_functions.h b/src/script_functions.h
index 6a2f2d0..87bffaa 100644
--- a/src/script_functions.h
+++ b/src/script_functions.h
@@ -143,6 +143,8 @@ int c_on_geometry_changed(lua_State *lua);
int c_get_process_name(lua_State *lua);
+int c_get_process_owner(lua_State *lua);
+
int c_millisleep(lua_State *lua);
#endif /*__HEADER_SCRIPT_FUNCTIONS_*/
diff --git a/src/xutils.c b/src/xutils.c
index 19a698b..d6c501e 100644
--- a/src/xutils.c
+++ b/src/xutils.c
@@ -1,7 +1,7 @@
/**
* This file is part of devilspie2
* Copyright (C) 2001 Havoc Pennington, 2011-2019 Andreas Rönnquist
- * Copyright (C) 2019-2021 Darren Salt
+ * Copyright (C) 2019-2025 Darren Salt
*
* devilspie2 is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@@ -24,6 +24,7 @@
#include
#include
#include
+#include
// FIXME: retrieve screen position via wnck
#include