1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
/*
* hh-greeter-power.c - a tiny Athena (Xaw) button bar with Shutdown and
* Reboot buttons for the xdm greeter, each guarded by a confirmation popup.
*
* xdm's classic xlogin greeter has no power buttons, and the greeter display
* runs with no window manager. This standalone client is launched by
* Xsetup_0 (as root, so `zygctl poweroff`/`reboot` have the privilege to run)
* and killed by Xstartup when a session begins, so it never leaks into the
* user's desktop. Styling comes from the HhGreeterPower* resources in
* Xresources (loaded by xrdb); placement from the -geometry Xsetup_0 passes.
*
* Build: cc hh-greeter-power.c -I$PREFIX/include -L$PREFIX/lib -R$PREFIX/lib \
* -lXaw7 -lXmu -lXt -lX11 -o hh-greeter-power
*/
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/Xaw/Box.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Dialog.h>
#include <stdlib.h>
static Widget toplevel;
static Widget confirm_popup = NULL;
static const char *pending_cmd = NULL;
static void
dismiss(void)
{
if (confirm_popup != NULL) {
XtPopdown(confirm_popup);
XtDestroyWidget(confirm_popup);
confirm_popup = NULL;
}
}
static void
do_it(Widget w, XtPointer client, XtPointer call)
{
(void) w; (void) client; (void) call;
if (pending_cmd != NULL)
(void) system(pending_cmd); /* machine goes down; no return expected */
dismiss();
}
static void
cancel(Widget w, XtPointer client, XtPointer call)
{
(void) w; (void) client; (void) call;
dismiss();
}
/* Pop a centered confirmation dialog for a power action. */
static void
confirm(const char *prompt, const char *cmd, const char *okLabel)
{
Widget dlg;
Dimension pw, ph;
Position px, py;
int sw, sh;
dismiss(); /* only one popup at a time */
pending_cmd = cmd;
confirm_popup = XtVaCreatePopupShell("confirm",
transientShellWidgetClass, toplevel, (char *)NULL);
dlg = XtVaCreateManagedWidget("dialog", dialogWidgetClass, confirm_popup,
XtNlabel, prompt, (char *)NULL);
XawDialogAddButton(dlg, okLabel, do_it, NULL);
XawDialogAddButton(dlg, "Cancel", cancel, NULL);
/* Center on screen (no window manager to place it). */
XtRealizeWidget(confirm_popup);
XtVaGetValues(confirm_popup, XtNwidth, &pw, XtNheight, &ph, (char *)NULL);
sw = WidthOfScreen(XtScreen(toplevel));
sh = HeightOfScreen(XtScreen(toplevel));
px = (Position)((sw - (int)pw) / 2);
py = (Position)((sh - (int)ph) / 2);
XtVaSetValues(confirm_popup, XtNx, px, XtNy, py, (char *)NULL);
XtPopup(confirm_popup, XtGrabExclusive);
}
static void
shutdown_cb(Widget w, XtPointer client, XtPointer call)
{
(void) w; (void) client; (void) call;
confirm("Shut down this system?", "/sbin/zygctl poweroff", "Shut down");
}
static void
reboot_cb(Widget w, XtPointer client, XtPointer call)
{
(void) w; (void) client; (void) call;
confirm("Reboot this system?", "/sbin/zygctl reboot", "Reboot");
}
int
main(int argc, char **argv)
{
XtAppContext app;
Widget box, sd, rb;
toplevel = XtOpenApplication(&app, "HhGreeterPower", NULL, 0, &argc, argv,
NULL, applicationShellWidgetClass, NULL, 0);
box = XtVaCreateManagedWidget("box", boxWidgetClass, toplevel,
XtNorientation, XtorientHorizontal, (char *)NULL);
sd = XtVaCreateManagedWidget("Shutdown", commandWidgetClass, box,
(char *)NULL);
XtAddCallback(sd, XtNcallback, shutdown_cb, NULL);
rb = XtVaCreateManagedWidget("Reboot", commandWidgetClass, box,
(char *)NULL);
XtAddCallback(rb, XtNcallback, reboot_cb, NULL);
XtRealizeWidget(toplevel);
XtAppMainLoop(app);
return 0;
}
|