// 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/debug_commands.h" #include #include #include "ash/accelerators/accelerator_commands.h" #include "ash/constants/ash_features.h" #include "ash/constants/ash_switches.h" #include "ash/constants/notifier_catalogs.h" #include "ash/hud_display/hud_display.h" #include "ash/public/cpp/accelerators.h" #include "ash/public/cpp/debug_utils.h" #include "ash/public/cpp/system/toast_data.h" #include "ash/shell.h" #include "ash/system/toast/toast_manager_impl.h" #include "ash/touch/touch_devices_controller.h" #include "ash/wallpaper/wallpaper_controller_impl.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "base/command_line.h" #include "base/metrics/user_metrics.h" #include "base/metrics/user_metrics_action.h" #include "base/strings/utf_string_conversions.h" #include "ui/accessibility/ax_tree_id.h" #include "ui/aura/client/aura_constants.h" #include "ui/display/manager/display_manager.h" #include "ui/gfx/canvas.h" #include "ui/gfx/geometry/skia_conversions.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia_rep.h" #include "ui/views/widget/widget.h" namespace ash { namespace debug { namespace { void HandlePrintLayerHierarchy() { std::ostringstream out; PrintLayerHierarchy(&out); LOG(ERROR) << out.str(); } void HandlePrintViewHierarchy() { std::ostringstream out; PrintViewHierarchy(&out); LOG(ERROR) << out.str(); } void HandlePrintWindowHierarchy() { std::ostringstream out; PrintWindowHierarchy(&out, /*scrub_data=*/false); 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); SkBitmap bitmap; bitmap.allocN32Pixels(image_size.width(), image_size.height(), true); SkCanvas canvas(bitmap); canvas.drawColor(fill); SkPaint paint; paint.setColor(rect); paint.setStrokeWidth(10); paint.setStyle(SkPaint::kStroke_Style); paint.setBlendMode(SkBlendMode::kSrcOver); canvas.drawRoundRect(gfx::RectToSkRect(gfx::Rect(image_size)), 100.f, 100.f, paint); return gfx::ImageSkia::CreateFromBitmap(std::move(bitmap), 1.f); } void HandleToggleWallpaperMode() { static int index = 0; auto* wallpaper_controller = Shell::Get()->wallpaper_controller(); WallpaperInfo info("", WALLPAPER_LAYOUT_STRETCH, WallpaperType::kDefault, base::Time::Now().LocalMidnight()); switch (++index % 4) { case 0: wallpaper_controller->ShowDefaultWallpaperForTesting(); break; case 1: wallpaper_controller->ShowWallpaperImage( CreateWallpaperImage(SK_ColorRED, SK_ColorBLUE), info, /*preview_mode=*/false, /*always_on_top=*/false); break; case 2: info.layout = WALLPAPER_LAYOUT_CENTER; wallpaper_controller->ShowWallpaperImage( CreateWallpaperImage(SK_ColorBLUE, SK_ColorGREEN), info, /*preview_mode=*/false, /*always_on_top=*/false); break; case 3: info.layout = WALLPAPER_LAYOUT_CENTER_CROPPED; wallpaper_controller->ShowWallpaperImage( CreateWallpaperImage(SK_ColorGREEN, SK_ColorRED), info, /*preview_mode=*/false, /*always_on_top=*/false); break; } } void HandleDumpCalendarModel() { accelerators::DumpCalendarModel(); } void HandleToggleKeyboardBacklight() { if (ash::features::IsKeyboardBacklightToggleEnabled()) { base::RecordAction(base::UserMetricsAction("Accel_Keyboard_Backlight")); accelerators::ToggleKeyboardBacklight(); } } void HandleToggleMicrophoneMute() { base::RecordAction(base::UserMetricsAction("Accel_Microphone_Mute")); accelerators::MicrophoneMuteToggle(); } void HandleToggleTouchpad() { base::RecordAction(base::UserMetricsAction("Accel_Toggle_Touchpad")); Shell::Get()->touch_devices_controller()->ToggleTouchpad(); } void HandleToggleTouchscreen() { base::RecordAction(base::UserMetricsAction("Accel_Toggle_Touchscreen")); TouchDevicesController* controller = Shell::Get()->touch_devices_controller(); controller->SetTouchscreenEnabled( !controller->GetTouchscreenEnabled(TouchDeviceEnabledSource::USER_PREF), TouchDeviceEnabledSource::USER_PREF); } void HandleToggleTabletMode() { TabletModeController* controller = Shell::Get()->tablet_mode_controller(); controller->SetEnabledForDev(!controller->InTabletMode()); } void HandleTriggerCrash() { LOG(FATAL) << "Intentional crash via debug accelerator."; } void HandleTriggerHUDDisplay() { hud_display::HUDDisplayView::Toggle(); } } // 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 base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kAshDebugShortcuts); } bool DeveloperAcceleratorsEnabled() { return base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kAshDeveloperShortcuts); } void PerformDebugActionIfEnabled(AcceleratorAction action) { if (!DebugAcceleratorsEnabled()) return; switch (action) { case DEBUG_DUMP_CALENDAR_MODEL: HandleDumpCalendarModel(); break; case DEBUG_KEYBOARD_BACKLIGHT_TOGGLE: HandleToggleKeyboardBacklight(); break; case DEBUG_MICROPHONE_MUTE_TOGGLE: HandleToggleMicrophoneMute(); break; case DEBUG_PRINT_LAYER_HIERARCHY: HandlePrintLayerHierarchy(); break; case DEBUG_PRINT_VIEW_HIERARCHY: HandlePrintViewHierarchy(); break; case DEBUG_PRINT_WINDOW_HIERARCHY: HandlePrintWindowHierarchy(); break; case DEBUG_SHOW_TOAST: Shell::Get()->toast_manager()->Show(ToastData( /*id=*/"id", ToastCatalogName::kDebugCommand, /*text=*/u"Toast", ToastData::kDefaultToastDuration, /*visible_on_lock_screen=*/false, /*has_dismiss_button=*/true, /*custom_dismiss_text=*/u"Dismiss")); break; case DEBUG_TOGGLE_TOUCH_PAD: HandleToggleTouchpad(); break; case DEBUG_TOGGLE_TOUCH_SCREEN: HandleToggleTouchscreen(); break; case DEBUG_TOGGLE_TABLET_MODE: HandleToggleTabletMode(); break; case DEBUG_TOGGLE_WALLPAPER_MODE: HandleToggleWallpaperMode(); break; case DEBUG_TRIGGER_CRASH: HandleTriggerCrash(); break; case DEBUG_TOGGLE_HUD_DISPLAY: HandleTriggerHUDDisplay(); break; default: break; } } } // namespace debug } // namespace ash