policy: add a simple policy stub, broke some layouting tho
[staging/windowmanager.git] / src / app.cpp
index b290248..246b629 100644 (file)
@@ -83,7 +83,8 @@ App::App(wl::display *d)
      layouts(),
      layers(),
      id_alloc{},
-     pending_events(false) {
+     pending_events(false),
+     policy{} {
    assert(g_app == nullptr);
    g_app = this;
 
@@ -305,7 +306,9 @@ void App::surface_set_layout(int surface_id, optional<int> sub_surface_id) {
 
    if (sub_surface_id) {
       if (o_layer_id != this->layers.get_layer_id(*sub_surface_id)) {
-         logerror("surface_set_layout: layers of surfaces (%d and %d) don't match!", surface_id, *sub_surface_id);
+         logerror(
+            "surface_set_layout: layers of surfaces (%d and %d) don't match!",
+            surface_id, *sub_surface_id);
          return;
       }
 
@@ -323,8 +326,8 @@ void App::surface_set_layout(int surface_id, optional<int> sub_surface_id) {
 
       auto &ss = this->controller->surfaces[*sub_surface_id];
 
-      logdebug("surface_set_layout for sub surface %u on layer %u", *sub_surface_id,
-               layer_id);
+      logdebug("surface_set_layout for sub surface %u on layer %u",
+               *sub_surface_id, layer_id);
 
       // configure surface to wxh dimensions
       ss->set_configuration(w, h);
@@ -401,8 +404,6 @@ char const *App::api_activate_surface(char const *drawing_name) {
          flush = true;
       }
 
-      l.state.s = LayoutState::Single;
-
       if (flush) {
          this->layout_commit();
       }
@@ -417,45 +418,51 @@ char const *App::api_activate_surface(char const *drawing_name) {
    // XXX: input focus missing!!1
 
    if (state.main == -1) {
-      this->surface_set_layout(*surface_id);
-      this->activate(*surface_id);  // XXX do we need to activate after enddraw?
-      state.main = *surface_id;
-      state.sub = -1;
-      state.s = LayoutState::Single;
-
-      this->layout_commit();
-      this->emit_syncdraw(drawing_name);
-      this->enqueue_flushdraw(state.main);
+      this->try_layout(
+         state, LayoutState{*surface_id}, [&] (LayoutState const &nl) {
+            this->surface_set_layout(*surface_id);
+            // XXX do we need to activate after enddraw?
+            this->activate(*surface_id);
+            state = nl;
+            this->layout_commit();
+            this->emit_syncdraw(drawing_name);
+            this->enqueue_flushdraw(state.main);
+         });
    } else {
       bool can_split = this->can_split(state, *surface_id);
 
       if (state.sub == -1) {
          if (can_split) {
-            if (state.main != *surface_id) {
-               std::string main = std::move(*this->lookup_name(state.main));
-
-               this->surface_set_layout(state.main, surface_id);
-               this->activate(*surface_id);
-               state.sub = *surface_id;
-
-               this->layout_commit();
-               this->emit_syncdraw(drawing_name);
-               this->emit_syncdraw(main.c_str());
-               this->enqueue_flushdraw(state.main);
-               this->enqueue_flushdraw(state.sub);
-            }
+            this->try_layout(
+               state,
+               LayoutState{state.main, *surface_id},
+               [&] (LayoutState const &nl) {
+                  std::string main =
+                     std::move(*this->lookup_name(state.main));
+
+                  this->surface_set_layout(state.main, surface_id);
+                  this->activate(*surface_id);
+                  state = nl;
+
+                  this->layout_commit();
+                  this->emit_syncdraw(drawing_name);
+                  this->emit_syncdraw(main.c_str());
+                  this->enqueue_flushdraw(state.main);
+                  this->enqueue_flushdraw(state.sub);
+               });
          } else {
-            this->surface_set_layout(*surface_id);
-            this->deactivate(state.main);
-            this->activate(*surface_id);
-            this->deactivate(state.sub);
-            state.main = *surface_id;
-            state.sub = -1;
-            state.s = LayoutState::Single;
-
-            this->layout_commit();
-            this->emit_syncdraw(drawing_name);
-            this->enqueue_flushdraw(state.main);
+            this->try_layout(
+               state, LayoutState{*surface_id}, [&] (LayoutState const &nl) {
+                  this->surface_set_layout(*surface_id);
+                  this->deactivate(state.main);
+                  this->activate(*surface_id);
+                  this->deactivate(state.sub);
+                  state = nl;
+
+                  this->layout_commit();
+                  this->emit_syncdraw(drawing_name);
+                  this->enqueue_flushdraw(state.main);
+               });
          }
       }
    }
@@ -488,7 +495,8 @@ char const *App::api_deactivate_surface(char const *drawing_name) {
       return "No surface active";
    }
 
-   // XXX: check against main_surface, main_surface_name is the configuration item.
+   // XXX: check against main_surface, main_surface_name is the configuration
+   // item.
    if (*surface_id == this->layers.main_surface) {
       logdebug("Refusing to deactivate main_surface %d", *surface_id);
       return nullptr;
@@ -496,33 +504,37 @@ char const *App::api_deactivate_surface(char const *drawing_name) {
 
    if (state.main == *surface_id) {
       if (state.sub != -1) {
-         std::string sub = std::move(*this->lookup_name(state.sub));
+         this->try_layout(
+            state, LayoutState{state.sub, -1}, [&] (LayoutState const &nl) {
+               std::string sub = std::move(*this->lookup_name(state.sub));
 
-         this->deactivate(*surface_id);
-         this->surface_set_layout(state.sub);
-         state.main = state.sub;
-         state.sub = -1;
-         state.s = LayoutState::Single;
+               this->deactivate(*surface_id);
+               this->surface_set_layout(state.sub);
+               state = nl;
 
-         this->layout_commit();
-         this->emit_syncdraw(sub.c_str());
-         this->enqueue_flushdraw(state.sub);
+               this->layout_commit();
+               this->emit_syncdraw(sub.c_str());
+               this->enqueue_flushdraw(state.sub);
+            });
       } else {
-         this->deactivate(*surface_id);
-         state.main = -1;
+         this->try_layout(state, LayoutState{-1, -1}, [&] (LayoutState const &nl) {
+            this->deactivate(*surface_id);
+            state = nl;
+         });
       }
    } else if (state.sub == *surface_id) {
-      std::string main = std::move(*this->lookup_name(state.main));
+      this->try_layout(
+         state, LayoutState{state.main, -1}, [&] (LayoutState const &nl) {
+            std::string main = std::move(*this->lookup_name(state.main));
 
-      this->deactivate(*surface_id);
-      this->deactivate(*surface_id);
-      this->surface_set_layout(state.main);
-      state.sub = -1;
-      state.s = LayoutState::Single;
+            this->deactivate(*surface_id);
+            this->surface_set_layout(state.main);
+            state = nl;
 
-      this->layout_commit();
-      this->emit_syncdraw(main.c_str());
-      this->enqueue_flushdraw(state.main);
+            this->layout_commit();
+            this->emit_syncdraw(main.c_str());
+            this->enqueue_flushdraw(state.main);
+         });
    } else {
       return "Surface is not active";
    }
@@ -544,7 +556,7 @@ void App::check_flushdraw(int surface_id) {
       logerror("Application %s (%d) has pending EndDraw call(s)!",
                n ? n->c_str() : "unknown-name", surface_id);
       std::swap(this->pending_end_draw[std::distance(
-         std::begin(this->pending_end_draw), i)],
+                   std::begin(this->pending_end_draw), i)],
                 this->pending_end_draw.back());
       this->pending_end_draw.resize(this->pending_end_draw.size() - 1);
    }
@@ -564,14 +576,7 @@ char const *App::api_enddraw(char const *drawing_name) {
    return "No EndDraw pending for surface";
 }
 
-void App::api_ping() {
-   this->dispatch_pending_events();
-}
-
-void App::deactivate_main_surface() {
-   this->layers.main_surface = -1;
-   this->api_deactivate_surface(this->layers.main_surface_name.c_str());
-}
+void App::api_ping() { this->dispatch_pending_events(); }
 
 //                      _          _   _____                 _
 //  _ __  _ __ _____  _(_) ___  __| | | ____|_   _____ _ __ | |_ ___
@@ -693,6 +698,11 @@ void App::deactivate(int id) {
    }
 }
 
+void App::deactivate_main_surface() {
+   this->layers.main_surface = -1;
+   this->api_deactivate_surface(this->layers.main_surface_name.c_str());
+}
+
 bool App::can_split(struct LayoutState const &state, int new_id) {
    if (state.main != -1 && state.main != new_id) {
       auto new_id_layer = this->layers.get_layer_id(new_id).value();
@@ -732,6 +742,14 @@ bool App::can_split(struct LayoutState const &state, int new_id) {
    return false;
 }
 
+void App::try_layout(struct LayoutState &state,
+                     struct LayoutState const &new_layout,
+                     std::function<void(LayoutState const &nl)> apply) {
+   if (this->policy.layout_is_valid(new_layout)) {
+      apply(new_layout);
+   }
+}
+
 //                  _             _ _            _                 _
 //   ___ ___  _ __ | |_ _ __ ___ | | | ___ _ __ | |__   ___   ___ | | _____
 //  / __/ _ \| '_ \| __| '__/ _ \| | |/ _ \ '__|| '_ \ / _ \ / _ \| |/ / __|