--- a/plugins/cube/cube.cpp +++ b/plugins/cube/cube.cpp @@ -512,12 +512,6 @@ } } - int selected_overview_row() - { - return std::clamp(int(std::floor(float(overview_row) + 0.5f)), 0, - output->wset()->get_workspace_grid_size().height - 1); - } - void end_mouse_overview() { if (mouse_overview_active) @@ -1042,7 +1036,7 @@ int dvx = calculate_viewport_dx_from_rotation(); auto cws = output->wset()->get_current_workspace(); int nvx = (cws.x + (dvx % size) + size) % size; - int nvy = mouse_overview_active ? selected_overview_row() : cws.y; + int nvy = cws.y; output->wset()->set_workspace({nvx, nvy}); } @@ -1199,7 +1193,7 @@ int dvx = calculate_viewport_dx_from_rotation(); auto cws = output->wset()->get_current_workspace(); int nvx = (cws.x + (dvx % size) + size) % size; - int nvy = mouse_overview_active ? selected_overview_row() : cws.y; + int nvy = cws.y; output->wset()->set_workspace({nvx, nvy}); wf::get_core().seat->focus_output(output); @@ -1297,13 +1291,16 @@ float fit = 0.8f / std::max(1.0f, extent); float scale = 1 + float(overview_mix) * (fit - 1); auto frame = glm::scale(glm::mat4(1.0), glm::vec3(scale, scale, 1)); - return output_transform(dest) * frame * row_translation * animation.projection * animation.view * scale_matrix; + // Overview rows share one camera and horizontal axis. Their + // spacing belongs to the model, before perspective projection, + // so adjoining faces meet along the same edge while rotating. + return output_transform(dest) * frame * animation.projection * animation.view * scale_matrix; } return output_transform(dest) * row_translation * animation.projection * animation.view * scale_matrix; } /* Calculate the base model matrix for the i-th side of the cube */ - glm::mat4 calculate_model_matrix(int i) + glm::mat4 calculate_model_matrix(int i, float row_offset = 0.0f) { const float angle = i * animation.side_angle + animation.cube_animation.rotation; @@ -1320,7 +1317,7 @@ } auto translation = glm::translate(glm::mat4(1.0), - glm::vec3(0, 0, identity_z_offset + additional_z)); + glm::vec3(0, row_offset, identity_z_offset + additional_z)); return rotation * translation; } @@ -1337,8 +1334,8 @@ const int rows = (vertical_transition || mouse_overview_active) ? (int)buffers.size() / faces : 1; for (int row = 0; row < rows; row++) { - // Move every face of a row together without changing its yaw, - // orientation, or perspective, including through the final frame. + // Mouse overview stacks faces in the shared model space. + // Keyboard row slides retain their projected viewport offsets. const float offset = mouse_overview_active ? row - float(overview_row) : vertical_transition ? row - cws.y + float(row_translation) : 0.0f; program.uniformMatrix4f("VP", calculate_vp_matrix(target, offset)); @@ -1346,7 +1343,8 @@ { int index = row * faces + (cws.x + i) % faces; GL_CALL(glBindTexture(GL_TEXTURE_2D, wf::gles_texture_t::from_aux(buffers[index]).tex_id)); - program.uniformMatrix4f("model", calculate_model_matrix(i)); + program.uniformMatrix4f("model", calculate_model_matrix(i, + mouse_overview_active ? offset : 0.0f)); if (tessellation_support) { @@ -1491,13 +1489,18 @@ double xdiff = ev->delta_x; double ydiff = ev->delta_y * -1.0; + // The overview stays level and on its current workspace row. Pure + // vertical motion must not restart animations or wake a settled cube. + if (mouse_overview_active && (xdiff == 0)) + { + return; + } + animation.cube_animation.zoom.restart_with_end( animation.cube_animation.zoom.end); if (mouse_overview_active) { - float last = output->wset()->get_workspace_grid_size().height - 1; - overview_row.restart_with_end(std::clamp(float(overview_row.end + ydiff * YVelocity), 0.0f, last)); overview_mix.restart_with_end(1); animation.cube_animation.offset_y.set(0, 0); } else --- a/metadata/cube.xml +++ b/metadata/cube.xml @@ -69,7 +69,7 @@ <_short>Mouse overview