Files
wmaker/WPrefs.app/HotCornerShortcuts.c
T
trurl f3961ba66f Reimplement the PropList data structure in Rust.
While this large change has some unit tests, it has not been integration tested
thoroughly. Removing the global case insensitivity flag may be an issue in
particular.

A few of PropList API functions have been modified (mostly to get rid of
varargs). The definition of one such function has been left in C for cleanup
later.
2025-10-23 14:46:56 -04:00

466 lines
14 KiB
C

/* HotCornerShortcuts.c - screen corners actions
*
* WPrefs - Window Maker Preferences Program
*
* Copyright (c) 2023 Window Maker Team
*
* 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 2 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, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "WPrefs.h"
typedef struct _Panel {
WMBox *box;
char *sectionName;
char *description;
CallbackRec callbacks;
WMWidget *parent;
WMPixmap *icon;
Pixmap quarter[4];
WMFrame *hcF;
WMButton *hcB;
WMFrame *hceF;
WMSlider *hceS;
WMLabel *hceL;
WMFrame *hcdescF;
WMLabel *hcdescL;
WMFrame *hcdelayF;
WMButton *hcdelayB[5];
WMTextField *hcdelayT;
WMLabel *hcdelayL;
WMLabel *icornerL;
WMFrame *hcactionsF;
WMTextField *hcactionsT[4];
char hotcornerDelaySelected;
} _Panel;
#define ICON_FILE "hotcorners"
#define DELAY_ICON "timer%i"
#define DELAY_ICON_S "timer%is"
static void edgeCallback(WMWidget * w, void *data)
{
_Panel *panel = (_Panel *) data;
char buffer[64];
int i;
/* Parameter not used, but tell the compiler that it is ok */
(void) w;
i = WMGetSliderValue(panel->hceS);
if (i == 0)
sprintf(buffer, _("OFF"));
else if (i == 1)
sprintf(buffer, _("1 pixel"));
else if (i <= 4)
/* 2-4 */
sprintf(buffer, _("%i pixels"), i);
else
/* >4 */
sprintf(buffer, _("%i pixels "), i); /* note space! */
WMSetLabelText(panel->hceL, buffer);
}
static void showData(_Panel * panel)
{
int i;
char buffer[32];
WMPropList *array;
if (!GetObjectForKey("HotCornerDelay"))
i = 250;
else
i = GetIntegerForKey("HotCornerDelay");
sprintf(buffer, "%i", i);
WMSetTextFieldText(panel->hcdelayT, buffer);
switch (i) {
case 0:
WMPerformButtonClick(panel->hcdelayB[0]);
break;
case 250:
WMPerformButtonClick(panel->hcdelayB[1]);
break;
case 500:
WMPerformButtonClick(panel->hcdelayB[2]);
break;
case 750:
WMPerformButtonClick(panel->hcdelayB[3]);
break;
case 1000:
WMPerformButtonClick(panel->hcdelayB[4]);
break;
}
i = GetIntegerForKey("HotCornerEdge");
i = i < 0 ? 2 : i;
i = i > 10 ? 10 : i;
WMSetSliderValue(panel->hceS, i);
edgeCallback(NULL, panel);
WMSetButtonSelected(panel->hcB, GetBoolForKey("HotCorners"));
array = GetObjectForKey("HotCornerActions");
if (array && (!WMIsPLArray(array) || WMGetPropListItemCount(array) != sizeof(panel->hcactionsT) / sizeof(WMTextField *))) {
wwarning(_("invalid data in option HotCornerActions."));
} else {
if (array) {
for (i = 0; i < sizeof(panel->hcactionsT) / sizeof(WMTextField *); i++)
if (strcasecmp(WMGetFromPLString(WMGetFromPLArray(array, i)), "None") != 0)
WMSetTextFieldText(panel->hcactionsT[i], WMGetFromPLString(WMGetFromPLArray(array, i)));
}
}
}
static void storeData(_Panel * panel)
{
WMPropList *list;
WMPropList *tmp;
char *str;
int i;
SetBoolForKey(WMGetButtonSelected(panel->hcB), "HotCorners");
str = WMGetTextFieldText(panel->hcdelayT);
if (sscanf(str, "%i", &i) != 1)
i = 0;
SetIntegerForKey(i, "HotCornerDelay");
free(str);
SetIntegerForKey(WMGetSliderValue(panel->hceS), "HotCornerEdge");
list = WMCreateEmptyPLArray();
for (i = 0; i < sizeof(panel->hcactionsT) / sizeof(WMTextField *); i++) {
str = WMGetTextFieldText(panel->hcactionsT[i]);
if (strlen(str) == 0)
str = "None";
tmp = WMCreatePLString(str);
WMAddToPLArray(list, tmp);
}
SetObjectForKey(list, "HotCornerActions");
}
static void pushDelayButton(WMWidget * w, void *data)
{
_Panel *panel = (_Panel *) data;
panel->hotcornerDelaySelected = 1;
if (w == panel->hcdelayB[0]) {
WMSetTextFieldText(panel->hcdelayT, "0");
} else if (w == panel->hcdelayB[1]) {
WMSetTextFieldText(panel->hcdelayT, "250");
} else if (w == panel->hcdelayB[2]) {
WMSetTextFieldText(panel->hcdelayT, "500");
} else if (w == panel->hcdelayB[3]) {
WMSetTextFieldText(panel->hcdelayT, "700");
} else if (w == panel->hcdelayB[4]) {
WMSetTextFieldText(panel->hcdelayT, "1000");
}
}
static void delayTextChanged(void *observerData, WMNotification * notification)
{
_Panel *panel = (_Panel *) observerData;
int i;
/* Parameter not used, but tell the compiler that it is ok */
(void) notification;
if (panel->hotcornerDelaySelected) {
for (i = 0; i < 5; i++) {
WMSetButtonSelected(panel->hcdelayB[i], False);
}
panel->hotcornerDelaySelected = 0;
}
}
static void createPanel(Panel * p)
{
_Panel *panel = (_Panel *) p;
int i;
char *buf1, *buf2;
WMColor *color;
WMFont *font;
char *path;
RImage *xis = NULL;
WMScreen *scr = WMWidgetScreen(panel->parent);
RContext *rc = WMScreenRContext(scr);
GC gc = XCreateGC(scr->display, WMWidgetXID(panel->parent), 0, NULL);
path = LocateImage(ICON_FILE);
if (path) {
xis = RLoadImage(rc, path, 0);
if (!xis) {
wwarning(_("could not load image file %s"), path);
}
wfree(path);
}
panel->box = WMCreateBox(panel->parent);
WMSetViewExpandsToParent(WMWidgetView(panel->box), 2, 2, 2, 2);
/***************** Hot Corner lelf side frames *****************/
panel->hcF = WMCreateFrame(panel->box);
WMResizeWidget(panel->hcF, 240, 53);
WMMoveWidget(panel->hcF, 15, 17);
panel->hcB = WMCreateSwitchButton(panel->hcF);
WMResizeWidget(panel->hcB, 150, 30);
WMMoveWidget(panel->hcB, 15, 12);
WMSetButtonText(panel->hcB, _("Enable Hot Corners"));
WMMapSubwidgets(panel->hcF);
panel->hceF = WMCreateFrame(panel->box);
WMSetFrameTitle(panel->hceF, _("Hot Corner Edge"));
WMResizeWidget(panel->hceF, 240, 40);
WMMoveWidget(panel->hceF, 15, 77);
panel->hceS = WMCreateSlider(panel->hceF);
WMResizeWidget(panel->hceS, 80, 15);
WMMoveWidget(panel->hceS, 15, 18);
WMSetSliderMinValue(panel->hceS, 2);
WMSetSliderMaxValue(panel->hceS, 10);
WMSetSliderAction(panel->hceS, edgeCallback, panel);
panel->hceL = WMCreateLabel(panel->hceF);
WMResizeWidget(panel->hceL, 100, 15);
WMMoveWidget(panel->hceL, 105, 18);
WMMapSubwidgets(panel->hceF);
panel->hcdescF = WMCreateFrame(panel->box);
WMResizeWidget(panel->hcdescF, 240, 95);
WMMoveWidget(panel->hcdescF, 15, 130);
panel->hcdescL = WMCreateLabel(panel->hcdescF);
WMResizeWidget(panel->hcdescL, 200, 60);
WMMoveWidget(panel->hcdescL, 15, 10);
WMSetLabelText(panel->hcdescL,
_("Instructions:\n\n"
" - assign command to corner\n"
" - or leave it empty\n"));
WMMapSubwidgets(panel->hcdescF);
/***************** Hot Corner Action Delay *****************/
panel->hcdelayF = WMCreateFrame(panel->box);
WMResizeWidget(panel->hcdelayF, 245, 60);
WMMoveWidget(panel->hcdelayF, 265, 10);
WMSetFrameTitle(panel->hcdelayF, _("Hot Corner Delay"));
buf1 = wmalloc(strlen(DELAY_ICON) + 1);
buf2 = wmalloc(strlen(DELAY_ICON_S) + 1);
for (i = 0; i < 5; i++) {
char *path;
panel->hcdelayB[i] = WMCreateCustomButton(panel->hcdelayF, WBBStateChangeMask);
WMResizeWidget(panel->hcdelayB[i], 25, 25);
WMMoveWidget(panel->hcdelayB[i], 12 + (30 * i), 25);
WMSetButtonBordered(panel->hcdelayB[i], False);
WMSetButtonImagePosition(panel->hcdelayB[i], WIPImageOnly);
WMSetButtonAction(panel->hcdelayB[i], pushDelayButton, panel);
if (i > 0)
WMGroupButtons(panel->hcdelayB[0], panel->hcdelayB[i]);
sprintf(buf1, DELAY_ICON, i);
sprintf(buf2, DELAY_ICON_S, i);
path = LocateImage(buf1);
if (path) {
panel->icon = WMCreatePixmapFromFile(scr, path);
if (panel->icon) {
WMSetButtonImage(panel->hcdelayB[i], panel->icon);
WMReleasePixmap(panel->icon);
} else {
wwarning(_("could not load icon file %s"), path);
}
wfree(path);
}
path = LocateImage(buf2);
if (path) {
panel->icon = WMCreatePixmapFromFile(scr, path);
if (panel->icon) {
WMSetButtonAltImage(panel->hcdelayB[i], panel->icon);
WMReleasePixmap(panel->icon);
} else {
wwarning(_("could not load icon file %s"), path);
}
wfree(path);
}
}
wfree(buf1);
wfree(buf2);
panel->hcdelayT = WMCreateTextField(panel->hcdelayF);
WMResizeWidget(panel->hcdelayT, 36, 20);
WMMoveWidget(panel->hcdelayT, 165, 28);
WMAddNotificationObserver(delayTextChanged, panel, WMTextDidChangeNotification, panel->hcdelayT);
panel->hcdelayL = WMCreateLabel(panel->hcdelayF);
WMResizeWidget(panel->hcdelayL, 36, 16);
WMMoveWidget(panel->hcdelayL, 205, 32);
WMSetLabelText(panel->hcdelayL, _("ms"));
color = WMDarkGrayColor(scr);
font = WMSystemFontOfSize(scr, 10);
WMSetLabelTextColor(panel->hcdelayL, color);
WMSetLabelFont(panel->hcdelayL, font);
WMReleaseColor(color);
WMReleaseFont(font);
WMMapSubwidgets(panel->hcdelayF);
/***************** Set Hot Corner Actions ****************/
panel->hcactionsF = WMCreateFrame(panel->box);
WMSetFrameTitle(panel->hcactionsF, _("Hot Corner Actions"));
WMResizeWidget(panel->hcactionsF, 245, 148);
WMMoveWidget(panel->hcactionsF, 265, 77);
panel->icornerL = WMCreateLabel(panel->hcactionsF);
WMResizeWidget(panel->icornerL, 24, 24);
WMMoveWidget(panel->icornerL, 10, 18);
WMSetLabelImagePosition(panel->icornerL, WIPImageOnly);
CreateImages(scr, rc, xis, ICON_FILE, &panel->icon, NULL);
if (panel->icon)
{
WMPixmap *nicon;
panel->quarter[0] = XCreatePixmap(scr->display, WMWidgetXID(panel->parent), panel->icon->width/2, panel->icon->height/2, WMScreenDepth(scr));
XCopyArea(scr->display, WMGetPixmapXID(panel->icon), panel->quarter[0], gc, 0, 0, panel->icon->width/2, panel->icon->height/2, 0, 0);
nicon = WMCreatePixmapFromXPixmaps(scr, panel->quarter[0], WMGetPixmapMaskXID(panel->icon),
panel->icon->width/2, panel->icon->height/2, WMScreenDepth(scr));
WMSetLabelImage(panel->icornerL, nicon);
WMReleasePixmap(nicon);
}
panel->hcactionsT[0] = WMCreateTextField(panel->hcactionsF);
WMResizeWidget(panel->hcactionsT[0], 180, 20);
WMMoveWidget(panel->hcactionsT[0], 50, 20);
panel->icornerL = WMCreateLabel(panel->hcactionsF);
WMResizeWidget(panel->icornerL, 24, 24);
WMMoveWidget(panel->icornerL, 10, 48);
WMSetLabelImagePosition(panel->icornerL, WIPImageOnly);
if (panel->icon)
{
WMPixmap *nicon;
panel->quarter[1] = XCreatePixmap(scr->display, WMWidgetXID(panel->parent), panel->icon->width/2, panel->icon->height/2, WMScreenDepth(scr));
XCopyArea(scr->display, WMGetPixmapXID(panel->icon), panel->quarter[1], gc, panel->icon->width/2, 0, panel->icon->width/2, panel->icon->height/2, 0, 0);
nicon = WMCreatePixmapFromXPixmaps(scr, panel->quarter[1], WMGetPixmapMaskXID(panel->icon),
panel->icon->width/2, panel->icon->height/2, WMScreenDepth(scr));
WMSetLabelImage(panel->icornerL, nicon);
WMReleasePixmap(nicon);
}
panel->hcactionsT[1] = WMCreateTextField(panel->hcactionsF);
WMResizeWidget(panel->hcactionsT[1], 180, 20);
WMMoveWidget(panel->hcactionsT[1], 50, 50);
panel->icornerL = WMCreateLabel(panel->hcactionsF);
WMResizeWidget(panel->icornerL, 24, 24);
WMMoveWidget(panel->icornerL, 10, 78);
WMSetLabelImagePosition(panel->icornerL, WIPImageOnly);
if (panel->icon)
{
WMPixmap *nicon;
panel->quarter[2] = XCreatePixmap(scr->display, WMWidgetXID(panel->parent), panel->icon->width/2, panel->icon->height/2, WMScreenDepth(scr));
XCopyArea(scr->display, WMGetPixmapXID(panel->icon), panel->quarter[2], gc, 0, panel->icon->height/2, panel->icon->width/2, panel->icon->height/2, 0, 0);
nicon = WMCreatePixmapFromXPixmaps(scr, panel->quarter[2], WMGetPixmapMaskXID(panel->icon),
panel->icon->width/2, panel->icon->height/2, WMScreenDepth(scr));
WMSetLabelImage(panel->icornerL, nicon);
WMReleasePixmap(nicon);
}
panel->hcactionsT[2] = WMCreateTextField(panel->hcactionsF);
WMResizeWidget(panel->hcactionsT[2], 180, 20);
WMMoveWidget(panel->hcactionsT[2], 50, 80);
panel->icornerL = WMCreateLabel(panel->hcactionsF);
WMResizeWidget(panel->icornerL, 24, 24);
WMMoveWidget(panel->icornerL, 10, 108);
WMSetLabelImagePosition(panel->icornerL, WIPImageOnly);
if (panel->icon)
{
WMPixmap *nicon;
panel->quarter[3] = XCreatePixmap(scr->display, WMWidgetXID(panel->parent), panel->icon->width/2, panel->icon->height/2, WMScreenDepth(scr));
XCopyArea(scr->display, WMGetPixmapXID(panel->icon), panel->quarter[3], gc, panel->icon->width/2, panel->icon->height/2, panel->icon->width/2, panel->icon->height/2, 0, 0);
nicon = WMCreatePixmapFromXPixmaps(scr, panel->quarter[3], WMGetPixmapMaskXID(panel->icon),
panel->icon->width/2, panel->icon->height/2, WMScreenDepth(scr));
WMSetLabelImage(panel->icornerL, nicon);
WMReleasePixmap(nicon);
}
panel->hcactionsT[3] = WMCreateTextField(panel->hcactionsF);
WMResizeWidget(panel->hcactionsT[3], 180, 20);
WMMoveWidget(panel->hcactionsT[3], 50, 107);
WMMapSubwidgets(panel->hcactionsF);
if (xis)
RReleaseImage(xis);
XFreeGC(scr->display, gc);
WMRealizeWidget(panel->box);
WMMapSubwidgets(panel->box);
showData(panel);
}
static void prepareForClose(_Panel *panel)
{
int i;
WMScreen *scr = WMWidgetScreen(panel->parent);
WMReleasePixmap(panel->icon);
for (i = 0; i < sizeof(panel->quarter) / sizeof(Pixmap); i++)
XFreePixmap(scr->display, panel->quarter[i]);
}
Panel *InitHotCornerShortcuts(WMWidget *parent)
{
_Panel *panel;
panel = wmalloc(sizeof(_Panel));
panel->sectionName = _("Hot Corner Shortcut Preferences");
panel->description = _("Choose actions to perform when you move the\n"
"mouse pointer to the screen corners.");
panel->parent = parent;
panel->callbacks.createWidgets = createPanel;
panel->callbacks.updateDomain = storeData;
panel->callbacks.prepareForClose = prepareForClose;
AddSection(panel, ICON_FILE);
return panel;
}