First version with support of multiple monitors. Problems given if resolutions of monitors differs...
This commit is contained in:
parent
5eb0bff042
commit
fb41c192d2
31
src/app.vala
31
src/app.vala
|
@ -41,9 +41,7 @@ namespace NeoLayoutViewer{
|
|||
#endif
|
||||
|
||||
#if _NO_WIN
|
||||
manager = new KeybindingManager(this.neo_win);
|
||||
manager.bind(configm.getConfig().get("show_shortcut"), ()=>{this.neo_win.toggle();});
|
||||
manager.bind(configm.getConfig().get("move_shortcut"), ()=>{this.neo_win.numkeypad_move(0);});
|
||||
bind_shortcuts();
|
||||
#endif
|
||||
|
||||
this.add_window(this.neo_win);
|
||||
|
@ -53,10 +51,35 @@ namespace NeoLayoutViewer{
|
|||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
if (move_shortcut.length > 0){
|
||||
manager.bind(move_shortcut, ()=>{this.neo_win.numkeypad_move(0);});
|
||||
}
|
||||
|
||||
if (show_shortcut == monitor_shortcut){
|
||||
// combination of show + monitor move
|
||||
debug("Use combined shortcut for window show and monitor switch.");
|
||||
manager.bind(monitor_shortcut, ()=>{this.neo_win.monitor_move(-1, 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();});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
|
||||
foreach (File file in files) {
|
||||
var slayer = file.get_basename();
|
||||
this.start_layer = int.parse(slayer);
|
||||
|
|
|
@ -82,14 +82,26 @@ namespace NeoLayoutViewer {
|
|||
//config.set("show_shortcut", "<Mod4><Super_L>n", "Toggle the visibility of the window.");
|
||||
addSetting("show_shortcut", "<Ctrl><Alt>q", "Toggle the visibility of the window.");
|
||||
addSetting("on_top", "1", "Show window on top.");
|
||||
addSetting("position", "3", "Window position on startup (num pad orientation)");
|
||||
addSetting("position", "3", "Window position on startup (num pad orientation)\n"
|
||||
+ "# Add 10 to start on second monitor, etc.");
|
||||
/* width of application window
|
||||
if value between 'resolution width'*max_width and 'resolution width'*min_width */
|
||||
addSetting("width", "1000", "Width in Pixel. Min_width and max_width bound sensible values. ");
|
||||
addSetting("min_width", "0.25", "Minimal width. 1=full screen width");
|
||||
addSetting("max_width", "0.5", "Maximal width. 1=full screen width");
|
||||
addSetting("move_shortcut", "<Ctrl><Alt>n", "Circle through window posisitions.");
|
||||
addSetting("position_cycle", "2 3 6 1 3 9 4 7 8", "List of positions (num pad orientation)\n# The n-th number marks the next position of the window.\n# To limit the used positions to screen corners use\n#position_cycle = 3 3 9 1 3 9 1 7 7");
|
||||
addSetting("monitor_shortcut", "<Ctrl><Alt><Shift>n", "Circle window through monitors.\n"
|
||||
+ "# Use same value as 'show_shortcut' to combine both functionalities.");
|
||||
addSetting("move_shortcut", "<Ctrl><Alt>n", "Circle through window positions.");
|
||||
addSetting("position_cycle", "2 3 6 1 3 9 4 7 8 | 12 13 16 11 13 19 14 17 18 |",
|
||||
"""List of positions (num pad orientation)
|
||||
# The number on the n-th index marks the next position of the window.
|
||||
#
|
||||
# Examples:
|
||||
# pos. index 1 2 3 4 5 6 7 8 9 | 11 12 13 14 15 18 17 18 19 | …
|
||||
# position_cycle = 2 3 6 1 3 9 4 7 8 | 12 13 16 11 13 19 14 17 18 |(counter clockwise, default)
|
||||
# position_cycle = 3 3 9 1 3 9 1 7 7 | 13 13 19 11 13 19 11 17 17 |(corners only)
|
||||
# position_cycle =3 3 11 1 3 9 1 7 7 | 13 13 19 11 13 19 9 17 17 |(cycle over two monitors)""");
|
||||
|
||||
addSetting("display_numpad", "1", null);
|
||||
addSetting("display_function_keys", "0", null);
|
||||
addSetting("window_selectable", "0", "Disable window selection to use the program as virtual keyboard.");
|
||||
|
@ -123,7 +135,7 @@ namespace NeoLayoutViewer {
|
|||
|
||||
// Test for the existence of file
|
||||
if (!file.query_exists()) {
|
||||
stdout.printf("Can't create config file.\n");
|
||||
GLib.stdout.printf("Can't create config file.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,10 @@ using Posix;//system-calls
|
|||
|
||||
namespace NeoLayoutViewer {
|
||||
|
||||
errordomain PositionArrayParsingError {
|
||||
CODE_1A
|
||||
}
|
||||
|
||||
public class Modkey {
|
||||
public Gtk.Image modKeyImage;
|
||||
public int modifier_index;
|
||||
|
@ -141,19 +145,49 @@ namespace NeoLayoutViewer {
|
|||
this.active_modifier_by_keyboard = {0, 0, 0, 0, 0, 0};
|
||||
this.active_modifier_by_mouse = {0, 0, 0, 0, 0, 0};
|
||||
|
||||
this.modifier_key_images = new Gee.ArrayList<Modkey>();
|
||||
this.position_num = int.max(int.min(int.parse(this.config.get("position")), 9), 1);
|
||||
this.modifier_key_images = new Gee.ArrayList<Modkey>();
|
||||
this.position_num = int.min(200, int.max(int.parse(this.config.get("position")), 1));
|
||||
|
||||
//Anlegen des Arrays, welches den Positionsdurchlauf beschreibt.
|
||||
try {
|
||||
var space = new Regex(" ");
|
||||
string[] split = space.split(this.config.get("position_cycle"));
|
||||
position_cycle = new int[int.max(9, split.length)];
|
||||
//var space = new Regex(" ");
|
||||
//string[] split = space.split(this.config.get("position_cycle"));
|
||||
var non_numeral = new Regex("[^0-9]+");
|
||||
string[] split = non_numeral.split(this.config.get("position_cycle"));
|
||||
|
||||
/* Create array which can hold the parsed integers, but also some
|
||||
unused indizes (0th. entry, 10th entry, …)
|
||||
*/
|
||||
var min_len = ((position_num-1)/10 + 1)*10;
|
||||
position_cycle = new int[int.max(min_len, ( (split.length-1)/10 + 1)*10)]; // multiple of 10 and > 0
|
||||
|
||||
GLib.assert( position_cycle.length/10 >= split.length/9 );
|
||||
|
||||
// Prefill with default values. Call is not redundant!
|
||||
debug(@"Cycle array length: $(position_cycle.length)");
|
||||
fill_position_cycle_default(ref position_cycle);
|
||||
|
||||
// Read positions from config string
|
||||
int j = 1;
|
||||
//position_cycle[0] = -1; // already set in fill_position_cycle_default(...)
|
||||
for (int i = 0;i < split.length; i++) {
|
||||
position_cycle[i] = int.max(int.min(int.parse(split[i]), 9), 1);//Zulässiger Bereich: 1-9
|
||||
// Valid range: [1, 10*number_of_monitors - 1]
|
||||
position_cycle[j] = int.max(int.min(int.parse(split[i]), position_cycle.length-1), 1);
|
||||
|
||||
if ( position_cycle[j] == 0 ){
|
||||
// Invalid number parsed (or parsing failed). Print error message and use predefined array
|
||||
GLib.stdout.printf("Position cycle reading failed. Problematic value: $(split[i])\n");
|
||||
throw new PositionArrayParsingError.CODE_1A("Unexpected Integer");
|
||||
}
|
||||
GLib.assert( position_cycle[j] > 0 );
|
||||
|
||||
j++;
|
||||
if (j%10 == 0){ j++; }
|
||||
}
|
||||
} catch (PositionArrayParsingError e) {
|
||||
fill_position_cycle_default(ref position_cycle);
|
||||
} catch (RegexError e) {
|
||||
position_cycle = {3, 3, 9, 1, 3, 9, 1, 7, 7};
|
||||
fill_position_cycle_default(ref position_cycle);
|
||||
}
|
||||
|
||||
if (app.start_layer > 0 ){
|
||||
|
@ -282,53 +316,107 @@ namespace NeoLayoutViewer {
|
|||
}
|
||||
|
||||
public void numkeypad_move(int pos){
|
||||
int screen_width = this.get_screen_width();
|
||||
int screen_height = this.get_screen_height();
|
||||
|
||||
if( (pos%10) <= 0 ){
|
||||
/* Resolve next position */
|
||||
pos = this.position_cycle[this.position_num];
|
||||
}
|
||||
|
||||
GLib.assert( (pos%10) > 0 );
|
||||
if ( pos <= 0 || pos >= this.position_cycle.length ){
|
||||
GLib.stdout.printf("======= Positioning error! ======\n");
|
||||
pos = 5;
|
||||
}
|
||||
|
||||
var display = Gdk.Display.get_default();
|
||||
//var screen = Gdk.Screen.get_default();
|
||||
var screen = display.get_default_screen();
|
||||
//var screen = this.get_screen();
|
||||
//var monitor = display.get_monitor_at_window(screen.get_active_window());
|
||||
|
||||
#if GTK_MAJOR_VERSION == 2 || GTK_MINOR_VERSION == 18 || GTK_MINOR_VERSION == 19 || GTK_MINOR_VERSION == 20 || GTK_MINOR_VERSION == 21
|
||||
// Old variant for ubuntu 16.04 (Glib version < 3.22)
|
||||
var n_monitors = screen.get_n_monitors();
|
||||
#else
|
||||
var n_monitors = display.get_n_monitors(); // Könnte n_1+n_2+…n_k sein mit k Screens?!
|
||||
#endif
|
||||
debug(@"Number of monitors: $(n_monitors)");
|
||||
|
||||
GLib.assert(n_monitors > 0);
|
||||
GLib.assert(pos >= 0);
|
||||
|
||||
/* Positions supports multiple screens, now.
|
||||
1-9 on monitor 0, 11-19 on monitor 1, …
|
||||
|
||||
This line shift indicies of non connected monitors to a available one.
|
||||
*/
|
||||
pos %= 10 * n_monitors;
|
||||
|
||||
// Get monitor for this position
|
||||
int monitor_index = pos/10;
|
||||
GLib.assert(monitor_index >= 0);
|
||||
if (monitor_index >= n_monitors){
|
||||
monitor_index %= n_monitors;
|
||||
}
|
||||
|
||||
// Get the position within the monitor
|
||||
int pos_on_screen = pos % 10;
|
||||
|
||||
Gdk.Rectangle monitor_rect_dest;
|
||||
screen.get_monitor_geometry(monitor_index, out monitor_rect_dest);
|
||||
|
||||
debug(@"Monitor($(monitor_index)) values: x=$(monitor_rect_dest.width), " +
|
||||
@"y=$(monitor_rect_dest.y), w=$(monitor_rect_dest.width), h=$(monitor_rect_dest.height)\n");
|
||||
|
||||
//int screen_width = this.get_screen_width();
|
||||
//int screen_height = this.get_screen_height();
|
||||
|
||||
int x, y, w, h;
|
||||
this.get_size(out w, out h);
|
||||
|
||||
switch(pos) {
|
||||
switch(pos_on_screen) {
|
||||
case 0: //Zur nächsten Position wechseln
|
||||
numkeypad_move(this.position_cycle[this.position_num-1]);
|
||||
GLib.assert(false); // Case should already handled.
|
||||
return;
|
||||
case 7:
|
||||
x = 0;
|
||||
y = 0;
|
||||
break;
|
||||
case 8:
|
||||
x = (screen_width - w) / 2;
|
||||
x = (monitor_rect_dest.width - w) / 2;
|
||||
y = 0;
|
||||
break;
|
||||
case 9:
|
||||
x = screen_width - w;
|
||||
x = monitor_rect_dest.width - w;
|
||||
y = 0;
|
||||
break;
|
||||
case 4:
|
||||
x = 0;
|
||||
y = (screen_height - h) / 2;
|
||||
y = (monitor_rect_dest.height - h) / 2;
|
||||
break;
|
||||
case 5:
|
||||
x = (screen_width - w) / 2;
|
||||
y = (screen_height - h) / 2;
|
||||
x = (monitor_rect_dest.width - w) / 2;
|
||||
y = (monitor_rect_dest.height - h) / 2;
|
||||
break;
|
||||
case 6:
|
||||
x = screen_width - w;
|
||||
y = (screen_height - h) / 2;
|
||||
x = monitor_rect_dest.width - w;
|
||||
y = (monitor_rect_dest.height - h) / 2;
|
||||
break;
|
||||
case 1:
|
||||
x = 0;
|
||||
y = screen_height - h;
|
||||
y = monitor_rect_dest.height - h;
|
||||
break;
|
||||
case 2:
|
||||
x = (screen_width - w) / 2;
|
||||
y = screen_height - h;
|
||||
x = (monitor_rect_dest.width - w) / 2;
|
||||
y = monitor_rect_dest.height - h;
|
||||
break;
|
||||
default:
|
||||
x = screen_width - w;
|
||||
y = screen_height - h;
|
||||
x = monitor_rect_dest.width - w;
|
||||
y = monitor_rect_dest.height - h;
|
||||
break;
|
||||
}
|
||||
x += monitor_rect_dest.x;
|
||||
y += monitor_rect_dest.y;
|
||||
|
||||
this.position_num = pos;
|
||||
|
||||
|
@ -340,6 +428,30 @@ namespace NeoLayoutViewer {
|
|||
this.move(x, y);
|
||||
}
|
||||
|
||||
public void monitor_move(int i_monitor=-1, bool hide_after_latest=false){
|
||||
|
||||
if (hide_after_latest ){
|
||||
if (this.minimized ){
|
||||
debug(@"Show minimized window again. $(this.position_num)");
|
||||
show();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( i_monitor < 0 ){
|
||||
numkeypad_move(this.position_num + 10);
|
||||
}else{
|
||||
numkeypad_move(i_monitor + (this.position_num % 10));
|
||||
}
|
||||
debug(@"New position: $(this.position_num)");
|
||||
|
||||
if( hide_after_latest && this.position_num < 10 ){
|
||||
// First monitor reached again
|
||||
debug(@"Hide window. $(this.position_num)");
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
public Gdk.Pixbuf open_image (int layer) {
|
||||
var bildpfad = @"$(config.get("asset_folder"))/neo2.0/tastatur_neo_Ebene$(layer).png";
|
||||
return open_image_str(bildpfad);
|
||||
|
@ -591,6 +703,41 @@ namespace NeoLayoutViewer {
|
|||
return screen_dim[1];
|
||||
}
|
||||
|
||||
private void fill_position_cycle_default(ref int[] positions){
|
||||
/* Position Next position o ← o ← o
|
||||
9 8 9 4 7 8 ↓ ↑
|
||||
6 5 6 ====> 1 3 9 o o o
|
||||
3 2 3 2 3 6 ↓ ↘ ↑
|
||||
o → o → o
|
||||
|
||||
Values for monitor 4 are 11,…,19 and so on.
|
||||
|
||||
Example output:
|
||||
positions = {
|
||||
-1, 3, 3, 9, 1, 3, 9, 1, 7, 7,
|
||||
-11, 13, 13, 19, 11, 13, 19, 11, 17, 17,
|
||||
-21, 23, 23, 29, 21, 23, 29, 21, 27, 27,
|
||||
-31, 33, 33, 39, 31, 33, 39, 31, 37, 37,
|
||||
};
|
||||
*/
|
||||
|
||||
GLib.assert( positions.length%10 == 0 && positions.length > 0);
|
||||
int n_monitors = positions.length/10;
|
||||
for(int i_monitor=0; i_monitor < n_monitors; i_monitor++){
|
||||
int s = i_monitor*10;
|
||||
positions[s] = -1;
|
||||
positions[s+1] = s + 2;
|
||||
positions[s+2] = s + 3;
|
||||
positions[s+3] = s + 6;
|
||||
positions[s+4] = s + 1;
|
||||
positions[s+5] = s + 3;
|
||||
positions[s+6] = s + 9;
|
||||
positions[s+7] = s + 4;
|
||||
positions[s+8] = s + 7;
|
||||
positions[s+9] = s + 8;
|
||||
}
|
||||
}
|
||||
|
||||
} //End class NeoWindow
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue