blob: 7bd4e71af34eefa59c6c375d96b7f66b9bc7b425 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/accelerators/accelerator_commands.h"
#include "ash/accelerators/accelerator_table.h"
#include "ash/ash_switches.h"
#include "ash/debug.h"
#include "ash/desktop_background/desktop_background_controller.h"
#include "ash/desktop_background/user_wallpaper_delegate.h"
#include "ash/display/display_manager.h"
#include "ash/host/ash_window_tree_host.h"
#include "ash/root_window_controller.h"
#include "ash/shell.h"
#include "ash/wm/window_util.h"
#include "base/command_line.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/compositor/debug_utils.h"
#include "ui/compositor/layer.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/views/debug_utils.h"
#include "ui/views/widget/widget.h"
namespace ash {
namespace debug {
namespace {
void HandlePrintLayerHierarchy() {
aura::Window::Windows root_windows = Shell::GetAllRootWindows();
for (size_t i = 0; i < root_windows.size(); ++i) {
ui::PrintLayerHierarchy(
root_windows[i]->layer(),
root_windows[i]->GetHost()->dispatcher()->GetLastMouseLocationInRoot());
}
}
void HandlePrintViewHierarchy() {
aura::Window* active_window = ash::wm::GetActiveWindow();
if (!active_window)
return;
views::Widget* browser_widget =
views::Widget::GetWidgetForNativeWindow(active_window);
if (!browser_widget)
return;
views::PrintViewHierarchy(browser_widget->GetRootView());
}
void PrintWindowHierarchy(aura::Window* window,
int indent,
std::ostringstream* out) {
std::string indent_str(indent, ' ');
std::string name(window->name());
if (name.empty())
name = "\"\"";
*out << indent_str << name << " (" << window << ")"
<< " type=" << window->type()
<< (wm::IsActiveWindow(window) ? " [active] " : " ")
<< (window->IsVisible() ? " visible " : " ")
<< window->bounds().ToString()
<< '\n';
for (size_t i = 0; i < window->children().size(); ++i)
PrintWindowHierarchy(window->children()[i], indent + 3, out);
}
void HandlePrintWindowHierarchy() {
Shell::RootWindowControllerList controllers =
Shell::GetAllRootWindowControllers();
for (size_t i = 0; i < controllers.size(); ++i) {
std::ostringstream out;
out << "RootWindow " << i << ":\n";
PrintWindowHierarchy(controllers[i]->GetRootWindow(), 0, &out);
// Error so logs can be collected from end-users.
LOG(ERROR) << out.str();
}
}
gfx::ImageSkia CreateWallpaperImage(SkColor fill, SkColor rect) {
// TODO(oshima): Consider adding a command line option to control
// wallpaper images for testing.
// The size is randomly picked.
gfx::Size image_size(1366, 768);
gfx::Canvas canvas(image_size, 1.0f, true);
canvas.DrawColor(fill);
SkPaint paint;
paint.setColor(rect);
paint.setStrokeWidth(10);
paint.setStyle(SkPaint::kStroke_Style);
paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
canvas.DrawRoundRect(gfx::Rect(image_size), 100, paint);
return gfx::ImageSkia(canvas.ExtractImageRep());
}
void HandleToggleDesktopBackgroundMode() {
static int index = 0;
DesktopBackgroundController* desktop_background_controller =
Shell::GetInstance()->desktop_background_controller();
switch (++index % 4) {
case 0:
ash::Shell::GetInstance()->user_wallpaper_delegate()->
InitializeWallpaper();
break;
case 1:
desktop_background_controller->SetWallpaperImage(
CreateWallpaperImage(SK_ColorRED, SK_ColorBLUE),
WALLPAPER_LAYOUT_STRETCH);
break;
case 2:
desktop_background_controller->SetWallpaperImage(
CreateWallpaperImage(SK_ColorBLUE, SK_ColorGREEN),
WALLPAPER_LAYOUT_CENTER);
break;
case 3:
desktop_background_controller->SetWallpaperImage(
CreateWallpaperImage(SK_ColorGREEN, SK_ColorRED),
WALLPAPER_LAYOUT_CENTER_CROPPED);
break;
}
}
} // namespace
void PrintUIHierarchies() {
// This is a separate command so the user only has to hit one key to generate
// all the logs. Developers use the individual dumps repeatedly, so keep
// those as separate commands to avoid spamming their logs.
HandlePrintLayerHierarchy();
HandlePrintWindowHierarchy();
HandlePrintViewHierarchy();
}
bool DebugAcceleratorsEnabled() {
return CommandLine::ForCurrentProcess()->HasSwitch(
switches::kAshDebugShortcuts);
}
void PerformDebugAction(int action) {
if (!DebugAcceleratorsEnabled())
return;
switch (action) {
#if defined(OS_CHROMEOS)
case DEBUG_ADD_REMOVE_DISPLAY:
Shell::GetInstance()->display_manager()->AddRemoveDisplay();
break;
#endif
case DEBUG_PRINT_LAYER_HIERARCHY:
HandlePrintLayerHierarchy();
break;
case DEBUG_PRINT_VIEW_HIERARCHY:
HandlePrintViewHierarchy();
break;
case DEBUG_PRINT_WINDOW_HIERARCHY:
HandlePrintWindowHierarchy();
break;
case DEBUG_TOGGLE_DESKTOP_BACKGROUND_MODE:
HandleToggleDesktopBackgroundMode();
break;
case DEBUG_TOGGLE_DEVICE_SCALE_FACTOR:
Shell::GetInstance()->display_manager()->ToggleDisplayScaleFactor();
break;
case DEBUG_TOGGLE_ROOT_WINDOW_FULL_SCREEN:
Shell::GetPrimaryRootWindowController()->ash_host()->ToggleFullScreen();
break;
case DEBUG_TOGGLE_SHOW_DEBUG_BORDERS:
ToggleShowDebugBorders();
break;
case DEBUG_TOGGLE_SHOW_FPS_COUNTER:
ToggleShowFpsCounter();
break;
case DEBUG_TOGGLE_SHOW_PAINT_RECTS:
ToggleShowPaintRects();
break;
default:
break;
}
}
} // namespace debug
} // namespace ash