diff --git a/src/configsys.c b/src/configsys.c index 8214ac0c..674be24d 100644 --- a/src/configsys.c +++ b/src/configsys.c @@ -74,6 +74,7 @@ static cfg_opt_t config_opts[] = { CFG_STR("normalize_font_size_key", "0", CFGF_NONE), CFG_STR("show_on_monitor", "", CFGF_NONE), CFG_STR("word_chars", DEFAULT_WORD_CHARS, CFGF_NONE), + CFG_STR("cycle_monitor_key", "Right", CFGF_NONE), /* ints */ CFG_INT("lines", 5000, CFGF_NONE), diff --git a/src/tilda.ui b/src/tilda.ui index f70b6d24..6a0b2d45 100644 --- a/src/tilda.ui +++ b/src/tilda.ui @@ -3670,6 +3670,43 @@ 0 11 + 1 + 1 + + + + + True + False + 0 + + + True + False + 12 + + + + True + True + True + 2 + + + + + + + True + False + <b>Move To Next Monitor</b> + True + + + + + 1 + 11 diff --git a/src/tilda_window.c b/src/tilda_window.c index b6811674..eb936dae 100644 --- a/src/tilda_window.c +++ b/src/tilda_window.c @@ -312,6 +312,57 @@ static gboolean decrease_font_size (tilda_window *tw) return GDK_EVENT_STOP; } +gint cycle_monitor_cb (tilda_window *tw) +{ + DEBUG_FUNCTION("cycle_monitor_cb"); + DEBUG_ASSERT(tw != NULL); + + // Figure out what monitor we're on, and + // which monitor we're going to + GdkScreen* screen = gtk_window_get_screen(GTK_WINDOW(tw->window)); + int original_monitor = config_getint("show_on_monitor_number"); + int num_monitors = gdk_screen_get_n_monitors(screen); + int new_monitor = (original_monitor + 1) % num_monitors; + + // Calculate the workareas of the two + // monitors + GdkRectangle* rect = malloc(sizeof(GdkRectangle) * num_monitors); + for (int i = 0; i < num_monitors; i++) { + gdk_screen_get_monitor_workarea(screen, i, rect + i); + } + GdkRectangle *original_workarea = rect + original_monitor; + GdkRectangle *new_workarea = rect + new_monitor; + + // Try to keep the same relative position + // on the new monitor if possible, but + // sometimes the saved (x, y) absolutes + // are in disagreement with the selected + // monitor; in that case set x or y to 0 + int original_absolute_x = config_getint("x_pos"); + int original_absolute_y = config_getint("y_pos"); + int relative_x = original_absolute_x - original_workarea->x; + int relative_y = original_absolute_y - original_workarea->y; + if (relative_x < 0 || relative_x > new_workarea->width) { + relative_x = 0; + } + if (relative_y < 0 || relative_y > new_workarea->height) { + relative_y = 0; + } + int new_absolute_x = new_workarea->x + relative_x; + int new_absolute_y = new_workarea->y + relative_y; + + config_setint("show_on_monitor_number", new_monitor); + config_setint("x_pos", new_absolute_x); + config_setint("y_pos", new_absolute_y); + + // Make the change + gtk_window_move(GTK_WINDOW(tw->window), new_absolute_x, new_absolute_y); + generate_animation_positions(tw); + free(rect); + + return GDK_EVENT_STOP; +} + gint tilda_window_next_tab (tilda_window *tw) { DEBUG_FUNCTION ("next_tab"); @@ -674,6 +725,7 @@ static gint tilda_window_setup_keyboard_accelerators (tilda_window *tw) tilda_add_config_accelerator_by_path("quit_key", "/context/Quit", G_CALLBACK(gtk_main_quit), tw); tilda_add_config_accelerator_by_path("toggle_transparency_key", "/context/Toggle Transparency", G_CALLBACK(toggle_transparency_cb), tw); tilda_add_config_accelerator_by_path("toggle_searchbar_key", "/context/Toggle Searchbar", G_CALLBACK(tilda_window_toggle_searchbar), tw); + tilda_add_config_accelerator_by_path("cycle_monitor_key", "/context/Cycle Monitor", G_CALLBACK(cycle_monitor_cb), tw); tilda_add_config_accelerator_by_path("nexttab_key", "/context/Next Tab", G_CALLBACK(tilda_window_next_tab), tw); tilda_add_config_accelerator_by_path("prevtab_key", "/context/Previous Tab", G_CALLBACK(tilda_window_prev_tab), tw); diff --git a/src/wizard.c b/src/wizard.c index 81f7831e..50548dfd 100644 --- a/src/wizard.c +++ b/src/wizard.c @@ -387,6 +387,7 @@ static void wizard_close_dialog (tilda_window *tw) const gchar *fullscreen_key = GET_BUTTON_LABEL("button_keybinding_fullscreen"); const gchar *toggle_transparency_key = GET_BUTTON_LABEL("button_keybinding_toggle_transparency"); const gchar *toggle_searchbar_key = GET_BUTTON_LABEL("button_keybinding_toggle_searchbar"); + const gchar *cycle_monitor_key = GET_BUTTON_LABEL("button_keybinding_cycle_monitor"); const GtkWidget *entry_custom_command = GTK_WIDGET (gtk_builder_get_object(xml, "entry_custom_command")); @@ -444,6 +445,8 @@ static void wizard_close_dialog (tilda_window *tw) return; if (!validate_keybinding(toggle_searchbar_key, tw, _("The keybinding you chose for \"Toggle Search Bar\" is invalid. Please choose another."))) return; + if (!validate_keybinding(cycle_monitor_key, wizard_window, _("The keybinding you chose for \"Move To Next Monitor\" is invalid. Please choose another."))) + return; /* Now that our shortcuts are validated, store them back into the config. */ config_setstr ("key", key); @@ -469,6 +472,7 @@ static void wizard_close_dialog (tilda_window *tw) config_setstr ("fullscreen_key", fullscreen_key); config_setstr ("toggle_transparency_key", toggle_transparency_key); config_setstr ("toggle_searchbar_key", toggle_searchbar_key); + config_setstr ("cycle_monitor_key", cycle_monitor_key); /* Now that they're in the config, reset the keybindings right now. */ tilda_window_update_keyboard_accelerators("/context/New Tab", addtab_key); @@ -493,6 +497,7 @@ static void wizard_close_dialog (tilda_window *tw) tilda_window_update_keyboard_accelerators("/context/Toggle Fullscreen", fullscreen_key); tilda_window_update_keyboard_accelerators("/context/Toggle Transparency", toggle_transparency_key); tilda_window_update_keyboard_accelerators("/context/Toggle Searchbar", toggle_searchbar_key); + tilda_window_update_keyboard_accelerators("/context/Cycle Monitor", cycle_monitor_key); /* TODO: validate this?? */ @@ -2062,6 +2067,7 @@ static void button_keybinding_clicked_cb (GtkWidget *w, tilda_window *tw) const GtkWidget *button_keybinding_fullscreen = GTK_WIDGET (gtk_builder_get_object (xml, "button_keybinding_fullscreen")); const GtkWidget *button_keybinding_toggle_transparency = GTK_WIDGET (gtk_builder_get_object (xml, "button_keybinding_toggle_transparency")); const GtkWidget *button_keybinding_toggle_searchbar = GTK_WIDGET (gtk_builder_get_object (xml, "button_keybinding_toggle_searchbar")); + const GtkWidget *button_keybinding_cycle_monitor = GTK_WIDGET (gtk_builder_get_object (xml, "button_keybinding_cycle_monitor")); /* Make the preferences window and buttons non-sensitive while we are grabbing keys. */ gtk_widget_set_sensitive (GTK_WIDGET(wizard_notebook), FALSE); @@ -2089,6 +2095,7 @@ static void button_keybinding_clicked_cb (GtkWidget *w, tilda_window *tw) gtk_widget_set_sensitive (GTK_WIDGET(button_keybinding_fullscreen), FALSE); gtk_widget_set_sensitive (GTK_WIDGET(button_keybinding_toggle_transparency), FALSE); gtk_widget_set_sensitive (GTK_WIDGET(button_keybinding_toggle_searchbar), FALSE); + gtk_widget_set_sensitive (GTK_WIDGET(button_keybinding_cycle_monitor), FALSE); /* Bring up the dialog that will accept the new keybinding */ GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW(wizard_window), @@ -2131,6 +2138,7 @@ static void button_keybinding_clicked_cb (GtkWidget *w, tilda_window *tw) gtk_widget_set_sensitive (GTK_WIDGET(button_keybinding_fullscreen), TRUE); gtk_widget_set_sensitive (GTK_WIDGET(button_keybinding_toggle_transparency), TRUE); gtk_widget_set_sensitive (GTK_WIDGET(button_keybinding_toggle_searchbar), TRUE); + gtk_widget_set_sensitive (GTK_WIDGET(button_keybinding_cycle_monitor), TRUE); /* If the dialog was "programmatically destroyed" (we got a key), we don't want to destroy it again. Otherwise, we do want to destroy it, otherwise it would stick around even after hitting Cancel. */ @@ -2383,6 +2391,7 @@ static void set_wizard_state_from_config (tilda_window *tw) { BUTTON_LABEL_FROM_CFG ("button_keybinding_fullscreen", "fullscreen_key"); BUTTON_LABEL_FROM_CFG ("button_keybinding_toggle_transparency", "toggle_transparency_key"); BUTTON_LABEL_FROM_CFG ("button_keybinding_toggle_searchbar", "toggle_searchbar_key"); + BUTTON_LABEL_FROM_CFG ("button_keybinding_cycle_monitor", "cycle_monitor_key"); } static void initialize_scrollback_settings(void) { @@ -2538,6 +2547,7 @@ static void connect_wizard_signals (tilda_window *tw) CONNECT_SIGNAL ("button_keybinding_fullscreen", "clicked", button_keybinding_clicked_cb, tw); CONNECT_SIGNAL ("button_keybinding_toggle_transparency", "clicked", button_keybinding_clicked_cb, tw); CONNECT_SIGNAL ("button_keybinding_toggle_searchbar", "clicked", button_keybinding_clicked_cb, tw); + CONNECT_SIGNAL ("button_keybinding_cycle_monitor", "clicked", button_keybinding_clicked_cb, tw); /* Close Button */ CONNECT_SIGNAL ("button_wizard_close","clicked", wizard_button_close_clicked_cb, tw);