From 6bc49c4fd8dd1a0ff35e30eba71c8b081b05c3f2 Mon Sep 17 00:00:00 2001 From: Jesse Portnoy Date: Sat, 8 Feb 2025 16:48:53 +0000 Subject: [PATCH 1/5] Implement `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()`. --- README.md | 7 +++++++ src/script.c | 2 ++ src/script_functions.c | 45 ++++++++++++++++++++++++++++++++++++++++++ src/script_functions.h | 2 ++ 4 files changed, 56 insertions(+) diff --git a/README.md b/README.md index 8523cbf..8a68281 100644 --- a/README.md +++ b/README.md @@ -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()` diff --git a/src/script.c b/src/script.c index 399680b..bb08e6a 100644 --- a/src/script.c +++ b/src/script.c @@ -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..3aac141 100644 --- a/src/script_functions.c +++ b/src/script_functions.c @@ -22,6 +22,9 @@ #include #include #include +#include +#include +#include #define WNCK_I_KNOW_THIS_IS_UNSTABLE #include @@ -2523,6 +2526,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 +2612,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_*/ From 9819fa179e7da99e805da8aa7713890abba939e6 Mon Sep 17 00:00:00 2001 From: Jesse Portnoy Date: Sat, 8 Feb 2025 21:14:39 +0000 Subject: [PATCH 2/5] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8a68281..fe7ce5c 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)). From ac5d7286d16e64ca145393c1f88e3b9ba0854871 Mon Sep 17 00:00:00 2001 From: Jesse Portnoy Date: Sun, 9 Feb 2025 17:13:30 +0000 Subject: [PATCH 3/5] - README revisions - Copyright adjustments --- AUTHORS | 2 +- Makefile | 2 +- README.md | 21 +++++++++++---------- devilspie2.1 | 2 +- src/compat.h | 2 +- src/error_strings.c | 2 +- src/intl.h | 2 +- src/script.c | 2 +- src/script_functions.c | 2 +- src/xutils.c | 2 +- 10 files changed, 20 insertions(+), 19 deletions(-) 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..37d7c9b 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. @@ -245,7 +245,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 +271,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 +320,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 +531,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 +698,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 +832,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..a19b999 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 diff --git a/src/script_functions.c b/src/script_functions.c index 240d582..478e70f 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 diff --git a/src/xutils.c b/src/xutils.c index 19a698b..dbc668a 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 From 43fbfdc2c175ebf7fc00d91e402a7afd92912421 Mon Sep 17 00:00:00 2001 From: Jesse Portnoy Date: Sun, 9 Feb 2025 19:51:46 +0000 Subject: [PATCH 4/5] Fix build issues - In C, you can't declare variables directly under case labels - declaration needs to be inside a block. GCC forgives it but Clang 17 and above does not. I've also corrected the indentation - Need to include to use uint type --- src/script_functions.c | 110 +++++++++++++++++++++++------------------ src/xutils.c | 1 + 2 files changed, 63 insertions(+), 48 deletions(-) diff --git a/src/script_functions.c b/src/script_functions.c index 240d582..8866f75 100644 --- a/src/script_functions.c +++ b/src/script_functions.c @@ -1746,7 +1746,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 +1761,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 +1931,7 @@ int c_set_viewport(lua_State *lua) switch (top) { case 1: + { WnckScreen *screen; int x; int type = lua_type(lua, 1); @@ -1982,7 +1985,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 +2037,7 @@ int c_set_viewport(lua_State *lua) lua_pushboolean(lua, TRUE); return 1; + } } return 0; } @@ -2353,6 +2359,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 +2375,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 +2406,7 @@ int c_xy(lua_State *lua) } } break; + } } return 0; } @@ -2415,54 +2425,58 @@ int c_xywh(lua_State *lua) switch (top) { - case 0: - // Return the xywh settings of the window - - WnckWindow *window = get_current_window(); - if (window) { - - int 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); - - return 4; + case 0: + { + // Return the xywh settings of the window + + WnckWindow *window = get_current_window(); + if (window) { + + int 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); + + 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); + + 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); + + if (!devilspie2_emulate) { + WnckWindow *window = get_current_window(); + if (window) { + set_window_geometry(window, x, y, xsize, ysize, adjusting_for_decoration); + } + } + + return 0; } - 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); - - 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); - - 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; } diff --git a/src/xutils.c b/src/xutils.c index 19a698b..a29dc2c 100644 --- a/src/xutils.c +++ b/src/xutils.c @@ -24,6 +24,7 @@ #include #include #include +#include // FIXME: retrieve screen position via wnck #include From cd1db261bf8cf03c85c890726760683520c4e093 Mon Sep 17 00:00:00 2001 From: Jesse Portnoy Date: Sun, 9 Feb 2025 20:13:42 +0000 Subject: [PATCH 5/5] CI: Test with Clang as well --- .github/workflows/build.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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