SimulaVR / Simula

Linux VR Desktop
MIT License
2.91k stars 87 forks source link

Simula treats Chrome popups as new windows #91

Closed georgewsinger closed 4 years ago

georgewsinger commented 4 years ago

Video of the bug. The bug is demonstrated in the following video:

https://www.youtube.com/watch?v=mIDMb_fDuxw

The video first shows Firefox subsurfaces working properly, and then follows it with a demonstration of the chrome bug.

How our code is failing. Every time a new surface xwayland surface is mapped, the handle_map gdwlroots function is fired:

void WlrXWaylandSurface::handle_map(
    struct wl_listener *listener, void *data) {
  WlrXWaylandSurface *xwayland_surface = wl_container_of(
      listener, xwayland_surface, map);

  // Attempt to only map parent surfaces
  if( xwayland_surface->wlr_xwayland_surface->parent == NULL ) {
    xwayland_surface->emit_signal("map", xwayland_surface);}
}

Notice that we don't emit the Godot "map" signal unless xwayland_surface->wlr_xwayland_surface->parent == NULL. Apparently, this test isn't sufficient for chrome popups: every chrome popup has wlr_xwayland_surface->parent == NULL, and so Simula thinks they should spawn their own \~GodotSimulaViewSprite\~s.

On the other hand, when we draw subsurfaces onto the parent chrome window, the popups aren't drawn either. That is, the chrome popups aren't retrieved by WlrXWaylandSurface::get_children() function:

//Doesn't retrieve chrome popups
Array WlrXWaylandSurface::get_children() {
  Array array_xwayland_surfaces;
  struct wlr_xwayland_surface * xws;

  wl_list_for_each(xws, &wlr_xwayland_surface->children, parent_link) {
    WlrXWaylandSurface * xWS;
    xWS = new WlrXWaylandSurface(xws);
    Variant _xws = Variant( (Object *) xWS );
    array_xwayland_surfaces.push_front(_xws);
  }
  return array_xwayland_surfaces;
}

So they don't draw properly onto chrome.

georgewsinger commented 4 years ago

GDB Experiments

Inspecting the wlr_xwayland_surface of a popup (firefox vs. chrome). In the experiments below, we put a gdb breakpoint on handle_map and inspect the contents of its wlr_xwayland_surface. The first surface in each experiment is the parent browser. The second surface is the popup (in Chrome the popup causes two surfaces to be mapped, for a total of three surfaces).

Experiment 1: launch google-chrome, and then right-click.

Thread 1 "godot" hit Breakpoint 1, WlrXWaylandSurface::print_xwayland_surface_properties (this=0x6f18d50) at modules/gdwlroots/wlr_xwayland.cpp:319
319 }
$1 = {
  window_id = 6291457, 
  xwm = 0x6f20e00, 
  surface_id = 0, 
  link = {
    prev = 0x6f07ae8, 
    next = 0x6f112b8
  }, 
  unpaired_link = {
    prev = 0x0, 
    next = 0x0
  }, 
  surface = 0x6f2f5d0, 
  x = 70, 
  y = 27, 
  width = 508, 
  height = 101, 
  saved_width = 0, 
  saved_height = 0, 
  override_redirect = false, 
  mapped = false, 
  title = 0x6f129b0 "New Tab - Google Chrome", 
  c_class = 0x6f1cc20 "Google-chrome", 
  instance = 0x6f1d040 "google-chrome", 
  role = 0x0, 
  pid = 31495, 
  has_utf8_title = true, 
  children = {
    prev = 0x6f18b78, 
    next = 0x6f18b78
  }, 
  parent = 0x0, 
  parent_link = {
    prev = 0x6f18b90, 
    next = 0x6f18b90
  }, 
  window_type = 0x6f126e0, 
  window_type_len = 1, 
  protocols = 0x6f12680, 
  protocols_len = 2, 
  decorations = 3, 
  hints = 0x0, 
  hints_urgency = 0, 
  size_hints = 0x6f2f970, 
  pinging = true, 
  ping_timer = 0x6f01e40, 
  modal = false, 
  fullscreen = false, 
  maximized_vert = true, 
  maximized_horz = true, 
  has_alpha = false, 
  events = {
    destroy = {
      listener_list = {
        prev = 0x6f18f98, 
        next = 0x6f18f98
      }
    }, 
    request_configure = {
      listener_list = {
        prev = 0x6f18fe0, 
        next = 0x6f18fe0
      }
    }, 
    request_move = {
      listener_list = {
        prev = 0x6f18f20, 
        next = 0x6f18f20
      }
    }, 
    request_resize = {
      listener_list = {
        prev = 0x6f18f38, 
        next = 0x6f18f38
      }
    }, 
    request_maximize = {
      listener_list = {
        prev = 0x6f18ed8, 
        next = 0x6f18ed8
      }
    }, 
    request_fullscreen = {
      listener_list = {
        prev = 0x6f18ef0, 
        next = 0x6f18ef0
      }
    }, 
    request_activate = {
      listener_list = {
        prev = 0x6f18c58, 
        next = 0x6f18c58
      }
    }, 
    map = {
      listener_list = {
        prev = 0x7fffffffd0e0, 
        next = 0x6f18fb0
      }
    }, 
    unmap = {
      listener_list = {
        prev = 0x6f18fc8, 
        next = 0x6f18fc8
      }
    }, 
    set_title = {
      listener_list = {
        prev = 0x6f18c88, 
        next = 0x6f18c88
      }
    }, 
    set_class = {
      listener_list = {
        prev = 0x6f18c98, 
        next = 0x6f18c98
      }
    }, 
    set_role = {
      listener_list = {
        prev = 0x6f18ca8, 
        next = 0x6f18ca8
      }
    }, 
    set_parent = {
      listener_list = {
        prev = 0x6f18cb8, 
        next = 0x6f18cb8
      }
    }, 
    set_pid = {
      listener_list = {
        prev = 0x6f18cc8, 
        next = 0x6f18cc8
      }
    }, 
    set_window_type = {
      listener_list = {
        prev = 0x6f18cd8, 
        next = 0x6f18cd8
      }
    }, 
    set_hints = {
      listener_list = {
        prev = 0x6f18ce8, 
        next = 0x6f18ce8
      }
    }, 
    set_decorations = {
      listener_list = {
        prev = 0x6f18cf8, 
        next = 0x6f18cf8
      }
    }, 
    set_override_redirect = {
      listener_list = {
        prev = 0x6f18d08, 
        next = 0x6f18d08
      }
    }, 
    ping_timeout = {
      listener_list = {
        prev = 0x6f18d18, 
        next = 0x6f18d18
      }
    }
  }, 
  surface_destroy = {
    link = {
      prev = 0x6f2f890, 
      next = 0x6f2f890
    }, 
    notify = 0x7ffff744bec5 <handle_surface_destroy>
  }, 
  data = 0x6f18d50
}

Thread 1 "godot" hit Breakpoint 1, WlrXWaylandSurface::print_xwayland_surface_properties (this=0xf173d60) at modules/gdwlroots/wlr_xwayland.cpp:319
319 }
$2 = {
  window_id = 6291466, 
  xwm = 0x6f20e00, 
  surface_id = 0, 
  link = {
    prev = 0x6f21128, 
    next = 0x6f07ae8
  }, 
  unpaired_link = {
    prev = 0x0, 
    next = 0x0
  }, 
  surface = 0xf176850, 
  x = 308, 
  y = 62, 
  width = 48, 
  height = 26, 
  saved_width = 0, 
  saved_height = 0, 
  override_redirect = true, 
  mapped = false, 
  title = 0x0, 
  c_class = 0x0, 
  instance = 0x0, 
  role = 0x0, 
  pid = 31495, 
  has_utf8_title = false, 
  children = {
    prev = 0xf173b88, 
    next = 0xf173b88
  }, 
  parent = 0x0, 
  parent_link = {
    prev = 0xf173ba0, 
    next = 0xf173ba0
  }, 
  window_type = 0xf1587f0, 
  window_type_len = 1, 
  protocols = 0xf158030, 
  protocols_len = 2, 
  decorations = 3, 
  hints = 0x0, 
  hints_urgency = 0, 
  size_hints = 0xf176d80, 
  pinging = false, 
  ping_timer = 0xf16e4a0, 
  modal = false, 
  fullscreen = false, 
  maximized_vert = false, 
  maximized_horz = false, 
  has_alpha = false, 
  events = {
    destroy = {
      listener_list = {
        prev = 0xf173fa8, 
        next = 0xf173fa8
      }
    }, 
    request_configure = {
      listener_list = {
        prev = 0xf173ff0, 
        next = 0xf173ff0
      }
    }, 
    request_move = {
      listener_list = {
        prev = 0xf173f30, 
        next = 0xf173f30
      }
    }, 
    request_resize = {
      listener_list = {
        prev = 0xf173f48, 
        next = 0xf173f48
      }
    }, 
    request_maximize = {
      listener_list = {
        prev = 0xf173ee8, 
        next = 0xf173ee8
      }
    }, 
    request_fullscreen = {
      listener_list = {
        prev = 0xf173f00, 
        next = 0xf173f00
      }
    }, 
    request_activate = {
      listener_list = {
        prev = 0xf173c68, 
        next = 0xf173c68
      }
    }, 
    map = {
      listener_list = {
        prev = 0x7fffffffd0e0, 
        next = 0xf173fc0
      }
    }, 
    unmap = {
      listener_list = {
        prev = 0xf173fd8, 
        next = 0xf173fd8
      }
    }, 
    set_title = {
      listener_list = {
        prev = 0xf173c98, 
        next = 0xf173c98
      }
    }, 
    set_class = {
      listener_list = {
        prev = 0xf173ca8, 
        next = 0xf173ca8
      }
    }, 
    set_role = {
      listener_list = {
        prev = 0xf173cb8, 
        next = 0xf173cb8
      }
    }, 
    set_parent = {
      listener_list = {
        prev = 0xf173cc8, 
        next = 0xf173cc8
      }
    }, 
    set_pid = {
      listener_list = {
        prev = 0xf173cd8, 
        next = 0xf173cd8
      }
    }, 
    set_window_type = {
      listener_list = {
        prev = 0xf173ce8, 
        next = 0xf173ce8
      }
    }, 
    set_hints = {
      listener_list = {
        prev = 0xf173cf8, 
        next = 0xf173cf8
      }
    }, 
    set_decorations = {
      listener_list = {
        prev = 0xf173d08, 
        next = 0xf173d08
      }
    }, 
    set_override_redirect = {
      listener_list = {
        prev = 0xf173d18, 
        next = 0xf173d18
      }
    }, 
    ping_timeout = {
      listener_list = {
        prev = 0xf173d28, 
        next = 0xf173d28
      }
    }
  }, 
  surface_destroy = {
    link = {
      prev = 0xf176b10, 
      next = 0xf176b10
    }, 
    notify = 0x7ffff744bec5 <handle_surface_destroy>
  }, 
  data = 0xf173d60
}

Thread 1 "godot" hit Breakpoint 1, WlrXWaylandSurface::print_xwayland_surface_properties (this=0xf4f87a0) at modules/gdwlroots/wlr_xwayland.cpp:319
319 }
$3 = {
  window_id = 6291467, 
  xwm = 0x6f20e00, 
  surface_id = 0, 
  link = {
    prev = 0x6f21128, 
    next = 0xf173b28
  }, 
  unpaired_link = {
    prev = 0x0, 
    next = 0x0
  }, 
  surface = 0xf61a0b0, 
  x = 70, 
  y = 27, 
  width = 365, 
  height = 227, 
  saved_width = 0, 
  saved_height = 0, 
  override_redirect = true, 
  mapped = false, 
  title = 0x0, 
  c_class = 0x0, 
  instance = 0x0, 
  role = 0x0, 
  pid = 31495, 
  has_utf8_title = false, 
  children = {
    prev = 0xf60b978, 
    next = 0xf60b978
  }, 
  parent = 0x0, 
  parent_link = {
    prev = 0xf60b990, 
    next = 0xf60b990
  }, 
  window_type = 0xf177760, 
  window_type_len = 1, 
  protocols = 0xf15ad70, 
  protocols_len = 2, 
  decorations = 3, 
  hints = 0x0, 
  hints_urgency = 0, 
  size_hints = 0xf61a5e0, 
  pinging = false, 
  ping_timer = 0xf601c00, 
  modal = false, 
  fullscreen = false, 
  maximized_vert = false, 
  maximized_horz = false, 
  has_alpha = false, 
  events = {
    destroy = {
      listener_list = {
        prev = 0xf4f89e8, 
        next = 0xf4f89e8
      }
    }, 
    request_configure = {
      listener_list = {
        prev = 0xf4f8a30, 
        next = 0xf4f8a30
      }
    }, 
    request_move = {
      listener_list = {
        prev = 0xf4f8970, 
        next = 0xf4f8970
      }
    }, 
    request_resize = {
      listener_list = {
        prev = 0xf4f8988, 
        next = 0xf4f8988
      }
    }, 
    request_maximize = {
      listener_list = {
        prev = 0xf4f8928, 
        next = 0xf4f8928
      }
    }, 
    request_fullscreen = {
      listener_list = {
        prev = 0xf4f8940, 
        next = 0xf4f8940
      }
    }, 
    request_activate = {
      listener_list = {
        prev = 0xf60ba58, 
        next = 0xf60ba58
      }
    }, 
    map = {
      listener_list = {
        prev = 0x7fffffffd0e0, 
        next = 0xf4f8a00
      }
    }, 
    unmap = {
      listener_list = {
        prev = 0xf4f8a18, 
        next = 0xf4f8a18
      }
    }, 
    set_title = {
      listener_list = {
        prev = 0xf60ba88, 
        next = 0xf60ba88
      }
    }, 
    set_class = {
      listener_list = {
        prev = 0xf60ba98, 
        next = 0xf60ba98
      }
    }, 
    set_role = {
      listener_list = {
        prev = 0xf60baa8, 
        next = 0xf60baa8
      }
    }, 
    set_parent = {
      listener_list = {
        prev = 0xf60bab8, 
        next = 0xf60bab8
      }
    }, 
    set_pid = {
      listener_list = {
        prev = 0xf60bac8, 
        next = 0xf60bac8
      }
    }, 
    set_window_type = {
      listener_list = {
        prev = 0xf60bad8, 
        next = 0xf60bad8
      }
    }, 
    set_hints = {
      listener_list = {
        prev = 0xf60bae8, 
        next = 0xf60bae8
      }
    }, 
    set_decorations = {
      listener_list = {
        prev = 0xf60baf8, 
        next = 0xf60baf8
      }
    }, 
    set_override_redirect = {
      listener_list = {
        prev = 0xf60bb08, 
        next = 0xf60bb08
      }
    }, 
    ping_timeout = {
      listener_list = {
        prev = 0xf60bb18, 
        next = 0xf60bb18
      }
    }
  }, 
  surface_destroy = {
    link = {
      prev = 0xf61a370, 
      next = 0xf61a370
    }, 
    notify = 0x7ffff744bec5 <handle_surface_destroy>
  }, 
  data = 0xf4f87a0
}

Experiment 2: Firefox Right-Click.

Thread 1 "godot" hit Breakpoint 1, WlrXWaylandSurface::print_xwayland_surface_properties (this=0x6f0aab0) at modules/gdwlroots/wlr_xwayland.cpp:319
319 }
$1 = {
  window_id = 6291472, 
  xwm = 0x6f21c50, 
  surface_id = 0, 
  link = {
    prev = 0x6f0c808, 
    next = 0x6f05678
  }, 
  unpaired_link = {
    prev = 0x0, 
    next = 0x0
  }, 
  surface = 0x6f17d50, 
  x = 0, 
  y = 0, 
  width = 1152, 
  height = 648, 
  saved_width = 0, 
  saved_height = 0, 
  override_redirect = false, 
  mapped = false, 
  title = 0x6f00ff0 "Mozilla Firefox", 
  c_class = 0x6f11170 "Firefox", 
  instance = 0x6f11150 "Navigator", 
  role = 0x6f11130 "browser", 
  pid = 5003, 
  has_utf8_title = true, 
  children = {
    prev = 0x6f0a8d8, 
    next = 0x6f0a8d8
  }, 
  parent = 0x0, 
  parent_link = {
    prev = 0x6f0a8f0, 
    next = 0x6f0a8f0
  }, 
  window_type = 0x6f29830, 
  window_type_len = 1, 
  protocols = 0x6f29810, 
  protocols_len = 4, 
  decorations = 0, 
  hints = 0x6bc5cd0, 
  hints_urgency = 0, 
  size_hints = 0x6f18070, 
  pinging = false, 
  ping_timer = 0x6f09ba0, 
  modal = false, 
  fullscreen = false, 
  maximized_vert = true, 
  maximized_horz = true, 
  has_alpha = false, 
  events = {
    destroy = {
      listener_list = {
        prev = 0x6f0acf8, 
        next = 0x6f0acf8
      }
    }, 
    request_configure = {
      listener_list = {
        prev = 0x6f0ad40, 
        next = 0x6f0ad40
      }
    }, 
    request_move = {
      listener_list = {
        prev = 0x6f0ac80, 
        next = 0x6f0ac80
      }
    }, 
    request_resize = {
      listener_list = {
        prev = 0x6f0ac98, 
        next = 0x6f0ac98
      }
    }, 
    request_maximize = {
      listener_list = {
        prev = 0x6f0ac38, 
        next = 0x6f0ac38
      }
    }, 
    request_fullscreen = {
      listener_list = {
        prev = 0x6f0ac50, 
        next = 0x6f0ac50
      }
    }, 
    request_activate = {
      listener_list = {
        prev = 0x6f0a9b8, 
        next = 0x6f0a9b8
      }
    }, 
    map = {
      listener_list = {
        prev = 0x7fffffffd0e0, 
        next = 0x6f0ad10
      }
    }, 
    unmap = {
      listener_list = {
        prev = 0x6f0ad28, 
        next = 0x6f0ad28
      }
    }, 
    set_title = {
      listener_list = {
        prev = 0x6f0a9e8, 
        next = 0x6f0a9e8
      }
    }, 
    set_class = {
      listener_list = {
        prev = 0x6f0a9f8, 
        next = 0x6f0a9f8
      }
    }, 
    set_role = {
      listener_list = {
        prev = 0x6f0aa08, 
        next = 0x6f0aa08
      }
    }, 
    set_parent = {
      listener_list = {
        prev = 0x6f0aa18, 
        next = 0x6f0aa18
      }
    }, 
    set_pid = {
      listener_list = {
        prev = 0x6f0aa28, 
        next = 0x6f0aa28
      }
    }, 
    set_window_type = {
      listener_list = {
        prev = 0x6f0aa38, 
        next = 0x6f0aa38
      }
    }, 
    set_hints = {
      listener_list = {
        prev = 0x6f0aa48, 
        next = 0x6f0aa48
      }
    }, 
    set_decorations = {
      listener_list = {
        prev = 0x6f0aa58, 
        next = 0x6f0aa58
      }
    }, 
    set_override_redirect = {
      listener_list = {
        prev = 0x6f0aa68, 
        next = 0x6f0aa68
      }
    }, 
    ping_timeout = {
      listener_list = {
        prev = 0x6f0aa78, 
        next = 0x6f0aa78
      }
    }
  }, 
  surface_destroy = {
    link = {
      prev = 0x6f18010, 
      next = 0x6f18010
    }, 
    notify = 0x7ffff744bec5 <handle_surface_destroy>
  }, 
  data = 0x6f0aab0
}
georgewsinger commented 4 years ago

Fixed in https://github.com/SimulaVR/Simula/commit/8bd3018754efe0d7af0b0c226a871dfc9fdc576a.