New upstream version 3.5.99.27
This commit is contained in:
22
nxdialog/Makefile.am
Normal file
22
nxdialog/Makefile.am
Normal file
@@ -0,0 +1,22 @@
|
||||
NULL =
|
||||
|
||||
SUBDIRS = bin man
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
MAINTAINERCLEANFILES = \
|
||||
$(srcdir)/autom4te.cache/* \
|
||||
$(srcdir)/build-aux/* \
|
||||
$(srcdir)/Makefile.in \
|
||||
$(srcdir)/bin/Makefile.in \
|
||||
$(srcdir)/man/Makefile.in \
|
||||
$(srcdir)/src/Makefile.in \
|
||||
$(srcdir)/aclocal.m4 \
|
||||
$(srcdir)/config.h.in \
|
||||
$(srcdir)/config.h.in~ \
|
||||
$(srcdir)/config.guess \
|
||||
$(srcdir)/config.sub \
|
||||
$(srcdir)/configure \
|
||||
$(NULL)
|
||||
|
||||
DISTCLEANFILES=$(MAINTAINERCLEANFILES)
|
||||
23
nxdialog/README.md
Normal file
23
nxdialog/README.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# NX Dialog Helper Tool
|
||||
|
||||
The ``nxdialog`` script can be executed with Python 2.6.x (or higher) and
|
||||
Python 3.4.x (or higher) alike.
|
||||
|
||||
## Runtime Dependencies
|
||||
|
||||
Required Python modules:
|
||||
|
||||
* argparse
|
||||
* gi
|
||||
|
||||
Required GIR namespaces:
|
||||
|
||||
* Gtk
|
||||
* Gdk
|
||||
* GdkX11
|
||||
|
||||
See the man page for more details.
|
||||
|
||||
## License
|
||||
|
||||
The ``nxdialog`` script and related files have been licensed under GPLv2+.
|
||||
1
nxdialog/VERSION
Symbolic link
1
nxdialog/VERSION
Symbolic link
@@ -0,0 +1 @@
|
||||
../VERSION
|
||||
3
nxdialog/bin/Makefile.am
Normal file
3
nxdialog/bin/Makefile.am
Normal file
@@ -0,0 +1,3 @@
|
||||
NULL =
|
||||
|
||||
dist_bin_SCRIPTS = nxdialog
|
||||
400
nxdialog/bin/nxdialog
Executable file
400
nxdialog/bin/nxdialog
Executable file
@@ -0,0 +1,400 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# ^^^ This is working with python2 and python3 so we choose a shebang
|
||||
# that will find either version.
|
||||
# Citing PEP394: "One exception to this is scripts that are
|
||||
# deliberately written to be source compatible with both Python
|
||||
# 2.x and 3.x. Such scripts may continue to use python on their
|
||||
# shebang line.
|
||||
|
||||
# Copyright (C) 2008 Google Inc.
|
||||
# Copyright (C) 2019-2021 Ulrich Sibiller <uli42@gmx.de>
|
||||
#
|
||||
# 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.
|
||||
|
||||
# This version is based on the nxdialog.py of the long abandoned
|
||||
# Google project "neatx" (https://code.google.com/archive/p/neatx/).
|
||||
# List of changes:
|
||||
# - pulled in the few parts of the neatx python modules that are actually
|
||||
# required to make it a standlone script
|
||||
# - added usage output
|
||||
# - dropped logging code, print errors to stderr
|
||||
# - can handle the "yesno" dialog type
|
||||
# - added missing docstrings
|
||||
# - pylint improvements
|
||||
# - removed neatx entry from the pulldown menu
|
||||
# - use PyGObject instead of PyGtk and thus Gtk3
|
||||
# - replace optparse by argparse
|
||||
# - make code compatible to python2 and python3.
|
||||
|
||||
"""nxdialog program for handling dialog display."""
|
||||
|
||||
# If an "NX_CLIENT" environment variable is not provided to nxagent
|
||||
# nxcomp library assumes this script is located in /usr/NX/bin/nxclient
|
||||
#
|
||||
# Examples:
|
||||
# nxdialog --dialog yesno --message "text" --caption "title" --parent 0
|
||||
# nxdialog --dialog pulldown --message "text" --caption "title" --window 0x123456 --parent 0
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import signal
|
||||
import sys
|
||||
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
# pylint: disable=wrong-import-position
|
||||
from gi.repository import Gtk, Gdk, GdkX11
|
||||
|
||||
PROGRAM = "nxdialog"
|
||||
|
||||
DISCONNECT = 1
|
||||
TERMINATE = 2
|
||||
|
||||
EXIT_SUCCESS = 0
|
||||
EXIT_FAILURE = 1
|
||||
|
||||
CANCEL_TEXT = "Cancel"
|
||||
DISCONNECT_TEXT = "Disconnect"
|
||||
TERMINATE_TEXT = "Terminate"
|
||||
YES_TEXT = "Yes"
|
||||
NO_TEXT = "No"
|
||||
|
||||
DLG_TYPE_ERROR = "error"
|
||||
DLG_TYPE_OK = "ok"
|
||||
DLG_TYPE_PANIC = "panic"
|
||||
DLG_TYPE_PULLDOWN = "pulldown"
|
||||
DLG_TYPE_QUIT = "quit"
|
||||
DLG_TYPE_YESNO = "yesno"
|
||||
DLG_TYPE_YESNOSUSPEND = "yesnosuspend"
|
||||
|
||||
VALID_DLG_TYPES = frozenset([
|
||||
DLG_TYPE_ERROR,
|
||||
DLG_TYPE_OK,
|
||||
DLG_TYPE_PANIC,
|
||||
DLG_TYPE_PULLDOWN,
|
||||
DLG_TYPE_QUIT,
|
||||
DLG_TYPE_YESNO,
|
||||
DLG_TYPE_YESNOSUSPEND,
|
||||
])
|
||||
|
||||
|
||||
class PullDownMenu(object):
|
||||
""" Shows a popup menu to disconnect/terminate session. """
|
||||
|
||||
def __init__(self, window_id):
|
||||
""" Initializes this class.
|
||||
|
||||
@type window_id: int
|
||||
@param window_id: X11 window id of target window
|
||||
|
||||
"""
|
||||
self.window_id = window_id
|
||||
self.result = None
|
||||
|
||||
def show(self):
|
||||
""" Shows popup and returns result. """
|
||||
|
||||
display = Gdk.Display.get_default()
|
||||
win = GdkX11.X11Window.foreign_new_for_display(display, int(self.window_id, 0))
|
||||
|
||||
menu = Gtk.Menu()
|
||||
menu.connect("deactivate", self.menu_deactivate)
|
||||
|
||||
# TODO: Show title item in bold font
|
||||
title = Gtk.MenuItem(label="Session control")
|
||||
title.set_sensitive(False)
|
||||
menu.append(title)
|
||||
|
||||
disconnect = Gtk.MenuItem(label=DISCONNECT_TEXT)
|
||||
disconnect.connect("activate", self.item_activate, DISCONNECT)
|
||||
menu.append(disconnect)
|
||||
|
||||
terminate = Gtk.MenuItem(label=TERMINATE_TEXT)
|
||||
terminate.connect("activate", self.item_activate, TERMINATE)
|
||||
menu.append(terminate)
|
||||
|
||||
menu.append(Gtk.SeparatorMenuItem())
|
||||
|
||||
cancel = Gtk.MenuItem(label=CANCEL_TEXT)
|
||||
menu.append(cancel)
|
||||
|
||||
menu.show_all()
|
||||
|
||||
menu.popup(parent_menu_shell=None, parent_menu_item=None,
|
||||
func=self.pos_menu, data=win,
|
||||
button=0, activate_time=Gtk.get_current_event_time())
|
||||
|
||||
Gtk.main()
|
||||
|
||||
return self.result
|
||||
|
||||
def item_activate(self, _, result):
|
||||
""" called when a menu item is selected """
|
||||
self.result = result
|
||||
Gtk.main_quit()
|
||||
|
||||
@staticmethod
|
||||
def menu_deactivate(_):
|
||||
""" called when menu is deactivated """
|
||||
Gtk.main_quit()
|
||||
|
||||
@staticmethod
|
||||
# pylint: disable=unused-argument
|
||||
def pos_menu(menu, _xpos, _ypos, *data):
|
||||
""" Positions menu at the top center of the parent window. """
|
||||
parent = data[0]
|
||||
|
||||
# Get parent geometry and origin
|
||||
_, _, win_width, _ = parent.get_geometry()
|
||||
_, win_x, win_y = parent.get_origin()
|
||||
|
||||
# Calculate width of menu
|
||||
#menu_width = menu.get_preferred_width().natural_width
|
||||
menu_width = menu.get_allocated_width()
|
||||
|
||||
# Calculate center
|
||||
center_x = int(win_x + ((win_width - menu_width) / 2))
|
||||
|
||||
return (center_x, win_y, True)
|
||||
|
||||
|
||||
def show_yes_no_suspend_box(title, text):
|
||||
""" Shows a message box to disconnect/terminate session.
|
||||
|
||||
@type title: str
|
||||
@param title: Message box title
|
||||
@type text: str
|
||||
@param text: Message box text
|
||||
@return: Chosen action
|
||||
|
||||
"""
|
||||
dlg = Gtk.MessageDialog(type=Gtk.MessageType.QUESTION,
|
||||
flags=Gtk.DialogFlags.MODAL)
|
||||
dlg.set_title(title)
|
||||
dlg.set_markup(text)
|
||||
dlg.add_button(DISCONNECT_TEXT, DISCONNECT)
|
||||
dlg.add_button(TERMINATE_TEXT, TERMINATE)
|
||||
dlg.add_button(CANCEL_TEXT, Gtk.ResponseType.CANCEL)
|
||||
|
||||
res = dlg.run()
|
||||
|
||||
if res in (DISCONNECT, TERMINATE):
|
||||
return res
|
||||
|
||||
# Everything else is cancel
|
||||
return None
|
||||
|
||||
|
||||
def show_yes_no_box(title, text):
|
||||
""" Shows a message box with answers yes and no.
|
||||
|
||||
@type title: str
|
||||
@param title: Message box title
|
||||
@type text: str
|
||||
@param text: Message box text
|
||||
@return: Chosen action
|
||||
|
||||
"""
|
||||
dlg = Gtk.MessageDialog(type=Gtk.MessageType.QUESTION,
|
||||
flags=Gtk.DialogFlags.MODAL)
|
||||
dlg.set_title(title)
|
||||
dlg.set_markup(text)
|
||||
dlg.add_button(YES_TEXT, TERMINATE)
|
||||
dlg.add_button(NO_TEXT, Gtk.ResponseType.CANCEL)
|
||||
|
||||
res = dlg.run()
|
||||
|
||||
if res == TERMINATE:
|
||||
return res
|
||||
|
||||
# Everything else is cancel
|
||||
return None
|
||||
|
||||
|
||||
def handle_session_action(agentpid, action):
|
||||
""" Execute session action chosen by user.
|
||||
|
||||
@type agentpid: int
|
||||
@param agentpid: Nxagent process id as passed by command line
|
||||
@type action: int or None
|
||||
@param action: Chosen action
|
||||
|
||||
"""
|
||||
|
||||
if action == DISCONNECT:
|
||||
print("Disconnecting from session, sending SIGHUP to %s" % (agentpid))
|
||||
if agentpid != 0:
|
||||
os.kill(agentpid, signal.SIGHUP)
|
||||
|
||||
elif action == TERMINATE:
|
||||
print("Terminating session, sending SIGTERM to process %s" % (agentpid))
|
||||
if agentpid != 0:
|
||||
os.kill(agentpid, signal.SIGTERM)
|
||||
|
||||
elif action is None:
|
||||
pass
|
||||
|
||||
else:
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
def show_simple_message_box(icon, title, text):
|
||||
""" Shows a simple message box.
|
||||
|
||||
@type icon: QMessageBox.Icon
|
||||
@param icon: Icon for message box
|
||||
@type title: str
|
||||
@param title: Message box title
|
||||
@type text: str
|
||||
@param text: Message box text
|
||||
|
||||
"""
|
||||
dlg = Gtk.MessageDialog(type=icon, flags=Gtk.DialogFlags.MODAL,
|
||||
buttons=Gtk.ButtonsType.OK)
|
||||
dlg.set_title(title)
|
||||
dlg.set_markup(text)
|
||||
dlg.run()
|
||||
|
||||
|
||||
class NxDialogProgram(object):
|
||||
""" the main program """
|
||||
|
||||
def __init__(self):
|
||||
self.args = None
|
||||
self.options = None
|
||||
|
||||
def main(self):
|
||||
""" let's do something """
|
||||
try:
|
||||
self.options = self.parse_args()
|
||||
|
||||
self.run()
|
||||
|
||||
except (SystemExit, KeyboardInterrupt):
|
||||
raise
|
||||
|
||||
except Exception as expt:
|
||||
sys.stderr.write("Caught exception: %s" % (expt) + os.linesep)
|
||||
sys.exit(EXIT_FAILURE)
|
||||
|
||||
@staticmethod
|
||||
def parse_args():
|
||||
""" init parser """
|
||||
|
||||
parser = argparse.ArgumentParser(description="Helper for nxagent to display dialogs")
|
||||
|
||||
# nxagent 3.5.99.27 only uses yesno, ok, pulldown and yesnosuspend
|
||||
# yesno dialogs will always kill the session if "yes" is selected
|
||||
parser.add_argument("--dialog", dest="dialog_type",
|
||||
help='type of dialog to show, one of "yesno", \
|
||||
"ok", "error", "panic", "quit", "pulldown", \
|
||||
"yesnosuspend"')
|
||||
parser.add_argument("--message", dest="text",
|
||||
help="message text to display in the dialog")
|
||||
parser.add_argument("--caption", dest="caption",
|
||||
help="window title of the dialog")
|
||||
parser.add_argument("--display", dest="display",
|
||||
help="X11 display where the dialog should be \
|
||||
shown")
|
||||
parser.add_argument("--parent", type=int, dest="agentpid",
|
||||
help="pid of the nxagent")
|
||||
parser.add_argument("--window", dest="window",
|
||||
help="id of window where to embed the \
|
||||
pulldown dialog type")
|
||||
# -class, -local, -allowmultiple are unused in nxlibs 3.5.99.27
|
||||
parser.add_argument("--class", dest="dlgclass", default="info",
|
||||
help="class of the message (info, warning, error) \
|
||||
default: info) [currently unimplemented]")
|
||||
parser.add_argument("--local", action="store_true", dest="local",
|
||||
help="specify that proxy mode is used \
|
||||
[currently unimplemented]")
|
||||
parser.add_argument("--allowmultiple", action="store_true",
|
||||
dest="allowmultiple",
|
||||
help="allow launching more than one dialog with \
|
||||
the same message [currently unimplemented]")
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
def show_dialog(self, message_caption, message_text):
|
||||
""" Show the dialog or exit with failure if not implemented. """
|
||||
dlgtype = self.options.dialog_type
|
||||
if dlgtype == DLG_TYPE_OK:
|
||||
show_simple_message_box(
|
||||
Gtk.MessageType.INFO, message_caption, message_text)
|
||||
|
||||
elif dlgtype in (DLG_TYPE_ERROR, DLG_TYPE_PANIC):
|
||||
show_simple_message_box(
|
||||
Gtk.MessageType.ERROR, message_caption, message_text)
|
||||
|
||||
elif dlgtype == DLG_TYPE_PULLDOWN:
|
||||
handle_session_action(self.options.agentpid,
|
||||
PullDownMenu(self.options.window).show())
|
||||
|
||||
elif dlgtype == DLG_TYPE_YESNOSUSPEND:
|
||||
handle_session_action(self.options.agentpid,
|
||||
show_yes_no_suspend_box(message_caption, message_text))
|
||||
|
||||
elif dlgtype == DLG_TYPE_YESNO:
|
||||
handle_session_action(self.options.agentpid,
|
||||
show_yes_no_box(message_caption, message_text))
|
||||
|
||||
else:
|
||||
# TODO: Implement all dialog types
|
||||
sys.stderr.write("Dialog type '%s' not implemented" % (dlgtype))
|
||||
sys.exit(EXIT_FAILURE)
|
||||
|
||||
def run(self):
|
||||
""" Disconnect/terminate NX session upon user's request. """
|
||||
|
||||
if not self.options.dialog_type:
|
||||
sys.stderr.write("Dialog type not supplied via --dialog" + os.linesep)
|
||||
sys.exit(EXIT_FAILURE)
|
||||
|
||||
dlgtype = self.options.dialog_type
|
||||
|
||||
if dlgtype not in VALID_DLG_TYPES:
|
||||
sys.stderr.write("Invalid dialog type '%s'" % (dlgtype) + os.linesep)
|
||||
sys.exit(EXIT_FAILURE)
|
||||
|
||||
if dlgtype in (DLG_TYPE_PULLDOWN,
|
||||
DLG_TYPE_YESNOSUSPEND,
|
||||
DLG_TYPE_YESNO) and self.options.agentpid is None:
|
||||
sys.stderr.write("Agent pid not supplied via --parent" + os.linesep)
|
||||
sys.exit(EXIT_FAILURE)
|
||||
|
||||
if dlgtype == DLG_TYPE_PULLDOWN and not self.options.window:
|
||||
sys.stderr.write("Window id not supplied via --window" + os.linesep)
|
||||
sys.exit(EXIT_FAILURE)
|
||||
|
||||
if self.options.caption:
|
||||
message_caption = self.options.caption
|
||||
else:
|
||||
message_caption = sys.argv[0]
|
||||
|
||||
if self.options.text:
|
||||
message_text = self.options.text
|
||||
else:
|
||||
message_text = ""
|
||||
|
||||
if self.options.display:
|
||||
os.environ["DISPLAY"] = self.options.display
|
||||
|
||||
self.show_dialog(message_caption, message_text)
|
||||
|
||||
NxDialogProgram().main()
|
||||
22
nxdialog/configure.ac
Normal file
22
nxdialog/configure.ac
Normal file
@@ -0,0 +1,22 @@
|
||||
dnl ***************************************************************************
|
||||
dnl *** configure.ac for nxdialog ***
|
||||
dnl ***************************************************************************
|
||||
|
||||
m4_define([nxdialog_version], m4_esyscmd([tr -d '\n' < VERSION]))
|
||||
|
||||
# Initialize Autoconf
|
||||
AC_PREREQ(2.60)
|
||||
|
||||
AC_INIT([NX Dialog], [nxdialog_version], [https://github.com/ArcticaProject/nx-libs/issues])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_PREFIX_DEFAULT([/usr/local])
|
||||
|
||||
AM_INIT_AUTOMAKE([foreign no-dist-gzip dist-bzip2])
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
bin/Makefile
|
||||
man/Makefile
|
||||
])
|
||||
|
||||
AC_OUTPUT
|
||||
0
nxdialog/m4/.keep
Normal file
0
nxdialog/m4/.keep
Normal file
5
nxdialog/man/Makefile.am
Normal file
5
nxdialog/man/Makefile.am
Normal file
@@ -0,0 +1,5 @@
|
||||
NULL =
|
||||
|
||||
dist_man_MANS = \
|
||||
nxdialog.1 \
|
||||
$(NULL)
|
||||
72
nxdialog/man/nxdialog.1
Normal file
72
nxdialog/man/nxdialog.1
Normal file
@@ -0,0 +1,72 @@
|
||||
'\" -*- coding: utf-8 -*-
|
||||
.if \n(.g .ds T< \\FC
|
||||
.if \n(.g .ds T> \\F[\n[.fam]]
|
||||
.de URL
|
||||
\\$2 \(la\\$1\(ra\\$3
|
||||
..
|
||||
.if \n(.g .mso www.tmac
|
||||
.TH nxdialog 1 "Jun 2023" "Version 3.5.99.27" "NX Dialog"
|
||||
.SH NAME
|
||||
nxdialog \- NX Dialog Helper
|
||||
.SH SYNOPSIS
|
||||
'nh
|
||||
.fi
|
||||
.ad l
|
||||
\fBnxdialog\fR \fI[-h] [--dialog DIALOG_TYPE] [--message TEXT]
|
||||
[--caption CAPTION] [--display DISPLAY] [--parent AGENTPID]
|
||||
[--window WINDOW] [--class DLGCLASS] [--local]
|
||||
[--allowmultiple]\fR
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fBnxdialog\fR is a GUI helper that can be used with nxagent to provide
|
||||
user interaction on certain events inside nxagent. It adds graphical
|
||||
widgets (menus, dialog boxes, etc.) to nxagent that allow a smarter user
|
||||
interaction with the agent.
|
||||
.PP
|
||||
\fBnxagent\fR is not using \fBnxdialog\fR by default, set the
|
||||
\fI$NX_CLIENT\fR environment variable to make the \fBnxdialog\fR path known to
|
||||
\fBnxagent\fR.
|
||||
.PP
|
||||
If you want to disable \fBnxdialog\fR usage in \fBnxagent\fR, then make
|
||||
sure that the \fI$NX_CLIENT\fR environment variable is unset.
|
||||
.PP
|
||||
.SH COMMAND LINE OPTIONS
|
||||
.TP 8
|
||||
.B \-h, \-\-help
|
||||
Show this help message and exit.
|
||||
.TP 8
|
||||
.B --dialog DIALOG_TYPE
|
||||
Type of dialog to show, one of "yesno", "ok", "error", "panic", "quit", "pulldown", "yesnosuspend".
|
||||
.TP 8
|
||||
.B --message \fITEXT\fR
|
||||
Message text to display in the dialog.
|
||||
.TP 8
|
||||
.B --caption CAPTION
|
||||
Window title of the dialog.
|
||||
.TP 8
|
||||
.B --display DISPLAY
|
||||
X11 display where the dialog should be shown (default: \fI$DISPLAY\fR).
|
||||
.TP 8
|
||||
.B --parent AGENTPID
|
||||
PID of the nxagent. The agent PID can be 0 for testing \fBnxdialog\fR.
|
||||
.TP 8
|
||||
.B --window WINDOW
|
||||
X11 id of window where to embed the pulldown dialog type.
|
||||
.TP 8
|
||||
.B --class DLGCLASS
|
||||
Class of the message (info, warning, error) default: info) [currently unimplemented].
|
||||
.TP 8
|
||||
.B --local
|
||||
Specify that proxy mode is used [currently unimplemented].
|
||||
.TP 8
|
||||
.B --allowmultiple
|
||||
Allow launching more than one dialog with the same message [currently unimplemented].
|
||||
|
||||
.SH AUTHOR
|
||||
The \fBnxdialog\fR application has been derived from Google's
|
||||
NeatX client application by Ulrich Sibiller <uli42@gmx.de>.
|
||||
.PP
|
||||
This manual has been written by Mike Gabriel
|
||||
<mike.gabriel@das\-netzwerkteam.de> for the X2Go Project
|
||||
(https://wiki.x2go.org) and the Arctica Project
|
||||
(https://arctica-project.org).
|
||||
Reference in New Issue
Block a user