# Global Metrics

path: .metrics.cyclomatic.sum
old: 121.0
new: 25.0
path: .metrics.cyclomatic.average
old: 2.1607142857142856
new: 1.6666666666666667
path: .metrics.mi.mi_sei
old: -66.52767086372864
new: -0.25675347532985526
path: .metrics.mi.mi_original
old: -16.582158762728383
new: 34.29280974268012
path: .metrics.mi.mi_visual_studio
old: 0.0
new: 20.054274703321703
path: .metrics.loc.ploc
old: 577.0
new: 151.0
path: .metrics.loc.blank
old: 111.0
new: 40.0
path: .metrics.loc.cloc
old: 57.0
new: 21.0
path: .metrics.loc.sloc
old: 745.0
new: 212.0
path: .metrics.loc.lloc
old: 184.0
new: 68.0
path: .metrics.cognitive.sum
old: 86.0
new: 12.0
path: .metrics.cognitive.average
old: 1.6862745098039216
new: 0.8571428571428571
path: .metrics.nargs.sum
old: 112.0
new: 3.0
path: .metrics.nargs.average
old: 2.196078431372549
new: 0.21428571428571427
path: .metrics.nexits.average
old: 1.3725490196078431
new: 0.7142857142857143
path: .metrics.nexits.sum
old: 70.0
new: 10.0
path: .metrics.halstead.estimated_program_length
old: 1929.7836052918128
new: 841.5415307421127
path: .metrics.halstead.N2
old: 1270.0
new: 286.0
path: .metrics.halstead.length
old: 3097.0
new: 694.0
path: .metrics.halstead.volume
old: 24793.419228853443
new: 4896.366010237825
path: .metrics.halstead.bugs
old: 5.15822811283093
new: 1.0561459852936046
path: .metrics.halstead.N1
old: 1827.0
new: 408.0
path: .metrics.halstead.vocabulary
old: 257.0
new: 133.0
path: .metrics.halstead.time
old: 106944.92816327373
new: 9908.21235090579
path: .metrics.halstead.n1
old: 28.0
new: 27.0
path: .metrics.halstead.difficulty
old: 77.64192139737992
new: 36.424528301886795
path: .metrics.halstead.level
old: 0.012879640044994376
new: 0.027454027454027453
path: .metrics.halstead.n2
old: 229.0
new: 106.0
path: .metrics.halstead.purity_ratio
old: 0.6231138538236399
new: 1.2125958656226408
path: .metrics.halstead.effort
old: 1925008.7069389268
new: 178347.8223163042
path: .metrics.nom.closures
old: 0.0
new: 2.0
path: .metrics.nom.total
old: 51.0
new: 14.0
path: .metrics.nom.functions
old: 51.0
new: 12.0

# Spaces Data

## Minimal test - lines (19, 212)

path: .spaces[0].metrics.nexits.average
old: 1.0
new: 0.7142857142857143
path: .spaces[0].metrics.nexits.sum
old: 1.0
new: 10.0
path: .spaces[0].metrics.cyclomatic.average
old: 1.0
new: 1.7142857142857142
path: .spaces[0].metrics.cyclomatic.sum
old: 1.0
new: 24.0
path: .spaces[0].metrics.loc.ploc
old: 5.0
new: 141.0
path: .spaces[0].metrics.loc.sloc
old: 6.0
new: 194.0
path: .spaces[0].metrics.loc.blank
old: 0.0
new: 38.0
path: .spaces[0].metrics.loc.cloc
old: 1.0
new: 15.0
path: .spaces[0].metrics.loc.lloc
old: 1.0
new: 68.0
path: .spaces[0].metrics.cognitive.sum
old: 0.0
new: 12.0
path: .spaces[0].metrics.cognitive.average
old: 0.0
new: 0.8571428571428571
path: .spaces[0].metrics.halstead.n1
old: 9.0
new: 27.0
path: .spaces[0].metrics.halstead.estimated_program_length
old: 57.05865002596162
new: 768.573508250565
path: .spaces[0].metrics.halstead.difficulty
old: 6.0
new: 38.41237113402062
path: .spaces[0].metrics.halstead.effort
old: 650.5083002250007
new: 182447.85684596415
path: .spaces[0].metrics.halstead.time
old: 36.13935001250004
new: 10135.992046998008
path: .spaces[0].metrics.halstead.N2
old: 12.0
new: 276.0
path: .spaces[0].metrics.halstead.N1
old: 14.0
new: 407.0
path: .spaces[0].metrics.halstead.length
old: 26.0
new: 683.0
path: .spaces[0].metrics.halstead.volume
old: 108.41805003750012
new: 4749.716079994236
path: .spaces[0].metrics.halstead.level
old: 0.16666666666666666
new: 0.026033279656468063
path: .spaces[0].metrics.halstead.purity_ratio
old: 2.194563462536985
new: 1.1252906416552928
path: .spaces[0].metrics.halstead.bugs
old: 0.02502537766060993
new: 1.0722710714706876
path: .spaces[0].metrics.halstead.n2
old: 9.0
new: 97.0
path: .spaces[0].metrics.halstead.vocabulary
old: 18.0
new: 124.0
path: .spaces[0].metrics.nargs.average
old: 1.0
new: 0.21428571428571427
path: .spaces[0].metrics.nargs.sum
old: 1.0
new: 3.0
path: .spaces[0].metrics.nom.functions
old: 1.0
new: 12.0
path: .spaces[0].metrics.nom.closures
old: 0.0
new: 2.0
path: .spaces[0].metrics.nom.total
old: 1.0
new: 14.0
path: .spaces[0].metrics.mi.mi_visual_studio
old: 68.64112557824586
new: 21.121829933102344
path: .spaces[0].metrics.mi.mi_original
old: 117.37632473880043
new: 36.118329185605006
path: .spaces[0].metrics.mi.mi_sei
old: 123.29556534659632
new: -0.2706894464990661

### Code

    namespace mozilla {
    namespace widget {

    static StaticRefPtr sWinCompositorWindowThread;

    WinCompositorWindowThread::WinCompositorWindowThread(base::Thread* aThread)
        : mThread(aThread) {}

    WinCompositorWindowThread::~WinCompositorWindowThread() { delete mThread; }

    /* static */
    WinCompositorWindowThread* WinCompositorWindowThread::Get() {
      return sWinCompositorWindowThread;
    }

    /* static */
    void WinCompositorWindowThread::Start() {
      MOZ_ASSERT(NS_IsMainThread());
      MOZ_ASSERT(!sWinCompositorWindowThread);

      base::Thread* thread = new base::Thread("WinCompositor");

      base::Thread::Options options;
      // HWND requests ui thread.
      options.message_loop_type = MessageLoop::TYPE_UI;

      if (!thread->StartWithOptions(options)) {
        delete thread;
        return;
      }

      sWinCompositorWindowThread = new WinCompositorWindowThread(thread);
    }

    /* static */
    void WinCompositorWindowThread::ShutDown() {
      MOZ_ASSERT(NS_IsMainThread());
      MOZ_ASSERT(sWinCompositorWindowThread);

      layers::SynchronousTask task("WinCompositorWindowThread");
      RefPtr runnable = WrapRunnable(
          RefPtr(sWinCompositorWindowThread.get()),
          &WinCompositorWindowThread::ShutDownTask, &task);
      sWinCompositorWindowThread->Loop()->PostTask(runnable.forget());
      task.Wait();

      sWinCompositorWindowThread = nullptr;
    }

    void WinCompositorWindowThread::ShutDownTask(layers::SynchronousTask* aTask) {
      layers::AutoCompleteTask complete(aTask);
      MOZ_ASSERT(IsInCompositorWindowThread());
    }

    /* static */
    MessageLoop* WinCompositorWindowThread::Loop() {
      return sWinCompositorWindowThread
                 ? sWinCompositorWindowThread->mThread->message_loop()
                 : nullptr;
    }

    /* static */
    bool WinCompositorWindowThread::IsInCompositorWindowThread() {
      return sWinCompositorWindowThread &&
             sWinCompositorWindowThread->mThread->thread_id() ==
                 PlatformThread::CurrentId();
    }

    const wchar_t kClassNameCompositorInitalParent[] =
        L"MozillaCompositorInitialParentClass";
    const wchar_t kClassNameCompositor[] = L"MozillaCompositorWindowClass";

    ATOM g_compositor_inital_parent_window_class;
    ATOM g_compositor_window_class;

    // This runs on the window owner thread.
    void InitializeInitialParentWindowClass() {
      if (g_compositor_inital_parent_window_class) {
        return;
      }

      WNDCLASSW wc;
      wc.style = 0;
      wc.lpfnWndProc = ::DefWindowProcW;
      wc.cbClsExtra = 0;
      wc.cbWndExtra = 0;
      wc.hInstance = GetModuleHandle(nullptr);
      wc.hIcon = nullptr;
      wc.hCursor = nullptr;
      wc.hbrBackground = nullptr;
      wc.lpszMenuName = nullptr;
      wc.lpszClassName = kClassNameCompositorInitalParent;
      g_compositor_inital_parent_window_class = ::RegisterClassW(&wc);
    }

    // This runs on the window owner thread.
    void InitializeWindowClass() {
      if (g_compositor_window_class) {
        return;
      }

      WNDCLASSW wc;
      wc.style = CS_OWNDC;
      wc.lpfnWndProc = ::DefWindowProcW;
      wc.cbClsExtra = 0;
      wc.cbWndExtra = 0;
      wc.hInstance = GetModuleHandle(nullptr);
      wc.hIcon = nullptr;
      wc.hCursor = nullptr;
      wc.hbrBackground = nullptr;
      wc.lpszMenuName = nullptr;
      wc.lpszClassName = kClassNameCompositor;
      g_compositor_window_class = ::RegisterClassW(&wc);
    }

    /* static */
    WinCompositorWnds WinCompositorWindowThread::CreateCompositorWindow() {
      MOZ_ASSERT(Loop());

      if (!Loop()) {
        return WinCompositorWnds(nullptr, nullptr);
      }

      layers::SynchronousTask task("Create compositor window");

      HWND initialParentWnd = nullptr;
      HWND compositorWnd = nullptr;

      RefPtr runnable = NS_NewRunnableFunction(
          "WinCompositorWindowThread::CreateCompositorWindow::Runnable", [&]() {
            layers::AutoCompleteTask complete(&task);

            InitializeInitialParentWindowClass();
            InitializeWindowClass();

            // Create initial parent window.
            // We could not directly create a compositor window with a main window
            // as parent window, so instead create it with a temporary placeholder
            // parent. Its parent is set as main window in UI process.
            initialParentWnd =
                ::CreateWindowEx(WS_EX_TOOLWINDOW, kClassNameCompositorInitalParent,
                                 nullptr, WS_POPUP | WS_DISABLED, 0, 0, 1, 1,
                                 nullptr, 0, GetModuleHandle(nullptr), 0);
            if (!initialParentWnd) {
              gfxCriticalNoteOnce << "Inital parent window failed "
                                  << ::GetLastError();
              return;
            }

            DWORD extendedStyle = WS_EX_NOPARENTNOTIFY | WS_EX_NOREDIRECTIONBITMAP;

            if (!StaticPrefs::apz_windows_force_disable_direct_manipulation()) {
              extendedStyle |= WS_EX_LAYERED | WS_EX_TRANSPARENT;
            }

            compositorWnd = ::CreateWindowEx(
                extendedStyle, kClassNameCompositor, nullptr,
                WS_CHILDWINDOW | WS_DISABLED | WS_VISIBLE, 0, 0, 1, 1,
                initialParentWnd, 0, GetModuleHandle(nullptr), 0);
            if (!compositorWnd) {
              gfxCriticalNoteOnce << "Compositor window failed "
                                  << ::GetLastError();
            }
          });

      Loop()->PostTask(runnable.forget());

      task.Wait();

      return WinCompositorWnds(compositorWnd, initialParentWnd);
    }

    /* static */
    void WinCompositorWindowThread::DestroyCompositorWindow(
        WinCompositorWnds aWnds) {
      MOZ_ASSERT(aWnds.mCompositorWnd);
      MOZ_ASSERT(aWnds.mInitialParentWnd);
      MOZ_ASSERT(Loop());

      if (!Loop()) {
        return;
      }

      RefPtr runnable = NS_NewRunnableFunction(
          "WinCompositorWidget::CreateNativeWindow::Runnable", [aWnds]() {
            ::DestroyWindow(aWnds.mCompositorWnd);
            ::DestroyWindow(aWnds.mInitialParentWnd);
          });

      Loop()->PostTask(runnable.forget());
    }

    }  // namespace widget
    }  // namespace mozilla