Browse Source

Add command line actions and fix DBus-issue

A second instance of the app now waits until
it sends it's messages to the primary one.
This fixes issue #12 .

New command line options:
 --version --layer --hide --show --toggle
 --move --pos and --quit
 They can be used to send commands to the primary
 instance of the app.
master
Olaf Schulz 10 months ago
parent
commit
a9faf4d710
4 changed files with 246 additions and 101 deletions
  1. +1
    -1
      Makefile
  2. +144
    -62
      src/app.vala
  3. +75
    -15
      src/main.vala
  4. +26
    -23
      src/neo-window.vala

+ 1
- 1
Makefile View File

@ -169,7 +169,7 @@ info:
"Notes:$(NL)" \
" Use 'ICON=... make' to switch type of panel menu.$(NL)" \
" indicator: For gnome 3.x (default)$(NL)" \
" tray: For gnome 2.x (default)$(NL)" \
" tray: For gnome 2.x$(NL)" \
" none: Disables icon$(NL)$(NL)" \
" Use 'BUILD_TYPE=[release|debug] make' to switch build type$(NL)$(NL)" \


+ 144
- 62
src/app.vala View File

@ -7,89 +7,171 @@ namespace NeoLayoutViewer{
public class NeoLayoutViewerApp: Gtk.Application {
//public int start_layer = 0; // > 0: keybord events do not change displayed layer
public int counter { get; set; }
public NeoWindow neo_win = null;
private bool primary_start_finished = false;
// Some options need references to static variables. These are
// defined here, but not by add_main_option_entries(...)
private static bool _opt_version = false;
private static int _opt_move = -1; // != 0
private const GLib.OptionEntry[] options = {
// --version
{ "version", 'v', 0, OptionArg.NONE, ref _opt_version, "Display version number", null },
// --move
{"move", 'm', OptionFlags.NONE, OptionArg.INT, ref _opt_move,
"Move application window", "position (Num pad style)"},
// list terminator
{ null }
};
public NeoLayoutViewerApp() {
Object(application_id: "org.gnome.neo_layout_viewer",
//flags: ApplicationFlags.HANDLES_OPEN );
flags: ApplicationFlags.HANDLES_COMMAND_LINE);
this.add_main_option_entries(options);
this.add_main_option("layer", 'l',
OptionFlags.NONE, OptionArg.INT
, "Force displayed layer, if > 0", "0-6");
this.add_main_option("show", 's', OptionFlags.NONE, OptionArg.NONE
, "Show application window", null);
this.add_main_option("hide", 'h', OptionFlags.NONE, OptionArg.NONE
, "Hide application window", null);
this.add_main_option("toggle", 't', OptionFlags.NONE, OptionArg.NONE
, "Toggle application window", null);
this.add_main_option("pos", 'p', OptionFlags.NONE, OptionArg.STRING
, "Set explicit position of application window", "x,y");
this.add_main_option("quit", 'q', OptionFlags.NONE, OptionArg.NONE
, "Quit primary instance", null);
this.neo_win = null;
this.counter = -2;
}
#if tray
public AppStatusIcon neo_tray; //for gnome2.x, kde(?)
#endif
#if indicator
public NeoIndicator neo_indicator; //for gnome3.x
#endif
#if _NO_WIN
public KeybindingManager manager;
#endif
public int start_layer = 0; // > 0: keybord events do not change displayed layer
public ConfigManager configm;
public override int handle_local_options (VariantDict options){
// Return -1 to signal app that options should be handled
// in command_line(...) of primary instance.
if( _opt_version ) {
print(@"Version $(RELEASE_VERSION) (git $(GIT_COMMIT_VERSION))\n");
this.quit();
return 0;
}
public NeoLayoutViewerApp(ConfigManager configm) {
Object(application_id: "org.gnome.neo_layout_viewer",
flags: ApplicationFlags.HANDLES_OPEN );
/* The --move option was added by add_main_option_entries(...) because
* the default value should be -1, not 0.
* Otherwise '--move 0' can not be distinct from unset option(?!)
this.configm = configm;
}
* We need to add this option here again because the VariantDict
* 'options' only contains options added by add_main_option(...).
*/
options.insert_value("move", new Variant.int32(_opt_move));
protected override void activate () {
if (this.neo_win == null) {
// Create the window of this application and show it
this.neo_win = new NeoWindow (this);
GLib.assert(options.lookup("move", "i"));
//var opt_move = options.lookup_value("move", VariantType.INT32);
//print(@"Move: $(opt_move.get_int32())");
#if tray
this.neo_tray = new AppStatusIcon(neo_win);
#endif
return -1;
}
#if indicator
this.neo_indicator = new NeoIndicator(neo_win);
#endif
public override int command_line (ApplicationCommandLine command_line){
// Note: This method can be called multiple times.
// Multiple starts of the app call this method in the primary instance.
#if _NO_WIN
bind_shortcuts();
#endif
VariantDict options = command_line.get_options_dict();
if ( options == null ){
debug("Hey, option dict undefined?!\n");
return 0;
}
this.add_window(this.neo_win);
} else {
// reached if app.activate() called by remote instance
this.neo_win.toggle();
var opt_quit = options.lookup_value("quit", VariantType.BOOLEAN);
if( opt_quit != null && opt_quit.get_boolean() ){
debug("Quit app");
this.quit();
return 0;
}
}
private void bind_shortcuts() {
manager = new KeybindingManager(this.neo_win);
var show_shortcut = configm.getConfig().get("show_shortcut").strip();
var move_shortcut = configm.getConfig().get("move_shortcut").strip();
var monitor_shortcut = configm.getConfig().get("monitor_shortcut").strip();
var opt_layer = options.lookup_value("layer", VariantType.INT32);
var opt_show = options.lookup_value("show", VariantType.ANY);
var opt_hide = options.lookup_value("hide", VariantType.ANY);
var opt_toggle = options.lookup_value("toggle", VariantType.ANY);
var opt_move = options.lookup_value("move", VariantType.INT32);
var opt_pos = options.lookup_value("pos", VariantType.STRING);
bool show_handled = false;
if( opt_move != null && opt_move.get_int32() > -1 ){
print(@"Move: $(opt_move.get_int32())\n");
this.neo_win.numkeypad_move(opt_move.get_int32());
show_handled = true;
}else if( opt_pos != null ){
debug("Not implemented");
Regex separator = null;
try {
separator = new Regex(",");
} catch (RegexError e) {
error("Hm, regex compiling failed.");
}
if (separator != null) {
string[] str_xy = separator.split(opt_pos.get_string());
int new_x = 0; int new_y = 0;
if (int.try_parse(str_xy[0], out new_x) &&
int.try_parse(str_xy[1], out new_y) ) {
// TODO: Maybe the ints should get a boundary check.
debug(@"Move window to ($(new_x), $(new_y))");
this.neo_win.move(new_x, new_y);
}
}
show_handled = true;
}
if (move_shortcut.length > 0) {
manager.bind(move_shortcut, ()=>{this.neo_win.numkeypad_move(0);});
if( opt_layer != null ){
this.neo_win.fixed_layer = opt_layer.get_int32();
show_handled = true;
}
if (show_shortcut == monitor_shortcut) {
// combination of show + monitor move
debug("Use combined shortcut for window showing and monitor switching.");
manager.bind(monitor_shortcut, ()=>{this.neo_win.monitor_move(-1, true);});
if( opt_show != null ){
this.neo_win.show();
show_handled = true;
}else if (opt_hide != null ){
this.neo_win.hide();
show_handled = true;
}else if (opt_toggle != null ){
this.neo_win.toggle();
show_handled = true;
}
} else {
if (monitor_shortcut.length > 0) {
manager.bind(monitor_shortcut, ()=>{this.neo_win.monitor_move();});
}
if (show_shortcut.length > 0) {
manager.bind(show_shortcut, ()=>{this.neo_win.toggle();});
/* No option set which had changed the visibility state.
* Threat lack of option like '--toggle'.
*/
if (!show_handled ) {
// Filtering first call out because option config file decide
// inital visibility.
if (this.primary_start_finished ){
this.neo_win.toggle();
}
}else if (!this.neo_win.minimized) {
this.neo_win.redraw();
}
this.primary_start_finished = true;
return 0;
}
public override void open (File[] files, string hint) {
// Threat non-option argument(s) as layer to show at startup.
// Note: This signal is not called in remote-case.
protected override void activate () {
debug(@"Activate called");
this.hold();
// Only a stub.
// The functionality was shifted into handling of command line
this.release();
}
foreach (File file in files) {
var slayer = file.get_basename();
this.start_layer = int.parse(slayer);
break;
}
this.activate(); // init neo_win
this.neo_win.show();
public override void open (File[] files, string hint) {
debug(@"Open called, but without functionality!");
// Only a stub because app is now controled over options
// and ApplicationFlags.HANDLES_OPEN flag is not set anymore.
}
}


+ 75
- 15
src/main.vala View File

@ -8,8 +8,66 @@ namespace NeoLayoutViewer{
public ConfigManager configm;
public NeoLayoutViewerApp app;
public NeoWindow neo_win = null;
#if tray
public AppStatusIcon neo_tray = null; //for gnome2.x, kde(?)
#endif
#if indicator
public NeoIndicator neo_indicator = null; //for gnome3.x
#endif
#if _NO_WIN
public KeybindingManager manager = null;
#endif
private void bind_shortcuts() {
manager = new KeybindingManager(neo_win);
var show_shortcut = configm.getConfig().get("show_shortcut").strip();
var move_shortcut = configm.getConfig().get("move_shortcut").strip();
var monitor_shortcut = configm.getConfig().get("monitor_shortcut").strip();
if (move_shortcut.length > 0) {
manager.bind(move_shortcut, ()=>{neo_win.numkeypad_move(0);});
}
if (show_shortcut == monitor_shortcut) {
// combination of show + monitor move
debug("Use combined shortcut for window showing and monitor switching.");
manager.bind(monitor_shortcut, ()=>{neo_win.monitor_move(-1, true);});
} else {
if (monitor_shortcut.length > 0) {
manager.bind(monitor_shortcut, ()=>{neo_win.monitor_move();});
}
if (show_shortcut.length > 0) {
manager.bind(show_shortcut, ()=>{neo_win.toggle();});
}
}
}
public static int main(string[] args) {
// Minimal initialization. Check if primary instance and quit otherwise
app = new NeoLayoutViewerApp ();
try {
app.register(); // returns false if and only if throws Error
} catch (Error e) {
debug(@"Gtk.Application.register() failed.\n");
return -1;
}
if (app.is_remote) {
print(@"Application is already running.\n");
// Run without further initalization. It triggers transfer of arguments
// to command_line()-call of primary instance.
app.run(args);
/* Gives D-Bus some time.
* Only needed if app.run() isn't called.
*/
//GLib.Thread.usleep(100000);
return 0;
}
string[] paths = {
GLib.Environment.get_user_config_dir(),
GLib.Environment.get_home_dir(),
@ -30,23 +88,25 @@ namespace NeoLayoutViewer{
configm.getConfig().set("asset_folder", asset_folder);
debug(@"Asset folder: $(asset_folder)\n");
// Init application window.
app = new NeoLayoutViewerApp (configm);
// Create the window of this application and show it
neo_win = new NeoWindow (configm, app);
try {
app.register(); // returns false if and only if throws Error
} catch (Error e) {
debug(@"Gtk.Application.register() failed.\n");
return -1;
}
if (app.is_remote) {
print(@"Application is already running.\n");
app.activate();
} else {
return app.run(args);
}
#if tray
neo_tray = new AppStatusIcon(neo_win);
#endif
#if indicator
neo_indicator = new NeoIndicator(neo_win);
#endif
#if _NO_WIN
bind_shortcuts();
#endif
app.neo_win = neo_win; // Required for action handlers.
app.add_window(neo_win);
return 0;
return app.run(args);
}
private static void quit() {


+ 26
- 23
src/neo-window.vala View File

@ -53,17 +53,20 @@ namespace NeoLayoutViewer {
public Gee.List<Modkey> modifier_key_images; // for modifier which didn't toggle a layout layer. I.e. ctrl, alt.
public Gee.Map<string, string> config;
public bool fix_layer = false;
public int fixed_layer { get; set; }
private int _layer = 1;
public int layer {
get { return _layer; }
set { if (value < 1 || value > 6) { _layer = 1; } else { _layer = value; } }
set {
if (value < 1 || value > 6) { _layer = 1; } else { _layer = value; }
}
}
public int[] active_modifier_by_keyboard;
public int[] active_modifier_by_mouse;
public int numpad_width;
public int function_keys_height;
private bool minimized;
private bool _minimized;
public bool minimized { get {return _minimized; } }
private int position_num;
private int[] position_cycle;
private int position_on_hide_x;
@ -131,11 +134,12 @@ namespace NeoLayoutViewer {
{ {0, 0} , {1, 1} } }//1100, 1101; 1110, 1111; //k=m=1 should be impossible
};
public NeoWindow (NeoLayoutViewerApp app) {
this.config = app.configm.getConfig();
this.minimized = true;
public NeoWindow (ConfigManager configm, NeoLayoutViewerApp app) {
//this.config = app.configm.getConfig();
this.config = configm.getConfig();
this._minimized = true;
this.layoutType = this.config.get("layout_type");
this.layoutType = this.config.get("layout_type");
/* Set window type to let tiling window manager, i.e. i3-wm,
* the chance to float the window automatically.
@ -215,14 +219,11 @@ namespace NeoLayoutViewer {
debug(@"$(i)=> $(position_cycle[i])");
}
if (app.start_layer > 0) {
this.fix_layer = true;
this.layer = app.start_layer;
this.active_modifier_by_mouse[1] = this.LAYER_TO_MODIFIERS[this.layer-1, 0];
this.active_modifier_by_mouse[2] = this.LAYER_TO_MODIFIERS[this.layer-1, 1];
this.active_modifier_by_mouse[3] = this.LAYER_TO_MODIFIERS[this.layer-1, 2];
if (this.fixed_layer > 0 && this.fixed_layer <= 6) {
for (int i = 0; i < 3; i++) {
this.active_modifier_by_mouse[i+1] = this.LAYER_TO_MODIFIERS[this.layer-1, i];
}
}
// Crawl dimensions of screen/display/monitor
// Should be done before load_images() is called.
screen_dim_auto[0] = (this.config.get("screen_width") == "auto");
@ -316,7 +317,7 @@ namespace NeoLayoutViewer {
}
public override void show() {
this.minimized = false;
this._minimized = false;
this.move(this.position_on_hide_x, this.position_on_hide_y);
debug(@"Show window on $(this.position_on_hide_x), $(this.position_on_hide_y)\n");
base.show();
@ -343,7 +344,7 @@ namespace NeoLayoutViewer {
this.position_on_hide_y = tmpy;
debug(@"Hide window on $(this.position_on_hide_x), $(this.position_on_hide_y)\n");
this.minimized = true;
this._minimized = true;
base.hide();
}
@ -371,6 +372,8 @@ namespace NeoLayoutViewer {
GLib.assert(n_monitors > 0);
if( pos < 0 ){ pos = 0; }
// Automatic set of next position
if ((pos%10) == 0) {
/* Resolve next position */
@ -562,7 +565,7 @@ namespace NeoLayoutViewer {
break;
}
}
return open_image_str(bildpfad);
return open_image_str(bildpfad);
}
public Gdk.Pixbuf open_image_str (string bildpfad) {
@ -719,13 +722,12 @@ namespace NeoLayoutViewer {
public void redraw() {
var tlayer = this.layer;
if (this.fix_layer) { // Ignore key events
this.layer = this.MODIFIER_MAP2[
this.active_modifier_by_mouse[1], //shift
this.active_modifier_by_mouse[2], //neo-mod3
this.active_modifier_by_mouse[3] //neo-mod4
] + 1;
if (this.fixed_layer > 0) { // Ignore key events
for (int i = 0; i < 3; i++) {
this.active_modifier_by_mouse[i+1] = this.LAYER_TO_MODIFIERS[this.fixed_layer-1, i];
}
this.layer = this.fixed_layer;
} else {
this.layer = this.MODIFIER_MAP2[
this.active_modifier_by_keyboard[1] | this.active_modifier_by_mouse[1], //shift
@ -742,6 +744,7 @@ namespace NeoLayoutViewer {
}
if (tlayer != this.layer) {
debug(@"Redraw with layer $(this.layer)");
render_page();
}


Loading…
Cancel
Save