]> git.sur5r.net Git - i3/i3/commitdiff
Merge pull request #1693 from mh21/wm-class-garbage-no-copy
authorMichael Stapelberg <stapelberg@users.noreply.github.com>
Thu, 7 May 2015 06:55:47 +0000 (23:55 -0700)
committerMichael Stapelberg <stapelberg@users.noreply.github.com>
Thu, 7 May 2015 06:55:47 +0000 (23:55 -0700)
Don't duplicate property value on class change.

12 files changed:
docs/debugging
docs/userguide
include/config.h
include/config_directives.h
parser-specs/config.spec
src/config.c
src/config_directives.c
src/main.c
src/randr.c
src/workspace.c
testcases/t/201-config-parser.t
testcases/t/244-new-workspace-floating-enable-center.t [new file with mode: 0644]

index 639dbdfe979d67d4469b17885c6c0fa9faec6813..cf61813d4789b52c1c4791f4b28f92698c73e4b2 100644 (file)
@@ -67,6 +67,30 @@ fly:
 i3-msg 'debuglog on; shmlog on; reload'
 ---------------------------------------
 
+== Reproducing the problem
+
+Before submitting an issue, please make sure to close down on the problem as
+much as you can yourself. Here are some steps you should consider:
+
+* Find a deterministic, reliable way to reproduce the problem and provide it
+  with your bug report.
+* Try using the default i3 config to reproduce the problem. If the issue does
+  not appear with the default config, gradually adapt it to track down what 
+  change(s) to the config introduce the problem.
+* Reproduce the problem with a minimal setup, i.e., only use as few applications,
+  windows and steps as necessary.
+* In addition, try to stick to applications that are common and, even more
+  importantly, free / open source.
+* Before obtaining the log file, restart i3 in-place, execute the steps to
+  reproduce the problem and then save the logs. This keeps the log file as
+  small as possible and necessary.
+
+Please be aware that we cannot support compatibility issues with closed-source
+software, as digging into compatibility problems without having access to the
+source code is too time-consuming. Additionally, experience has shown that
+often, the software in question is responsible for the issue. Please raise an
+issue with the software in question, not i3.
+
 == Obtaining the debug logfile
 
 Please note that log files may contain sensitive data such as window titles.
index 301d8c811d5976a1d5d0a1e6f153c6b972d115c7..6975c943161b2c3fb712b11d2d78126210f5bd5e 100644 (file)
@@ -725,8 +725,8 @@ also when restarting i3 you should use the +exec_always+
 keyword. These commands will be run in order.
 
 See <<command_chaining>> for details on the special meaning of +;+ (semicolon)
-and +,+ (comma): they chain commands together in i3 and need to be escaped if
-you want to use them in your command.
+and +,+ (comma): they chain commands together in i3, so you need to use quoted
+strings if they appear in your command.
 
 *Syntax*:
 -------------------
@@ -1010,6 +1010,31 @@ force_display_urgency_hint <timeout> ms
 force_display_urgency_hint 500 ms
 ---------------------------------
 
+=== Delaying exiting on zero displays
+
+Outputs may disappear momentarily and come back later. For example,
+using a docking station that does not announce the undock (e.g. ACPI Undock 
+event triggered through manually pushing a button before actually ejecting 
+the notebook). During the removal of the notebook from the docking station,
+all outputs disappear momentarily.
+
+To prevent i3 from exiting when no output is available momentarily, you can 
+tell i3 to delay a certain time first and check available outputs again using 
+the +delay_exit_on_zero_displays+ directive. Setting the value to 0 disables 
+this feature.
+
+The default is 500ms.
+
+*Syntax*:
+----------------------------------------
+delay_exit_on_zero_displays <timeout> ms
+----------------------------------------
+
+*Example*:
+----------------------------------
+delay_exit_on_zero_displays 500 ms
+----------------------------------
+
 === Focus on window activation
 
 [[focus_on_window_activation]]
@@ -1549,8 +1574,8 @@ shell. This implies that you can use globbing (wildcards) and programs will be
 searched in your +$PATH+.
 
 See <<command_chaining>> for details on the special meaning of +;+ (semicolon)
-and +,+ (comma): they chain commands together in i3 and need to be escaped if
-you want to use them in your command.
+and +,+ (comma): they chain commands together in i3, so you need to use quoted
+strings if they appear in your command.
 
 *Syntax*:
 ------------------------------
index 4cc58a459c18f2a89b366be1d82f12df357f0423..75e0b127f96e084b9e566dad84b1db7e9ed0a3c7 100644 (file)
@@ -167,6 +167,10 @@ struct Config {
      * flag can be delayed using an urgency timer. */
     float workspace_urgency_timer;
 
+    /** Use a timer to delay exiting when no output is available.
+      * This can prevent i3 from exiting when all outputs disappear momentarily. */
+    float zero_disp_exit_timer_ms;
+
     /** Behavior when a window sends a NET_ACTIVE_WINDOW message. */
     enum {
         /* Focus if the target workspace is visible, set urgency hint otherwise. */
index 019b9bcdedfc9795523b4fcf1eb53d236636c316..1a7a39329e06c765e1de8ae3b637f36e94f64201 100644 (file)
@@ -51,6 +51,7 @@ CFGFUN(force_focus_wrapping, const char *value);
 CFGFUN(force_xinerama, const char *value);
 CFGFUN(fake_outputs, const char *outputs);
 CFGFUN(force_display_urgency_hint, const long duration_ms);
+CFGFUN(delay_exit_on_zero_displays, const long duration_ms);
 CFGFUN(focus_on_window_activation, const char *mode);
 CFGFUN(show_marks, const char *value);
 CFGFUN(hide_edge_borders, const char *borders);
index 422efe485947c23fb30d20598fe8a1a53de80467..986086c7d27d90e06644d0d34610cc2f52ed0c58 100644 (file)
@@ -39,6 +39,7 @@ state INITIAL:
   'workspace_auto_back_and_forth'          -> WORKSPACE_BACK_AND_FORTH
   'fake_outputs', 'fake-outputs'           -> FAKE_OUTPUTS
   'force_display_urgency_hint'             -> FORCE_DISPLAY_URGENCY_HINT
+  'delay_exit_on_zero_displays'            -> DELAY_EXIT_ON_ZERO_DISPLAYS
   'focus_on_window_activation'             -> FOCUS_ON_WINDOW_ACTIVATION
   'show_marks'                             -> SHOW_MARKS
   'workspace'                              -> WORKSPACE
@@ -228,6 +229,17 @@ state FORCE_DISPLAY_URGENCY_HINT_MS:
   end
       -> call cfg_force_display_urgency_hint(&duration_ms)
 
+# delay_exit_on_zero_displays <delay> ms
+state DELAY_EXIT_ON_ZERO_DISPLAYS:
+  duration_ms = number
+      -> DELAY_EXIT_ON_ZERO_DISPLAYS_MS
+
+state DELAY_EXIT_ON_ZERO_DISPLAYS_MS:
+  'ms'
+      ->
+  end
+      -> call cfg_delay_exit_on_zero_displays(&duration_ms)
+
 # focus_on_window_activation <smart|urgent|focus|none>
 state FOCUS_ON_WINDOW_ACTIVATION:
   mode = word
index 6eb67a121fe6f377469674ed0db3ed58340fbf40..bac9d7f369b168c6f9ed345d66c7c1281b606140 100644 (file)
@@ -203,6 +203,10 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
     if (config.workspace_urgency_timer == 0)
         config.workspace_urgency_timer = 0.5;
 
+    /* Set default zero displays exit delay to 500ms */
+    if (config.zero_disp_exit_timer_ms == 0)
+        config.zero_disp_exit_timer_ms = 500;
+
     parse_configuration(override_configpath, true);
 
     if (reload) {
index ff1c280e4f6d7fac4adb51c70510b6d5722694a8..ae78e0c0e87b255ad7e3c3a1ac63c24f27dc43f4 100644 (file)
@@ -354,6 +354,10 @@ CFGFUN(force_display_urgency_hint, const long duration_ms) {
     config.workspace_urgency_timer = duration_ms / 1000.0;
 }
 
+CFGFUN(delay_exit_on_zero_displays, const long duration_ms) {
+    config.zero_disp_exit_timer_ms = duration_ms;
+}
+
 CFGFUN(focus_on_window_activation, const char *mode) {
     if (strcmp(mode, "smart") == 0)
         config.focus_on_window_activation = FOWA_SMART;
index 86e40831902eef2051eb940d7fdd8b33cb91f01e..e8e0daa8c84a4bbfa783ef5afb8f691cda19de5e 100644 (file)
@@ -621,6 +621,8 @@ int main(int argc, char *argv[]) {
             ELOG("ERROR: No screen at (%d, %d), starting on the first screen\n",
                  pointerreply->root_x, pointerreply->root_y);
             output = get_first_output();
+            if (!output)
+                die("No usable outputs available.\n");
         }
 
         con_focus(con_descend_focused(output_get_content(output->con)));
index 9e236dcb517e8bab4214dba72821f4d5a3e10a12..1bd9993164d946b455db95ba3a5b0fd31f2ef503 100644 (file)
@@ -69,7 +69,7 @@ Output *get_first_output(void) {
     if (output->active)
         return output;
 
-    die("No usable outputs available.\n");
+    return NULL;
 }
 
 /*
@@ -570,6 +570,8 @@ static void handle_output(xcb_connection_t *conn, xcb_randr_output_t id,
     if (!new->active) {
         DLOG("width/height 0/0, disabling output\n");
         return;
+    } else {
+        new->to_be_disabled = false;
     }
 
     DLOG("mode: %dx%d+%d+%d\n", new->rect.width, new->rect.height,
@@ -591,11 +593,7 @@ static void handle_output(xcb_connection_t *conn, xcb_randr_output_t id,
     new->changed = true;
 }
 
-/*
- * (Re-)queries the outputs via RandR and stores them in the list of outputs.
- *
- */
-void randr_query_outputs(void) {
+static bool __randr_query_outputs(void) {
     Output *output, *other, *first;
     xcb_randr_get_output_primary_cookie_t pcookie;
     xcb_randr_get_screen_resources_current_cookie_t rcookie;
@@ -609,7 +607,7 @@ void randr_query_outputs(void) {
     xcb_randr_output_t *randr_outputs;
 
     if (randr_disabled)
-        return;
+        return true;
 
     /* Get screen resources (primary output, crtcs, outputs, modes) */
     rcookie = xcb_randr_get_screen_resources_current(conn, root);
@@ -621,7 +619,7 @@ void randr_query_outputs(void) {
         DLOG("primary output is %08x\n", primary->output);
     if ((res = xcb_randr_get_screen_resources_current_reply(conn, rcookie, NULL)) == NULL) {
         disable_randr(conn);
-        return;
+        return true;
     }
     cts = res->config_timestamp;
 
@@ -703,6 +701,11 @@ void randr_query_outputs(void) {
             DLOG("Output %s disabled, re-assigning workspaces/docks\n", output->name);
 
             first = get_first_output();
+            if (!first) {
+                FREE(res);
+                FREE(primary);
+                return false;
+            }
 
             /* TODO: refactor the following code into a nice function. maybe
              * use an on_destroy callback which is implement differently for
@@ -818,6 +821,32 @@ void randr_query_outputs(void) {
 
     FREE(res);
     FREE(primary);
+
+    return true;
+}
+
+/*
+ * (Re-)queries the outputs via RandR and stores them in the list of outputs.
+ *
+ */
+void randr_query_outputs(void) {
+    static bool first_query = true;
+
+    if (first_query) {
+        /* find monitors at least once via RandR */
+        if (!__randr_query_outputs())
+            die("No usable outputs available.\n");
+        first_query = false;
+    } else {
+        /* requery */
+        if (!__randr_query_outputs()) {
+            DLOG("sleep %f ms due to zero displays\n", config.zero_disp_exit_timer_ms);
+            usleep(config.zero_disp_exit_timer_ms * 1000);
+
+            if (!__randr_query_outputs())
+                die("No usable outputs available.\n");
+        }
+    }
 }
 
 /*
index 9034f6d5957cd643da1809a8beba50835df26f7a..c7f1a1bbc0605a30257a72c4bf41511b737b6b46 100644 (file)
@@ -29,6 +29,7 @@ static void _workspace_apply_default_orientation(Con *ws) {
     if (config.default_orientation == NO_ORIENTATION) {
         Con *output = con_get_output(ws);
         ws->layout = (output->rect.height > output->rect.width) ? L_SPLITV : L_SPLITH;
+        ws->rect = output->rect;
         DLOG("Auto orientation. Workspace size set to (%d,%d), setting layout to %d.\n",
              output->rect.width, output->rect.height, ws->layout);
     } else {
index 7568de48394e4ba4c09edcce2af289fca191ee32..de25e7ff70f52c3e6b02e763fba2e4fb71d58c86 100644 (file)
@@ -369,6 +369,40 @@ is(parser_calls($config),
    $expected,
    'force_display_urgency_hint ok');
 
+################################################################################
+# delay_exit_on_zero_displays
+################################################################################
+
+is(parser_calls('delay_exit_on_zero_displays 300'),
+   "cfg_delay_exit_on_zero_displays(300)\n",
+   'delay_exit_on_zero_displays ok');
+
+is(parser_calls('delay_exit_on_zero_displays 500 ms'),
+   "cfg_delay_exit_on_zero_displays(500)\n",
+   'delay_exit_on_zero_displays ok');
+
+is(parser_calls('delay_exit_on_zero_displays 700ms'),
+   "cfg_delay_exit_on_zero_displays(700)\n",
+   'delay_exit_on_zero_displays ok');
+
+$config = <<'EOT';
+delay_exit_on_zero_displays 300
+delay_exit_on_zero_displays 500 ms
+delay_exit_on_zero_displays 700ms
+delay_exit_on_zero_displays 700
+EOT
+
+$expected = <<'EOT';
+cfg_delay_exit_on_zero_displays(300)
+cfg_delay_exit_on_zero_displays(500)
+cfg_delay_exit_on_zero_displays(700)
+cfg_delay_exit_on_zero_displays(700)
+EOT
+
+is(parser_calls($config),
+   $expected,
+   'delay_exit_on_zero_displays ok');
+
 ################################################################################
 # workspace
 ################################################################################
@@ -441,7 +475,7 @@ client.focused          #4c7899 #285577 #ffffff #2e9ef4
 EOT
 
 my $expected_all_tokens = <<'EOT';
-ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'bindsym', 'bindcode', 'bind', 'bar', 'font', 'mode', 'floating_minimum_size', 'floating_maximum_size', 'floating_modifier', 'default_orientation', 'workspace_layout', 'new_window', 'new_float', 'hide_edge_borders', 'for_window', 'assign', 'no_focus', 'focus_follows_mouse', 'mouse_warping', 'force_focus_wrapping', 'force_xinerama', 'force-xinerama', 'workspace_auto_back_and_forth', 'fake_outputs', 'fake-outputs', 'force_display_urgency_hint', 'focus_on_window_activation', 'show_marks', 'workspace', 'ipc_socket', 'ipc-socket', 'restart_state', 'popup_during_fullscreen', 'exec_always', 'exec', 'client.background', 'client.focused_inactive', 'client.focused', 'client.unfocused', 'client.urgent', 'client.placeholder'
+ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'bindsym', 'bindcode', 'bind', 'bar', 'font', 'mode', 'floating_minimum_size', 'floating_maximum_size', 'floating_modifier', 'default_orientation', 'workspace_layout', 'new_window', 'new_float', 'hide_edge_borders', 'for_window', 'assign', 'no_focus', 'focus_follows_mouse', 'mouse_warping', 'force_focus_wrapping', 'force_xinerama', 'force-xinerama', 'workspace_auto_back_and_forth', 'fake_outputs', 'fake-outputs', 'force_display_urgency_hint', 'delay_exit_on_zero_displays', 'focus_on_window_activation', 'show_marks', 'workspace', 'ipc_socket', 'ipc-socket', 'restart_state', 'popup_during_fullscreen', 'exec_always', 'exec', 'client.background', 'client.focused_inactive', 'client.focused', 'client.unfocused', 'client.urgent', 'client.placeholder'
 EOT
 
 my $expected_end = <<'EOT';
diff --git a/testcases/t/244-new-workspace-floating-enable-center.t b/testcases/t/244-new-workspace-floating-enable-center.t
new file mode 100644 (file)
index 0000000..dbc9a80
--- /dev/null
@@ -0,0 +1,53 @@
+#!perl
+# vim:ts=4:sw=4:expandtab
+#
+# Please read the following documents before working on tests:
+# • http://build.i3wm.org/docs/testsuite.html
+#   (or docs/testsuite)
+#
+# • http://build.i3wm.org/docs/lib-i3test.html
+#   (alternatively: perldoc ./testcases/lib/i3test.pm)
+#
+# • http://build.i3wm.org/docs/ipc.html
+#   (or docs/ipc)
+#
+# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+#   (unless you are already familiar with Perl)
+#
+# Ensures that 'move workspace $new, floating enable' on a marked window
+# leaves the window centered on the new workspace.
+# Bug still in: 4.10.2-137-ga4f0ed6
+use i3test i3_autostart => 0;
+
+my $config = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+
+new_window none
+new_float none
+EOT
+
+my $pid = launch_with_config($config);
+
+#####################################################################
+# Open a tiled window, and then simultaneously move it to another
+# workspace and float it, ensuring that it ends up centered.
+#####################################################################
+
+my $window = open_window;
+my $unused = get_unused_workspace();
+
+cmd "mark foo; [con_mark=\"foo\"] move workspace $unused, floating enable";
+
+sync_with_i3;
+
+my $pos = $window->rect;
+
+is(int($pos->{x} + $pos->{width} / 2), int($x->root->rect->width / 2),
+    'x coordinates match');
+is(int($pos->{y} + $pos->{height} / 2), int($x->root->rect->height / 2),
+    'y coordinates match');
+
+exit_gracefully($pid);
+
+done_testing;