First version with support of multiple monitors. Problems given if resolutions of monitors differs...

This commit is contained in:
Olaf Schulz 2019-11-06 21:04:59 +01:00
parent 5eb0bff042
commit fb41c192d2
3 changed files with 213 additions and 31 deletions

View File

@ -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);

View File

@ -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;
}

View File

@ -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
}